diff --git a/lld/CMakeLists.txt b/lld/CMakeLists.txt index 80e25204a65ee..619ff352a5165 100644 --- a/lld/CMakeLists.txt +++ b/lld/CMakeLists.txt @@ -177,6 +177,18 @@ if (LLD_DEFAULT_LD_LLD_IS_MINGW) add_definitions("-DLLD_DEFAULT_LD_LLD_IS_MINGW=1") endif() +set(LLD_ALL_LINKERS "COFF;ELF;MachO;MinGW;Wasm") +set(LLD_LINKERS_TO_BUILD "all" CACHE STRING + "Semicolon-separated list of linker flavors to build (${LLD_ALL_LINKERS}), or \"all\".") +if(LLD_LINKERS_TO_BUILD STREQUAL "all") + set(LLD_LINKERS_TO_BUILD ${LLD_ALL_LINKERS}) +endif() + +# Validate: MinGW depends on COFF +if("MinGW" IN_LIST LLD_LINKERS_TO_BUILD AND NOT "COFF" IN_LIST LLD_LINKERS_TO_BUILD) + message(FATAL_ERROR "LLD MinGW linker requires COFF. Add COFF to LLD_LINKERS_TO_BUILD.") +endif() + if (MSVC) add_definitions(-wd4530) # Suppress 'warning C4530: C++ exception handler used, but unwind semantics are not enabled.' add_definitions(-wd4062) # Suppress 'warning C4062: enumerator X in switch of enum Y is not handled' from system header. @@ -187,6 +199,12 @@ include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}/include ) +# Propagate enabled flavors to C++ via compile definitions (used in lld.cpp). +foreach(linker ${LLD_LINKERS_TO_BUILD}) + string(TOUPPER ${linker} upper) + add_definitions(-DLLD_ENABLE_${upper}=1) +endforeach() + add_subdirectory(Common) add_subdirectory(tools/lld) @@ -200,11 +218,15 @@ if (LLVM_INCLUDE_TESTS) endif() add_subdirectory(docs) -add_subdirectory(COFF) -add_subdirectory(ELF) -add_subdirectory(MachO) -add_subdirectory(MinGW) -add_subdirectory(wasm) + +# Add subdirectories for enabled linker flavors. +foreach(linker ${LLD_LINKERS_TO_BUILD}) + if(linker STREQUAL "Wasm") + add_subdirectory(wasm) + else() + add_subdirectory(${linker}) + endif() +endforeach() add_custom_target(lld-headers) set_target_properties(lld-headers PROPERTIES FOLDER "Misc") diff --git a/lld/tools/lld/CMakeLists.txt b/lld/tools/lld/CMakeLists.txt index 8498a91597a93..8d2c30e11a6b4 100644 --- a/lld/tools/lld/CMakeLists.txt +++ b/lld/tools/lld/CMakeLists.txt @@ -24,19 +24,39 @@ function(lld_target_link_libraries target type) target_link_libraries(${target} ${type} ${ARGN}) endfunction() -lld_target_link_libraries(lld - PRIVATE - lldCommon - lldCOFF - lldELF - lldMachO - lldMinGW - lldWasm - ) +set(LLD_FLAVOR_LIBS lldCommon) +if("COFF" IN_LIST LLD_LINKERS_TO_BUILD) + list(APPEND LLD_FLAVOR_LIBS lldCOFF) +endif() +if("ELF" IN_LIST LLD_LINKERS_TO_BUILD) + list(APPEND LLD_FLAVOR_LIBS lldELF) +endif() +if("MachO" IN_LIST LLD_LINKERS_TO_BUILD) + list(APPEND LLD_FLAVOR_LIBS lldMachO) +endif() +if("MinGW" IN_LIST LLD_LINKERS_TO_BUILD) + list(APPEND LLD_FLAVOR_LIBS lldMinGW) +endif() +if("Wasm" IN_LIST LLD_LINKERS_TO_BUILD) + list(APPEND LLD_FLAVOR_LIBS lldWasm) +endif() + +lld_target_link_libraries(lld PRIVATE ${LLD_FLAVOR_LIBS}) if(NOT LLD_SYMLINKS_TO_CREATE) - set(LLD_SYMLINKS_TO_CREATE - lld-link ld.lld ld64.lld wasm-ld) + set(LLD_SYMLINKS_TO_CREATE "") + if("COFF" IN_LIST LLD_LINKERS_TO_BUILD) + list(APPEND LLD_SYMLINKS_TO_CREATE lld-link) + endif() + if("ELF" IN_LIST LLD_LINKERS_TO_BUILD) + list(APPEND LLD_SYMLINKS_TO_CREATE ld.lld) + endif() + if("MachO" IN_LIST LLD_LINKERS_TO_BUILD) + list(APPEND LLD_SYMLINKS_TO_CREATE ld64.lld) + endif() + if("Wasm" IN_LIST LLD_LINKERS_TO_BUILD) + list(APPEND LLD_SYMLINKS_TO_CREATE wasm-ld) + endif() endif() foreach(link ${LLD_SYMLINKS_TO_CREATE}) diff --git a/lld/tools/lld/lld.cpp b/lld/tools/lld/lld.cpp index d6800fa1eea4b..f5df8a543316e 100644 --- a/lld/tools/lld/lld.cpp +++ b/lld/tools/lld/lld.cpp @@ -66,11 +66,39 @@ static unsigned inTestVerbosity() { return v; } +#ifdef LLD_ENABLE_COFF LLD_HAS_DRIVER(coff) +#endif +#ifdef LLD_ENABLE_ELF LLD_HAS_DRIVER(elf) +#endif +#ifdef LLD_ENABLE_MINGW LLD_HAS_DRIVER(mingw) +#endif +#ifdef LLD_ENABLE_MACHO LLD_HAS_DRIVER(macho) +#endif +#ifdef LLD_ENABLE_WASM LLD_HAS_DRIVER(wasm) +#endif + +static constexpr DriverDef enabledDrivers[] = { +#ifdef LLD_ENABLE_COFF + {lld::WinLink, &lld::coff::link}, +#endif +#ifdef LLD_ENABLE_ELF + {lld::Gnu, &lld::elf::link}, +#endif +#ifdef LLD_ENABLE_MINGW + {lld::MinGW, &lld::mingw::link}, +#endif +#ifdef LLD_ENABLE_MACHO + {lld::Darwin, &lld::macho::link}, +#endif +#ifdef LLD_ENABLE_WASM + {lld::Wasm, &lld::wasm::link}, +#endif +}; int lld_main(int argc, char **argv, const llvm::ToolContext &) { sys::Process::UseANSIEscapeCodes(true); @@ -87,7 +115,7 @@ int lld_main(int argc, char **argv, const llvm::ToolContext &) { // exception handling and no memory cleanup on exit. if (!inTestVerbosity()) { int r = - lld::unsafeLldMain(args, llvm::outs(), llvm::errs(), LLD_ALL_DRIVERS, + lld::unsafeLldMain(args, llvm::outs(), llvm::errs(), enabledDrivers, /*exitEarly=*/true); return r; } @@ -100,7 +128,7 @@ int lld_main(int argc, char **argv, const llvm::ToolContext &) { inTestOutputDisabled = (i != 1); // Execute one iteration. - auto r = lldMain(args, llvm::outs(), llvm::errs(), LLD_ALL_DRIVERS); + auto r = lldMain(args, llvm::outs(), llvm::errs(), enabledDrivers); if (!r.canRunAgain) exitLld(r.retCode); // Exit now, can't re-execute again.