diff options
Diffstat (limited to 'mesonbuild/environment.py')
-rw-r--r-- | mesonbuild/environment.py | 228 |
1 files changed, 100 insertions, 128 deletions
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index f8603f6..ce78162 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -510,22 +510,6 @@ class Environment: self.default_cmake = ['cmake'] self.default_pkgconfig = ['pkg-config'] - # Various prefixes and suffixes for import libraries, shared libraries, - # static libraries, and executables. - # Versioning is added to these names in the backends as-needed. - if mesonlib.for_windows(self): - self.exe_suffix = 'exe' - self.object_suffix = 'obj' - self.win_libdir_layout = True - elif mesonlib.for_cygwin(self): - self.exe_suffix = 'exe' - self.object_suffix = 'o' - self.win_libdir_layout = True - else: - self.exe_suffix = '' - self.object_suffix = 'o' - self.win_libdir_layout = False - def create_new_coredata(self, options): # WARNING: Don't use any values from coredata in __init__. It gets # re-initialized with project options by the interpreter during @@ -631,17 +615,11 @@ class Environment: return CompilerType.GCC_CYGWIN return CompilerType.GCC_STANDARD - def _get_compilers(self, lang, want_cross): + def _get_compilers(self, lang, for_machine): ''' The list of compilers is detected in the exact same way for C, C++, ObjC, ObjC++, Fortran, CS so consolidate it here. ''' - - # This morally assumes `want_cross = !native`. It may not yet be - # consistently set that way in the non cross build case, but it doesn't - # really matter since both options are the same in that case. - for_machine = MachineChoice.HOST if want_cross else MachineChoice.BUILD - value = self.binaries[for_machine].lookup_entry(lang) if value is not None: compilers, ccache = BinaryTable.parse_entry(value) @@ -654,13 +632,11 @@ class Environment: ccache = BinaryTable.detect_ccache() if self.machines.matches_build_machine(for_machine): - is_cross = False exe_wrap = None else: - is_cross = True exe_wrap = self.get_exe_wrapper() - return compilers, ccache, is_cross, exe_wrap + return compilers, ccache, exe_wrap def _handle_exceptions(self, exceptions, binaries, bintype='compiler'): errmsg = 'Unknown {}(s): {}'.format(bintype, binaries) @@ -670,9 +646,10 @@ class Environment: errmsg += '\nRunning "{0}" gave "{1}"'.format(c, e) raise EnvironmentException(errmsg) - def _detect_c_or_cpp_compiler(self, lang, want_cross): + def _detect_c_or_cpp_compiler(self, lang, for_machine): popen_exceptions = {} - compilers, ccache, is_cross, exe_wrap = self._get_compilers(lang, want_cross) + compilers, ccache, exe_wrap = self._get_compilers(lang, for_machine) + is_cross = not self.machines.matches_build_machine(for_machine) for compiler in compilers: if isinstance(compiler, str): @@ -737,7 +714,7 @@ class Environment: else: version = self.get_gnu_version_from_defines(defines) cls = GnuCCompiler if lang == 'c' else GnuCPPCompiler - return cls(ccache + compiler, version, compiler_type, is_cross, exe_wrap, defines, full_version=full_version) + return cls(ccache + compiler, version, compiler_type, for_machine, is_cross, exe_wrap, defines, full_version=full_version) if 'armclang' in out: # The compiler version is not present in the first line of output, @@ -755,7 +732,7 @@ class Environment: full_version = arm_ver_str compiler_type = CompilerType.ARM_WIN cls = ArmclangCCompiler if lang == 'c' else ArmclangCPPCompiler - return cls(ccache + compiler, version, compiler_type, is_cross, exe_wrap, full_version=full_version) + return cls(ccache + compiler, version, compiler_type, for_machine, is_cross, exe_wrap, full_version=full_version) if 'CL.EXE COMPATIBILITY' in out: # if this is clang-cl masquerading as cl, detect it as cl, not # clang @@ -771,21 +748,22 @@ class Environment: else: target = 'unknown target' cls = ClangClCCompiler if lang == 'c' else ClangClCPPCompiler - return cls(compiler, version, is_cross, exe_wrap, target) + return cls(compiler, version, for_machine, is_cross, exe_wrap, target) if 'clang' in out: - if 'Apple' in out or mesonlib.for_darwin(self): + if 'Apple' in out or self.machines[for_machine].is_darwin(): compiler_type = CompilerType.CLANG_OSX - elif 'windows' in out or mesonlib.for_windows(self): + elif 'windows' in out or self.machines[for_machine].is_windows(): compiler_type = CompilerType.CLANG_MINGW else: compiler_type = CompilerType.CLANG_STANDARD cls = ClangCCompiler if lang == 'c' else ClangCPPCompiler - return cls(ccache + compiler, version, compiler_type, is_cross, exe_wrap, full_version=full_version) + return cls(ccache + compiler, version, compiler_type, for_machine, is_cross, exe_wrap, full_version=full_version) if 'Intel(R) C++ Intel(R)' in err: version = search_version(err) target = 'x86' if 'IA-32' in err else 'x86_64' cls = IntelClCCompiler if lang == 'c' else IntelClCPPCompiler - return cls(compiler, version, is_cross, exe_wrap, target) + return cls(compiler, version, for_machine, is_cross, exe_wrap, target) + return cls(ccache + compiler, version, compiler_type, for_machine, is_cross, exe_wrap, full_version=full_version) if 'Microsoft' in out or 'Microsoft' in err: # Latest versions of Visual Studio print version # number to stderr but earlier ones print version @@ -804,8 +782,7 @@ class Environment: else: target = 'x86' cls = VisualStudioCCompiler if lang == 'c' else VisualStudioCPPCompiler - return cls(compiler, version, is_cross, exe_wrap, target) - + return cls(compiler, version, for_machine, is_cross, exe_wrap, target) if 'PGI Compilers' in out: if self.machines[for_machine].is_darwin(): compiler_type = CompilerType.PGI_OSX @@ -814,37 +791,37 @@ class Environment: else: compiler_type = CompilerType.PGI_STANDARD cls = PGICCompiler if lang == 'c' else PGICPPCompiler - return cls(ccache + compiler, version, compiler_type, is_cross, exe_wrap) + return cls(ccache + compiler, version, compiler_type, for_machine, is_cross, compiler_type, exe_wrap) if '(ICC)' in out: - if self.machine[for_macine].is_darwin(): + if self.machines[for_machine].is_darwin(): compiler_type = CompilerType.ICC_OSX - elif mesonlib.for_windows(want_cross, self): + elif self.machines[for_machine].is_windows(): # TODO: fix ICC on Windows compiler_type = CompilerType.ICC_WIN else: compiler_type = CompilerType.ICC_STANDARD cls = IntelCCompiler if lang == 'c' else IntelCPPCompiler - return cls(ccache + compiler, version, compiler_type, is_cross, exe_wrap, full_version=full_version) + return cls(ccache + compiler, version, compiler_type, for_machine, is_cross, exe_wrap, full_version=full_version) if 'ARM' in out: compiler_type = CompilerType.ARM_WIN cls = ArmCCompiler if lang == 'c' else ArmCPPCompiler - return cls(ccache + compiler, version, compiler_type, is_cross, exe_wrap, full_version=full_version) + return cls(ccache + compiler, version, compiler_type, for_machine, is_cross, exe_wrap, full_version=full_version) if 'RX Family' in out: compiler_type = CompilerType.CCRX_WIN cls = CcrxCCompiler if lang == 'c' else CcrxCPPCompiler - return cls(ccache + compiler, version, compiler_type, is_cross, exe_wrap, full_version=full_version) + return cls(ccache + compiler, version, compiler_type, for_machine, is_cross, exe_wrap, full_version=full_version) self._handle_exceptions(popen_exceptions, compilers) - def detect_c_compiler(self, want_cross): - return self._detect_c_or_cpp_compiler('c', want_cross) + def detect_c_compiler(self, for_machine): + return self._detect_c_or_cpp_compiler('c', for_machine) - def detect_cpp_compiler(self, want_cross): - return self._detect_c_or_cpp_compiler('cpp', want_cross) + def detect_cpp_compiler(self, for_machine): + return self._detect_c_or_cpp_compiler('cpp', for_machine) - def detect_cuda_compiler(self, want_cross): + def detect_cuda_compiler(self, for_machine): popen_exceptions = {} - compilers, ccache, is_cross, exe_wrap = self._get_compilers('cuda', want_cross) + compilers, ccache, exe_wrap = self._get_compilers('cuda', for_machine) for compiler in compilers: if isinstance(compiler, str): compiler = [compiler] @@ -873,12 +850,13 @@ class Environment: # the full version: version = out.strip().split('V')[-1] cls = CudaCompiler - return cls(ccache + compiler, version, is_cross, exe_wrap) + return cls(ccache + compiler, version, for_machine, exe_wrap) raise EnvironmentException('Could not find suitable CUDA compiler: "' + ' '.join(compilers) + '"') - def detect_fortran_compiler(self, want_cross): + def detect_fortran_compiler(self, for_machine): popen_exceptions = {} - compilers, ccache, is_cross, exe_wrap = self._get_compilers('fortran', want_cross) + compilers, ccache, exe_wrap = self._get_compilers('fortran', for_machine) + is_cross = not self.machines.matches_build_machine(for_machine) for compiler in compilers: if isinstance(compiler, str): compiler = [compiler] @@ -910,14 +888,14 @@ class Environment: else: version = self.get_gnu_version_from_defines(defines) cls = GnuFortranCompiler - return cls(compiler, version, compiler_type, is_cross, exe_wrap, defines, full_version=full_version) + return cls(compiler, version, compiler_type, for_machine, is_cross, exe_wrap, defines, full_version=full_version) if 'G95' in out: - return G95FortranCompiler(compiler, version, is_cross, exe_wrap, full_version=full_version) + return G95FortranCompiler(compiler, version, for_machine, is_cross, exe_wrap, full_version=full_version) if 'Sun Fortran' in err: version = search_version(err) - return SunFortranCompiler(compiler, version, is_cross, exe_wrap, full_version=full_version) + return SunFortranCompiler(compiler, version, for_machine, is_cross, exe_wrap, full_version=full_version) if 'Intel(R) Visual Fortran' in err: version = search_version(err) @@ -925,36 +903,37 @@ class Environment: return IntelClFortranCompiler(compiler, version, is_cross, target, exe_wrap) if 'ifort (IFORT)' in out: - return IntelFortranCompiler(compiler, version, is_cross, exe_wrap, full_version=full_version) + return IntelFortranCompiler(compiler, version, for_machine, is_cross, exe_wrap, full_version=full_version) if 'PathScale EKOPath(tm)' in err: - return PathScaleFortranCompiler(compiler, version, is_cross, exe_wrap, full_version=full_version) + return PathScaleFortranCompiler(compiler, version, for_machine, is_cross, exe_wrap, full_version=full_version) if 'PGI Compilers' in out: - if self.machine[for_macine].is_darwin(): + if self.machine[for_machine].is_darwin(): compiler_type = CompilerType.PGI_OSX elif self.machines[for_machine].is_windows(): compiler_type = CompilerType.PGI_WIN else: compiler_type = CompilerType.PGI_STANDARD - return PGIFortranCompiler(compiler, version, compiler_type, is_cross, exe_wrap, full_version=full_version) + return PGIFortranCompiler(compiler, version, compiler_type, for_machine, is_cross, exe_wrap, full_version=full_version) if 'flang' in out or 'clang' in out: - return FlangFortranCompiler(compiler, version, is_cross, exe_wrap, full_version=full_version) + return FlangFortranCompiler(compiler, version, for_machine, is_cross, exe_wrap, full_version=full_version) if 'Open64 Compiler Suite' in err: - return Open64FortranCompiler(compiler, version, is_cross, exe_wrap, full_version=full_version) + return Open64FortranCompiler(compiler, version, for_machine, is_cross, exe_wrap, full_version=full_version) if 'NAG Fortran' in err: - return NAGFortranCompiler(compiler, version, is_cross, exe_wrap, full_version=full_version) + return NAGFortranCompiler(compiler, version, for_machine, is_cross, exe_wrap, full_version=full_version) self._handle_exceptions(popen_exceptions, compilers) def get_scratch_dir(self): return self.scratch_dir - def detect_objc_compiler(self, want_cross): + def detect_objc_compiler(self, for_machine): popen_exceptions = {} - compilers, ccache, is_cross, exe_wrap = self._get_compilers('objc', want_cross) + compilers, ccache, exe_wrap = self._get_compilers('objc', for_machine) + is_cross = not self.machines.matches_build_machine(for_machine) for compiler in compilers: if isinstance(compiler, str): compiler = [compiler] @@ -972,18 +951,19 @@ class Environment: continue compiler_type = self.get_gnu_compiler_type(defines) version = self.get_gnu_version_from_defines(defines) - return GnuObjCCompiler(ccache + compiler, version, compiler_type, is_cross, exe_wrap, defines) + return GnuObjCCompiler(ccache + compiler, version, compiler_type, for_machine, is_cross, exe_wrap, defines) if out.startswith('Apple LLVM'): - return ClangObjCCompiler(ccache + compiler, version, CompilerType.CLANG_OSX, is_cross, exe_wrap) + return ClangObjCCompiler(ccache + compiler, version, CompilerType.CLANG_OSX, for_machine, is_cross, exe_wrap) if 'windows' in out: - return ClangObjCCompiler(ccache + compiler, version, CompilerType.CLANG_MINGW, is_cross, exe_wrap) + return ClangObjCCompiler(ccache + compiler, version, CompilerType.CLANG_MINGW, for_machine, is_cross, exe_wrap) if out.startswith(('clang', 'OpenBSD clang')): - return ClangObjCCompiler(ccache + compiler, version, CompilerType.CLANG_STANDARD, is_cross, exe_wrap) + return ClangObjCCompiler(ccache + compiler, version, CompilerType.CLANG_STANDARD, for_machine, is_cross, exe_wrap) self._handle_exceptions(popen_exceptions, compilers) - def detect_objcpp_compiler(self, want_cross): + def detect_objcpp_compiler(self, for_machine): popen_exceptions = {} - compilers, ccache, is_cross, exe_wrap = self._get_compilers('objcpp', want_cross) + compilers, ccache, exe_wrap = self._get_compilers('objcpp', for_machine) + is_cross = not self.machines.matches_build_machine(for_machine) for compiler in compilers: if isinstance(compiler, str): compiler = [compiler] @@ -1001,16 +981,16 @@ class Environment: continue compiler_type = self.get_gnu_compiler_type(defines) version = self.get_gnu_version_from_defines(defines) - return GnuObjCPPCompiler(ccache + compiler, version, compiler_type, is_cross, exe_wrap, defines) + return GnuObjCPPCompiler(ccache + compiler, version, compiler_type, for_machine, is_cross, exe_wrap, defines) if out.startswith('Apple LLVM'): - return ClangObjCPPCompiler(ccache + compiler, version, CompilerType.CLANG_OSX, is_cross, exe_wrap) + return ClangObjCPPCompiler(ccache + compiler, version, CompilerType.CLANG_OSX, for_machine, is_cross, exe_wrap) if 'windows' in out: - return ClangObjCPPCompiler(ccache + compiler, version, CompilerType.CLANG_MINGW, is_cross, exe_wrap) + return ClangObjCPPCompiler(ccache + compiler, version, CompilerType.CLANG_MINGW, for_machine, is_cross, exe_wrap) if out.startswith(('clang', 'OpenBSD clang')): - return ClangObjCPPCompiler(ccache + compiler, version, CompilerType.CLANG_STANDARD, is_cross, exe_wrap) + return ClangObjCPPCompiler(ccache + compiler, version, CompilerType.CLANG_STANDARD, for_machine, is_cross, exe_wrap) self._handle_exceptions(popen_exceptions, compilers) - def detect_java_compiler(self): + def detect_java_compiler(self, for_machine): exelist = self.binaries.host.lookup_entry('java') if exelist is None: # TODO support fallback @@ -1026,11 +1006,11 @@ class Environment: parts = (err if 'javac' in err else out).split() if len(parts) > 1: version = parts[1] - return JavaCompiler(exelist, version) + return JavaCompiler(exelist, version, for_machine) raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"') - def detect_cs_compiler(self): - compilers, ccache, is_cross, exe_wrap = self._get_compilers('cs', False) + def detect_cs_compiler(self, for_machine): + compilers, ccache, exe_wrap = self._get_compilers('cs', for_machine) popen_exceptions = {} for comp in compilers: if not isinstance(comp, list): @@ -1043,14 +1023,15 @@ class Environment: version = search_version(out) if 'Mono' in out: - return MonoCompiler(comp, version) + return MonoCompiler(comp, version, for_machine) elif "Visual C#" in out: - return VisualStudioCsCompiler(comp, version) + return VisualStudioCsCompiler(comp, version, for_machine) self._handle_exceptions(popen_exceptions, compilers) - def detect_vala_compiler(self): + def detect_vala_compiler(self, for_machine): exelist = self.binaries.host.lookup_entry('vala') + is_cross = not self.machines.matches_build_machine(for_machine) if exelist is None: # TODO support fallback exelist = [self.default_vala[0]] @@ -1061,12 +1042,13 @@ class Environment: raise EnvironmentException('Could not execute Vala compiler "%s"' % ' '.join(exelist)) version = search_version(out) if 'Vala' in out: - return ValaCompiler(exelist, version) + return ValaCompiler(exelist, version, for_machine, is_cross) raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"') - def detect_rust_compiler(self, want_cross): + def detect_rust_compiler(self, for_machine): popen_exceptions = {} - compilers, ccache, is_cross, exe_wrap = self._get_compilers('rust', want_cross) + compilers, ccache, exe_wrap = self._get_compilers('rust', for_machine) + is_cross = not self.machines.matches_build_machine(for_machine) for compiler in compilers: if isinstance(compiler, str): compiler = [compiler] @@ -1080,13 +1062,12 @@ class Environment: version = search_version(out) if 'rustc' in out: - return RustCompiler(compiler, version, is_cross, exe_wrap) + return RustCompiler(compiler, version, for_machine, is_cross, exe_wrap) self._handle_exceptions(popen_exceptions, compilers) - def detect_d_compiler(self, want_cross): - is_cross = want_cross and self.is_cross_build() - exelist = self.binaries.host.lookup_entry('d') + def detect_d_compiler(self, for_machine: MachineChoice): + exelist = self.binaries[for_machine].lookup_entry('d') # Search for a D compiler. # We prefer LDC over GDC unless overridden with the DC # environment variable because LDC has a much more @@ -1115,22 +1096,23 @@ class Environment: c_compiler = {} is_msvc = mesonlib.is_windows() and 'VCINSTALLDIR' in os.environ if is_msvc: - c_compiler = {'c': self.detect_c_compiler(want_cross)} # MSVC compiler is required for correct platform detection. + c_compiler = {'c': self.detect_c_compiler(for_machine)} # MSVC compiler is required for correct platform detection. arch = detect_cpu_family(c_compiler) if is_msvc and arch == 'x86': arch = 'x86_mscoff' if 'LLVM D compiler' in out: - return compilers.LLVMDCompiler(exelist, version, is_cross, arch, full_version=full_version) + return compilers.LLVMDCompiler(exelist, version, for_machine, arch, full_version=full_version) elif 'gdc' in out: - return compilers.GnuDCompiler(exelist, version, is_cross, arch, full_version=full_version) + return compilers.GnuDCompiler(exelist, version, for_machine, arch, full_version=full_version) elif 'The D Language Foundation' in out or 'Digital Mars' in out: - return compilers.DmdDCompiler(exelist, version, is_cross, arch, full_version=full_version) + return compilers.DmdDCompiler(exelist, version, for_machine, arch, full_version=full_version) raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"') - def detect_swift_compiler(self): + def detect_swift_compiler(self, for_machine): exelist = self.binaries.host.lookup_entry('swift') + is_cross = not self.machines.matches_build_machine(for_machine) if exelist is None: # TODO support fallback exelist = [self.default_swift[0]] @@ -1141,53 +1123,47 @@ class Environment: raise EnvironmentException('Could not execute Swift compiler "%s"' % ' '.join(exelist)) version = search_version(err) if 'Swift' in err: - return compilers.SwiftCompiler(exelist, version) + return compilers.SwiftCompiler(exelist, version, for_machine, is_cross) raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"') - def compiler_from_language(self, lang: str, want_cross: bool): + def compiler_from_language(self, lang: str, for_machine: MachineChoice): if lang == 'c': - comp = self.detect_c_compiler(want_cross) + comp = self.detect_c_compiler(for_machine) elif lang == 'cpp': - comp = self.detect_cpp_compiler(want_cross) + comp = self.detect_cpp_compiler(for_machine) elif lang == 'objc': - comp = self.detect_objc_compiler(want_cross) + comp = self.detect_objc_compiler(for_machine) elif lang == 'cuda': - comp = self.detect_cuda_compiler(want_cross) + comp = self.detect_cuda_compiler(for_machine) elif lang == 'objcpp': - comp = self.detect_objcpp_compiler(want_cross) + comp = self.detect_objcpp_compiler(for_machine) elif lang == 'java': - comp = self.detect_java_compiler() # Java is platform independent. + comp = self.detect_java_compiler(for_machine) elif lang == 'cs': - comp = self.detect_cs_compiler() # C# is platform independent. + comp = self.detect_cs_compiler(for_machine) elif lang == 'vala': - comp = self.detect_vala_compiler() # Vala compiles to platform-independent C + comp = self.detect_vala_compiler(for_machine) elif lang == 'd': - comp = self.detect_d_compiler(want_cross) + comp = self.detect_d_compiler(for_machine) elif lang == 'rust': - comp = self.detect_rust_compiler(want_cross) + comp = self.detect_rust_compiler(for_machine) elif lang == 'fortran': - comp = self.detect_fortran_compiler(want_cross) + comp = self.detect_fortran_compiler(for_machine) elif lang == 'swift': - if want_cross: - raise EnvironmentException('Cross compilation with Swift is not working yet.') - comp = self.detect_swift_compiler() + comp = self.detect_swift_compiler(for_machine) else: comp = None return comp - def detect_compilers(self, lang: str, need_cross_compiler: bool): - comp = self.compiler_from_language(lang, False) - if need_cross_compiler: - cross_comp = self.compiler_from_language(lang, True) - else: - cross_comp = None + def detect_compiler_for(self, lang: str, for_machine: MachineChoice): + comp = self.compiler_from_language(lang, for_machine) if comp is not None: - self.coredata.process_new_compilers(lang, comp, cross_comp, self) - return comp, cross_comp + assert comp.for_machine == for_machine + self.coredata.process_new_compiler(lang, comp, self) + return comp def detect_static_linker(self, compiler): - for_machine = MachineChoice.HOST if compiler.is_cross else MachineChoice.BUILD - linker = self.binaries[for_machine].lookup_entry('ar') + linker = self.binaries[compiler.for_machine].lookup_entry('ar') if linker is not None: linkers = [linker] else: @@ -1255,9 +1231,6 @@ class Environment: def get_build_dir(self): return self.build_dir - def get_exe_suffix(self): - return self.exe_suffix - def get_import_lib_dir(self) -> str: "Install dir for the import library (library used for linking)" return self.get_libdir() @@ -1268,7 +1241,9 @@ class Environment: def get_shared_lib_dir(self) -> str: "Install dir for the shared library" - if self.win_libdir_layout: + m = self.machines.host + # Windows has no RPATH or similar, so DLLs must be next to EXEs. + if m.is_windows() or m.is_cygwin(): return self.get_bindir() return self.get_libdir() @@ -1276,9 +1251,6 @@ class Environment: "Install dir for the static library" return self.get_libdir() - def get_object_suffix(self): - return self.object_suffix - def get_prefix(self) -> str: return self.coredata.get_builtin_option('prefix') @@ -1300,8 +1272,8 @@ class Environment: def get_datadir(self) -> str: return self.coredata.get_builtin_option('datadir') - def get_compiler_system_dirs(self): - for comp in self.coredata.compilers.values(): + def get_compiler_system_dirs(self, for_machine: MachineChoice): + for comp in self.coredata.compilers[for_machine].values(): if isinstance(comp, compilers.ClangCompiler): index = 1 break |