Skip to content
This repository has been archived by the owner on Jul 1, 2023. It is now read-only.

Commit

Permalink
Add flags to setup.dart required to get Android build working (#48)
Browse files Browse the repository at this point in the history
* Add a bunch of args to setup.dart to customize the build

* Remove unused function

* Fix a linker error

* Fix DynamicLibrary load path

* Changelog entry
  • Loading branch information
liamappelbe authored Oct 14, 2021
1 parent a243c52 commit 786c899
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 56 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
- Update to Wasmer 2.0.0
- All WASM modules and isntances use a singleton store, to enable sharing of
memory and functions.
- Add options to setup.dart for configuring the build.

## 0.1.0+1

Expand Down
146 changes: 116 additions & 30 deletions bin/setup.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,75 @@
// BSD-style license that can be found in the LICENSE file.

// Builds the wasmer runtime library, to by used by package:wasm. Requires
// rustc, cargo, clang, and clang++. If a target triple is not specified, it
// will default to the host target.
// Usage: dart run wasm:setup [optional target-triple]
// Rust (rustc, rustup, cargo), and Clang (clang, clang++, ar).
// Usage: dart run wasm:setup
// For more details use the --help option.

import 'dart:convert';
import 'dart:io' hide exit;

import 'package:args/args.dart';
import 'package:package_config/package_config.dart' show findPackageConfig;
import 'package:wasm/src/shared.dart';

Future<void> main(List<String> args) async {
if (args.length > 1) {
print('Usage: $invocationString [target-triple]');
exitCode = 64; // bad usage
Future<void> main(List<String> arguments) async {
final parser = ArgParser()
..addOption(
'target',
abbr: 't',
help: 'Target triple. Defaults to host target.',
)
..addOption(
'out-dir',
abbr: 'o',
help: 'Output directory. Defaults to the directory that package:wasm '
'searches.',
)
..addOption(
'rustc',
help: "Path of rustc. Defaults to assuming it's in PATH variable.",
)
..addOption(
'rustup',
help: "Path of rustup. Defaults to assuming it's in PATH variable.",
)
..addOption(
'cargo',
help: "Path of cargo. Defaults to assuming it's in PATH variable.",
)
..addOption(
'clang',
help: "Path of clang. Defaults to assuming it's in PATH variable.",
)
..addOption(
'clangpp',
help: "Path of clang++. Defaults to assuming it's in PATH variable.",
)
..addOption(
'ar',
help: "Path of ar. Defaults to assuming it's in PATH variable.",
)
..addOption(
'sysroot',
help: 'Sysroot argument passed to linker.',
)
..addFlag(
'help',
abbr: 'h',
negatable: false,
help: 'Show this help.',
);
final args = parser.parse(arguments);

if (args['help'] as bool) {
print('Usage: $invocationString [OPTION...]\n');
print(parser.usage);
exitCode = 0; // ok
return;
}

final target = args.isNotEmpty ? args[0] : await _getTargetTriple();

try {
await _main(target);
await _main(args);
} on ProcessException catch (e) {
final invocation = [e.executable, ...e.arguments].join(' ');
print('FAILED with exit code ${e.errorCode} `$invocation`');
Expand Down Expand Up @@ -144,9 +192,9 @@ String _getWasmerLib(String os) {
return 'libwasmer.a';
}

Future<String> _getTargetTriple() async {
Future<String> _getTargetTriple(String rustc) async {
final _regexp = RegExp(r'^([^=]+)="(.*)"$');
final process = await Process.start('rustc', ['--print', 'cfg']);
final process = await Process.start(rustc, ['--print', 'cfg']);
final sub = process.stderr
.transform(utf8.decoder)
.transform(const LineSplitter())
Expand All @@ -170,21 +218,42 @@ Future<String> _getTargetTriple() async {
.join('-');
}

Future<void> _run(String exe, List<String> args) async {
Future<void> _run(
String exe,
List<String> args, {
Map<String, String>? environment,
}) async {
print('\n$exe ${args.join(' ')}\n');
final process =
await Process.start(exe, args, mode: ProcessStartMode.inheritStdio);
final process = await Process.start(
exe,
args,
mode: ProcessStartMode.inheritStdio,
environment: environment,
);
final result = await process.exitCode;
if (result != 0) {
throw ProcessException(exe, args, '', result);
}
}

Future<void> _main(String target) async {
String _toUpperUnderscore(String string) {
return string.toUpperCase().replaceAll('-', '_');
}

Future<void> _main(ArgResults args) async {
final rustc = args['rustc'] as String? ?? 'rustc';
final rustup = args['rustup'] as String? ?? 'rustup';
final cargo = args['cargo'] as String? ?? 'cargo';
final clang = args['clang'] as String? ?? 'clang';
final clangpp = args['clangpp'] as String? ?? 'clang++';

final target = args['target'] as String? ?? await _getTargetTriple(rustc);
final sdkDir = _getSdkDir();
final sdkIncDir = _getSdkIncDir(sdkDir);
final srcDir = await _getSrcDir();
final outDir = _getOutDir(Directory.current.uri);
final outDir = args['out-dir'] != null
? Uri.directory(args['out-dir'] as String)
: _getOutDir(Directory.current.uri);
final os = _getOsFromTarget(target);
final outLib = outDir.resolve(_getOutLib(os)).toFilePath();

Expand All @@ -196,17 +265,32 @@ Future<void> _main(String target) async {
print('OS: $os');
print('Output library: $outLib');

// Make sure rust libs are installed for the target.
await _run(rustup, ['target', 'add', target]);

// Build wasmer crate.
await _run('cargo', [
'build',
'--target',
target,
'--target-dir',
outDir.toFilePath(),
'--manifest-path',
srcDir.resolve('Cargo.toml').toFilePath(),
'--release'
]);
await _run(
cargo,
[
'build',
'--target',
target,
'--target-dir',
outDir.toFilePath(),
'--manifest-path',
srcDir.resolve('Cargo.toml').toFilePath(),
'--release'
],
environment: {
if (args['clangpp'] != null) ...{
'CC': clangpp,
'CXX': clangpp,
'LINKER': clangpp,
'CARGO_TARGET_${_toUpperUnderscore(target)}_LINKER': clangpp,
},
if (args['ar'] != null) 'AR': args['ar'] as String,
},
);

// Hack around a bug with dart_api_dl_impl.h include path in dart_api_dl.c.
const dartApiDlImplPath = 'include/internal/dart_api_dl_impl.h';
Expand All @@ -218,7 +302,7 @@ Future<void> _main(String target) async {
}

// Build dart_api_dl.o.
await _run('clang', [
await _run(clang, [
'-DDART_SHARED_LIB',
'-DNDEBUG',
'-fno-exceptions',
Expand All @@ -237,7 +321,7 @@ Future<void> _main(String target) async {
]);

// Build finalizers.o.
await _run('clang++', [
await _run(clangpp, [
'-DDART_SHARED_LIB',
'-DNDEBUG',
'-fno-exceptions',
Expand All @@ -258,8 +342,9 @@ Future<void> _main(String target) async {
]);

// Link wasmer, dart_api_dl, and finalizers to create the output library.
await _run('clang++', [
await _run(clang, [
'-shared',
if (args['sysroot'] != null) '--sysroot=${args['sysroot']}',
if (os != 'windows') '-fPIC',
if (os == 'windows') ...[
'-lws2_32',
Expand All @@ -271,6 +356,7 @@ Future<void> _main(String target) async {
'-z',
'/NODEFAULTLIB:MSVCRT',
],
'-lm',
'-target',
target,
outDir.resolve('dart_api_dl.o').toFilePath(),
Expand Down
10 changes: 8 additions & 2 deletions lib/src/runtime.dart
Original file line number Diff line number Diff line change
Expand Up @@ -99,26 +99,32 @@ class _WasiStreamIterable extends Iterable<List<int>> {

String _getLibName() {
if (Platform.isMacOS) return appleLib;
if (Platform.isLinux) return linuxLib;
if (Platform.isLinux || Platform.isAndroid) return linuxLib;
if (Platform.isWindows) return windowsLib;
// TODO(dartbug.com/37882): Support more platforms.
throw WasmError('Wasm not currently supported on this platform');
}

String? _getLibPathFrom(Uri root) {
final pkgRoot = packageRootUri(root);

return pkgRoot?.resolve('$wasmToolDir${_getLibName()}').toFilePath();
}

String _getLibPath() {
if (Platform.isAndroid) return _getLibName();
var path = _getLibPathFrom(Platform.script.resolve('./'));
if (path != null) return path;
path = _getLibPathFrom(Directory.current.uri);
if (path != null) return path;
throw WasmError('Wasm library not found. Did you `$invocationString`?');
}

DynamicLibrary _loadDynamicLib() {
return Platform.isIOS
? DynamicLibrary.process()
: DynamicLibrary.open(_getLibPath());
}

String getSignatureString(
String name,
List<int> argTypes,
Expand Down
13 changes: 1 addition & 12 deletions lib/src/runtime.g.dart
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ class WasmRuntime {
late final WasmerWasmerLastErrorLengthFn _wasmer_last_error_length;
late final WasmerWasmerLastErrorMessageFn _wasmer_last_error_message;

WasmRuntime._init() : _lib = _load_dynamic_lib() {
WasmRuntime._init() : _lib = _loadDynamicLib() {
_Dart_InitializeApiDL = _lib.lookupFunction<
NativeWasmerDartInitializeApiDLFn, WasmerDartInitializeApiDLFn>(
'Dart_InitializeApiDL',
Expand Down Expand Up @@ -511,17 +511,6 @@ class WasmRuntime {
_set_finalizer_for_store(this, _store);
}

static DynamicLibrary _load_dynamic_lib() {
try {
return DynamicLibrary.open(_getLibPath());
} catch (e) {
throw WasmError(
'Failed to load Wasm dynamic library. '
'Have you run `dart run wasm:setup`?\n $e',
);
}
}

Pointer<WasmerModule> compile(
Object owner,
Uint8List data,
Expand Down
1 change: 1 addition & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ environment:
sdk: '>=2.12.0 <3.0.0'

dependencies:
args: ^2.3.0
ffi: ^1.0.0
package_config: ^2.0.0

Expand Down
13 changes: 1 addition & 12 deletions tool/runtime_template.dart.t
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class WasmRuntime {

/* <RUNTIME_MEMB> */

WasmRuntime._init() : _lib = _load_dynamic_lib() {
WasmRuntime._init() : _lib = _loadDynamicLib() {
/* <RUNTIME_LOAD> */

if (_Dart_InitializeApiDL(NativeApi.initializeApiDLData) != 0) {
Expand All @@ -32,17 +32,6 @@ class WasmRuntime {
_set_finalizer_for_store(this, _store);
}

static DynamicLibrary _load_dynamic_lib() {
try {
return DynamicLibrary.open(_getLibPath());
} catch (e) {
throw WasmError(
'Failed to load Wasm dynamic library. '
'Have you run `dart run wasm:setup`?\n $e',
);
}
}

Pointer<WasmerModule> compile(
Object owner,
Uint8List data,
Expand Down

0 comments on commit 786c899

Please sign in to comment.