def test_hello_cpp_clangpp(self): scheduler_request_specs = [ # We need GCC to provide libstdc++.so.6, which clang needs to run on Linux. (self.toolchain, GCCCppCompiler), (self.toolchain, LLVMCppCompiler), (self.toolchain, Linker), ] with self._hello_world_source_environment( 'hello.cpp', contents=""" #include <iostream> int main() { std::cout << "I C the world, ++ more!" << std::endl; } """, scheduler_request_specs=scheduler_request_specs) as products: gpp_wrapper, clangpp_wrapper, linker = products gpp = gpp_wrapper.cpp_compiler clangpp = clangpp_wrapper.cpp_compiler # FIXME(#5951): we should be matching the linker to the compiler here, instead of trying to # use the same linker for everything. This is a temporary workaround. linker_with_clangpp_workaround = Linker( path_entries=(clangpp.path_entries + linker.path_entries), exe_filename=clangpp.exe_filename, library_dirs=(gpp.library_dirs + linker.library_dirs + clangpp.library_dirs)) self._do_compile_link(clangpp, linker_with_clangpp_workaround, 'hello.cpp', 'hello_clangpp', "I C the world, ++ more!")
def linker(self, platform): return Linker( path_entries=self.path_entries(), # FIXME(#5951): This actually links correctly for both C and C++ sources -- there should # probably be some testing to ensure this is correct in CI as well. exe_filename='clang++', platform=platform)
def linker(self, platform): return Linker(path_entries=self.path_entries, exe_filename=platform.resolve_platform_specific( self._PLATFORM_SPECIFIC_LINKER_NAME), library_dirs=[], linking_library_dirs=[], extra_args=[])
def linker(self): return Linker( path_entries=self.path_entries(), exe_filename='ld', library_dirs=[], linking_library_dirs=[], extra_args=[])
def linker(self) -> Linker: return Linker( path_entries=self.path_entries(), exe_filename="ld", runtime_library_dirs=(), linking_library_dirs=(), extra_args=(), extra_object_files=(), )
def linker(self): return Linker( path_entries=self.path_entries(), exe_filename='ld', runtime_library_dirs=[], linking_library_dirs=[], extra_args=[MIN_OSX_VERSION_ARG], extra_object_files=[], )
def linker(self, platform: Platform) -> Linker: return Linker( path_entries=self.path_entries, exe_filename=match(platform, { Platform.darwin: "ld64.lld", Platform.linux: "lld", }), runtime_library_dirs=(), linking_library_dirs=(), extra_args=(), extra_object_files=(), )
def linker(self, platform): return Linker( path_entries=self.path_entries, exe_filename=platform.match({ Platform.darwin: "ld64.lld", Platform.linux: "lld", }), library_dirs=[], linking_library_dirs=[], extra_args=[], extra_object_files=[], )
def linker(self, platform): return Linker( path_entries=self.path_entries, exe_filename=platform.resolve_for_enum_variant({ 'darwin': 'ld64.lld', 'linux': 'lld', }), library_dirs=[], linking_library_dirs=[], extra_args=[], extra_object_files=[], )
def select_llvm_c_toolchain(platform, native_toolchain): provided_clang = yield Get(CCompiler, LLVM, native_toolchain._llvm) # These arguments are shared across platforms. llvm_c_compiler_args = [ '-x', 'c', '-std=c11', '-nobuiltininc', ] if platform.normalized_os_name == 'darwin': xcode_clang = yield Get(CCompiler, XCodeCLITools, native_toolchain._xcode_cli_tools) working_c_compiler = CCompiler( path_entries=(provided_clang.path_entries + xcode_clang.path_entries), exe_filename=provided_clang.exe_filename, library_dirs=(provided_clang.library_dirs + xcode_clang.library_dirs), include_dirs=(provided_clang.include_dirs + xcode_clang.include_dirs), extra_args=(llvm_c_compiler_args + xcode_clang.extra_args)) else: gcc_install = yield Get(GCCInstallLocationForLLVM, GCC, native_toolchain._gcc) provided_gcc = yield Get(CCompiler, GCC, native_toolchain._gcc) working_c_compiler = CCompiler( path_entries=provided_clang.path_entries, exe_filename=provided_clang.exe_filename, # We need g++'s version of the GLIBCXX library to be able to run, unfortunately. library_dirs=(provided_gcc.library_dirs + provided_clang.library_dirs), include_dirs=provided_gcc.include_dirs, extra_args=(llvm_c_compiler_args + gcc_install.as_clang_argv)) base_linker_wrapper = yield Get(BaseLinker, NativeToolchain, native_toolchain) base_linker = base_linker_wrapper.linker libc_dev = yield Get(LibcDev, NativeToolchain, native_toolchain) working_linker = Linker( path_entries=(base_linker.path_entries + working_c_compiler.path_entries), exe_filename=working_c_compiler.exe_filename, library_dirs=(base_linker.library_dirs + working_c_compiler.library_dirs), linking_library_dirs=(base_linker.linking_library_dirs + libc_dev.get_libc_dirs(platform)), extra_args=base_linker.extra_args) yield LLVMCToolchain(CToolchain(working_c_compiler, working_linker))
def select_gcc_cpp_toolchain(platform, native_toolchain): provided_gpp = yield Get(CppCompiler, GCC, native_toolchain._gcc) # GCC needs an assembler, so we provide that (platform-specific) tool here. assembler = yield Get(Assembler, NativeToolchain, native_toolchain) if platform.normalized_os_name == 'darwin': # GCC needs access to some headers that are only provided by the XCode toolchain # currently (e.g. "_stdio.h"). These headers are unlikely to change across versions, so this is # probably safe. # TODO: we should be providing all of these (so we can eventually phase out XCodeCLITools # entirely). xcode_clangpp = yield Get(CppCompiler, XCodeCLITools, native_toolchain._xcode_cli_tools) new_include_dirs = xcode_clangpp.include_dirs + provided_gpp.include_dirs else: new_include_dirs = provided_gpp.include_dirs working_cpp_compiler = CppCompiler( path_entries=(provided_gpp.path_entries + assembler.path_entries), exe_filename=provided_gpp.exe_filename, library_dirs=provided_gpp.library_dirs, include_dirs=new_include_dirs, extra_args=([ '-x', 'c++', '-std=c++11', '-nostdinc++', ])) base_linker_wrapper = yield Get(BaseLinker, NativeToolchain, native_toolchain) base_linker = base_linker_wrapper.linker libc_dev = yield Get(LibcDev, NativeToolchain, native_toolchain) working_linker = Linker( path_entries=(working_cpp_compiler.path_entries + base_linker.path_entries), exe_filename=working_cpp_compiler.exe_filename, library_dirs=(base_linker.library_dirs + working_cpp_compiler.library_dirs), linking_library_dirs=(base_linker.linking_library_dirs + libc_dev.get_libc_dirs(platform)), extra_args=base_linker.extra_args) yield GCCCppToolchain(CppToolchain(working_cpp_compiler, working_linker))
def select_linker(platform, native_toolchain): # TODO(#5933): make it possible to yield Get with a non-static # subject type and use `platform.resolve_platform_specific()`, something like: # linker = platform.resolve_platform_specific({ # 'darwin': lambda: Get(Linker, XCodeCLITools, native_toolchain._xcode_cli_tools), # 'linux': lambda: Get(Linker, Binutils, native_toolchain._binutils), # }) if platform.normalized_os_name == 'darwin': # TODO(#5663): turn this into LLVM when lld works. linker = yield Get(Linker, XCodeCLITools, native_toolchain._xcode_cli_tools) libc_dirs = [] else: linker = yield Get(Linker, Binutils, native_toolchain._binutils) libc_dirs = [native_toolchain._libc_dev.host_libc.get_lib_dir()] # NB: We need to link through a provided compiler's frontend, and we need to know where all the # compiler's libraries/etc are, so we set the executable name to the C++ compiler, which can find # its own set of C++-specific files for the linker if necessary. Using e.g. 'g++' as the linker # appears to produce byte-identical output when linking even C-only object files, and also # happens to work when C++ is used. gcc_c_compiler = yield Get(GCCCCompiler, NativeToolchain, native_toolchain) c_compiler = gcc_c_compiler.c_compiler gcc_cpp_compiler = yield Get(GCCCppCompiler, NativeToolchain, native_toolchain) cpp_compiler = gcc_cpp_compiler.cpp_compiler # NB: If needing to create an environment for process invocation that could use either a compiler # or a linker (e.g. when we compile native code from `python_dist()`s), use the environment from # the linker object (in addition to any further customizations), which has the paths from the C # and C++ compilers baked in. # FIXME(#5951): we need a way to compose executables more hygienically. linker = Linker( path_entries=(c_compiler.path_entries + cpp_compiler.path_entries + linker.path_entries), exe_filename=cpp_compiler.exe_filename, library_dirs=(libc_dirs + c_compiler.library_dirs + cpp_compiler.library_dirs + linker.library_dirs)) yield linker
def select_llvm_cpp_toolchain(platform, native_toolchain): provided_clangpp = yield Get(CppCompiler, LLVM, native_toolchain._llvm) # These arguments are shared across platforms. llvm_cpp_compiler_args = [ '-x', 'c++', '-std=c++11', # This mean we don't use any of the headers from our LLVM distribution's C++ stdlib # implementation, or any from the host system. Instead, we use include dirs from the # XCodeCLITools or GCC. '-nobuiltininc', '-nostdinc++', ] if platform.normalized_os_name == 'darwin': xcode_clang = yield Get(CppCompiler, XCodeCLITools, native_toolchain._xcode_cli_tools) working_cpp_compiler = CppCompiler( path_entries=(provided_clangpp.path_entries + xcode_clang.path_entries), exe_filename=provided_clangpp.exe_filename, library_dirs=(provided_clangpp.library_dirs + xcode_clang.library_dirs), include_dirs=(provided_clangpp.include_dirs + xcode_clang.include_dirs), # On OSX, this uses the libc++ (LLVM) C++ standard library implementation. This is # feature-complete for OSX, but not for Linux (see https://libcxx.llvm.org/ for more info). extra_args=(llvm_cpp_compiler_args + xcode_clang.extra_args)) linking_library_dirs = [] linker_extra_args = [] else: gcc_install = yield Get(GCCInstallLocationForLLVM, GCC, native_toolchain._gcc) provided_gpp = yield Get(CppCompiler, GCC, native_toolchain._gcc) working_cpp_compiler = CppCompiler( path_entries=provided_clangpp.path_entries, exe_filename=provided_clangpp.exe_filename, # We need g++'s version of the GLIBCXX library to be able to run, unfortunately. library_dirs=(provided_gpp.library_dirs + provided_clangpp.library_dirs), # NB: we use g++'s headers on Linux, and therefore their C++ standard library. include_dirs=provided_gpp.include_dirs, extra_args=(llvm_cpp_compiler_args + gcc_install.as_clang_argv)) linking_library_dirs = provided_gpp.library_dirs + provided_clangpp.library_dirs # Ensure we use libstdc++, provided by g++, during the linking stage. linker_extra_args = ['-stdlib=libstdc++'] libc_dev = yield Get(LibcDev, NativeToolchain, native_toolchain) base_linker_wrapper = yield Get(BaseLinker, NativeToolchain, native_toolchain) base_linker = base_linker_wrapper.linker working_linker = Linker( path_entries=(base_linker.path_entries + working_cpp_compiler.path_entries), exe_filename=working_cpp_compiler.exe_filename, library_dirs=(base_linker.library_dirs + working_cpp_compiler.library_dirs), linking_library_dirs=(base_linker.linking_library_dirs + linking_library_dirs + libc_dev.get_libc_dirs(platform)), extra_args=(base_linker.extra_args + linker_extra_args)) yield LLVMCppToolchain(CppToolchain(working_cpp_compiler, working_linker))
def linker(self, platform): return Linker(path_entries=self.path_entries(), exe_filename='ld', platform=platform)
def linker(self, platform): return Linker(path_entries=self.path_entries(), exe_filename=platform.resolve_platform_specific( self._PLATFORM_SPECIFIC_LINKER_NAME), platform=platform)