mesonbuild / meson

The Meson Build System
http://mesonbuild.com
Apache License 2.0
5.53k stars 1.61k forks source link

meson needs to choose MSVC toolset on the basis of target #11435

Open mcdurdin opened 1 year ago

mcdurdin commented 1 year ago

When meson is attempting to locate MSVC using vswhere.exe, it has the opportunity to select the appropriate toolset for the target architecture. vsdevcmd.bat gives the following options in VS2019:

Syntax: vsdevcmd.bat [options]
[options] :
    -arch=architecture : Architecture for compiled binaries/libraries
           ** x86 [default]
           ** amd64
           ** arm
           ** arm64
    -host_arch=architecture : Architecture of compiler binaries
           ** x86 [default]
           ** amd64

vsdevcmd.bat was introduced in VS2017 under Common7/Tools and replaces VC/Auxiliary/Build/vcvarsall.bat. I have been told that vcvarsall.bat is gone in VS2022 (not verified).

At present, the target architecture is hard-coded to either amd64 or ARM, making it impossible, for example, to build a Windows x86 executable:

https://github.com/mesonbuild/meson/blob/616bf1f79d855c6d5494f71806ce42961d8ce85e/mesonbuild/utils/vsenv.py#L76-L84

The current workaround is of course to run vsdevcmd -arch=x86 before running meson setup, but this is troublesome when integrating with other shells (for example as noted in https://github.com/mesonbuild/meson/issues/2622#issuecomment-592773450).

We encountered this issue when trying to simplify our meson builds at https://github.com/keymanapp/keyman/pull/8279; I would submit a patch for meson but really not sure the right way to address this within meson :smile:. Our desired approach would be for meson to figure out which toolchain architecture is needed for the target and use that to call vsdevcmd.bat/vcvarsall.bat with the -arch parameter.

The host architecture may be important for very large projects -- given it is either x86 or amd64, this should be easy enough to ascertain with the existing native architecture check?

eli-schwartz commented 1 year ago

We want to tie this back into Meson's concept of the build (native) and host (cross compile) machines.

I think this basically only matters for cross compilation, though, right? For native builds, letting the batch script choose the OS default is the correct move?

Since we can guarantee that cross compiling involves a cross file, I think we can take advantage of specifying the machine at https://mesonbuild.com/Cross-compilation.html#machine-entries and simply call the batch script with information from the cpu_family that was defined.

What do you think?

mcdurdin commented 1 year ago

That all makes sense to me.

Windows is a bit of a funny beast here, because both x86 and amd64 can be considered 'native' architectures on an amd64 machine. For native builds, letting the batch file choose is probably fine -- but it will be x86 I think by default on all versions of MSVC so that would be a change in behavior for meson.

eli-schwartz commented 1 year ago

We usually consider the native architecture to be whatever the compiler thinks it is, for example on Linux running a 64-bit kernel, the only difference between a 32-bit userland and a 64-bit userland is which binaries you happen to run... or in the case of the compiler, whether you happen to define CC='gcc -m32'. ;)

Looks like we indeed do some guessing on Windows in order to call the "correct" vcvars script based on ctypes magic. I'm okay with keeping that high-level logic, although really I know very little about MSVC so maybe another Meson developer has a stronger opinion.

xclaesse commented 1 year ago

What I had in mind for a while is to add a value to --vsenv <arch>. That should work at least to select between amd64 and x86. Not sure how arm cross compilation works.

mcdurdin commented 1 year ago

vsdevcmd.bat makes cross compilation fairly clear, I think, with its -arch and -host_arch parameters (see first comment). Generally, only need to specify -arch=<target> but -host_arch= may be important for very large projects that rely on a 64-bit compiler to build.

jibsen commented 10 months ago

I just ran into this issue as well. I was updating my CI to use --vsenv, which is really nice to abstract away the Visual Studio version specific script locations, but realized I was no longer able to test both the x86 and amd64 builds.

micha4w commented 3 months ago

Would love this to be able to get an easy x86 env in VSCode.

I would propose a very simple solution where you can pass an option like --vsenv {x86, x86_x64, x86_arm, x86_arm64, x64, x64_x86, x64_arm, x64_arm64} which then gets directly forwarded to vcvarsall as specified here, and then let the user figure out which option they want. (There is no Option for ARM Host, so I'm not sure how that would work)

I can also confirm that vcvarsall still exists in VS2022.