-
Notifications
You must be signed in to change notification settings - Fork 83
Initial version #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
d496843
Initial version
dcharkes b10ce94
Rename CBuilder to RunCBuilder
dcharkes 62551be
remove unused import
dcharkes 92f04c2
new CBuilder API
dcharkes 6f79a12
test new CBuilder API
dcharkes ce7ee20
Remove unused file
dcharkes e4638c3
Refactor c_compiler implementation
dcharkes 652369c
massage dependencies
dcharkes 1d0262b
which clang version on GitHub CI?
dcharkes 983f332
Allow tool pre-release in smoke test
dcharkes 40582b9
Use `printOnFailure`
dcharkes a59abce
Add archiver tools and logger to tool resolvers
dcharkes dac31bd
Find linkers
dcharkes eb11562
Cleanup tool naming
dcharkes 157236d
Recognize tools from just Uri
dcharkes 9a9b3e7
Use compiler recognizer
dcharkes 5d4b2b9
Test compiler resolver
dcharkes 13b5cba
Cover archiver in BuildConfig
dcharkes 93ea2d6
Cleanup Process.run invocations
dcharkes 1f95e02
Address comments
dcharkes 40f9b35
Pin workflow action versions
dcharkes c68a59b
Enable running tests from different directories
dcharkes 3907fc8
Fix imports
dcharkes d3874e9
Add reference to bug
dcharkes a25c01f
Address comments
dcharkes 293a9a1
At logger output that no CC / AR env variables were set
dcharkes 5bc4ba0
Pick up environment variables for native compilers in tests
dcharkes File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,124 @@ | ||
| // Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file | ||
| // 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:io'; | ||
|
|
||
| import 'package:logging/logging.dart'; | ||
| import 'package:native_assets_cli/native_assets_cli.dart'; | ||
|
|
||
| import 'run_cbuilder.dart'; | ||
|
|
||
| abstract class Builder { | ||
| Future<void> run({ | ||
| required BuildConfig buildConfig, | ||
| required BuildOutput buildOutput, | ||
| Logger? logger, | ||
| }); | ||
| } | ||
|
|
||
| /// Specification for building an artifact with a C compiler. | ||
| class CBuilder implements Builder { | ||
| /// What kind of artifact to build. | ||
| final _CBuilderType _type; | ||
|
|
||
| /// Name of the library or executable to build. | ||
| /// | ||
| /// The filename will be decided by [BuildConfig.target] and | ||
| /// [OS.libraryFileName] or [OS.executableFileName]. | ||
| /// | ||
| /// File will be placed in [BuildConfig.outDir]. | ||
| final String name; | ||
|
|
||
| /// Asset identifier. | ||
| /// | ||
| /// Used to output the [BuildOutput.assets]. | ||
| /// | ||
| /// If omitted, no asset will be added to the build output. | ||
| final String? assetName; | ||
|
|
||
| /// Sources to build the library or executable. | ||
| /// | ||
| /// Resolved against [BuildConfig.packageRoot]. | ||
| /// | ||
| /// Used to output the [BuildOutput.dependencies]. | ||
| final List<String> sources; | ||
dcharkes marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| /// The dart files involved in building this artifact. | ||
| /// | ||
| /// Resolved against [BuildConfig.packageRoot]. | ||
| /// | ||
| /// Used to output the [BuildOutput.dependencies]. | ||
| final List<String> dartBuildFiles; | ||
|
|
||
| CBuilder.library({ | ||
| required this.name, | ||
| required this.assetName, | ||
| this.sources = const [], | ||
| this.dartBuildFiles = const ['build.dart'], | ||
| }) : _type = _CBuilderType.library; | ||
|
|
||
| CBuilder.executable({ | ||
| required this.name, | ||
| this.sources = const [], | ||
| this.dartBuildFiles = const ['build.dart'], | ||
| }) : _type = _CBuilderType.executable, | ||
| assetName = null; | ||
|
|
||
| @override | ||
| Future<void> run({ | ||
| required BuildConfig buildConfig, | ||
| required BuildOutput buildOutput, | ||
| Logger? logger, | ||
| }) async { | ||
| logger ??= Logger(''); | ||
| final outDir = buildConfig.outDir; | ||
| final packageRoot = buildConfig.packageRoot; | ||
| await Directory.fromUri(outDir).create(recursive: true); | ||
| final packaging = buildConfig.packaging.preferredPackaging.first; | ||
| final libUri = | ||
| outDir.resolve(buildConfig.target.os.libraryFileName(name, packaging)); | ||
| final exeUri = | ||
| outDir.resolve(buildConfig.target.os.executableFileName(name)); | ||
| final sources = [ | ||
| for (final source in this.sources) packageRoot.resolve(source), | ||
| ]; | ||
| final dartBuildFiles = [ | ||
| for (final source in this.dartBuildFiles) packageRoot.resolve(source), | ||
| ]; | ||
|
|
||
| final task = RunCBuilder( | ||
| buildConfig: buildConfig, | ||
| logger: logger, | ||
| sources: sources, | ||
| dynamicLibrary: | ||
| _type == _CBuilderType.library && packaging == Packaging.dynamic | ||
| ? libUri | ||
| : null, | ||
| staticLibrary: | ||
| _type == _CBuilderType.library && packaging == Packaging.static | ||
| ? libUri | ||
| : null, | ||
| executable: _type == _CBuilderType.executable ? exeUri : null, | ||
| ); | ||
| await task.run(); | ||
|
|
||
| if (assetName != null) { | ||
| buildOutput.assets.add(Asset( | ||
| name: assetName!, | ||
| packaging: packaging, | ||
| target: buildConfig.target, | ||
| path: AssetAbsolutePath(libUri), | ||
| )); | ||
| } | ||
| buildOutput.dependencies.dependencies.addAll([ | ||
| ...sources, | ||
| ...dartBuildFiles, | ||
| ]); | ||
| } | ||
| } | ||
|
|
||
| enum _CBuilderType { | ||
| executable, | ||
| library, | ||
| } | ||
154 changes: 154 additions & 0 deletions
154
pkgs/c_compiler/lib/src/cbuilder/compiler_resolver.dart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,154 @@ | ||
| // Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file | ||
| // 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:io'; | ||
|
|
||
| import 'package:logging/logging.dart'; | ||
| import 'package:native_assets_cli/native_assets_cli.dart'; | ||
|
|
||
| import '../native_toolchain/android_ndk.dart'; | ||
| import '../native_toolchain/clang.dart'; | ||
| import '../native_toolchain/gcc.dart'; | ||
| import '../native_toolchain/recognizer.dart'; | ||
| import '../tool/tool.dart'; | ||
| import '../tool/tool_error.dart'; | ||
| import '../tool/tool_instance.dart'; | ||
|
|
||
| // TODO(dacoharkes): This should support alternatives. | ||
| // For example use Clang or MSVC on Windows. | ||
| class CompilerResolver { | ||
| final BuildConfig buildConfig; | ||
| final Logger? logger; | ||
| final Target host; | ||
|
|
||
| CompilerResolver({ | ||
| required this.buildConfig, | ||
| required this.logger, | ||
| Target? host, // Only visible for testing. | ||
| }) : host = host ?? Target.current; | ||
|
|
||
| Future<ToolInstance> resolveCompiler() async { | ||
| // First, check if the launcher provided a direct path to the compiler. | ||
| var result = await _tryLoadCompilerFromConfig( | ||
| BuildConfig.ccConfigKey, | ||
| (buildConfig) => buildConfig.cc, | ||
| ); | ||
|
|
||
| // Then, try to detect on the host machine. | ||
| final tool = _selectCompiler(); | ||
| if (tool != null) { | ||
| result ??= await _tryLoadToolFromNativeToolchain(tool); | ||
| } | ||
|
|
||
| if (result != null) { | ||
| return result; | ||
| } | ||
|
|
||
| final target = buildConfig.target; | ||
| final errorMessage = | ||
| "No tools configured on host '$host' with target '$target'."; | ||
| logger?.severe(errorMessage); | ||
| throw ToolError(errorMessage); | ||
| } | ||
|
|
||
| /// Select the right compiler for cross compiling to the specified target. | ||
| Tool? _selectCompiler() { | ||
| final target = buildConfig.target; | ||
|
|
||
| if (target == host) return clang; | ||
| if (target.os == OS.android) return androidNdkClang; | ||
| if (host.os == OS.linux) { | ||
| switch (target) { | ||
| case Target.linuxArm: | ||
| return armLinuxGnueabihfGcc; | ||
| case Target.linuxArm64: | ||
| return aarch64LinuxGnuGcc; | ||
| case Target.linuxIA32: | ||
| return i686LinuxGnuGcc; | ||
| } | ||
| } | ||
|
|
||
| return null; | ||
| } | ||
|
|
||
| Future<ToolInstance?> _tryLoadCompilerFromConfig( | ||
| String configKey, Uri? Function(BuildConfig) getter) async { | ||
| final configCcUri = getter(buildConfig); | ||
| if (configCcUri != null) { | ||
| assert(await File.fromUri(configCcUri).exists()); | ||
| logger?.finer('Using compiler ${configCcUri.path} ' | ||
| 'from config[${BuildConfig.ccConfigKey}].'); | ||
| return (await CompilerRecognizer(configCcUri).resolve(logger: logger)) | ||
| .first; | ||
| } | ||
| logger?.finer('No compiler set in config[${BuildConfig.ccConfigKey}].'); | ||
| return null; | ||
| } | ||
|
|
||
| Future<ToolInstance?> _tryLoadToolFromNativeToolchain(Tool tool) async { | ||
| final resolved = (await tool.defaultResolver!.resolve(logger: logger)) | ||
| .where((i) => i.tool == tool) | ||
| .toList() | ||
| ..sort(); | ||
| return resolved.isEmpty ? null : resolved.first; | ||
| } | ||
|
|
||
| Future<ToolInstance> resolveArchiver() async { | ||
| // First, check if the launcher provided a direct path to the compiler. | ||
| var result = await _tryLoadArchiverFromConfig( | ||
| BuildConfig.arConfigKey, | ||
| (buildConfig) => buildConfig.ar, | ||
| ); | ||
|
|
||
| // Then, try to detect on the host machine. | ||
| final tool = _selectArchiver(); | ||
| if (tool != null) { | ||
| result ??= await _tryLoadToolFromNativeToolchain(tool); | ||
| } | ||
|
|
||
| if (result != null) { | ||
| return result; | ||
| } | ||
|
|
||
| final target = buildConfig.target; | ||
| final errorMessage = | ||
| "No tools configured on host '$host' with target '$target'."; | ||
| logger?.severe(errorMessage); | ||
| throw ToolError(errorMessage); | ||
| } | ||
|
|
||
| /// Select the right archiver for cross compiling to the specified target. | ||
| Tool? _selectArchiver() { | ||
| final target = buildConfig.target; | ||
|
|
||
| if (target == host) return llvmAr; | ||
| if (target.os == OS.android) return androidNdkLlvmAr; | ||
| if (host.os == OS.linux) { | ||
| switch (target) { | ||
| case Target.linuxArm: | ||
| return armLinuxGnueabihfGccAr; | ||
| case Target.linuxArm64: | ||
| return aarch64LinuxGnuGccAr; | ||
| case Target.linuxIA32: | ||
| return i686LinuxGnuGccAr; | ||
| } | ||
| } | ||
|
|
||
| return null; | ||
| } | ||
|
|
||
| Future<ToolInstance?> _tryLoadArchiverFromConfig( | ||
| String configKey, Uri? Function(BuildConfig) getter) async { | ||
| final configArUri = getter(buildConfig); | ||
| if (configArUri != null) { | ||
| assert(await File.fromUri(configArUri).exists()); | ||
| logger?.finer('Using archiver ${configArUri.path} ' | ||
| 'from config[${BuildConfig.arConfigKey}].'); | ||
| return (await ArchiverRecognizer(configArUri).resolve(logger: logger)) | ||
| .first; | ||
| } | ||
| logger?.finer('No archiver set in config[${BuildConfig.arConfigKey}].'); | ||
| return null; | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.