diff options
author | Nirbheek Chauhan <nirbheek@centricular.com> | 2016-09-25 10:57:49 +0530 |
---|---|---|
committer | Nirbheek Chauhan <nirbheek@centricular.com> | 2016-09-26 19:48:46 +0530 |
commit | ac8c8c2ba8244714702fdc6c7ee2362c5a05c034 (patch) | |
tree | f557fe0f244ad7652e46812a1e6cba27d21342e1 /mesonbuild/environment.py | |
parent | 6590b7221e1e3a30b33a6b74b380ee5a2b24d7ef (diff) | |
download | meson-ac8c8c2ba8244714702fdc6c7ee2362c5a05c034.zip meson-ac8c8c2ba8244714702fdc6c7ee2362c5a05c034.tar.gz meson-ac8c8c2ba8244714702fdc6c7ee2362c5a05c034.tar.bz2 |
Treat 32-bit compiles on 64-bit Windows as native
It's a terrible user experience to force people building 32-bit
applications on 64-bit Windows to use a cross-info file when every other
tool treats it as a 'native' compilation -- it satisfies all the
requirements for a native compile.
This commit also fixes the platform detection on Windows which would
cause the 'native cpu' to be detected as 32-bit if you installed 32-bit
Python on 64-bit Windows, or if you were building with a 32-bit
toolchain on 64-bit Windows.
Doesn't support MinGW yet -- the next commits will add that since the
changes required for that are more involved.
Diffstat (limited to 'mesonbuild/environment.py')
-rw-r--r-- | mesonbuild/environment.py | 84 |
1 files changed, 75 insertions, 9 deletions
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 341e5e8..79c09ba 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -57,26 +57,90 @@ def detect_ninja(): if p.returncode == 0 and mesonlib.version_compare(version, ">=1.6"): return n -def detect_cpu_family(): +def detect_native_windows_arch(): + """ + The architecture of Windows itself: x86 or amd64 + """ + # These env variables are always available. See: + # https://msdn.microsoft.com/en-us/library/aa384274(VS.85).aspx + # https://blogs.msdn.microsoft.com/david.wang/2006/03/27/howto-detect-process-bitness/ + arch = os.environ.get('PROCESSOR_ARCHITEW6432', '').lower() + if not arch: + try: + # If this doesn't exist, something is messing with the environment + arch = os.environ['PROCESSOR_ARCHITECTURE'].lower() + except KeyError: + raise InterpreterException('Unable to detect native OS architecture') + return arch + +def detect_windows_arch(compilers): + """ + Detecting the 'native' architecture of Windows is not a trivial task. We + cannot trust that the architecture that Python is built for is the 'native' + one because you can run 32-bit apps on 64-bit Windows using WOW64 and + people sometimes install 32-bit Python on 64-bit Windows. + + We also can't rely on the architecture of the OS itself, since it's + perfectly normal to compile and run 32-bit applications on Windows as if + they were native applications. It's a terrible experience to require the + user to supply a cross-info file to compile 32-bit applications on 64-bit + Windows. Thankfully, the only way to compile things with Visual Studio on + Windows is by entering the 'msvc toolchain' environment, which can be + easily detected. + + In the end, the sanest method is as follows: + 1. Check if we're in an MSVC toolchain environment, and if so, return the + MSVC toolchain architecture as our 'native' architecture. + 2. If not, check environment variables that are set by Windows and WOW64 to + find out the architecture that Windows is built for, and use that as our + 'native' architecture. + """ + os_arch = detect_native_windows_arch() + if os_arch != 'amd64': + return os_arch + # If we're on 64-bit Windows, 32-bit apps can be compiled without + # cross-compilation. So if we're doing that, just set the native arch as + # 32-bit and pretend like we're running under WOW64. Else, return the + # actual Windows architecture that we deduced above. + for compiler in compilers.values(): + # Check if we're using and inside an MSVC toolchain environment + if compiler.id == 'msvc' and 'VCINSTALLDIR' in os.environ: + # 'Platform' is only set when the target arch is not 'x86'. + # It's 'x64' when targetting x86_64 and 'arm' when targetting ARM. + platform = os.environ.get('Platform', 'x86').lower() + if platform == 'x86': + return platform + if compiler.id == 'gcc': + # TODO: Implement this + pass + return os_arch + +def detect_cpu_family(compilers): """ Python is inconsistent in its platform module. It returns different values for the same cpu. For x86 it might return 'x86', 'i686' or somesuch. Do some canonicalization. """ - trial = platform.machine().lower() + if mesonlib.is_windows(): + trial = detect_windows_arch(compilers) + else: + trial = platform.machine().lower() if trial.startswith('i') and trial.endswith('86'): return 'x86' if trial.startswith('arm'): return 'arm' - if trial == 'amd64': + if trial in ('amd64', 'x64'): return 'x86_64' # Add fixes here as bugs are reported. return trial -def detect_cpu(): - trial = platform.machine().lower() - if trial == 'amd64': +def detect_cpu(compilers): + if mesonlib.is_windows(): + trial = detect_windows_arch(compilers) + else: + trial = platform.machine().lower() + if trial in ('amd64', 'x64'): return 'x86_64' # Add fixes here as bugs are reported. return trial @@ -846,10 +910,12 @@ class CrossBuildInfo(): return 'host_machine' in self.config def need_exe_wrapper(self): - if self.has_host() and detect_cpu_family() == 'x86_64' and \ + # Can almost always run 32-bit binaries on 64-bit natively if the host + # and build systems are the same. We don't pass any compilers to + # detect_cpu_family() here because we always want to know the OS + # architecture, not what the compiler environment tells us. + if self.has_host() and detect_cpu_family({}) == 'x86_64' and \ self.config['host_machine']['cpu_family'] == 'x86' and \ self.config['host_machine']['system'] == detect_system(): - # Can almost always run 32-bit binaries on 64-bit natively if the - # host and build systems are the same return False return True |