diff --git a/pkgs/c_compiler/lib/src/cbuilder/compiler_resolver.dart b/pkgs/c_compiler/lib/src/cbuilder/compiler_resolver.dart index 9ae3d36eb2..6763f3984d 100644 --- a/pkgs/c_compiler/lib/src/cbuilder/compiler_resolver.dart +++ b/pkgs/c_compiler/lib/src/cbuilder/compiler_resolver.dart @@ -174,4 +174,29 @@ class CompilerResolver { logger?.finer('No archiver set in config[${BuildConfig.arConfigKey}].'); return null; } + + Future toolchainEnvironmentScript(ToolInstance compiler) async { + final fromConfig = buildConfig.toolchainEnvScript; + if (fromConfig != null) { + logger?.fine('Using toolchainEnvScript from config: $fromConfig'); + return fromConfig; + } + + final compilerTool = compiler.tool; + assert(compilerTool == cl); + final vcvarsScript = + (await vcvars(compiler).defaultResolver!.resolve(logger: logger)).first; + return vcvarsScript.uri; + } + + List? toolchainEnvironmentScriptArguments() { + final fromConfig = buildConfig.toolchainEnvScriptArgs; + if (fromConfig != null) { + logger?.fine('Using toolchainEnvScriptArgs from config: $fromConfig'); + return fromConfig; + } + + // vcvars above already has x64 or x86 in the script name. + return null; + } } diff --git a/pkgs/c_compiler/lib/src/cbuilder/run_cbuilder.dart b/pkgs/c_compiler/lib/src/cbuilder/run_cbuilder.dart index e690f90713..9506ecdc0b 100644 --- a/pkgs/c_compiler/lib/src/cbuilder/run_cbuilder.dart +++ b/pkgs/c_compiler/lib/src/cbuilder/run_cbuilder.dart @@ -36,15 +36,12 @@ class RunCBuilder { .length == 1); - Future compiler() async { - final resolver = CompilerResolver(buildConfig: buildConfig, logger: logger); - return await resolver.resolveCompiler(); - } + late final _resolver = + CompilerResolver(buildConfig: buildConfig, logger: logger); - Future archiver() async { - final resolver = CompilerResolver(buildConfig: buildConfig, logger: logger); - return (await resolver.resolveArchiver()).uri; - } + Future compiler() async => await _resolver.resolveCompiler(); + + Future archiver() async => (await _resolver.resolveArchiver()).uri; Future iosSdk(IOSSdk iosSdk, {Logger? logger}) async { if (iosSdk == IOSSdk.iPhoneOs) { @@ -76,13 +73,7 @@ class RunCBuilder { return; } assert(compilerTool == cl); - final vcvarsScript = - (await vcvars(compiler_).defaultResolver!.resolve(logger: logger)) - .first; - await runCl( - compiler: compiler_.uri, - vcvars: vcvarsScript.uri, - ); + await runCl(compiler: compiler_); } Future runClangLike({required Uri compiler}) async { @@ -146,19 +137,19 @@ class RunCBuilder { } } - Future runCl({ - required Uri compiler, - required Uri vcvars, - }) async { + Future runCl({required ToolInstance compiler}) async { + final vcvars = (await _resolver.toolchainEnvironmentScript(compiler))!; + final vcvarsArgs = _resolver.toolchainEnvironmentScriptArguments(); + final environment = await envFromBat(vcvars, arguments: vcvarsArgs ?? []); + final isStaticLib = staticLibrary != null; Uri? archiver_; if (isStaticLib) { archiver_ = await archiver(); } - final environment = await envFromBat(vcvars); final result = await runProcess( - executable: compiler, + executable: compiler.uri, arguments: [ if (executable != null) ...[ ...sources.map((e) => e.toFilePath()), diff --git a/pkgs/c_compiler/test/cbuilder/cbuilder_test.dart b/pkgs/c_compiler/test/cbuilder/cbuilder_test.dart index d168e7a640..cabf8e1301 100644 --- a/pkgs/c_compiler/test/cbuilder/cbuilder_test.dart +++ b/pkgs/c_compiler/test/cbuilder/cbuilder_test.dart @@ -31,6 +31,8 @@ void main() { target: Target.current, packaging: PackagingPreference.dynamic, // Ignored by executables. cc: cc, + toolchainEnvScript: toolchainEnvScript, + toolchainEnvScriptArgs: toolchainEnvScriptArgs, ); final buildOutput = BuildOutput(); final cbuilder = CBuilder.executable( @@ -70,6 +72,8 @@ void main() { target: Target.current, packaging: PackagingPreference.dynamic, cc: cc, + toolchainEnvScript: toolchainEnvScript, + toolchainEnvScriptArgs: toolchainEnvScriptArgs, ); final buildOutput = BuildOutput(); diff --git a/pkgs/c_compiler/test/cbuilder/compiler_resolver_test.dart b/pkgs/c_compiler/test/cbuilder/compiler_resolver_test.dart index cb9034b8c9..5dae0159bb 100644 --- a/pkgs/c_compiler/test/cbuilder/compiler_resolver_test.dart +++ b/pkgs/c_compiler/test/cbuilder/compiler_resolver_test.dart @@ -9,6 +9,7 @@ import 'package:c_compiler/c_compiler.dart'; import 'package:c_compiler/src/cbuilder/compiler_resolver.dart'; import 'package:c_compiler/src/native_toolchain/msvc.dart'; import 'package:c_compiler/src/tool/tool_error.dart'; +import 'package:collection/collection.dart'; import 'package:native_assets_cli/native_assets_cli.dart'; import 'package:test/test.dart'; @@ -32,6 +33,9 @@ void main() { ...await lib.defaultResolver!.resolve(logger: logger), ...await lld.defaultResolver!.resolve(logger: logger), ].first.uri; + final toolchainEnvScript = [ + ...await vcvars64.defaultResolver!.resolve(logger: logger) + ].firstOrNull?.uri; final buildConfig = BuildConfig( outDir: tempUri, packageRoot: tempUri, @@ -40,6 +44,7 @@ void main() { ar: ar, cc: cc, ld: ld, + toolchainEnvScript: toolchainEnvScript, ); final resolver = CompilerResolver(buildConfig: buildConfig, logger: logger); diff --git a/pkgs/c_compiler/test/helpers.dart b/pkgs/c_compiler/test/helpers.dart index 3f8d8b94d9..7091ff57e3 100644 --- a/pkgs/c_compiler/test/helpers.dart +++ b/pkgs/c_compiler/test/helpers.dart @@ -96,6 +96,16 @@ final Uri? cc = Platform.environment['CC']?.asFileUri(); /// Linker provided by the environment. final Uri? ld = Platform.environment['LD']?.asFileUri(); +/// Path to script that sets environment variables for [cc], [ld], and [ar]. +/// +/// Provided by environment. +final Uri? toolchainEnvScript = + Platform.environment['ToolchainEnvScript']?.asFileUri(); + +/// Arguments for [toolchainEnvScript] provided by environment. +final List? toolchainEnvScriptArgs = + Platform.environment['ToolchainEnvScriptArguments']?.split(' '); + extension on String { Uri asFileUri() => Uri.file(this); } diff --git a/pkgs/native_assets_cli/lib/src/model/build_config.dart b/pkgs/native_assets_cli/lib/src/model/build_config.dart index f097953f09..2d648a6cf9 100644 --- a/pkgs/native_assets_cli/lib/src/model/build_config.dart +++ b/pkgs/native_assets_cli/lib/src/model/build_config.dart @@ -47,6 +47,14 @@ class BuildConfig { Uri? get ar => _ar; late final Uri? _ar; + /// Path to script that sets environment variables for [cc], [ld], and [ar]. + Uri? get toolchainEnvScript => _toolchainEnvScript; + late final Uri? _toolchainEnvScript; + + /// Arguments for [toolchainEnvScript]. + List? get toolchainEnvScriptArgs => _toolchainEnvScriptArgs; + late final List? _toolchainEnvScriptArgs; + /// Preferred packaging method for library. PackagingPreference get packaging => _packaging; late final PackagingPreference _packaging; @@ -73,6 +81,8 @@ class BuildConfig { Uri? ar, Uri? cc, Uri? ld, + Uri? toolchainEnvScript, + List? toolchainEnvScriptArgs, required PackagingPreference packaging, Map? dependencyMetadata, }) { @@ -84,6 +94,8 @@ class BuildConfig { .._ar = ar .._cc = cc .._ld = ld + .._toolchainEnvScript = toolchainEnvScript + .._toolchainEnvScriptArgs = toolchainEnvScriptArgs .._packaging = packaging .._dependencyMetadata = dependencyMetadata; final parsedConfigFile = nonValidated.toYaml(); @@ -143,10 +155,14 @@ class BuildConfig { static const arConfigKey = 'ar'; static const ccConfigKey = 'cc'; static const ldConfigKey = 'ld'; + static const toolchainEnvScriptConfigKey = 'toolchain_env_script'; + static const toolchainEnvScriptArgsConfigKey = + 'toolchain_env_script_arguments'; static const dependencyMetadataConfigKey = 'dependency_metadata'; List _readFieldsFromConfig() { var targetSet = false; + var ccSet = false; return [ (config) => _config = config, (config) => _outDir = config.path(outDirConfigKey), @@ -169,8 +185,19 @@ class BuildConfig { ) : null, (config) => _ar = config.optionalPath(arConfigKey, mustExist: true), - (config) => _cc = config.optionalPath(ccConfigKey, mustExist: true), + (config) { + _cc = config.optionalPath(ccConfigKey, mustExist: true); + ccSet = true; + }, (config) => _ld = config.optionalPath(ldConfigKey, mustExist: true), + (config) => _toolchainEnvScript = + (ccSet && cc != null && cc!.toFilePath().endsWith('cl.exe')) + ? config.path(toolchainEnvScriptConfigKey, mustExist: true) + : null, + (config) => _toolchainEnvScriptArgs = config.optionalStringList( + toolchainEnvScriptArgsConfigKey, + splitEnvironmentPattern: ' ', + ), (config) => _packaging = PackagingPreference.fromString( config.string( PackagingPreference.configKey, @@ -218,6 +245,10 @@ class BuildConfig { if (_ar != null) arConfigKey: _ar!.toFilePath(), if (_cc != null) ccConfigKey: _cc!.toFilePath(), if (_ld != null) ldConfigKey: _ld!.toFilePath(), + if (_toolchainEnvScript != null) + toolchainEnvScriptConfigKey: _toolchainEnvScript!.toFilePath(), + if (_toolchainEnvScriptArgs != null) + toolchainEnvScriptArgsConfigKey: _toolchainEnvScriptArgs!, PackagingPreference.configKey: _packaging.toString(), if (_dependencyMetadata != null) dependencyMetadataConfigKey: { @@ -240,6 +271,9 @@ class BuildConfig { if (other._ar != _ar) return false; if (other._cc != _cc) return false; if (other._ld != _ld) return false; + if (other.toolchainEnvScript != toolchainEnvScript) return false; + if (!ListEquality().equals( + other.toolchainEnvScriptArgs, toolchainEnvScriptArgs)) return false; if (other._packaging != _packaging) return false; if (!DeepCollectionEquality() .equals(other._dependencyMetadata, _dependencyMetadata)) return false; @@ -255,6 +289,8 @@ class BuildConfig { _ar, _cc, _ld, + _toolchainEnvScript, + ListEquality().hash(toolchainEnvScriptArgs), _packaging, DeepCollectionEquality().hash(_dependencyMetadata), ); diff --git a/pkgs/native_assets_cli/test/example/native_add_test.dart b/pkgs/native_assets_cli/test/example/native_add_test.dart index 7faacf31a5..7e0f355b47 100644 --- a/pkgs/native_assets_cli/test/example/native_add_test.dart +++ b/pkgs/native_assets_cli/test/example/native_add_test.dart @@ -35,6 +35,12 @@ void main() async { '-Dtarget=${Target.current}', '-Dpackaging=dynamic', if (cc != null) '-Dcc=${cc!.toFilePath()}', + if (toolchainEnvScript != null) + '-D${BuildConfig.toolchainEnvScriptConfigKey}=' + '${toolchainEnvScript!.toFilePath()}', + if (toolchainEnvScriptArgs != null) + '-D${BuildConfig.toolchainEnvScriptArgsConfigKey}=' + '${toolchainEnvScriptArgs!.join(' ')}', ], workingDirectory: testPackageUri.toFilePath(), ); diff --git a/pkgs/native_assets_cli/test/helpers.dart b/pkgs/native_assets_cli/test/helpers.dart index 5e2b000627..513af3d4a8 100644 --- a/pkgs/native_assets_cli/test/helpers.dart +++ b/pkgs/native_assets_cli/test/helpers.dart @@ -56,6 +56,16 @@ final Uri? cc = Platform.environment['CC']?.asFileUri(); /// Linker provided by the environment. final Uri? ld = Platform.environment['LD']?.asFileUri(); +/// Path to script that sets environment variables for [cc], [ld], and [ar]. +/// +/// Provided by environment. +final Uri? toolchainEnvScript = + Platform.environment['ToolchainEnvScript']?.asFileUri(); + +/// Arguments for [toolchainEnvScript] provided by environment. +final List? toolchainEnvScriptArgs = + Platform.environment['ToolchainEnvScriptArguments']?.split(' '); + extension on String { Uri asFileUri() => Uri.file(this); } diff --git a/pkgs/native_assets_cli/test/model/build_config_test.dart b/pkgs/native_assets_cli/test/model/build_config_test.dart index 7eeada8b98..15f745f11d 100644 --- a/pkgs/native_assets_cli/test/model/build_config_test.dart +++ b/pkgs/native_assets_cli/test/model/build_config_test.dart @@ -13,6 +13,8 @@ void main() async { late Uri fakeClang; late Uri fakeLd; late Uri fakeAr; + late Uri fakeCl; + late Uri fakeVcVars; setUp(() async { tempUri = (await Directory.systemTemp.createTemp()).uri; @@ -22,6 +24,10 @@ void main() async { await File.fromUri(fakeLd).create(); fakeAr = tempUri.resolve('fake_ar'); await File.fromUri(fakeAr).create(); + fakeCl = tempUri.resolve('cl.exe'); + await File.fromUri(fakeCl).create(); + fakeVcVars = tempUri.resolve('vcvarsall.bat'); + await File.fromUri(fakeVcVars).create(); }); tearDown(() async { @@ -275,4 +281,21 @@ target_ios_sdk: iphoneos'''; 'value', ); }); + + test('toolchainEnvScript', () { + final buildConfig1 = BuildConfig( + outDir: tempUri.resolve('out1/'), + packageRoot: tempUri.resolve('packageRoot/'), + target: Target.windowsX64, + cc: fakeCl, + toolchainEnvScript: fakeVcVars, + toolchainEnvScriptArgs: ['x64'], + packaging: PackagingPreference.dynamic, + ); + + final configFile = buildConfig1.toYaml(); + final config = Config(fileParsed: configFile); + final fromConfig = BuildConfig.fromConfig(config); + expect(fromConfig, equals(buildConfig1)); + }); }