Skip to content
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

Add MSVC support for Response Files #1618

Merged
merged 3 commits into from
Mar 9, 2023
Merged

Add MSVC support for Response Files #1618

merged 3 commits into from
Mar 9, 2023

Conversation

temportalflux
Copy link
Contributor

Goal

Add support for response/command files in MSVC as defined by the MSVC and Visual Studio MSBuild docs.

Related Issues

History of Response File support in MSVC implementation

Implementation Details

This change adds an iterator layer between the command-line argument iterator and the ArgIter, which used to compare arguments against the supported flags/options. This new layer determines if an option is a response-file directive (@file), and if it is, reads the options from the file before continuing to iterate over the command-line args. This requires an additional file-parsing iterating (SplitArgs) to split the file contents into arguments in a way which is consistent with the file format.

The encoding crate is used to read utf-8 (default encoding in rust) & utf-16 (big and little endian) encodings. The latter is used by MSBuild when generating response files.

Please see the Response Files doc in this PR for an overview of how response files are used in MSVC, what the expected format is, how they differ from GCC, and how they are implemented for both GCC and MSVC in SCCache.

Flags

This pull request also includes a handful of changes/additions to the MSVC flags. These flags could be separated into a separate PR, but given how small the changes are, they are currently bundled in with the MSVC changes. Our environment requires these flags, hence the need to have them supported.

Updated Flags

Added Flags

Flags which allow users to pass "disable" feature flags which do not affect cachability:

  • /Gm-, disable minimal rebuilds. flag docs
  • /WX-, disable "treat all compiler warnings as errors". flag docs
  • /openmp-, disable the openmp directive. flag docs

Flags which enable features:

  • /permissive, allows code which doesn't conform to standard, but doesnt change what needs to be compiled, just how the compiler does so. This is major for some legacy projects which are not up-to-date to standard conformance. flag docs

@Xuanwo
Copy link
Collaborator

Xuanwo commented Feb 23, 2023

suggestion: Can you add a basic test for this feature?

@temportalflux
Copy link
Contributor Author

suggestion: Can you add a basic test for this feature?

What do you mean by "basic test"? There are a number of tests in compiler/msvc.rs, including test_responsefile_absolute_path, which is the minimal viable successful test (the response file exists and contains arguments). Is there a more basic/minimal test you'd expect to see?

@Xuanwo
Copy link
Collaborator

Xuanwo commented Feb 23, 2023

I mean add a basic integration test like what we do in tests

@temportalflux
Copy link
Contributor Author

Hm yeah I can look into that. I honestly didn't even notice the integration tests, and I haven't yet found any documentation on how those tests are added to or maintained. I'll look through the commit history to see if I can find a decent template/example.

Copy link
Collaborator

@drahnr drahnr left a comment

Choose a reason for hiding this comment

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

First superficial pass, this is the quality we strive for ❤️ thank you for the time and effort put in.

Two questions: Is there a recursion limit on eval? Is that spec'd? And could you write an integration test as @Xuanwo asked?

The only thing after that is appeasing CI

@sylvestre
Copy link
Collaborator

I'll look through the commit history to see if I can find a decent template/example.

I love docs but here, copying the current model is easy enough:
https://github.com/mozilla/sccache/blob/main/.github/workflows/integration-tests.yml#L30-L76

@temportalflux
Copy link
Contributor Author

Is there a recursion limit on eval? Is that spec'd?

Yes there is a limit! I noted it in the docs/ResponseFiles.md doc; A response file cannot contain additional @file options, they are not recursive.. That comes straight out of the MSVC docs: It is not possible to specify the @ option from within a response file. That is, a response file cannot embed another response file.


Integration testing wise, I'm looking into that now. Seems like there is little to no obvious docs on adding one, but it looks like the pattern is adding a new function call to run_sccache_command_tests under the correct compiler (cl.exe for msvc) which runs the integration test (like test_msvc_deps).


Looks like CI is failing because clippy says let...else statements are unstable, even though they were stabilized recently. I can change the syntax on those two statements if folks prefer to not use let...else.

@codecov-commenter
Copy link

codecov-commenter commented Feb 23, 2023

Codecov Report

Patch coverage: 48.29% and project coverage change: +0.01 🎉

Comparison is base (e3eefb3) 29.52% compared to head (c165b3b) 29.54%.

❗ Current head c165b3b differs from pull request most recent head 1cb4928. Consider uploading reports for the commit 1cb4928 to get more accurate results

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1618      +/-   ##
==========================================
+ Coverage   29.52%   29.54%   +0.01%     
==========================================
  Files          49       49              
  Lines       16662    17012     +350     
  Branches     8042     8195     +153     
==========================================
+ Hits         4920     5026     +106     
- Misses       6836     6996     +160     
- Partials     4906     4990      +84     
Impacted Files Coverage Δ
tests/system.rs 28.57% <0.00%> (-1.63%) ⬇️
src/compiler/msvc.rs 44.87% <52.07%> (+2.07%) ⬆️

... and 12 files with indirect coverage changes

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

☔ View full report in Codecov by Sentry.
📢 Do you have feedback about the report comment? Let us know in this issue.

@temportalflux
Copy link
Contributor Author

Added a fairly minimal integration test. Please nitpick it because how the integration tests work in this repo is still somewhat evading me.

src/compiler/msvc.rs Outdated Show resolved Hide resolved
Copy link
Collaborator

@drahnr drahnr left a comment

Choose a reason for hiding this comment

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

A few small nits, generally not a a fan of manually parsing file formats, but in this case it's ok.

Thank you for you contribution! I really like the documentation you created in this PR!

@temportalflux
Copy link
Contributor Author

A few small nits, generally not a a fan of manually parsing file formats, but in this case it's ok.

Thank you for you contribution! I really like the documentation you created in this PR!

Thanks for the review, and I'm glad the documentation is helpful! I've addressed the nits and squashed all subsequent changes into the original 2 commits after rebasing onto latest main.

@temportalflux
Copy link
Contributor Author

@drahnr @sylvestre what does the timeline on getting this merged look like? Any chance it can make it in for the next pre-release or full release (0.4.0)?

@sylvestre
Copy link
Collaborator

I still would like to see an end to end integration test in
https://github.com/mozilla/sccache/blob/main/.github/workflows/integration-tests.yml if it makes sense

@temportalflux
Copy link
Contributor Author

temportalflux commented Mar 2, 2023

I still would like to see an end to end integration test in https://github.com/mozilla/sccache/blob/main/.github/workflows/integration-tests.yml if it makes sense

I'm not sure I fully follow. Are you saying that there should be a new job in the integration tests workflow which runs cargo test on the windows-2019 os against the x86_64-pc-windows-msvc to test msvc?

Edit: something like this?

  msvc:
    runs-on: windows-2019
    needs: build
    
    steps:
      - name: Clone repository
        uses: actions/checkout@v3

      - name: Install rust
        uses: ./.github/actions/rust-toolchain
        with:
          toolchain: "stable"

      - name: Build
        run: cargo clean && cargo test --no-run
      
      - name: Run tests
        run: cargo test --locked --target x86_64-pc-windows-msvc

@sylvestre
Copy link
Collaborator

Nope, building a fake project that uses MSVC / response files

@temportalflux
Copy link
Contributor Author

The above force push is just rebasing on latest so its easy to merge when that time comes

@sylvestre
Copy link
Collaborator

ilammy/[email protected] is not allowed to be used in mozilla/sccache.

is there an alternative ?
(i can ask to the Mozilla admin to enable it but it might take a few days/weeks)

@temportalflux
Copy link
Contributor Author

temportalflux commented Mar 5, 2023

Unfortunately I've yet to find a good alternative. All of the resources point towards using that action, which basically calls the vsvars.bat in the Visual Studio installation (bundled in the windows-2019 image) and copies the outputted results into the job's environment variables https://github.com/ilammy/msvc-dev-cmd/blob/master/index.js#L147. If we can't use that action, we could either copy the repo into .github/actions and maintain it until the action is approved, or find some way to manually do all the stuff that script is doing within the job. I'm totally open to any alternatives if I've missed another action that tackles the same thing, but all my research points to that one resource.

EDIT: A coworker informed me that https://github.com/microsoft/setup-msbuild exists, but after attempting to use it I found that it only sets up msbuild, not the msvc compiler cl.exe. So no change to the above comment from this discovery, just more context.

@temportalflux
Copy link
Contributor Author

Given that there are no other integration tests comparable new msvc one (they are all testing integrations with outside tools, not the underlying compilers), and I'd prefer to be efficient about work spent while minimizing delay time, I think the best route forward is:

  1. Separate the integration test job into its own PR, whiches uses ilammy/msvc-dev-cmd since it seems to be the standard
  2. Merge this PR w/o the integration test
  3. Mark the integration test PR as blocked until ilammy/msvc-dev-cmd is approved

@temportalflux
Copy link
Contributor Author

@sylvestre any thoughts on the msvc gh-action dependency & split-the-PR solution?

@drahnr
Copy link
Collaborator

drahnr commented Mar 6, 2023

I fully agree, we don't need to mention it in the release notes or mark it as experimental, worst case it's just as broken as before.

@sylvestre I am inclined to merge it now, regardless of the CI test case

@sylvestre
Copy link
Collaborator

Please give me a week to see if we can get it enabled
AFAIK, there isn't any rush.

@sylvestre
Copy link
Collaborator

I think we enabled the github action. Could you please rebase it to retrigger the CI? for some reasons, I can't do it on github on this PR ?!

Adds an iteration layer between the command-line argument iterator and the `ArgIter` used to compare arguments against the supported flags/options. This new layer determines if an option is a response-file directive (`@file`), and if it is, reads the options from the file before continuing to iterate over the command-line args. This requires an additional file-parsing iterating (`SplitArgs`) to split the file contents into arguments in a way which is consistent with the file format.

The `encoding` crate is used to read utf-8 (default encoding in rust) & utf-16 (big and little endian) encodings. The latter is used by `MSBuild` when generating response files.

Resources:
- [MSDN](https://docs.microsoft.com/en-us/cpp/build/reference/at-specify-a-compiler-response-file)
- [MSBuild](https://learn.microsoft.com/en-us/visualstudio/msbuild/msbuild-response-files?view=vs-2019)

Contributes to #107
Based off of #192
Closes #1082
Closes #1183
Updated Flags:
- `/FC` ([previously marked as TooHardFlag](https://github.com/proletariatgames/sccache/commit/bf6fb5de6f566d20321bf4a47714398250975d03)) changed to `PassThrough` because it only affects how the compiler prints debug information. [flag docs](https://learn.microsoft.com/en-us/cpp/build/reference/fc-full-path-of-source-code-file-in-diagnostics?view=msvc-170)

Added Flags, to allow users to pass "disable" feature flags which do not affect cachability:
- `/Gm-`, disable minimal rebuilds. [flag docs](https://learn.microsoft.com/en-us/cpp/build/reference/gm-enable-minimal-rebuild?view=msvc-170)
- `/WX-`, disable "treat all compiler warnings as errors". [flag docs](https://learn.microsoft.com/en-us/cpp/build/reference/compiler-option-warning-level?view=msvc-170)
- `/openmp-`, disable the openmp directive. [flag docs](https://learn.microsoft.com/en-us/cpp/build/reference/openmp-enable-openmp-2-0-support?view=msvc-170)

Added Flags which enable features:
- `/permissive`, allows code which doesn't conform to standard, but doesnt change what needs to be compiled, just how the compiler does so. This is major for some legacy projects which are not up-to-date to standard conformance. [flag docs](https://learn.microsoft.com/en-us/cpp/build/reference/permissive-standards-conformance?view=msvc-170)

Also added a comment to `/Fp` to specify why it is not supported. `/Fp` is used to adjust PCH behaviors when used in conjunction with `/Yu` or `/Yc`. [flag docs](https://learn.microsoft.com/en-us/cpp/build/reference/fp-name-dot-pch-file?view=msvc-170)

Contributes to #978
@temportalflux
Copy link
Contributor Author

Rebased and pushed!

@temportalflux
Copy link
Contributor Author

Whats going on with the freebsd check?

@sylvestre
Copy link
Collaborator

sylvestre commented Mar 9, 2023 via email

Builds against windows and performs a series of compilation checks to ensure that the mock project builds and response files are properly expanded
@temportalflux
Copy link
Contributor Author

Looks like it was only failing the integration test because the version allowed was @v1 and the PR was using the more specific @v1.4.1 for the msvc-dev-cmd. Squashed a change into the last commit which changed the version from 1.4.1 to 1 and hopefully it should be allowed now.

@sylvestre
Copy link
Collaborator

yeah, i asked if we could fix that on the admin side

@sylvestre
Copy link
Collaborator

Looks like it worked this time:

Compile requests                      2
Compile requests executed             2
Cache hits                            1
Cache hits (C/C++)                    1
Cache misses                          1
Cache misses (C/C++)                  1

well done :)

@assarbad
Copy link

EDIT: A coworker informed me that https://github.com/microsoft/setup-msbuild exists, but after attempting to use it I found that it only sets up msbuild, not the msvc compiler cl.exe. So no change to the above comment from this discovery, just more context.

Shameless plug: https://github.com/assarbad/scripts/blob/master/setvcvars.cmd

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants