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

Commit 786c899

Browse files
authored
Add flags to setup.dart required to get Android build working (#48)
* 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
1 parent a243c52 commit 786c899

File tree

6 files changed

+128
-56
lines changed

6 files changed

+128
-56
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
- Update to Wasmer 2.0.0
44
- All WASM modules and isntances use a singleton store, to enable sharing of
55
memory and functions.
6+
- Add options to setup.dart for configuring the build.
67

78
## 0.1.0+1
89

bin/setup.dart

+116-30
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,75 @@
33
// BSD-style license that can be found in the LICENSE file.
44

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

1010
import 'dart:convert';
1111
import 'dart:io' hide exit;
1212

13+
import 'package:args/args.dart';
1314
import 'package:package_config/package_config.dart' show findPackageConfig;
1415
import 'package:wasm/src/shared.dart';
1516

16-
Future<void> main(List<String> args) async {
17-
if (args.length > 1) {
18-
print('Usage: $invocationString [target-triple]');
19-
exitCode = 64; // bad usage
17+
Future<void> main(List<String> arguments) async {
18+
final parser = ArgParser()
19+
..addOption(
20+
'target',
21+
abbr: 't',
22+
help: 'Target triple. Defaults to host target.',
23+
)
24+
..addOption(
25+
'out-dir',
26+
abbr: 'o',
27+
help: 'Output directory. Defaults to the directory that package:wasm '
28+
'searches.',
29+
)
30+
..addOption(
31+
'rustc',
32+
help: "Path of rustc. Defaults to assuming it's in PATH variable.",
33+
)
34+
..addOption(
35+
'rustup',
36+
help: "Path of rustup. Defaults to assuming it's in PATH variable.",
37+
)
38+
..addOption(
39+
'cargo',
40+
help: "Path of cargo. Defaults to assuming it's in PATH variable.",
41+
)
42+
..addOption(
43+
'clang',
44+
help: "Path of clang. Defaults to assuming it's in PATH variable.",
45+
)
46+
..addOption(
47+
'clangpp',
48+
help: "Path of clang++. Defaults to assuming it's in PATH variable.",
49+
)
50+
..addOption(
51+
'ar',
52+
help: "Path of ar. Defaults to assuming it's in PATH variable.",
53+
)
54+
..addOption(
55+
'sysroot',
56+
help: 'Sysroot argument passed to linker.',
57+
)
58+
..addFlag(
59+
'help',
60+
abbr: 'h',
61+
negatable: false,
62+
help: 'Show this help.',
63+
);
64+
final args = parser.parse(arguments);
65+
66+
if (args['help'] as bool) {
67+
print('Usage: $invocationString [OPTION...]\n');
68+
print(parser.usage);
69+
exitCode = 0; // ok
2070
return;
2171
}
2272

23-
final target = args.isNotEmpty ? args[0] : await _getTargetTriple();
24-
2573
try {
26-
await _main(target);
74+
await _main(args);
2775
} on ProcessException catch (e) {
2876
final invocation = [e.executable, ...e.arguments].join(' ');
2977
print('FAILED with exit code ${e.errorCode} `$invocation`');
@@ -144,9 +192,9 @@ String _getWasmerLib(String os) {
144192
return 'libwasmer.a';
145193
}
146194

147-
Future<String> _getTargetTriple() async {
195+
Future<String> _getTargetTriple(String rustc) async {
148196
final _regexp = RegExp(r'^([^=]+)="(.*)"$');
149-
final process = await Process.start('rustc', ['--print', 'cfg']);
197+
final process = await Process.start(rustc, ['--print', 'cfg']);
150198
final sub = process.stderr
151199
.transform(utf8.decoder)
152200
.transform(const LineSplitter())
@@ -170,21 +218,42 @@ Future<String> _getTargetTriple() async {
170218
.join('-');
171219
}
172220

173-
Future<void> _run(String exe, List<String> args) async {
221+
Future<void> _run(
222+
String exe,
223+
List<String> args, {
224+
Map<String, String>? environment,
225+
}) async {
174226
print('\n$exe ${args.join(' ')}\n');
175-
final process =
176-
await Process.start(exe, args, mode: ProcessStartMode.inheritStdio);
227+
final process = await Process.start(
228+
exe,
229+
args,
230+
mode: ProcessStartMode.inheritStdio,
231+
environment: environment,
232+
);
177233
final result = await process.exitCode;
178234
if (result != 0) {
179235
throw ProcessException(exe, args, '', result);
180236
}
181237
}
182238

183-
Future<void> _main(String target) async {
239+
String _toUpperUnderscore(String string) {
240+
return string.toUpperCase().replaceAll('-', '_');
241+
}
242+
243+
Future<void> _main(ArgResults args) async {
244+
final rustc = args['rustc'] as String? ?? 'rustc';
245+
final rustup = args['rustup'] as String? ?? 'rustup';
246+
final cargo = args['cargo'] as String? ?? 'cargo';
247+
final clang = args['clang'] as String? ?? 'clang';
248+
final clangpp = args['clangpp'] as String? ?? 'clang++';
249+
250+
final target = args['target'] as String? ?? await _getTargetTriple(rustc);
184251
final sdkDir = _getSdkDir();
185252
final sdkIncDir = _getSdkIncDir(sdkDir);
186253
final srcDir = await _getSrcDir();
187-
final outDir = _getOutDir(Directory.current.uri);
254+
final outDir = args['out-dir'] != null
255+
? Uri.directory(args['out-dir'] as String)
256+
: _getOutDir(Directory.current.uri);
188257
final os = _getOsFromTarget(target);
189258
final outLib = outDir.resolve(_getOutLib(os)).toFilePath();
190259

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

268+
// Make sure rust libs are installed for the target.
269+
await _run(rustup, ['target', 'add', target]);
270+
199271
// Build wasmer crate.
200-
await _run('cargo', [
201-
'build',
202-
'--target',
203-
target,
204-
'--target-dir',
205-
outDir.toFilePath(),
206-
'--manifest-path',
207-
srcDir.resolve('Cargo.toml').toFilePath(),
208-
'--release'
209-
]);
272+
await _run(
273+
cargo,
274+
[
275+
'build',
276+
'--target',
277+
target,
278+
'--target-dir',
279+
outDir.toFilePath(),
280+
'--manifest-path',
281+
srcDir.resolve('Cargo.toml').toFilePath(),
282+
'--release'
283+
],
284+
environment: {
285+
if (args['clangpp'] != null) ...{
286+
'CC': clangpp,
287+
'CXX': clangpp,
288+
'LINKER': clangpp,
289+
'CARGO_TARGET_${_toUpperUnderscore(target)}_LINKER': clangpp,
290+
},
291+
if (args['ar'] != null) 'AR': args['ar'] as String,
292+
},
293+
);
210294

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

220304
// Build dart_api_dl.o.
221-
await _run('clang', [
305+
await _run(clang, [
222306
'-DDART_SHARED_LIB',
223307
'-DNDEBUG',
224308
'-fno-exceptions',
@@ -237,7 +321,7 @@ Future<void> _main(String target) async {
237321
]);
238322

239323
// Build finalizers.o.
240-
await _run('clang++', [
324+
await _run(clangpp, [
241325
'-DDART_SHARED_LIB',
242326
'-DNDEBUG',
243327
'-fno-exceptions',
@@ -258,8 +342,9 @@ Future<void> _main(String target) async {
258342
]);
259343

260344
// Link wasmer, dart_api_dl, and finalizers to create the output library.
261-
await _run('clang++', [
345+
await _run(clang, [
262346
'-shared',
347+
if (args['sysroot'] != null) '--sysroot=${args['sysroot']}',
263348
if (os != 'windows') '-fPIC',
264349
if (os == 'windows') ...[
265350
'-lws2_32',
@@ -271,6 +356,7 @@ Future<void> _main(String target) async {
271356
'-z',
272357
'/NODEFAULTLIB:MSVCRT',
273358
],
359+
'-lm',
274360
'-target',
275361
target,
276362
outDir.resolve('dart_api_dl.o').toFilePath(),

lib/src/runtime.dart

+8-2
Original file line numberDiff line numberDiff line change
@@ -99,26 +99,32 @@ class _WasiStreamIterable extends Iterable<List<int>> {
9999

100100
String _getLibName() {
101101
if (Platform.isMacOS) return appleLib;
102-
if (Platform.isLinux) return linuxLib;
102+
if (Platform.isLinux || Platform.isAndroid) return linuxLib;
103103
if (Platform.isWindows) return windowsLib;
104104
// TODO(dartbug.com/37882): Support more platforms.
105105
throw WasmError('Wasm not currently supported on this platform');
106106
}
107107

108108
String? _getLibPathFrom(Uri root) {
109109
final pkgRoot = packageRootUri(root);
110-
111110
return pkgRoot?.resolve('$wasmToolDir${_getLibName()}').toFilePath();
112111
}
113112

114113
String _getLibPath() {
114+
if (Platform.isAndroid) return _getLibName();
115115
var path = _getLibPathFrom(Platform.script.resolve('./'));
116116
if (path != null) return path;
117117
path = _getLibPathFrom(Directory.current.uri);
118118
if (path != null) return path;
119119
throw WasmError('Wasm library not found. Did you `$invocationString`?');
120120
}
121121

122+
DynamicLibrary _loadDynamicLib() {
123+
return Platform.isIOS
124+
? DynamicLibrary.process()
125+
: DynamicLibrary.open(_getLibPath());
126+
}
127+
122128
String getSignatureString(
123129
String name,
124130
List<int> argTypes,

lib/src/runtime.g.dart

+1-12
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ class WasmRuntime {
116116
late final WasmerWasmerLastErrorLengthFn _wasmer_last_error_length;
117117
late final WasmerWasmerLastErrorMessageFn _wasmer_last_error_message;
118118

119-
WasmRuntime._init() : _lib = _load_dynamic_lib() {
119+
WasmRuntime._init() : _lib = _loadDynamicLib() {
120120
_Dart_InitializeApiDL = _lib.lookupFunction<
121121
NativeWasmerDartInitializeApiDLFn, WasmerDartInitializeApiDLFn>(
122122
'Dart_InitializeApiDL',
@@ -511,17 +511,6 @@ class WasmRuntime {
511511
_set_finalizer_for_store(this, _store);
512512
}
513513

514-
static DynamicLibrary _load_dynamic_lib() {
515-
try {
516-
return DynamicLibrary.open(_getLibPath());
517-
} catch (e) {
518-
throw WasmError(
519-
'Failed to load Wasm dynamic library. '
520-
'Have you run `dart run wasm:setup`?\n $e',
521-
);
522-
}
523-
}
524-
525514
Pointer<WasmerModule> compile(
526515
Object owner,
527516
Uint8List data,

pubspec.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ environment:
77
sdk: '>=2.12.0 <3.0.0'
88

99
dependencies:
10+
args: ^2.3.0
1011
ffi: ^1.0.0
1112
package_config: ^2.0.0
1213

tool/runtime_template.dart.t

+1-12
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class WasmRuntime {
1818

1919
/* <RUNTIME_MEMB> */
2020

21-
WasmRuntime._init() : _lib = _load_dynamic_lib() {
21+
WasmRuntime._init() : _lib = _loadDynamicLib() {
2222
/* <RUNTIME_LOAD> */
2323

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

35-
static DynamicLibrary _load_dynamic_lib() {
36-
try {
37-
return DynamicLibrary.open(_getLibPath());
38-
} catch (e) {
39-
throw WasmError(
40-
'Failed to load Wasm dynamic library. '
41-
'Have you run `dart run wasm:setup`?\n $e',
42-
);
43-
}
44-
}
45-
4635
Pointer<WasmerModule> compile(
4736
Object owner,
4837
Uint8List data,

0 commit comments

Comments
 (0)