From 1a11e7d0e8aa38f3e14adbf78dac0e4f134da8c7 Mon Sep 17 00:00:00 2001 From: Gabriel Terwesten Date: Fri, 6 Dec 2024 21:36:07 +0100 Subject: [PATCH] wip --- .../native_dynamic_linking/hook/build.dart | 4 +- .../lib/src/cbuilder/cbuilder.dart | 47 +++++-------------- .../lib/src/cbuilder/clinker.dart | 2 + .../lib/src/cbuilder/ctool.dart | 8 +++- .../lib/src/cbuilder/run_cbuilder.dart | 28 ++++++++--- .../test/cbuilder/cbuilder_test.dart | 10 ++-- 6 files changed, 48 insertions(+), 51 deletions(-) diff --git a/pkgs/native_assets_cli/example/build/native_dynamic_linking/hook/build.dart b/pkgs/native_assets_cli/example/build/native_dynamic_linking/hook/build.dart index a396df219..0713eab62 100644 --- a/pkgs/native_assets_cli/example/build/native_dynamic_linking/hook/build.dart +++ b/pkgs/native_assets_cli/example/build/native_dynamic_linking/hook/build.dart @@ -26,7 +26,7 @@ void main(List args) async { sources: [ 'src/math.c', ], - dynamicallyLinkTo: ['debug'], + libraries: ['debug'], ), CBuilder.library( name: 'add', @@ -34,7 +34,7 @@ void main(List args) async { sources: [ 'src/add.c', ], - dynamicallyLinkTo: ['math'], + libraries: ['math'], ) ]; diff --git a/pkgs/native_toolchain_c/lib/src/cbuilder/cbuilder.dart b/pkgs/native_toolchain_c/lib/src/cbuilder/cbuilder.dart index c9568b18e..b1d59ebbc 100644 --- a/pkgs/native_toolchain_c/lib/src/cbuilder/cbuilder.dart +++ b/pkgs/native_toolchain_c/lib/src/cbuilder/cbuilder.dart @@ -47,21 +47,14 @@ class CBuilder extends CTool implements Builder { /// Defaults to `true`. final bool ndebugDefine; - /// Libraries to dynamically link to. - /// - /// The libraries are expected to be at the root of the output directory of - /// the build hook invocation. - /// - /// When using this option ensure that the builders producing the libraries - /// to link to are run before this builder. - final List dynamicallyLinkTo; - CBuilder.library({ required super.name, super.assetName, super.sources = const [], super.includes = const [], super.frameworks = CTool.defaultFrameworks, + super.libraries = const [], + super.libraryPaths = const [], @Deprecated( 'Newer Dart and Flutter SDKs automatically add the Dart hook ' 'sources as dependencies.', @@ -72,7 +65,6 @@ class CBuilder extends CTool implements Builder { super.defines = const {}, this.buildModeDefine = true, this.ndebugDefine = true, - this.dynamicallyLinkTo = const [], super.pic = true, super.std, super.language = Language.c, @@ -86,6 +78,8 @@ class CBuilder extends CTool implements Builder { super.sources = const [], super.includes = const [], super.frameworks = CTool.defaultFrameworks, + super.libraries = const [], + super.libraryPaths = const [], @Deprecated( 'Newer Dart and Flutter SDKs automatically add the Dart hook ' 'sources as dependencies.', @@ -95,7 +89,6 @@ class CBuilder extends CTool implements Builder { super.defines = const {}, this.buildModeDefine = true, this.ndebugDefine = true, - this.dynamicallyLinkTo = const [], bool? pie = false, super.std, super.language = Language.c, @@ -143,6 +136,11 @@ class CBuilder extends CTool implements Builder { // ignore: deprecated_member_use_from_same_package for (final source in this.dartBuildFiles) packageRoot.resolve(source), ]; + final libraryPaths = [ + outDir, + for (final path in this.libraryPaths) + outDir.resolveUri(Uri.file(path)), + ]; // ignore: deprecated_member_use if (!config.dryRun) { final task = RunCBuilder( @@ -152,6 +150,8 @@ class CBuilder extends CTool implements Builder { sources: sources, includes: includes, frameworks: frameworks, + libraries: libraries, + libraryPaths: libraryPaths, dynamicLibrary: type == OutputType.library && linkMode == DynamicLoadingBundled() ? libUri @@ -162,10 +162,7 @@ class CBuilder extends CTool implements Builder { executable: type == OutputType.executable ? exeUri : null, // ignore: invalid_use_of_visible_for_testing_member installName: installName, - flags: [ - ...flags, - ...config.dynamicLinkingFlags(dynamicallyLinkTo), - ], + flags: flags, defines: { ...defines, if (buildModeDefine) config.buildMode.name.toUpperCase(): null, @@ -216,23 +213,3 @@ class CBuilder extends CTool implements Builder { } } } - -extension on BuildConfig { - List dynamicLinkingFlags(List libraries) => - switch (targetOS) { - OS.macOS || OS.iOS => [ - '-L${outputDirectory.toFilePath()}', - for (final library in libraries) '-l$library', - ], - OS.linux || OS.android => [ - '-Wl,-rpath=\$ORIGIN/.', - '-L${outputDirectory.toFilePath()}', - for (final library in libraries) '-l$library', - ], - OS.windows => [ - for (final library in libraries) - outputDirectory.resolve('$library.lib').toFilePath(), - ], - _ => throw UnimplementedError('Unsupported OS: $targetOS'), - }; -} diff --git a/pkgs/native_toolchain_c/lib/src/cbuilder/clinker.dart b/pkgs/native_toolchain_c/lib/src/cbuilder/clinker.dart index b79174967..b1e108f5e 100644 --- a/pkgs/native_toolchain_c/lib/src/cbuilder/clinker.dart +++ b/pkgs/native_toolchain_c/lib/src/cbuilder/clinker.dart @@ -29,6 +29,8 @@ class CLinker extends CTool implements Linker { super.sources = const [], super.includes = const [], super.frameworks = CTool.defaultFrameworks, + super.libraries = const [], + super.libraryPaths = const [], @visibleForTesting super.installName, super.flags = const [], super.defines = const {}, diff --git a/pkgs/native_toolchain_c/lib/src/cbuilder/ctool.dart b/pkgs/native_toolchain_c/lib/src/cbuilder/ctool.dart index 1a977e106..4e71cc320 100644 --- a/pkgs/native_toolchain_c/lib/src/cbuilder/ctool.dart +++ b/pkgs/native_toolchain_c/lib/src/cbuilder/ctool.dart @@ -60,12 +60,16 @@ abstract class CTool { static const List defaultFrameworks = ['Foundation']; + final List libraries; + + final List libraryPaths; + /// TODO(https://github.com/dart-lang/native/issues/54): Move to [LinkConfig] /// or hide in public API. @visibleForTesting final Uri? installName; - /// Flags to pass to the linker. + /// Flags to pass to the compiler. final List flags; /// Definitions of preprocessor macros. @@ -130,6 +134,8 @@ abstract class CTool { required this.sources, required this.includes, required this.frameworks, + required this.libraries, + required this.libraryPaths, required this.installName, required this.flags, required this.defines, diff --git a/pkgs/native_toolchain_c/lib/src/cbuilder/run_cbuilder.dart b/pkgs/native_toolchain_c/lib/src/cbuilder/run_cbuilder.dart index 8342f109c..e5cd45913 100644 --- a/pkgs/native_toolchain_c/lib/src/cbuilder/run_cbuilder.dart +++ b/pkgs/native_toolchain_c/lib/src/cbuilder/run_cbuilder.dart @@ -28,6 +28,8 @@ class RunCBuilder { final List sources; final List includes; final List frameworks; + final List libraries; + final List libraryPaths; final Uri? executable; final Uri? dynamicLibrary; final Uri? staticLibrary; @@ -56,6 +58,8 @@ class RunCBuilder { this.sources = const [], this.includes = const [], required this.frameworks, + this.libraries = const [], + this.libraryPaths = const [], this.executable, this.dynamicLibrary, this.staticLibrary, @@ -298,8 +302,7 @@ class RunCBuilder { if (executable != null) ...[ '-o', outDir.resolveUri(executable!).toFilePath(), - ], - if (dynamicLibrary != null) ...[ + ] else if (dynamicLibrary != null) ...[ '--shared', '-o', outFile!.toFilePath(), @@ -310,6 +313,16 @@ class RunCBuilder { ], ...linkerOptions?.postSourcesFlags(toolInstance.tool, sourceFiles) ?? [], + if (executable != null || dynamicLibrary != null) ...[ + if (config.targetOS case OS.android || OS.linux) + if (linkerOptions != null) + '-rpath=\$ORIGIN' + else + '-Wl,-rpath=\$ORIGIN', + for (final libraryPath in libraryPaths) + '-L${libraryPath.toFilePath()}', + for (final library in libraries) '-l$library', + ], ], logger: logger, captureOutput: false, @@ -344,17 +357,20 @@ class RunCBuilder { ...sources.map((e) => e.toFilePath()), '/link', '/out:${outDir.resolveUri(executable!).toFilePath()}', - ], - if (dynamicLibrary != null) ...[ + ] else if (dynamicLibrary != null) ...[ ...sources.map((e) => e.toFilePath()), '/link', '/DLL', '/out:${outDir.resolveUri(dynamicLibrary!).toFilePath()}', - ], - if (staticLibrary != null) ...[ + ] else if (staticLibrary != null) ...[ '/c', ...sources.map((e) => e.toFilePath()), ], + if (executable != null || dynamicLibrary != null) ...[ + for (final libraryPath in libraryPaths) + '/LIBPATH:${libraryPath.toFilePath()}', + for (final library in libraries) '$library.lib', + ], ], workingDirectory: outDir, environment: environment, diff --git a/pkgs/native_toolchain_c/test/cbuilder/cbuilder_test.dart b/pkgs/native_toolchain_c/test/cbuilder/cbuilder_test.dart index f5332b4d6..94f8e2801 100644 --- a/pkgs/native_toolchain_c/test/cbuilder/cbuilder_test.dart +++ b/pkgs/native_toolchain_c/test/cbuilder/cbuilder_test.dart @@ -555,7 +555,7 @@ void main() { } }); - test('CBuilder dynamicallyLinkTo', () async { + test('CBuilder libraries', () async { final tempUri = await tempDirForTest(); final dynamicallyLinkedCUri = packageUri.resolve( 'test/cbuilder/testfiles/dynamically_linked/src/dynamically_linked.c'); @@ -579,11 +579,7 @@ void main() { buildMode: BuildMode.release, // Ignored by executables. linkModePreference: LinkModePreference.dynamic, - cCompiler: CCompilerConfig( - compiler: cc, - envScript: envScript, - envScriptArgs: envScriptArgs, - ), + cCompiler: cCompiler, linkingEnabled: false, ); final buildOutput = BuildOutput(); @@ -598,7 +594,7 @@ void main() { name: name, includes: [addSrcUri.toFilePath()], sources: [dynamicallyLinkedCUri.toFilePath()], - dynamicallyLinkTo: ['add'], + libraries: ['add'], ) ]; for (final builder in builders) {