Skip to content

Commit

Permalink
(Draft) add travis (#19)
Browse files Browse the repository at this point in the history
* add travis

- set up package:mono_repo
- add test to ffi/hello_world

* fix typo

* run dartfmt

* don't run tests for certain FFI samples

* update ffi/primitives sample for CI

* update structs and system-command for Dart 2.6

* disable stable testing for FFI samples
  • Loading branch information
johnpryan committed Nov 5, 2019
1 parent 9f2b84f commit 3933ad3
Show file tree
Hide file tree
Showing 27 changed files with 506 additions and 101 deletions.
132 changes: 132 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# Created with package:mono_repo v2.3.0
language: dart

jobs:
include:
- stage: analyze
name: "SDK: dev; PKG: ffi/hello_world; TASKS: `dartanalyzer .`"
dart: dev
os: linux
env: PKGS="ffi/hello_world"
script: ./tool/travis.sh dartanalyzer
- stage: analyze
name: "SDK: stable; PKG: ffi/hello_world; TASKS: `dartanalyzer .`"
dart: stable
os: linux
env: PKGS="ffi/hello_world"
script: ./tool/travis.sh dartanalyzer
- stage: analyze
name: "SDK: dev; PKG: ffi/hello_world; TASKS: `dartfmt -n --set-exit-if-changed .`"
dart: dev
os: linux
env: PKGS="ffi/hello_world"
script: ./tool/travis.sh dartfmt
- stage: analyze
name: "SDK: stable; PKG: ffi/hello_world; TASKS: `dartfmt -n --set-exit-if-changed .`"
dart: stable
os: linux
env: PKGS="ffi/hello_world"
script: ./tool/travis.sh dartfmt
- stage: analyze
name: "SDK: dev; PKG: ffi/primitives; TASKS: `dartanalyzer .`"
dart: dev
os: linux
env: PKGS="ffi/primitives"
script: ./tool/travis.sh dartanalyzer
- stage: analyze
name: "SDK: dev; PKG: ffi/primitives; TASKS: `dartfmt -n --set-exit-if-changed .`"
dart: dev
os: linux
env: PKGS="ffi/primitives"
script: ./tool/travis.sh dartfmt
- stage: analyze
name: "SDK: dev; PKG: ffi/structs; TASKS: `dartanalyzer .`"
dart: dev
os: linux
env: PKGS="ffi/structs"
script: ./tool/travis.sh dartanalyzer
- stage: analyze
name: "SDK: dev; PKG: ffi/structs; TASKS: `dartfmt -n --set-exit-if-changed .`"
dart: dev
os: linux
env: PKGS="ffi/structs"
script: ./tool/travis.sh dartfmt
- stage: analyze
name: "SDK: dev; PKG: ffi/system-command; TASKS: `dartanalyzer .`"
dart: dev
os: linux
env: "PKGS=\"ffi/system-command\""
script: ./tool/travis.sh dartanalyzer
- stage: analyze
name: "SDK: dev; PKG: ffi/system-command; TASKS: `dartfmt -n --set-exit-if-changed .`"
dart: dev
os: linux
env: "PKGS=\"ffi/system-command\""
script: ./tool/travis.sh dartfmt
- stage: analyze
name: "SDK: dev; PKG: native_app; TASKS: `dartanalyzer .`"
dart: dev
os: linux
env: PKGS="native_app"
script: ./tool/travis.sh dartanalyzer
- stage: analyze
name: "SDK: stable; PKG: native_app; TASKS: `dartanalyzer .`"
dart: stable
os: linux
env: PKGS="native_app"
script: ./tool/travis.sh dartanalyzer
- stage: analyze
name: "SDK: dev; PKG: native_app; TASKS: `dartfmt -n --set-exit-if-changed .`"
dart: dev
os: linux
env: PKGS="native_app"
script: ./tool/travis.sh dartfmt
- stage: analyze
name: "SDK: stable; PKG: native_app; TASKS: `dartfmt -n --set-exit-if-changed .`"
dart: stable
os: linux
env: PKGS="native_app"
script: ./tool/travis.sh dartfmt
- stage: unit_test
name: "SDK: dev; PKG: ffi/hello_world; TASKS: `pub run test`"
dart: dev
os: linux
env: PKGS="ffi/hello_world"
script: ./tool/travis.sh test
- stage: unit_test
name: "SDK: stable; PKG: ffi/hello_world; TASKS: `pub run test`"
dart: stable
os: linux
env: PKGS="ffi/hello_world"
script: ./tool/travis.sh test
- stage: unit_test
name: "SDK: dev; PKG: ffi/primitives; TASKS: `pub run test`"
dart: dev
os: linux
env: PKGS="ffi/primitives"
script: ./tool/travis.sh test
- stage: unit_test
name: "SDK: dev; PKG: native_app; TASKS: `pub run test`"
dart: dev
os: linux
env: PKGS="native_app"
script: ./tool/travis.sh test
- stage: unit_test
name: "SDK: stable; PKG: native_app; TASKS: `pub run test`"
dart: stable
os: linux
env: PKGS="native_app"
script: ./tool/travis.sh test

stages:
- analyze
- unit_test

# Only building master means that we don't run two builds for each pull request.
branches:
only:
- master

cache:
directories:
- "$HOME/.pub-cache"
8 changes: 8 additions & 0 deletions ffi/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,11 @@ A dll can be created in two ways.

More details on how to write/generate one [here](https://stackoverflow.com/a/32284832/8608146)

## Using Docker

Samples with a Dockerfile can be tested using Docker:

```
docker build -t dart-ffi .
docker run dart-ffi pub run test
```
10 changes: 10 additions & 0 deletions ffi/hello_world/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
FROM google/dart:2.6.0-dev.8.2

WORKDIR /app

ADD pubspec.* /app/
RUN pub get
COPY . /app
RUN pub get --offline

RUN apt-get update && apt-get install -y make gcc
8 changes: 8 additions & 0 deletions ffi/hello_world/c/LinuxMakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
hello.o: hello.c
gcc -c -fpic hello.c

so: hello.o
gcc -shared hello.o -o ../hello_world.so

clean:
rm -f hello.o ../hello_world.so
3 changes: 2 additions & 1 deletion ffi/hello_world/hello.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ typedef HelloWorld = void Function();

main() {
// Open the dynamic library
var path = "hello_world.dylib";
var path = "./hello_world.so";
if (Platform.isMacOS) path = "./hello_world.dylib";
if (Platform.isWindows) path = "hello_world.dll";
final dylib = ffi.DynamicLibrary.open(path);
// Look up the C function 'hello_world'
Expand Down
10 changes: 10 additions & 0 deletions ffi/hello_world/mono_pkg.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
dart:
- dev
- stable

stages:
- analyze:
- dartanalyzer
- dartfmt
- unit_test:
- test
33 changes: 33 additions & 0 deletions ffi/hello_world/test/hello_world_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import 'dart:io';

import 'package:test/test.dart';

// These tests are Linux-only. For platform-specific instructions, see the
// README.
void main() async {
group('hello_world', () {
test('make dylib + execute', () async {
// run 'make clean'
var clean = await Process.run('make', ['-f', 'LinuxMakefile', 'clean'],
workingDirectory: 'c');
expect(clean.exitCode, 0);

// run 'make so'
var dynamicLib = await Process.run('make', ['-f', 'LinuxMakefile', 'so'],
workingDirectory: 'c');
expect(dynamicLib.exitCode, 0);

// Verify dynamic library was created
var file = File('./hello_world.so');
expect(await file.exists(), true);

// Run the Dart script
var dartProcess = await Process.run('dart', ['hello.dart']);
expect(dartProcess.exitCode, equals(0));

// Verify program output
expect(dartProcess.stderr, isEmpty);
expect(dartProcess.stdout, equals('Hello World\n'));
});
});
}
10 changes: 10 additions & 0 deletions ffi/primitives/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
FROM google/dart:2.6.0-dev.8.2

WORKDIR /app

ADD pubspec.* /app/
RUN pub get
COPY . /app
RUN pub get --offline

RUN apt-get update && apt-get install -y make gcc
8 changes: 8 additions & 0 deletions ffi/primitives/c/LinuxMakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
primitives.o: primitives.c
gcc -c -fpic primitives.c

so: primitives.o
gcc -shared primitives.o -o ../primitives.so

clean:
rm -f a.out primitives.o ../primitives.so
9 changes: 9 additions & 0 deletions ffi/primitives/mono_pkg.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
dart:
- dev

stages:
- analyze:
- dartanalyzer
- dartfmt
- unit_test:
- test
62 changes: 31 additions & 31 deletions ffi/primitives/primitives.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,73 +2,73 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:ffi' as ffi;
import 'dart:ffi';
import 'dart:io' show Platform;

import 'package:ffi/ffi.dart';

// C sum function - int sum(int a, int b);
// Example of how to pass paramters into C and use the returned result
typedef sum_func = ffi.Int32 Function(ffi.Int32 a, ffi.Int32 b);
//
// Example of how to pass parameters into C and use the returned result
typedef sum_func = Int32 Function(Int32 a, Int32 b);
typedef Sum = int Function(int a, int b);

// C subtract function - int subtract(int *a, int b);
// Example of how to create pointers in Dart, alloc them, and pass them as parameters
typedef subtract_func = ffi.Int32 Function(
ffi.Pointer<ffi.Int32> a, ffi.Int32 b);
typedef Subtract = int Function(ffi.Pointer<ffi.Int32> a, int b);
//
// Example of how to create pointers in Dart, alloc them, and pass them as
// parameters
typedef subtract_func = Int32 Function(Pointer<Int32> a, Int32 b);
typedef Subtract = int Function(Pointer<Int32> a, int b);

// C multiply function - int *multiply(int a, int b);
//
// Example of how to receive pointers in Dart and access the data
typedef multiply_func = ffi.Pointer<ffi.Int32> Function(
ffi.Int32 a, ffi.Int32 b);
typedef Multiply = ffi.Pointer<ffi.Int32> Function(int a, int b);
typedef multiply_func = Pointer<Int32> Function(Int32 a, Int32 b);
typedef Multiply = Pointer<Int32> Function(int a, int b);

// C multi sum fuction - int multi_sum(int nr_count, ...);
// Example of how to call C functions with varargs with a fixed arg count in Dart
typedef multi_sum_func = ffi.Int32 Function(
ffi.Int32 numCount, ffi.Int32 a, ffi.Int32 b, ffi.Int32 c);
// C multi sum function - int multi_sum(int nr_count, ...);
//
// Example of how to call C functions with varargs with a fixed arg count in
// Dart
typedef multi_sum_func = Int32 Function(
Int32 numCount, Int32 a, Int32 b, Int32 c);
typedef MultiSum = int Function(int numCount, int a, int b, int c);

main() {
var path = 'primitives.dylib';
var path = './primitives.so';
if (Platform.isWindows) path = 'primitives.dll';
final dylib = ffi.DynamicLibrary.open(path);
if (Platform.isMacOS) path = './primitives.dylib';
final dylib = DynamicLibrary.open(path);

// calls int sum(int a, int b);
final sumPointer = dylib.lookup<ffi.NativeFunction<sum_func>>('sum');
final sumPointer = dylib.lookup<NativeFunction<sum_func>>('sum');
final sum = sumPointer.asFunction<Sum>();
print('3 + 5 = ${sum(3, 5)}');

// calls int subtract(int *a, int b);
// Create a pointer
final p = ffi.Pointer<ffi.Int32>.allocate();
Pointer<Int32> p = allocate();
// Place a value into the address
p.store(3);
p.value = 3;

final subtractPointer =
dylib.lookup<ffi.NativeFunction<subtract_func>>('subtract');
dylib.lookup<NativeFunction<subtract_func>>('subtract');
final subtract = subtractPointer.asFunction<Subtract>();
print('3 - 5 = ${subtract(p, 5)}');

// calls int *multiply(int a, int b);
final multiplyPointer =
dylib.lookup<ffi.NativeFunction<multiply_func>>('multiply');
dylib.lookup<NativeFunction<multiply_func>>('multiply');
final multiply = multiplyPointer.asFunction<Multiply>();
final resultPointer = multiply(3, 5);
// Fetch the result at the address pointed to
final int result = resultPointer.load();
final int result = resultPointer.value;
print('3 * 5 = $result');

// example calling a C function with varargs
// calls int multi_sum(int nr_count, ...);
final multiSumPointer =
dylib.lookup<ffi.NativeFunction<multi_sum_func>>('multi_sum');
dylib.lookup<NativeFunction<multi_sum_func>>('multi_sum');
final multiSum = multiSumPointer.asFunction<MultiSum>();
print('3 + 7 + 11 = ${multiSum(3, 3, 7, 11)}');
}

ffi.Pointer<ffi.Int32> _createCIntArray(List<int> nums) {
final ptr = ffi.Pointer<ffi.Int32>.allocate(count: nums.length);
for (var i = 0; i < nums.length; i++) {
ptr.elementAt(i).store(nums[i]);
}
return ptr;
}
2 changes: 2 additions & 0 deletions ffi/primitives/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,7 @@ description: >-
author: Matt Sullivan <mattsullivan@google.com>
environment:
sdk: '>=2.5.0 <3.0.0'
dependencies:
ffi: ^0.1.3-dev.3
dev_dependencies:
test: ^1.5.3
Loading

0 comments on commit 3933ad3

Please sign in to comment.