Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/native.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ jobs:
run: sudo apt-get update && sudo apt-get install clang-15 gcc-i686-linux-gnu gcc-aarch64-linux-gnu gcc-arm-linux-gnueabihf gcc-riscv64-linux-gnu
if: ${{ matrix.os == 'ubuntu' }}

- name: Install native toolchains
run: brew install lld
if: ${{ matrix.os == 'macos' }}

- run: dart pub get

- name: Run pub get, analysis, formatting, generators, tests, and examples.
Expand Down
1 change: 1 addition & 0 deletions pkgs/native_toolchain_c/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
- On iOS and macOS, use the `-encryptable` linker flag. This resolves an
[issue](https://github.com/dart-lang/native/issues/2973) with app store
rejections.
- Fix unportable link arg when cross-compiling from MacOS.

## 0.17.4

Expand Down
2 changes: 1 addition & 1 deletion pkgs/native_toolchain_c/lib/src/cbuilder/run_cbuilder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ class RunCBuilder {
// During bundling code assets are all placed in the same directory.
// Setting this rpath allows the binary to find other code assets
// it is linked against.
'-Wl,-rpath=\$ORIGIN',
'-Wl,-rpath,\$ORIGIN',
for (final directory in libraryDirectories)
'-L${directory.toFilePath()}',
for (final library in libraries) '-l$library',
Expand Down
2 changes: 1 addition & 1 deletion pkgs/native_toolchain_c/lib/src/tool/tool_resolver.dart
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ class PathToolResolver extends ToolResolver {
if (process.exitCode == 0) {
final file = File(LineSplitter.split(process.stdout).first);
final uri = File(await file.resolveSymbolicLinks()).uri;
if (uri.pathSegments.last == 'llvm') {
if (uri.pathSegments.last case 'llvm' || 'lld') {
// https://github.com/dart-lang/native/issues/136
return file.uri;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import 'dart:io';
import 'package:code_assets/code_assets.dart';
import 'package:hooks/hooks.dart';
import 'package:native_toolchain_c/native_toolchain_c.dart';
import 'package:native_toolchain_c/src/native_toolchain/apple_clang.dart';
import 'package:native_toolchain_c/src/tool/tool_resolver.dart';
import 'package:native_toolchain_c/src/utils/run_process.dart';
import 'package:test/test.dart';

Expand All @@ -22,27 +24,48 @@ void main() {
return;
}

const targets = [Architecture.arm64, Architecture.x64];
const targets = [
(OS.macOS, Architecture.arm64),
(OS.macOS, Architecture.x64),
(OS.linux, Architecture.arm),
(OS.linux, Architecture.arm64),
(OS.linux, Architecture.ia32),
(OS.linux, Architecture.x64),

// Not supported by Apple Clang right now.
// (OS.linux, Architecture.riscv32),
// (OS.linux, Architecture.riscv64),
];

// Dont include 'mach-o' or 'Mach-O', different spelling is used.
const objdumpFileFormat = {
Architecture.arm64: 'arm64',
Architecture.x64: '64-bit x86-64',
(OS.macOS, Architecture.arm64): 'arm64',
(OS.macOS, Architecture.x64): '64-bit x86-64',
(OS.linux, Architecture.arm): 'elf32-littlearm',
(OS.linux, Architecture.arm64): 'elf64-littleaarch64',
(OS.linux, Architecture.ia32): 'elf32-i386',
(OS.linux, Architecture.x64): 'elf64-x86-64',

(OS.linux, Architecture.riscv32): 'elf32-riscv32',
(OS.linux, Architecture.riscv64): 'elf64-riscv64',
};

const optimizationLevels = OptimizationLevel.values;
var selectOptimizationLevel = 0;

for (final language in [Language.c, Language.objectiveC]) {
for (final linkMode in [DynamicLoadingBundled(), StaticLinking()]) {
for (final target in targets) {
for (final (os, arch) in targets) {
// Don't build Objective-C targets for linux.
if (language == Language.objectiveC && os == OS.linux) continue;

// Cycle through all optimization levels.
final optimizationLevel = optimizationLevels[selectOptimizationLevel];
selectOptimizationLevel =
(selectOptimizationLevel + 1) % optimizationLevels.length;

test(
'CBuilder $linkMode $language library $target $optimizationLevel',
'CBuilder $linkMode $language library $os $arch $optimizationLevel',
() async {
final tempUri = await tempDirForTest();
final tempUri2 = await tempDirForTest();
Expand All @@ -57,6 +80,16 @@ void main() {
};
const name = 'add';

// When cross-compiling from MacOS, explicitly specify apple clang.
//
// The default tool-finding does not support macos cross compiling
// right now.
var chosenCCompiler = cCompiler;
if (os == OS.linux) {
// still respect the CI-provided compiler
chosenCCompiler ??= await resolveAppleToolchain();
}

final buildInputBuilder = BuildInputBuilder()
..setupShared(
packageName: name,
Expand All @@ -67,12 +100,12 @@ void main() {
..config.setupBuild(linkingEnabled: false)
..addExtension(
CodeAssetExtension(
targetOS: OS.macOS,
targetArchitecture: target,
targetOS: os,
targetArchitecture: arch,
linkModePreference: linkMode == DynamicLoadingBundled()
? LinkModePreference.dynamic
: LinkModePreference.static,
cCompiler: cCompiler,
cCompiler: chosenCCompiler,
macOS: MacOSCodeConfig(targetVersion: defaultMacOSVersion),
),
);
Expand All @@ -86,6 +119,27 @@ void main() {
language: language,
optimizationLevel: optimizationLevel,
buildMode: BuildMode.release,
flags: [
if (os == OS.linux)
switch (arch) {
Architecture.arm => '--target=arm-linux-gnueabihf',
Architecture.arm64 => '--target=aarch64-linux-gnu',
Architecture.ia32 => '--target=i686-linux-gnu',
Architecture.x64 => '--target=x86_64-linux-gnu',
Architecture.riscv32 => '--target=riscv32-linux-gnu',
Architecture.riscv64 => '--target=riscv64-linux-gnu',
_ => throw UnsupportedError(
'Unexpected linux architecture: $arch',
),
},
// Only homebrew lld can link for linux, and we don't have a
// sysroot so we can't use stdlibs / C-runtime files.
if (os == OS.linux) ...[
'--ld-path=ld.lld',
'-nostartfiles',
'-nostdlib',
],
],
);
await cbuilder.run(
input: buildInput,
Expand All @@ -94,7 +148,7 @@ void main() {
);

final libUri = buildInput.outputDirectory.resolve(
OS.macOS.libraryFileName(name, linkMode),
os.libraryFileName(name, linkMode),
);
final result = await runProcess(
executable: Uri.file('objdump'),
Expand All @@ -105,7 +159,7 @@ void main() {
final machine = result.stdout
.split('\n')
.firstWhere((e) => e.contains('file format'));
expect(machine, contains(objdumpFileFormat[target]));
expect(machine, contains(objdumpFileFormat[(os, arch)]));
},
);
}
Expand Down Expand Up @@ -193,3 +247,18 @@ Future<Uri> buildLib(
);
return libUri;
}

Future<CCompilerConfig> resolveAppleToolchain() async {
// (still respect the CI provided compiler)
final context = ToolResolvingContext(logger: logger);

final resolvedClang = await appleClang.defaultResolver!.resolve(context);
final resolvedAr = await appleAr.defaultResolver!.resolve(context);
final resolvedLd = await appleLd.defaultResolver!.resolve(context);

return CCompilerConfig(
compiler: resolvedClang.first.uri,
archiver: resolvedAr.first.uri,
linker: resolvedLd.first.uri,
);
}
Loading