Skip to content

[native_toolchain_c] Fix/windows program files spaces#3323

Open
JoshuaR457 wants to merge 9 commits intodart-lang:mainfrom
JoshuaR457:fix/windows-program-files-spaces
Open

[native_toolchain_c] Fix/windows program files spaces#3323
JoshuaR457 wants to merge 9 commits intodart-lang:mainfrom
JoshuaR457:fix/windows-program-files-spaces

Conversation

@JoshuaR457
Copy link
Copy Markdown

Description

Building a Flutter Windows app fails when Visual Studio Build Tools is installed in the default path (C:\Program Files (x86)\...) because runInShell: true causes cmd.exe to parse the executable path, splitting on the space in "Program Files" and trying to execute C:\Program as a command.

Fix

  • Remove runInShell: Platform.isWindows && workingDirectory != null. Modern Dart supports workingDirectory on Windows natively without needing a shell wrapper, so this workaround is no longer needed. Removing it means cl.exe is invoked directly, bypassing cmd.exe path parsing entirely.
  • Quote environment variable values containing spaces in the commandString log string so the logged command is accurate and reproducible.

Related Issues

Fixes #3321.
Fixes #2848.

PR Checklist

  • I’ve reviewed the contributor guide and applied the relevant portions to this PR.
  • I've run dart tool/ci.dart --all locally and resolved all issues identified. This ensures the PR is formatted, has no lint errors, and ran all code generators. This applies to the packages part of the toplevel pubspec.yaml workspace.
  • All existing and new tests are passing. I added new tests to check the change I am making.
  • The PR is actually solving the issue. PRs that don't solve the issue will be closed. Please be respectful of the maintainers' time. If it's not clear what the issue is, feel free to ask questions on the GitHub issue before submitting a PR.
  • I have updated CHANGELOG.md for the relevant packages. (Not needed for small changes such as doc typos).
  • I have updated the pubspec package version if necessary.

@google-cla
Copy link
Copy Markdown

google-cla Bot commented Apr 21, 2026

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

Copy link
Copy Markdown
Collaborator

@dcharkes dcharkes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great! 🙏

Comment thread pkgs/native_toolchain_c/CHANGELOG.md Outdated
## 0.18.1
- Remove `runInShell: Platform.isWindows && workingDirectory != null`. Modern
Dart supports `workingDirectory` on Windows natively without needing a shell
wrapper, so this workaround is no longer needed. Removing it means `cl.exe`
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have a reference to a PR that fixed that issue? (I don't remember why I added this, but I did add this because something failed on Windows.)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have a specific PR reference for when workingDirectory support was added for Windows without runInShell. If you added it originally because something failed, it may be safer to keep runInShell as-is and instead focus the fix on quoting the executable path when runInShell is true.

Would you prefer I take that approach instead?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the first copy of that code I added in https://dart-review.googlesource.com/c/sdk/+/300203/19/pkg/native_assets_builder/lib/src/utils/run_process.dart but I can't find the reason why. I just remember things broke without it.

it may be safer to keep runInShell as-is and instead focus the fix on quoting the executable path when runInShell is true.

Agreed. Let's try if that works.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done! I've reverted the runInShell change and instead quote the executable path when it contains spaces and runInShell is true on Windows. This prevents cmd.exe from splitting the path on spaces (e.g. C:\Program Files (x86)\...).

workingDirectory: workingDirectory?.toFilePath(),
environment: environment,
runInShell: Platform.isWindows && workingDirectory != null,
runInShell: false,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need an integration test that exercises this. Can you add a test that fails without the fix?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated the tests to use an executable that lives in a path containing spaces. Without the fix (runInShell: true), cmd.exe fails to find the executable. With the fix (runInShell: false), Process.start passes the path directly and it works correctly.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 21, 2026

Package publishing

Package Version Status Publish tag (post-merge)
package:code_assets 1.0.0 already published at pub.dev
package:data_assets 0.19.6 already published at pub.dev
package:ffi 2.2.0 already published at pub.dev
package:hooks 1.0.3 already published at pub.dev
package:hooks_runner 1.2.1 already published at pub.dev
package:jni_flutter 1.0.1 already published at pub.dev
package:native_toolchain_c 0.18.1 ready to publish native_toolchain_c-v0.18.1
package:record_use 0.6.1-wip WIP (no publish necessary)
package:swift2objc 0.2.0-wip WIP (no publish necessary)
package:swiftgen 0.1.2 already published at pub.dev

Documentation at https://github.com/dart-lang/ecosystem/wiki/Publishing-automation.

@github-actions
Copy link
Copy Markdown

PR Health

Changelog Entry ✔️
Package Changed Files

Changes to files need to be accounted for in their respective changelogs.

This check can be disabled by tagging the PR with skip-changelog-check.

Breaking changes ✔️
Package Change Current Version New Version Needed Version Looking good?
code_assets None 1.0.0 1.0.0 1.0.0 ✔️
native_toolchain_c None 0.18.0 0.18.1 0.18.0 ✔️

This check can be disabled by tagging the PR with skip-breaking-check.

API leaks ✔️

The following packages contain symbols visible in the public API, but not exported by the library. Export these symbols or remove them from your publicly visible API.

Package Leaked API symbol Leaking sources

This check can be disabled by tagging the PR with skip-leaking-check.

@JoshuaR457 JoshuaR457 changed the title Fix/windows program files spaces [native_toolchain_c] Fix/windows program files spaces Apr 21, 2026
final stderrBuffer = StringBuffer();
final executablePath = executable.toFilePath();
// When running in shell on Windows, cmd.exe splits unquoted paths on spaces.
// Quote the executable path if it contains spaces to prevent this.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe make a final runInShell =
and then final executable = runInShell && executablePath.contains(' ') ? ...

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactored as recommended. Also looked into the CI failure, I think I got the issue but please don't qute me on that.

import 'package:native_toolchain_c/src/utils/run_process.dart';
import 'package:test/test.dart';

export 'package:native_toolchain_c/src/utils/run_process.dart';
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this export do here?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey, to be honest I'm not to sure. I tried to fix the CI but didn't really understand it, Claude told me this was the fix. Sorry! I'm happy to reverse it though if you want to look into it.
The fix for the original issue however should be correct.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should query the AI to understand why. Good AI practices is that you understand the code that you're sending out for review. (I also write almost all of my code with AI, this wonderful new reality. 😄)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did and i believe I got it now. Unfortunately one of the steps to get the workflow to not fail, was formatting the files. If this isn't what you want feel free to revert it.

Copy link
Copy Markdown
Collaborator

@dcharkes dcharkes Apr 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah formatting 👍 Edit: Make sure you're on the last version of the Dart/Flutter SDK. Because it looks like the formatting is undoing some formatting that I saw a couple of weeks ago.

@dcharkes
Copy link
Copy Markdown
Collaborator

The PR also needs a rebase due to merge conflict.

@JoshuaR457 JoshuaR457 force-pushed the fix/windows-program-files-spaces branch from d8ec02c to 203ec15 Compare April 24, 2026 18:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

2 participants