Skip to content

Commit 16f7776

Browse files
Fix handle spaces in the path to the cl.exe compiler
When the Visual Studio C++ compiler (cl.exe) is installed in a path containing spaces (e.g., the default "C:\Program Files\Microsoft Visual Studio\2022\..."), the build system failed to execute it correctly. The command was invoked without proper quoting, leading to an error: 'C:\Program' is not recognized as an internal or external command This commit ensures that the path to cl.exe is properly quoted when invoking the compiler, allowing builds to succeed on systems with a standard Visual Studio installation.
1 parent 4341e37 commit 16f7776

File tree

5 files changed

+33
-5
lines changed

5 files changed

+33
-5
lines changed

pkgs/native_toolchain_c/lib/src/cbuilder/cbuilder.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ class CBuilder extends CTool implements Builder {
7979
super.linkModePreference,
8080
super.optimizationLevel = OptimizationLevel.o3,
8181
this.buildMode = BuildMode.release,
82+
super.runInShell = false,
8283
}) : super(type: OutputType.library);
8384

8485
CBuilder.executable({
@@ -105,6 +106,7 @@ class CBuilder extends CTool implements Builder {
105106
super.cppLinkStdLib,
106107
super.optimizationLevel = OptimizationLevel.o3,
107108
this.buildMode = BuildMode.release,
109+
super.runInShell = false,
108110
}) : super(
109111
type: OutputType.executable,
110112
assetName: null,
@@ -203,6 +205,7 @@ class CBuilder extends CTool implements Builder {
203205
language: language,
204206
cppLinkStdLib: cppLinkStdLib,
205207
optimizationLevel: optimizationLevel,
208+
runInShell: runInShell,
206209
);
207210
await task.run();
208211

pkgs/native_toolchain_c/lib/src/cbuilder/clinker.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class CLinker extends CTool implements Linker {
4141
super.cppLinkStdLib,
4242
super.linkModePreference,
4343
super.optimizationLevel = OptimizationLevel.o3,
44+
super.runInShell = false,
4445
}) : super(type: OutputType.library);
4546

4647
/// Runs the C Linker with on this C build spec.
@@ -94,6 +95,7 @@ class CLinker extends CTool implements Linker {
9495
language: language,
9596
cppLinkStdLib: cppLinkStdLib,
9697
optimizationLevel: optimizationLevel,
98+
runInShell: runInShell,
9799
);
98100
await task.run();
99101

pkgs/native_toolchain_c/lib/src/cbuilder/ctool.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,12 @@ abstract class CTool {
166166
/// What optimization level should be used for compiling.
167167
final OptimizationLevel optimizationLevel;
168168

169+
/// Whether to run the compiler/linker in a shell.
170+
///
171+
/// If the cl.exe path contains spaces, this parameter needs to be set to
172+
/// false.
173+
final bool runInShell;
174+
169175
CTool({
170176
required this.name,
171177
required this.packageName,
@@ -186,5 +192,6 @@ abstract class CTool {
186192
required this.linkModePreference,
187193
required this.type,
188194
required this.optimizationLevel,
195+
required this.runInShell,
189196
});
190197
}

pkgs/native_toolchain_c/lib/src/cbuilder/run_cbuilder.dart

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ class RunCBuilder {
5050
final Language language;
5151
final String? cppLinkStdLib;
5252
final OptimizationLevel optimizationLevel;
53+
final bool runInShell;
5354

5455
RunCBuilder({
5556
required this.input,
@@ -73,6 +74,7 @@ class RunCBuilder {
7374
this.language = Language.c,
7475
this.cppLinkStdLib,
7576
required this.optimizationLevel,
77+
this.runInShell = false,
7678
}) : outDir = input.outputDirectory,
7779
assert(
7880
[executable, dynamicLibrary, staticLibrary].whereType<Uri>().length ==
@@ -120,16 +122,19 @@ class RunCBuilder {
120122
final toolInstance_ = await compiler();
121123
final tool = toolInstance_.tool;
122124
if (tool.isClangLike || tool.isLdLike) {
123-
await runClangLike(tool: toolInstance_);
125+
await runClangLike(tool: toolInstance_, runInShell: runInShell);
124126
return;
125127
} else if (tool == cl) {
126-
await runCl(tool: toolInstance_);
128+
await runCl(tool: toolInstance_, runInShell: runInShell);
127129
} else {
128130
throw UnimplementedError('This package does not know how to run $tool.');
129131
}
130132
}
131133

132-
Future<void> runClangLike({required ToolInstance tool}) async {
134+
Future<void> runClangLike({
135+
required ToolInstance tool,
136+
bool runInShell = false,
137+
}) async {
133138
// Clang for Windows requires the MSVC Developer Environment.
134139
final environment = await _resolver.resolveEnvironment(tool);
135140

@@ -182,6 +187,7 @@ class RunCBuilder {
182187
[sourceFiles[i]],
183188
objectFile,
184189
environment,
190+
runInShell,
185191
);
186192
objectFiles.add(objectFile);
187193
}
@@ -196,6 +202,7 @@ class RunCBuilder {
196202
captureOutput: false,
197203
throwOnUnexpectedExitCode: true,
198204
environment: environment,
205+
runInShell: runInShell,
199206
);
200207
} else {
201208
await _compile(
@@ -208,6 +215,7 @@ class RunCBuilder {
208215
sourceFiles,
209216
dynamicLibrary != null ? outDir.resolveUri(dynamicLibrary!) : null,
210217
environment,
218+
runInShell,
211219
);
212220
}
213221
}
@@ -223,6 +231,7 @@ class RunCBuilder {
223231
Iterable<String> sourceFiles,
224232
Uri? outFile,
225233
Map<String, String> environment,
234+
bool runInShell,
226235
) async {
227236
await runProcess(
228237
executable: toolInstance.uri,
@@ -343,10 +352,14 @@ class RunCBuilder {
343352
logger: logger,
344353
captureOutput: false,
345354
throwOnUnexpectedExitCode: true,
355+
runInShell: runInShell,
346356
);
347357
}
348358

349-
Future<void> runCl({required ToolInstance tool}) async {
359+
Future<void> runCl({
360+
required ToolInstance tool,
361+
bool runInShell = true,
362+
}) async {
350363
final environment = await _resolver.resolveEnvironment(tool);
351364

352365
final isStaticLib = staticLibrary != null;
@@ -401,6 +414,7 @@ class RunCBuilder {
401414
captureOutput: false,
402415
stdoutLogLevel: Level.INFO,
403416
throwOnUnexpectedExitCode: true,
417+
runInShell: runInShell,
404418
);
405419

406420
if (staticLibrary != null) {
@@ -413,6 +427,7 @@ class RunCBuilder {
413427
captureOutput: false,
414428
stdoutLogLevel: Level.INFO,
415429
throwOnUnexpectedExitCode: true,
430+
runInShell: runInShell,
416431
);
417432
}
418433

pkgs/native_toolchain_c/lib/src/utils/run_process.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Future<RunProcessResult> runProcess({
2222
Level stdoutLogLevel = Level.FINE,
2323
int expectedExitCode = 0,
2424
bool throwOnUnexpectedExitCode = false,
25+
bool runInShell = false,
2526
}) async {
2627
final printWorkingDir =
2728
workingDirectory != null && workingDirectory != Directory.current.uri;
@@ -41,7 +42,7 @@ Future<RunProcessResult> runProcess({
4142
arguments,
4243
workingDirectory: workingDirectory?.toFilePath(),
4344
environment: environment,
44-
runInShell: Platform.isWindows && workingDirectory != null,
45+
runInShell: runInShell,
4546
);
4647

4748
final stdoutSub = process.stdout.listen((List<int> data) {

0 commit comments

Comments
 (0)