From 863e8b910fcbd999469198fd047004f29af1e8a5 Mon Sep 17 00:00:00 2001 From: Dhruv Menon Date: Thu, 3 Sep 2026 01:29:36 +0530 Subject: [PATCH 1/7] [CMake] Use keyword form of target_link_libraries after llvm_add_library LLVM 22's llvm_add_library already uses PRIVATE/PUBLIC. Mixing that with the plain signature fails CMake. Use PRIVATE on LayoutMap and the TargetInfo libraries. Signed-off-by: Dhruv Menon --- CMakeLists.txt | 12 ++++++++++++ lib/LayoutMap/CMakeLists.txt | 12 ++++++------ lib/LinkerWrapper/CMakeLists.txt | 5 ++++- lib/Target/AArch64/TargetInfo/CMakeLists.txt | 2 +- lib/Target/ARM/TargetInfo/CMakeLists.txt | 2 +- lib/Target/Hexagon/TargetInfo/CMakeLists.txt | 2 +- lib/Target/RISCV/TargetInfo/CMakeLists.txt | 2 +- lib/Target/X86/TargetInfo/CMakeLists.txt | 2 +- test/UnitTests/CMakeLists.txt | 10 ++++++++++ test/UnitTests/LTOPreserveListTests/CMakeLists.txt | 6 +++++- test/UnitTests/StaticResolverTests/CMakeLists.txt | 6 +++++- test/UnitTests/SymbolResolutionTests/CMakeLists.txt | 6 +++++- 12 files changed, 52 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 53ccf1ca60..a555bd18e1 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -255,6 +255,18 @@ else() link_directories("${PATH_TO_LLVM_BUILD}/lib") endif() +# Apple ld does not search Homebrew's prefix for short -l names. LLVMSupport +# records zstd as LLVM_SYSTEM_LIBS ("zstd" → -lzstd). In-tree Darwin builds +# then fail linking libLW with "ld: library 'zstd' not found" even when +# /opt/homebrew/lib/libzstd.dylib is already on the same link line. +if(APPLE) + foreach(_eld_brew_lib IN ITEMS /opt/homebrew/lib /usr/local/lib) + if(EXISTS "${_eld_brew_lib}") + link_directories("${_eld_brew_lib}") + endif() + endforeach() +endif() + add_subdirectory(include) # After the driver option TableGen targets are created diff --git a/lib/LayoutMap/CMakeLists.txt b/lib/LayoutMap/CMakeLists.txt index 9dd4d64047..f96e031f14 100644 --- a/lib/LayoutMap/CMakeLists.txt +++ b/lib/LayoutMap/CMakeLists.txt @@ -3,9 +3,9 @@ llvm_add_library(ELDLayout STATIC LayoutInfo.cpp target_link_libraries( ELDLayout - ELDConfig - ELDFragment - ELDSupport - ELDDiagnostics - ELDTarget - ELDSymbolResolver) + PRIVATE ELDConfig + ELDFragment + ELDSupport + ELDDiagnostics + ELDTarget + ELDSymbolResolver) diff --git a/lib/LinkerWrapper/CMakeLists.txt b/lib/LinkerWrapper/CMakeLists.txt index f210bbe78e..5e50091b77 100644 --- a/lib/LinkerWrapper/CMakeLists.txt +++ b/lib/LinkerWrapper/CMakeLists.txt @@ -99,7 +99,10 @@ if(ELD_ON_UNIX) set_target_properties( LW PROPERTIES SOVERSION ${LINKER_PLUGIN_API_MAJOR_VERSION} VERSION ${LINKER_PLUGIN_API_MAJOR_VERSION}) - add_no_version_symbol_exports(LW ${CMAKE_CURRENT_SOURCE_DIR}/LW.exports) + # GNU ld version scripts are not supported by Apple ld64. + if(NOT APPLE) + add_no_version_symbol_exports(LW ${CMAKE_CURRENT_SOURCE_DIR}/LW.exports) + endif() endif(ELD_ON_UNIX) # Add each target as part of the link step. diff --git a/lib/Target/AArch64/TargetInfo/CMakeLists.txt b/lib/Target/AArch64/TargetInfo/CMakeLists.txt index 2c660e69e2..72db12202e 100644 --- a/lib/Target/AArch64/TargetInfo/CMakeLists.txt +++ b/lib/Target/AArch64/TargetInfo/CMakeLists.txt @@ -1,3 +1,3 @@ llvm_add_library(ELDAArch64TargetInfo STATIC AArch64TargetInfo.cpp) -target_link_libraries(ELDAArch64TargetInfo LLVMAArch64AsmParser +target_link_libraries(ELDAArch64TargetInfo PRIVATE LLVMAArch64AsmParser LLVMAArch64CodeGen) diff --git a/lib/Target/ARM/TargetInfo/CMakeLists.txt b/lib/Target/ARM/TargetInfo/CMakeLists.txt index 062f8bb347..bd2e9010b4 100644 --- a/lib/Target/ARM/TargetInfo/CMakeLists.txt +++ b/lib/Target/ARM/TargetInfo/CMakeLists.txt @@ -1,2 +1,2 @@ llvm_add_library(ELDARMTargetInfo STATIC ARMTargetInfo.cpp) -target_link_libraries(ELDARMTargetInfo LLVMARMAsmParser LLVMARMCodeGen) +target_link_libraries(ELDARMTargetInfo PRIVATE LLVMARMAsmParser LLVMARMCodeGen) diff --git a/lib/Target/Hexagon/TargetInfo/CMakeLists.txt b/lib/Target/Hexagon/TargetInfo/CMakeLists.txt index 5b01a0f3c5..fc9b15bc72 100644 --- a/lib/Target/Hexagon/TargetInfo/CMakeLists.txt +++ b/lib/Target/Hexagon/TargetInfo/CMakeLists.txt @@ -1,3 +1,3 @@ llvm_add_library(ELDHexagonTargetInfo STATIC HexagonTargetInfo.cpp) -target_link_libraries(ELDHexagonTargetInfo LLVMHexagonAsmParser +target_link_libraries(ELDHexagonTargetInfo PRIVATE LLVMHexagonAsmParser LLVMHexagonCodeGen) diff --git a/lib/Target/RISCV/TargetInfo/CMakeLists.txt b/lib/Target/RISCV/TargetInfo/CMakeLists.txt index 66a87381f8..c618772ce1 100644 --- a/lib/Target/RISCV/TargetInfo/CMakeLists.txt +++ b/lib/Target/RISCV/TargetInfo/CMakeLists.txt @@ -1,2 +1,2 @@ llvm_add_library(ELDRISCVTargetInfo STATIC RISCVTargetInfo.cpp) -target_link_libraries(ELDRISCVTargetInfo LLVMRISCVAsmParser LLVMRISCVCodeGen) +target_link_libraries(ELDRISCVTargetInfo PRIVATE LLVMRISCVAsmParser LLVMRISCVCodeGen) diff --git a/lib/Target/X86/TargetInfo/CMakeLists.txt b/lib/Target/X86/TargetInfo/CMakeLists.txt index 6c8a7ec4c0..731ff611c8 100644 --- a/lib/Target/X86/TargetInfo/CMakeLists.txt +++ b/lib/Target/X86/TargetInfo/CMakeLists.txt @@ -1,2 +1,2 @@ llvm_add_library(ELDx86_64TargetInfo STATIC x86_64TargetInfo.cpp) -target_link_libraries(ELDx86_64TargetInfo LLVMX86AsmParser LLVMX86CodeGen) +target_link_libraries(ELDx86_64TargetInfo PRIVATE LLVMX86AsmParser LLVMX86CodeGen) diff --git a/test/UnitTests/CMakeLists.txt b/test/UnitTests/CMakeLists.txt index 3475497a70..a90b506b8c 100644 --- a/test/UnitTests/CMakeLists.txt +++ b/test/UnitTests/CMakeLists.txt @@ -13,6 +13,16 @@ set(LLVM_LINK_COMPONENTS Target TargetParser) +# libLW.dylib already contains a static copy of LLVM. On Darwin there is no +# version script to hide those symbols (see LW.exports), so also linking +# LLVM_LINK_COMPONENTS into unit tests that load LW registers cl::opt twice +# ("Option 'basic' already exists"). Restrict the extra LLVM .a files; tests +# that link LW resolve LLVM from the dylib. SampleTests / INIWriterTests do +# not load LW and only need Support via llvm_gtest. +if(APPLE) + set(LLVM_LINK_COMPONENTS Support) +endif() + add_custom_target(ELDUnitTests) set_target_properties(ELDUnitTests PROPERTIES FOLDER "eld unit tests") get_property( diff --git a/test/UnitTests/LTOPreserveListTests/CMakeLists.txt b/test/UnitTests/LTOPreserveListTests/CMakeLists.txt index 13cc1b55b8..f7157d095c 100644 --- a/test/UnitTests/LTOPreserveListTests/CMakeLists.txt +++ b/test/UnitTests/LTOPreserveListTests/CMakeLists.txt @@ -1,5 +1,9 @@ add_eld_unittest(LTOPreserveListTests LTOPreserveListTest.cpp) +set(_lto_lib) +if(NOT APPLE) + set(_lto_lib LLVMLTO) +endif() target_link_libraries( LTOPreserveListTests PRIVATE ELDCore @@ -7,5 +11,5 @@ target_link_libraries( ELDSymbolResolver ELDTarget ELDObject - LLVMLTO + ${_lto_lib} LW) diff --git a/test/UnitTests/StaticResolverTests/CMakeLists.txt b/test/UnitTests/StaticResolverTests/CMakeLists.txt index 7106dc5753..3b4bd35932 100644 --- a/test/UnitTests/StaticResolverTests/CMakeLists.txt +++ b/test/UnitTests/StaticResolverTests/CMakeLists.txt @@ -1,5 +1,9 @@ add_eld_unittest(StaticResolverTests StaticResolverTest.cpp) +set(_lto_lib) +if(NOT APPLE) + set(_lto_lib LLVMLTO) +endif() target_link_libraries( StaticResolverTests PRIVATE ELDCore @@ -7,6 +11,6 @@ target_link_libraries( ELDSymbolResolver ELDTarget ELDObject - LLVMLTO + ${_lto_lib} LW ${system_libs}) diff --git a/test/UnitTests/SymbolResolutionTests/CMakeLists.txt b/test/UnitTests/SymbolResolutionTests/CMakeLists.txt index 8dc69e8061..c7728fb4df 100644 --- a/test/UnitTests/SymbolResolutionTests/CMakeLists.txt +++ b/test/UnitTests/SymbolResolutionTests/CMakeLists.txt @@ -8,6 +8,10 @@ endif() add_eld_unittest(SymbolResolutionTests ${SYMBOL_RESOLUTION_TEST_SOURCES} PARTIAL_SOURCES_INTENDED) +set(_lto_lib) +if(NOT APPLE) + set(_lto_lib LLVMLTO) +endif() target_link_libraries( SymbolResolutionTests PRIVATE ELDCore @@ -15,5 +19,5 @@ target_link_libraries( ELDSymbolResolver ELDTarget ELDObject - LLVMLTO + ${_lto_lib} LW) From c5b761acedde74fd2f4ab6ffaa27666b8b64569a Mon Sep 17 00:00:00 2001 From: Dhruv Menon Date: Thu, 3 Sep 2026 01:29:37 +0530 Subject: [PATCH 2/7] [Support] Add Darwin host support for building and running ld.eld Unix Path.inc no longer includes unused Linux-only linux/nfs.h. Plugin libraries use .dylib, Mach-O-safe plugin metadata, and DYLD_LIBRARY_PATH / @loader_path search. CMake sets ELD_ON_APPLE, @loader_path rpath, bin/lib output dirs, and skips GNU version scripts on Apple ld64. Signed-off-by: Dhruv Menon --- CMakeLists.txt | 43 +++++++++++++------ .../modules/AddNoVersionedSymbolExports.cmake | 40 +++++++++-------- configure_external_llvm.sh | 10 ++++- include/eld/Config/Config.h.cmake | 2 + include/eld/PluginAPI/LinkerWrapper.h | 3 +- include/eld/PluginAPI/PluginBase.h.inc | 5 +++ lib/Input/SearchDirs.cpp | 19 +++++++- lib/Support/DynamicLibrary.cpp | 2 + lib/Support/Unix/Path.inc | 1 - 9 files changed, 90 insertions(+), 35 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a555bd18e1..b4cbb54234 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -171,37 +171,56 @@ configure_file(${ELD_SOURCE_DIR}/include/eld/Config/Targets.def.cmake ${ELD_BINARY_DIR}/include/eld/Config/Targets.def) # Platform detection +set(ELD_ON_WIN32 0) +set(ELD_ON_UNIX 0) +set(ELD_ON_MSVC 0) +set(ELD_ON_APPLE 0) + if(WIN32) if(CYGWIN) - set(ELD_ON_WIN32 0) set(ELD_ON_UNIX 1) else() set(ELD_ON_WIN32 1) - set(ELD_ON_UNIX 0) + set(ELD_ON_MSVC 1) endif() +elseif(APPLE) + set(ELD_ON_UNIX 1) + set(ELD_ON_APPLE 1) +elseif(UNIX) + set(ELD_ON_UNIX 1) else() - if(UNIX) - set(ELD_ON_WIN32 0) - set(ELD_ON_UNIX 1) - else() - message(SEND_ERROR "Unable to determine platform") - endif() + message(SEND_ERROR "Unable to determine platform") endif() -if(NOT WIN32) - set(ELD_ON_MSVC 0) +if(ELD_ON_APPLE) + info("Setting up build of ELD for Darwin") +elseif(ELD_ON_UNIX) info("Setting up build of ELD for Unix") else() - set(ELD_ON_MSVC 1) info("Setting up build of ELD for Windows") endif() -if(UNIX) +# $ORIGIN is ELF-specific; Mach-O uses @loader_path / @rpath. +if(APPLE) + set(CMAKE_MACOSX_RPATH ON) + set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) + set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) + set(CMAKE_INSTALL_RPATH "@loader_path/../lib") +elseif(UNIX) set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) set(CMAKE_INSTALL_RPATH "\$ORIGIN/../lib") endif() +# Match LLVM's bin/lib layout so $ORIGIN / @loader_path/../lib resolves in the +# build tree as well as after install. Integrated LLVM builds already set these. +if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") +endif() +if(NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY) + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") +endif() + # Configure header files configure_file(${ELD_SOURCE_DIR}/include/eld/Config/Config.h.cmake ${ELD_BINARY_DIR}/include/eld/Config/Config.h) diff --git a/cmake/modules/AddNoVersionedSymbolExports.cmake b/cmake/modules/AddNoVersionedSymbolExports.cmake index a90d8ce422..4ddcc274f7 100644 --- a/cmake/modules/AddNoVersionedSymbolExports.cmake +++ b/cmake/modules/AddNoVersionedSymbolExports.cmake @@ -1,28 +1,32 @@ # Handy function to export symbols without versioning function(add_no_version_symbol_exports target_name export_file) - if(LLVM_HAVE_LINK_VERSION_SCRIPT) - # Gold and BFD ld require a version script rather than a plain list. - set(native_export_file "${target_name}.exports") - add_custom_command( - OUTPUT ${native_export_file} - COMMAND echo "{" > ${native_export_file} - COMMAND grep -q "[[:alnum:]]" ${export_file} && echo " global:" >> - ${native_export_file} || : - COMMAND sed -e "s/$/;/" -e "s/^/ /" < ${export_file} >> - ${native_export_file} - COMMAND echo " local: *;" >> ${native_export_file} - COMMAND echo "};" >> ${native_export_file} - DEPENDS ${export_file} - VERBATIM - COMMENT "Creating export file for ${target_name}") - set_property( + # GNU version scripts are not supported by Apple ld64 (or linkers that + # do not set LLVM_HAVE_LINK_VERSION_SCRIPT). + if(NOT LLVM_HAVE_LINK_VERSION_SCRIPT) + return() + endif() + + # Gold and BFD ld require a version script rather than a plain list. + set(native_export_file "${target_name}.exports") + add_custom_command( + OUTPUT ${native_export_file} + COMMAND echo "{" > ${native_export_file} + COMMAND grep -q "[[:alnum:]]" ${export_file} && echo " global:" >> + ${native_export_file} || : + COMMAND sed -e "s/$/;/" -e "s/^/ /" < ${export_file} >> + ${native_export_file} + COMMAND echo " local: *;" >> ${native_export_file} + COMMAND echo "};" >> ${native_export_file} + DEPENDS ${export_file} + VERBATIM + COMMENT "Creating export file for ${target_name}") + set_property( TARGET ${target_name} APPEND_STRING PROPERTY LINK_FLAGS " -Wl,--version-script,\"${CMAKE_CURRENT_BINARY_DIR}/${native_export_file}\"" - ) - endif() + ) add_custom_target(${target_name}_exports DEPENDS ${native_export_file}) set_target_properties(${target_name}_exports PROPERTIES FOLDER "Misc") diff --git a/configure_external_llvm.sh b/configure_external_llvm.sh index 5cdb64fc54..dd6799c7ed 100755 --- a/configure_external_llvm.sh +++ b/configure_external_llvm.sh @@ -165,6 +165,14 @@ fi # Create build directory (already created during canonicalization) cd "${BUILD_DIR}" +# LLD is the default Linux linker for this script. Apple ld64 is used on +# Darwin unless the caller passes -DLLVM_ENABLE_LLD=ON. +if [[ "$(uname -s)" == "Darwin" ]]; then + LINKER_CMAKE_ARGS=(-DLLVM_ENABLE_LLD:BOOL=OFF) +else + LINKER_CMAKE_ARGS=(-DLLVM_ENABLE_LLD:BOOL=ON) +fi + # Configure with CMake cmake -G Ninja \ -DCMAKE_BUILD_TYPE=Release \ @@ -172,7 +180,7 @@ cmake -G Ninja \ -DCMAKE_CXX_COMPILER="${EXTERNAL_LLVM_ROOT}/bin/clang++" \ -DCMAKE_CXX_FLAGS="-stdlib=libc++" \ -DLLVM_DIR="${EXTERNAL_LLVM_CMAKE}" \ - -DLLVM_ENABLE_LLD:BOOL=ON \ + "${LINKER_CMAKE_ARGS[@]}" \ -DELD_USE_EXTERNAL_LLVM=ON \ -DELD_TARGETS_TO_BUILD="Hexagon;AArch64;ARM;RISCV;X86" \ -DLLVM_TABLEGEN_EXE="${EXTERNAL_LLVM_ROOT}/bin/llvm-tblgen" \ diff --git a/include/eld/Config/Config.h.cmake b/include/eld/Config/Config.h.cmake index 7802b783ca..179c9ecf78 100644 --- a/include/eld/Config/Config.h.cmake +++ b/include/eld/Config/Config.h.cmake @@ -19,6 +19,8 @@ #cmakedefine ELD_ON_MSVC "${ELD_ON_MSVC}" +#cmakedefine ELD_ON_APPLE "${ELD_ON_APPLE}" + #define RPATH "${CMAKE_INSTALL_RPATH}" #define LINKER_ALT_NAME "${USE_LINKER_ALT_NAME}" diff --git a/include/eld/PluginAPI/LinkerWrapper.h b/include/eld/PluginAPI/LinkerWrapper.h index 1d63e481c7..cacf452b08 100644 --- a/include/eld/PluginAPI/LinkerWrapper.h +++ b/include/eld/PluginAPI/LinkerWrapper.h @@ -765,7 +765,8 @@ class DLL_A_EXPORT LinkerWrapper { /// Return a handle to the library `LibraryName` or an error. /// `LibraryName` will be searched using the linker search path /// including -L directories. First the file called `LibraryName` will be - /// searched. If it is not found, `libLibraryName.so` or `libraryName.dll` on + /// searched. If it is not found, `libLibraryName.so` (Linux), + /// `libLibraryName.dylib` (macOS), or `libraryName.dll` on /// windows will be searched. If neither are found an error is returned. eld::Expected loadLibrary(const std::string &LibraryName); diff --git a/include/eld/PluginAPI/PluginBase.h.inc b/include/eld/PluginAPI/PluginBase.h.inc index b2e3ee7534..a46a19c046 100644 --- a/include/eld/PluginAPI/PluginBase.h.inc +++ b/include/eld/PluginAPI/PluginBase.h.inc @@ -35,6 +35,11 @@ class LinkerWrapper; #ifdef _WIN32 #pragma comment(user, "Plugin built with tools @LLVM_VENDOR_VERSION@") +#elif defined(__APPLE__) +__attribute__(( + used, + section("__DATA,__eld_plugin"))) static const char eld_plugin_built_with[] = + "Plugin built with tools @LLVM_VENDOR_VERSION@"; #else __asm__(".section .comment, \"MS\",@progbits,1\n\t" ".string \"Plugin built with tools @LLVM_VENDOR_VERSION@\""); diff --git a/lib/Input/SearchDirs.cpp b/lib/Input/SearchDirs.cpp index 7c06f2bb3e..8837f2e6e8 100644 --- a/lib/Input/SearchDirs.cpp +++ b/lib/Input/SearchDirs.cpp @@ -249,6 +249,10 @@ const eld::sys::fs::Path *SearchDirs::findInRPath(llvm::StringRef Type, std::string CRPath = R.str(); eld::string::ReplaceString(CRPath, "$ORIGIN", SearchDirs::MainExecutablePath); + eld::string::ReplaceString(CRPath, "@loader_path", + SearchDirs::MainExecutablePath); + eld::string::ReplaceString(CRPath, "@executable_path", + SearchDirs::MainExecutablePath); const std::string FileName = CRPath + "/" + LibraryName.str(); if (checkLibraryOrConfigFile(Type, LibraryName, FileName, "rpath", DiagEngine)) @@ -285,10 +289,21 @@ SearchDirs::findInPath(llvm::StringRef Type, return nullptr; PathSplit = eld::string::split(*Path, ';'); #else + std::string Combined; +#ifdef __APPLE__ + Path = llvm::sys::Process::GetEnv("DYLD_LIBRARY_PATH"); + if (Path && !Path->empty()) + Combined = *Path; +#endif Path = llvm::sys::Process::GetEnv("LD_LIBRARY_PATH"); - if (!Path) + if (Path && !Path->empty()) { + if (!Combined.empty()) + Combined += ":"; + Combined += *Path; + } + if (Combined.empty()) return nullptr; - PathSplit = eld::string::split(*Path, ':'); + PathSplit = eld::string::split(Combined, ':'); #endif for (auto R : PathSplit) { const std::string FileName = R + "/" + LibraryName.str(); diff --git a/lib/Support/DynamicLibrary.cpp b/lib/Support/DynamicLibrary.cpp index 54f4a9ceca..2415addcca 100644 --- a/lib/Support/DynamicLibrary.cpp +++ b/lib/Support/DynamicLibrary.cpp @@ -19,6 +19,8 @@ namespace DynamicLibrary { std::string getLibraryName(std::string Name) { #ifdef ELD_ON_MSVC return llvm::Twine(Name + ".dll").str(); +#elif defined(__APPLE__) + return llvm::Twine("lib" + Name + ".dylib").str(); #else return llvm::Twine("lib" + Name + ".so").str(); #endif diff --git a/lib/Support/Unix/Path.inc b/lib/Support/Unix/Path.inc index eff31faf84..72a1e30340 100644 --- a/lib/Support/Unix/Path.inc +++ b/lib/Support/Unix/Path.inc @@ -6,7 +6,6 @@ #include #include -#include std::string Path::getFullPath(const std::string &Path) { char ResolvedPath[PATH_MAX + 1]; From 3b65f1325527f6f1b299017bbcf936668d62b4c6 Mon Sep 17 00:00:00 2001 From: Dhruv Menon Date: Thu, 3 Sep 2026 01:29:37 +0530 Subject: [PATCH 3/7] [lit] Recognize Darwin as a test host Add darwin/arm-darwin/aarch64-darwin features, python3, BSD tar, and DYLD_LIBRARY_PATH. Allow plugin FileCheck to match .dylib as well as .so/.dll. Signed-off-by: Dhruv Menon --- .github/workflows/ci-macos.yml | 169 ++++++++++++++++++ .../ErrorOutAtCreatingSections.test | 2 +- test/Common/Plugin/GetUses/GetUses.test | 6 +- .../Plugin/GetUsesSymbols/GetUsesSymbols.test | 6 +- .../MatchIslandSections.test | 6 +- ...SectionsAndGetSymbolsDefinedInSection.test | 6 +- .../Plugin/NullFileSize/NullFileSize.test | 6 +- .../LinkerWrapperCommentSectionTest.test | 3 +- .../DynamicGOTPLT/DynamicGOTPLT_AArch64.test | 23 +-- .../DynamicGOTPLT/DynamicGOTPLT_ARM.test | 21 ++- .../DynamicGOTPLT/DynamicGOTPLT_Hexagon.test | 22 +-- .../DynamicGOTPLT/DynamicGOTPLT_RISCV32.test | 21 ++- .../DynamicGOTPLT/DynamicGOTPLT_RISCV64.test | 22 +-- .../ExplicitOutputSectionDataReproduce.test | 2 +- .../EmptyArchiveFile/EmptyArchiveFile.test | 2 +- test/Hexagon/Plugin/FileSize/FileSize.test | 6 +- .../MatchAndDiscardSections.test | 6 +- .../MatchSectionsAndGetRawData.test | 6 +- .../Plugin/SignalHandling/SignalHandling.test | 1 - test/UnitTests/lit.cfg | 10 +- test/lit.cfg | 47 ++++- .../DefaultImageBase/DefaultImageBase.test | 2 +- .../DynamicDataCall/DynamicDataCall.test | 2 +- .../EmulationSupport/EmulationOption.test | 2 +- .../TlsGDnonpreemptible.test | 2 +- .../TlsGDpreemptible/TlsGDpreemptible.test | 2 +- test/x86_64/linux/TlsIEModel/TlsIEModel.test | 2 +- test/x86_64/linux/TlsLDModel/TlsLDModel.test | 2 +- test/x86_64/linux/relocCOPY/relocCOPY.test | 2 +- .../linux/relocGOTPCREL/relocGOTPCREL.test | 2 +- .../linux/relocIRELATIVE/relocIRELATIVE.test | 2 +- .../relocPLT32Static/relocPLT32Static.test | 2 +- .../relocPLT32dynamic/relocPLT32dynamic.test | 2 +- 33 files changed, 311 insertions(+), 106 deletions(-) create mode 100644 .github/workflows/ci-macos.yml diff --git a/.github/workflows/ci-macos.yml b/.github/workflows/ci-macos.yml new file mode 100644 index 0000000000..656c0f1b6b --- /dev/null +++ b/.github/workflows/ci-macos.yml @@ -0,0 +1,169 @@ +name: macOS CI + +# GitHub-hosted Darwin host build of ld.eld (ELF linker, not a Mach-O target). + +on: + pull_request: + types: [opened, synchronize, reopened] + paths-ignore: + - '.github/workflows/sanitize.yml' + - '.github/workflows/reviter.yml' + - '.github/workflows/docs.yaml' + - '.github/workflows/docs-multiversion.yaml' + - '.github/workflows/ci.yml' + - '.github/workflows/ci-win.yml' + - '.github/workflows/clang-cross-schedule.yml' + - '.github/workflows/DownloadClangCrossToolchain/action.yaml' + - '.github/workflows/DownloadLatestBusybox/action.yaml' + - '.github/workflows/busybox.yml' + - '.github/workflows/linux-kernel-nightly.yml' + - '.github/workflows/linux-kernel-run.yml' + - '.github/workflows/linux-kernel-pr.yml' + - '.github/workflows/nightly-musl-builder.yml' + - '.github/workflows/picolibc-builder.yml' + - '.github/workflows/nightly-test.yml' + - '.github/workflows/update-build-dashboard-data.yml' + - '.github/workflows/scripts/record_builds.py' + - '.github/workflows/BuildStatusDataRecorder/action.yaml' + - '.github/workflows/clang-format-pr.yml' + - '.github/workflows/cpp-linter-pr.yml' + - 'etc/**/*.sh' + workflow_dispatch: {} + +permissions: + contents: read + +jobs: + build-macos: + name: macOS + runs-on: macos-latest + timeout-minutes: 180 + concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }} + cancel-in-progress: true + env: + BASE_BRANCH_NAME: ${{ github.event.pull_request.base.ref || 'main' }} + ELD_REPO: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name || github.repository }} + ELD_REF: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || github.ref_name }} + CCACHE_DIR: ${{ github.workspace }}/obj/ccache + CCACHE_BASEDIR: ${{ github.workspace }} + CCACHE_COMPILERCHECK: content + CCACHE_NOHASHDIR: true + + steps: + - name: Set up Python + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 #v7.0.0 + with: + python-version: '3.14' + + - name: Install build tools + env: + HOMEBREW_NO_AUTO_UPDATE: 1 + HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1 + run: | + command -v ninja >/dev/null || brew install ninja + command -v ccache >/dev/null || brew install ccache + python3 -m pip install pyyaml + echo "cmake $(cmake --version | head -n1)" + echo "ninja $(ninja --version)" + echo "ccache $(ccache --version | head -n1)" + echo "clang $(clang --version | head -n1)" + echo "python $(python3 --version) from $(which python3)" + sysctl hw.ncpu hw.physicalcpu hw.memsize || true + df -h . + + - name: Checkout llvm-project + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + repository: llvm/llvm-project + ref: ${{ env.BASE_BRANCH_NAME }} + path: llvm-project + fetch-depth: 1 + + - name: Checkout ELD + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + repository: ${{ env.ELD_REPO }} + ref: ${{ env.ELD_REF }} + path: llvm-project/llvm/tools/eld + fetch-depth: 0 + + - name: Check for non-doc changes + id: file-check + if: github.event_name == 'pull_request' + uses: ./llvm-project/llvm/tools/eld/.github/workflows/CheckNonDocChanges + with: + base-branch: ${{ env.BASE_BRANCH_NAME }} + base-sha: ${{ github.event.pull_request.base.sha }} + + - name: Restore ccache + if: github.event_name != 'pull_request' || steps.file-check.outputs.skip_build == 'false' + uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 #v6.1.0 + with: + path: ${{ github.workspace }}/obj/ccache + key: macos-eld-ccache-${{ runner.arch }}-${{ github.run_id }} + restore-keys: | + macos-eld-ccache-${{ runner.arch }}- + + - name: Configure CMake + if: github.event_name != 'pull_request' || steps.file-check.outputs.skip_build == 'false' + working-directory: ${{ github.workspace }} + run: | + set -euo pipefail + test -f llvm-project/cmake/Modules/CMakePolicy.cmake + test -d llvm-project/clang + test -d llvm-project/third-party/unittest + test -d llvm-project/llvm/tools/eld + mkdir -p "$CCACHE_DIR" obj + ccache --zero-stats || true + cmake -G Ninja -S llvm-project/llvm -B obj \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON \ + -DLLVM_ENABLE_PROJECTS="clang" \ + -DLLVM_ENABLE_ASSERTIONS:BOOL=ON \ + -DLLVM_ENABLE_LLD:BOOL=OFF \ + -DLLVM_TARGETS_TO_BUILD="ARM;AArch64;RISCV;Hexagon;X86" \ + -DELD_TARGETS_TO_BUILD='ARM;AArch64;RISCV;Hexagon;X86;Template' \ + -DCMAKE_C_COMPILER="$(xcrun --find clang)" \ + -DCMAKE_CXX_COMPILER="$(xcrun --find clang++)" \ + -DCMAKE_CXX_FLAGS="-stdlib=libc++" \ + -DLLVM_PARALLEL_LINK_JOBS=1 \ + -DLLVM_CCACHE_BUILD:BOOL=ON \ + -DLLVM_CCACHE_DIR:STRING="$CCACHE_DIR" \ + -DELD_ENABLE_SYMBOL_VERSIONING=ON + + - name: Build + if: github.event_name != 'pull_request' || steps.file-check.outputs.skip_build == 'false' + working-directory: ${{ github.workspace }}/obj + # Full tree so lit finds opt and other LLVM tools. `ninja ld.eld clang` + # leaves those missing, and the set of tools tests need can grow. + run: ninja + + - name: Cache usage after build + if: github.event_name != 'pull_request' || steps.file-check.outputs.skip_build == 'false' + run: ccache --show-stats --dir="$CCACHE_DIR" || true + + - name: Run tests + if: github.event_name != 'pull_request' || steps.file-check.outputs.skip_build == 'false' + working-directory: ${{ github.workspace }}/obj + run: ninja check-eld + + - name: Summarize test results + if: github.event_name != 'pull_request' || steps.file-check.outputs.skip_build == 'false' + working-directory: ${{ github.workspace }}/obj + run: ninja check-eld-summary + + - name: Prune ccache before save + if: always() && (github.event_name != 'pull_request' || steps.file-check.outputs.skip_build == 'false') + run: ccache --evict-older-than 7200s --dir="$CCACHE_DIR" || true + + - name: Save ccache + if: always() && (github.event_name != 'pull_request' || steps.file-check.outputs.skip_build == 'false') + uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 #v6.1.0 + with: + path: ${{ github.workspace }}/obj/ccache + key: macos-eld-ccache-${{ runner.arch }}-${{ github.run_id }} + + - name: Clean up + if: always() + run: rm -rf llvm-project obj diff --git a/test/Common/Plugin/ErrorOutAtCreatingSections/ErrorOutAtCreatingSections.test b/test/Common/Plugin/ErrorOutAtCreatingSections/ErrorOutAtCreatingSections.test index 6d8db8a863..4a65d1bb9e 100644 --- a/test/Common/Plugin/ErrorOutAtCreatingSections/ErrorOutAtCreatingSections.test +++ b/test/Common/Plugin/ErrorOutAtCreatingSections/ErrorOutAtCreatingSections.test @@ -11,7 +11,7 @@ RUN: --plugin-config %p/Inputs/PluginConfig.yaml -Map %t1.1.map.txt 2>&1 | %fi RUN: %filecheck --check-prefix=MAP %s < %t1.1.map.txt #END_TEST -CHECK: Error: Plugin ErrorOutAtCreatingSections defined in library {{(lib)?ErrorOutAtCreatingSections\.(so|dll)}} returned error Error! in state CreatingSections +CHECK: Error: Plugin ErrorOutAtCreatingSections defined in library {{(lib)?ErrorOutAtCreatingSections\.(so|dll|dylib)}} returned error Error! in state CreatingSections CHECK-NOT: Referenced Chunk {{.*}} MAP: # Output Section and Layout diff --git a/test/Common/Plugin/GetUses/GetUses.test b/test/Common/Plugin/GetUses/GetUses.test index adf669e87b..0cd87c28e0 100644 --- a/test/Common/Plugin/GetUses/GetUses.test +++ b/test/Common/Plugin/GetUses/GetUses.test @@ -7,10 +7,10 @@ RUN: %clang %clangopts -c %p/Inputs/1.c -o %t1.1.o -ffunction-sections RUN: %link %linkopts %t1.1.o -T %p/Inputs/script.t --trace=plugin -o %t2.out 2>&1 | %filecheck %s -check-prefix=PLUGINTRACE -#PLUGINTRACE: Note: Registration function found RegisterAll in Library {{.*}}{{[.sodll]}} -#PLUGINTRACE: Note: Plugin handler getPlugin found in Library {{.*}}{{[.sodll]}} +#PLUGINTRACE: Note: Registration function found RegisterAll in Library {{.*}}{{(so|dll|dylib)}} +#PLUGINTRACE: Note: Plugin handler getPlugin found in Library {{.*}}{{(so|dll|dylib)}} #PLUGINTRACE: Note: Registering all plugin handlers for plugin types -#PLUGINTRACE: Note: Found plugin handler for plugin type FINDUSES in Library {{.*}}{{[.sodll]}} +#PLUGINTRACE: Note: Found plugin handler for plugin type FINDUSES in Library {{.*}}{{(so|dll|dylib)}} #PLUGINTRACE: Uses for section .text #PLUGINTRACE: Uses for section .text.foo #PLUGINTRACE: Uses for section .text.bar diff --git a/test/Common/Plugin/GetUsesSymbols/GetUsesSymbols.test b/test/Common/Plugin/GetUsesSymbols/GetUsesSymbols.test index b95eca8162..cd7efec822 100644 --- a/test/Common/Plugin/GetUsesSymbols/GetUsesSymbols.test +++ b/test/Common/Plugin/GetUsesSymbols/GetUsesSymbols.test @@ -7,10 +7,10 @@ RUN: %clang %clangopts -c %p/Inputs/1.c -o %t1.1.o -ffunction-sections RUN: %link %linkopts %t1.1.o -T %p/Inputs/script.t --trace=plugin -o %t2.out 2>&1 | %filecheck %s -check-prefix=PLUGINTRACE -#PLUGINTRACE: Note: Registration function found RegisterAll in Library {{.*}}{{[.sodll]}} -#PLUGINTRACE: Note: Plugin handler getPlugin found in Library {{.*}}{{[.sodll]}} +#PLUGINTRACE: Note: Registration function found RegisterAll in Library {{.*}}{{(so|dll|dylib)}} +#PLUGINTRACE: Note: Plugin handler getPlugin found in Library {{.*}}{{(so|dll|dylib)}} #PLUGINTRACE: Note: Registering all plugin handlers for plugin types -#PLUGINTRACE: Note: Found plugin handler for plugin type FINDUSES in Library {{.*}}{{[.sodll]}} +#PLUGINTRACE: Note: Found plugin handler for plugin type FINDUSES in Library {{.*}}{{(so|dll|dylib)}} #PLUGINTRACE: Uses for section .text #PLUGINTRACE: References(Symbols) from section .text #PLUGINTRACE: Uses for section .text.foo diff --git a/test/Common/Plugin/MatchIslandSections/MatchIslandSections.test b/test/Common/Plugin/MatchIslandSections/MatchIslandSections.test index a86eb0565e..6b0241a8f9 100644 --- a/test/Common/Plugin/MatchIslandSections/MatchIslandSections.test +++ b/test/Common/Plugin/MatchIslandSections/MatchIslandSections.test @@ -10,10 +10,10 @@ RUN: %link %linkopts %t1.1.o --plugin-config %p/Inputs/plugin.config --trace=plu RUN: %not %link %linkopts %t1.1.o --plugin-config %p/Inputs/fail.config --trace=plugin -o %t2.out.2 2>&1 | %filecheck %s -check-prefix=NOTREGISTERED RUN: %not %link %linkopts %t1.1.o --plugin-config %p/Inputs/doesnotexit.config --trace=plugin -o %t2.out.2 2>&1 | %filecheck %s -#PLUGINTRACE: Note: Registration function found RegisterAll in Library {{.*}}{{[.sodll]}} -#PLUGINTRACE: Note: Plugin handler getPlugin found in Library {{.*}}{{[.sodll]}} +#PLUGINTRACE: Note: Registration function found RegisterAll in Library {{.*}}{{(so|dll|dylib)}} +#PLUGINTRACE: Note: Plugin handler getPlugin found in Library {{.*}}{{(so|dll|dylib)}} #PLUGINTRACE: Note: Registering all plugin handlers for plugin types -#PLUGINTRACE: Note: Found plugin handler for plugin type MATCHANDFINDUSES in Library {{.*}}{{[.sodll]}} +#PLUGINTRACE: Note: Found plugin handler for plugin type MATCHANDFINDUSES in Library {{.*}}{{(so|dll|dylib)}} #PLUGINTRACE: Uses for section .text.island_baz #PLUGINTRACE: .text.foo #PLUGINTRACE: .text.bar diff --git a/test/Common/Plugin/MatchIslandSectionsAndGetSymbolsDefinedInSection/MatchIslandSectionsAndGetSymbolsDefinedInSection.test b/test/Common/Plugin/MatchIslandSectionsAndGetSymbolsDefinedInSection/MatchIslandSectionsAndGetSymbolsDefinedInSection.test index 3de0cb751a..7ebdc26f60 100644 --- a/test/Common/Plugin/MatchIslandSectionsAndGetSymbolsDefinedInSection/MatchIslandSectionsAndGetSymbolsDefinedInSection.test +++ b/test/Common/Plugin/MatchIslandSectionsAndGetSymbolsDefinedInSection/MatchIslandSectionsAndGetSymbolsDefinedInSection.test @@ -9,10 +9,10 @@ RUN: %clang %clangopts -c %p/Inputs/1.c -o %t1.1.o -ffunction-sections %clangg0o RUN: %link %linkopts %t1.1.o -T %p/Inputs/script.t --trace=plugin -o %t2.out \ RUN: 2>&1 | %filecheck %s -check-prefix=PLUGINTRACE -#PLUGINTRACE-DAG: Note: Registration function found RegisterAll in Library {{.*}}{{[.sodll]}} -#PLUGINTRACE-DAG: Note: Plugin handler getPlugin found in Library {{.*}}{{[.sodll]}} +#PLUGINTRACE-DAG: Note: Registration function found RegisterAll in Library {{.*}}{{(so|dll|dylib)}} +#PLUGINTRACE-DAG: Note: Plugin handler getPlugin found in Library {{.*}}{{(so|dll|dylib)}} #PLUGINTRACE-DAG: Note: Registering all plugin handlers for plugin types -#PLUGINTRACE-DAG: Note: Found plugin handler for plugin type MATCHFINDUSESANDGETSYMBOLS in Library {{.*}}{{[.sodll]}} +#PLUGINTRACE-DAG: Note: Found plugin handler for plugin type MATCHFINDUSESANDGETSYMBOLS in Library {{.*}}{{(so|dll|dylib)}} #PLUGINTRACE-DAG: Symbols defined in section .text.island_baz #PLUGINTRACE-DAG: foo #PLUGINTRACE-DAG: bar diff --git a/test/Common/Plugin/NullFileSize/NullFileSize.test b/test/Common/Plugin/NullFileSize/NullFileSize.test index fded8329f5..224b8a548c 100644 --- a/test/Common/Plugin/NullFileSize/NullFileSize.test +++ b/test/Common/Plugin/NullFileSize/NullFileSize.test @@ -10,10 +10,10 @@ RUN: %clang %clangopts -c %p/Inputs/1.c -o %t1.1.o -ffunction-sections RUN: %link %linkopts %t1.1.o -T %p/Inputs/script.t --trace=plugin -o %t2.out 2>&1 | %filecheck %s -check-prefix=PLUGINTRACE RUN: %readelf -S -W %t2.out | %filecheck %s -#PLUGINTRACE: Note: Registration function found RegisterAll in Library {{.*}}{{[.sodll]}} -#PLUGINTRACE: Note: Plugin handler getPlugin found in Library {{.*}}{{[.sodll]}} +#PLUGINTRACE: Note: Registration function found RegisterAll in Library {{.*}}{{(so|dll|dylib)}} +#PLUGINTRACE: Note: Plugin handler getPlugin found in Library {{.*}}{{(so|dll|dylib)}} #PLUGINTRACE: Note: Registering all plugin handlers for plugin types -#PLUGINTRACE: Note: Found plugin handler for plugin type NULLBLOCKS in Library {{.*}}{{[.sodll]}} +#PLUGINTRACE: Note: Found plugin handler for plugin type NULLBLOCKS in Library {{.*}}{{(so|dll|dylib)}} #PLUGINTRACE: Note: Creating MemoryBlock sized {{.*}} for output section .foo #PLUGINTRACE: Note: Applying relocations for section .foo #PLUGINTRACE: Note: Syncing relocations for section .foo diff --git a/test/Common/libTest/LinkerWrapperCommentSectionTest/LinkerWrapperCommentSectionTest.test b/test/Common/libTest/LinkerWrapperCommentSectionTest/LinkerWrapperCommentSectionTest.test index 5263e9207f..fdf1c91e9d 100644 --- a/test/Common/libTest/LinkerWrapperCommentSectionTest/LinkerWrapperCommentSectionTest.test +++ b/test/Common/libTest/LinkerWrapperCommentSectionTest/LinkerWrapperCommentSectionTest.test @@ -1,4 +1,5 @@ -#UNSUPPORTED: windows +#UNSUPPORTED: windows, darwin +# Mach-O libLW has no ELF .comment section. #---LinkerWrapperCommentSectionTest.test--------------------------- Executable -----------------# #BEGIN_COMMENT diff --git a/test/Common/standalone/DynamicGOTPLT/DynamicGOTPLT_AArch64.test b/test/Common/standalone/DynamicGOTPLT/DynamicGOTPLT_AArch64.test index a7b9e75082..b0c134e7a1 100644 --- a/test/Common/standalone/DynamicGOTPLT/DynamicGOTPLT_AArch64.test +++ b/test/Common/standalone/DynamicGOTPLT/DynamicGOTPLT_AArch64.test @@ -11,28 +11,29 @@ RUN: %clang %clangopts -c %p/Inputs/1.c -fPIC -o %t.1.o RUN: %link %linkopts -shared %t.1.o -o %t.so RUN: %clang %clangopts -c %p/Inputs/2.c -fPIC -o %t.2.o -## Case 2: GOTPLT is in the beginning of the .got.plt section +## Case 1: GOTPLT is in the beginning of the .got.plt section RUN: %link %linkopts %t.2.o %t.so -o %t.out -T %p/Inputs/script.t -RUN: %readelf -S --dynamic %t.out >%t.out.txt -RUN: %objcopy -O binary --only-section=.got.plt %t.out - | od -v -Ax -w64 -t x8 >>%t.out.txt -RUN: %filecheck %s --input-file=%t.out.txt +RUN: %readelf -S --dynamic -x .got.plt %t.out | %filecheck %s CHECK: Section Headers: -CHECK-DAG: [{{[ 0-9]+}}] .plt PROGBITS [[PLT:[[:xdigit:]]+]] {{[[:xdigit:]]+}} +CHECK-DAG: [{{[ 0-9]+}}] .plt PROGBITS {{[[:xdigit:]]+}} {{[[:xdigit:]]+}} CHECK-DAG: [{{[ 0-9]+}}] .got.plt PROGBITS {{0*}}70000 {{[[:xdigit:]]+}} CHECK: Dynamic section at CHECK: 0x{{[[:xdigit:]]+}} (PLTGOT) 0x70000 -CHECK: {{0*}}0 {{0*}}0 {{0*}}0 [[PLT]] +CHECK: Hex dump of section '.got.plt': +CHECK-NEXT: 0x{{0*}}70000 00000000 00000000 00000000 00000000 +CHECK-NEXT: 0x{{0*}}70010 00000000 00000000 {{[[:xdigit:]]+}} 00000000 ## Case 2: GOTPLT is not in the beginning of the .got.plt section RUN: %link %linkopts %t.2.o %t.so -o %t-got.out -T %p/Inputs/script-gap.t -RUN: %readelf -S --dynamic -x .got.plt %t-got.out >%t-gap.out.txt -RUN: %objcopy -O binary --only-section=.got %t-got.out - | od -v -Ax -w64 -t x8 >>%t-gap.out.txt -RUN: %filecheck %s --input-file=%t-gap.out.txt --check-prefix=GAP +RUN: %readelf -S --dynamic -x .got %t-got.out | %filecheck %s --check-prefix=GAP GAP: Section Headers: -GAP-DAG: [{{[ 0-9]+}}] .plt PROGBITS [[PLT:[[:xdigit:]]+]] {{[[:xdigit:]]+}} +GAP-DAG: [{{[ 0-9]+}}] .plt PROGBITS {{[[:xdigit:]]+}} {{[[:xdigit:]]+}} GAP-DAG: [{{[ 0-9]+}}] .got PROGBITS {{0*}}90000 {{[[:xdigit:]]+}} GAP: Dynamic section at GAP: 0x{{[[:xdigit:]]+}} (PLTGOT) 0x90008 -GAP: {{0*}}0 {{0*}}deadc00c {{0*}}0 {{0*}}0 {{0*}}0 [[PLT]] +GAP: Hex dump of section '.got': +GAP-NEXT: 0x{{0*}}90000 0cc0adde 00000000 00000000 00000000 +GAP-NEXT: 0x{{0*}}90010 00000000 00000000 00000000 00000000 +GAP-NEXT: 0x{{0*}}90020 {{[[:xdigit:]]+}} 00000000 diff --git a/test/Common/standalone/DynamicGOTPLT/DynamicGOTPLT_ARM.test b/test/Common/standalone/DynamicGOTPLT/DynamicGOTPLT_ARM.test index cd9186d0fe..95771fdb47 100644 --- a/test/Common/standalone/DynamicGOTPLT/DynamicGOTPLT_ARM.test +++ b/test/Common/standalone/DynamicGOTPLT/DynamicGOTPLT_ARM.test @@ -11,28 +11,27 @@ RUN: %clang %clangopts -c %p/Inputs/1.c -fPIC -o %t.1.o RUN: %link %linkopts -shared %t.1.o -o %t.so RUN: %clang %clangopts -c %p/Inputs/2.c -fPIC -o %t.2.o -## Case 2: GOTPLT is in the beginning of the .got.plt section +## Case 1: GOTPLT is in the beginning of the .got.plt section RUN: %link %linkopts %t.2.o %t.so -o %t.out -T %p/Inputs/script.t -RUN: %readelf -S --dynamic %t.out >%t.out.txt -RUN: %objcopy -O binary --only-section=.got.plt %t.out - | od -v -Ax -w64 -t x4 >>%t.out.txt -RUN: %filecheck %s --input-file=%t.out.txt +RUN: %readelf -S --dynamic -x .got.plt %t.out | %filecheck %s CHECK: Section Headers: -CHECK-DAG: [{{[ 0-9]+}}] .plt PROGBITS [[PLT:[[:xdigit:]]+]] {{[[:xdigit:]]+}} +CHECK-DAG: [{{[ 0-9]+}}] .plt PROGBITS {{[[:xdigit:]]+}} {{[[:xdigit:]]+}} CHECK-DAG: [{{[ 0-9]+}}] .got.plt PROGBITS {{0*}}70000 {{[[:xdigit:]]+}} CHECK: Dynamic section at CHECK: 0x{{[[:xdigit:]]+}} (PLTGOT) 0x70000 -CHECK: {{0*}}0 {{0*}}0 {{0*}}0 [[PLT]] +CHECK: Hex dump of section '.got.plt': +CHECK-NEXT: 0x{{0*}}70000 00000000 00000000 00000000 {{[[:xdigit:]]+}} ## Case 2: GOTPLT is not in the beginning of the .got.plt section RUN: %link %linkopts %t.2.o %t.so -o %t-got.out -T %p/Inputs/script-gap.t -RUN: %readelf -S --dynamic -x .got.plt %t-got.out >%t-gap.out.txt -RUN: %objcopy -O binary --only-section=.got %t-got.out - | od -v -Ax -w64 -t x4 >>%t-gap.out.txt -RUN: %filecheck %s --input-file=%t-gap.out.txt --check-prefix=GAP +RUN: %readelf -S --dynamic -x .got %t-got.out | %filecheck %s --check-prefix=GAP GAP: Section Headers: -GAP-DAG: [{{[ 0-9]+}}] .plt PROGBITS [[PLT:[[:xdigit:]]+]] {{[[:xdigit:]]+}} +GAP-DAG: [{{[ 0-9]+}}] .plt PROGBITS {{[[:xdigit:]]+}} {{[[:xdigit:]]+}} GAP-DAG: [{{[ 0-9]+}}] .got PROGBITS {{0*}}90000 {{[[:xdigit:]]+}} GAP: Dynamic section at GAP: 0x{{[[:xdigit:]]+}} (PLTGOT) 0x90008 -GAP: {{0*}}0 deadc00c {{0*}}0 {{0*}}0 {{0*}}0 {{0*}}0 [[PLT]] +GAP: Hex dump of section '.got': +GAP-NEXT: 0x{{0*}}90000 0cc0adde 00000000 00000000 00000000 +GAP-NEXT: 0x{{0*}}90010 00000000 {{[[:xdigit:]]+}} diff --git a/test/Common/standalone/DynamicGOTPLT/DynamicGOTPLT_Hexagon.test b/test/Common/standalone/DynamicGOTPLT/DynamicGOTPLT_Hexagon.test index e0f4477950..4147ce8fc7 100644 --- a/test/Common/standalone/DynamicGOTPLT/DynamicGOTPLT_Hexagon.test +++ b/test/Common/standalone/DynamicGOTPLT/DynamicGOTPLT_Hexagon.test @@ -11,28 +11,28 @@ RUN: %clang %clangopts -c %p/Inputs/1.c -fPIC -o %t.1.o RUN: %link %linkopts -shared %t.1.o -o %t.so RUN: %clang %clangopts -c %p/Inputs/2.c -fPIC -o %t.2.o -## Case 2: GOTPLT is in the beginning of the .got.plt section +## Case 1: GOTPLT is in the beginning of the .got.plt section RUN: %link %linkopts -Bdynamic %t.2.o %t.so -o %t.out -T %p/Inputs/script.t -RUN: %readelf -S --dynamic %t.out >%t.out.txt -RUN: %objcopy -O binary --only-section=.got.plt %t.out - | od -v -Ax -w64 -t x4 >>%t.out.txt -RUN: %filecheck %s --input-file=%t.out.txt +RUN: %readelf -S --dynamic -x .got.plt %t.out | %filecheck %s CHECK: Section Headers: -CHECK-DAG: [{{[ 0-9]+}}] .plt PROGBITS [[PLT:[[:xdigit:]]+]] {{[[:xdigit:]]+}} +CHECK-DAG: [{{[ 0-9]+}}] .plt PROGBITS {{[[:xdigit:]]+}} {{[[:xdigit:]]+}} CHECK-DAG: [{{[ 0-9]+}}] .got.plt PROGBITS {{0*}}70000 {{[[:xdigit:]]+}} CHECK: Dynamic section at CHECK: 0x{{[[:xdigit:]]+}} (PLTGOT) 0x70000 -CHECK: {{0*}}0 {{0*}}0 {{0*}}0 [[PLT]] +CHECK: Hex dump of section '.got.plt': +CHECK-NEXT: 0x{{0*}}70000 00000000 00000000 00000000 00000000 +CHECK-NEXT: 0x{{0*}}70010 {{[[:xdigit:]]+}} ## Case 2: GOTPLT is not in the beginning of the .got.plt section RUN: %link %linkopts -Bdynamic %t.2.o %t.so -o %t-got.out -T %p/Inputs/script-gap.t -RUN: %readelf -S --dynamic -x .got.plt %t-got.out >%t-gap.out.txt -RUN: %objcopy -O binary --only-section=.got %t-got.out - | od -v -Ax -w64 -t x4 >>%t-gap.out.txt -RUN: %filecheck %s --input-file=%t-gap.out.txt --check-prefix=GAP +RUN: %readelf -S --dynamic -x .got %t-got.out | %filecheck %s --check-prefix=GAP GAP: Section Headers: -GAP-DAG: [{{[ 0-9]+}}] .plt PROGBITS [[PLT:[[:xdigit:]]+]] {{[[:xdigit:]]+}} +GAP-DAG: [{{[ 0-9]+}}] .plt PROGBITS {{[[:xdigit:]]+}} {{[[:xdigit:]]+}} GAP-DAG: [{{[ 0-9]+}}] .got PROGBITS {{0*}}90000 {{[[:xdigit:]]+}} GAP: Dynamic section at GAP: 0x{{[[:xdigit:]]+}} (PLTGOT) 0x90008 -GAP: {{0*}}0 deadc00c {{0*}}0 {{0*}}0 {{0*}}0 {{0*}}0 {{0*}}0 [[PLT]] +GAP: Hex dump of section '.got': +GAP-NEXT: 0x{{0*}}90000 0cc0adde 00000000 00000000 00000000 +GAP-NEXT: 0x{{0*}}90010 00000000 00000000 {{[[:xdigit:]]+}} diff --git a/test/Common/standalone/DynamicGOTPLT/DynamicGOTPLT_RISCV32.test b/test/Common/standalone/DynamicGOTPLT/DynamicGOTPLT_RISCV32.test index c3e1558f41..e585b9b7d5 100644 --- a/test/Common/standalone/DynamicGOTPLT/DynamicGOTPLT_RISCV32.test +++ b/test/Common/standalone/DynamicGOTPLT/DynamicGOTPLT_RISCV32.test @@ -11,28 +11,27 @@ RUN: %clang %clangopts -c %p/Inputs/1.c -fPIC -o %t.1.o RUN: %link %linkopts -shared %t.1.o -o %t.so RUN: %clang %clangopts -c %p/Inputs/2.c -fPIC -o %t.2.o -## Case 2: GOTPLT is in the beginning of the .got.plt section +## Case 1: GOTPLT is in the beginning of the .got.plt section RUN: %link %linkopts %t.2.o %t.so -o %t.out -T %p/Inputs/script.t -RUN: %readelf -S --dynamic %t.out >%t.out.txt -RUN: %objcopy -O binary --only-section=.got.plt %t.out - | od -v -Ax -w64 -t x4 >>%t.out.txt -RUN: %filecheck %s --input-file=%t.out.txt +RUN: %readelf -S --dynamic -x .got.plt %t.out | %filecheck %s CHECK: Section Headers: -CHECK-DAG: [{{[ 0-9]+}}] .plt PROGBITS [[PLT:[[:xdigit:]]+]] {{[[:xdigit:]]+}} +CHECK-DAG: [{{[ 0-9]+}}] .plt PROGBITS {{[[:xdigit:]]+}} {{[[:xdigit:]]+}} CHECK-DAG: [{{[ 0-9]+}}] .got.plt PROGBITS {{0*}}70000 {{[[:xdigit:]]+}} CHECK: Dynamic section at CHECK: 0x{{[[:xdigit:]]+}} (PLTGOT) 0x70000 -CHECK: {{0*}}0 {{0*}}0 {{0*}}0 [[PLT]] +CHECK: Hex dump of section '.got.plt': +CHECK-NEXT: 0x{{0*}}70000 00000000 00000000 {{[[:xdigit:]]+}} ## Case 2: GOTPLT is not in the beginning of the .got.plt section RUN: %link %linkopts %t.2.o %t.so -o %t-got.out -T %p/Inputs/script-gap.t -RUN: %readelf -S --dynamic -x .got.plt %t-got.out >%t-gap.out.txt -RUN: %objcopy -O binary --only-section=.got %t-got.out - | od -v -Ax -w64 -t x4 >>%t-gap.out.txt -RUN: %filecheck %s --input-file=%t-gap.out.txt --check-prefix=GAP +RUN: %readelf -S --dynamic -x .got %t-got.out | %filecheck %s --check-prefix=GAP GAP: Section Headers: -GAP-DAG: [{{[ 0-9]+}}] .plt PROGBITS [[PLT:[[:xdigit:]]+]] {{[[:xdigit:]]+}} +GAP-DAG: [{{[ 0-9]+}}] .plt PROGBITS {{[[:xdigit:]]+}} {{[[:xdigit:]]+}} GAP-DAG: [{{[ 0-9]+}}] .got PROGBITS {{0*}}90000 {{[[:xdigit:]]+}} GAP: Dynamic section at GAP: 0x{{[[:xdigit:]]+}} (PLTGOT) 0x90008 -GAP: {{0*}}0 deadc00c {{0*}}0 {{0*}}0 {{0*}}0 [[PLT]] +GAP: Hex dump of section '.got': +GAP-NEXT: 0x{{0*}}90000 0cc0adde 00000000 00000000 00000000 +GAP-NEXT: 0x{{0*}}90010 {{[[:xdigit:]]+}} diff --git a/test/Common/standalone/DynamicGOTPLT/DynamicGOTPLT_RISCV64.test b/test/Common/standalone/DynamicGOTPLT/DynamicGOTPLT_RISCV64.test index 295edb964c..d50703bcc4 100644 --- a/test/Common/standalone/DynamicGOTPLT/DynamicGOTPLT_RISCV64.test +++ b/test/Common/standalone/DynamicGOTPLT/DynamicGOTPLT_RISCV64.test @@ -11,28 +11,28 @@ RUN: %clang %clangopts -c %p/Inputs/1.c -fPIC -o %t.1.o RUN: %link %linkopts -shared %t.1.o -o %t.so RUN: %clang %clangopts -c %p/Inputs/2.c -fPIC -o %t.2.o -## Case 2: GOTPLT is in the beginning of the .got.plt section +## Case 1: GOTPLT is in the beginning of the .got.plt section RUN: %link %linkopts %t.2.o %t.so -o %t.out -T %p/Inputs/script.t -RUN: %readelf -S --dynamic %t.out >%t.out.txt -RUN: %objcopy -O binary --only-section=.got.plt %t.out - | od -v -Ax -w64 -t x8 >>%t.out.txt -RUN: %filecheck %s --input-file=%t.out.txt +RUN: %readelf -S --dynamic -x .got.plt %t.out | %filecheck %s CHECK: Section Headers: -CHECK-DAG: [{{[ 0-9]+}}] .plt PROGBITS [[PLT:[[:xdigit:]]+]] {{[[:xdigit:]]+}} +CHECK-DAG: [{{[ 0-9]+}}] .plt PROGBITS {{[[:xdigit:]]+}} {{[[:xdigit:]]+}} CHECK-DAG: [{{[ 0-9]+}}] .got.plt PROGBITS {{0*}}70000 {{[[:xdigit:]]+}} CHECK: Dynamic section at CHECK: 0x{{[[:xdigit:]]+}} (PLTGOT) 0x70000 -CHECK: {{0*}}0 {{0*}}0 {{0*}}0 [[PLT]] +CHECK: Hex dump of section '.got.plt': +CHECK-NEXT: 0x{{0*}}70000 00000000 00000000 00000000 00000000 +CHECK-NEXT: 0x{{0*}}70010 {{[[:xdigit:]]+}} 00000000 ## Case 2: GOTPLT is not in the beginning of the .got.plt section RUN: %link %linkopts %t.2.o %t.so -o %t-got.out -T %p/Inputs/script-gap.t -RUN: %readelf -S --dynamic -x .got.plt %t-got.out >%t-gap.out.txt -RUN: %objcopy -O binary --only-section=.got %t-got.out - | od -v -Ax -w64 -t x8 >>%t-gap.out.txt -RUN: %filecheck %s --input-file=%t-gap.out.txt --check-prefix=GAP +RUN: %readelf -S --dynamic -x .got %t-got.out | %filecheck %s --check-prefix=GAP GAP: Section Headers: -GAP-DAG: [{{[ 0-9]+}}] .plt PROGBITS [[PLT:[[:xdigit:]]+]] {{[[:xdigit:]]+}} +GAP-DAG: [{{[ 0-9]+}}] .plt PROGBITS {{[[:xdigit:]]+}} {{[[:xdigit:]]+}} GAP-DAG: [{{[ 0-9]+}}] .got PROGBITS {{0*}}90000 {{[[:xdigit:]]+}} GAP: Dynamic section at GAP: 0x{{[[:xdigit:]]+}} (PLTGOT) 0x90008 -GAP: {{0*}}0 {{0*}}deadc00c {{0*}}0 {{0*}}0 [[PLT]] +GAP: Hex dump of section '.got': +GAP-NEXT: 0x{{0*}}90000 0cc0adde 00000000 00000000 00000000 +GAP-NEXT: 0x{{0*}}90010 00000000 00000000 {{[[:xdigit:]]+}} 00000000 diff --git a/test/Common/standalone/ExplicitOutputSectionData/ExplicitOutputSectionDataReproduce.test b/test/Common/standalone/ExplicitOutputSectionData/ExplicitOutputSectionDataReproduce.test index 105b9b52b2..88fd50fc1b 100644 --- a/test/Common/standalone/ExplicitOutputSectionData/ExplicitOutputSectionDataReproduce.test +++ b/test/Common/standalone/ExplicitOutputSectionData/ExplicitOutputSectionDataReproduce.test @@ -28,7 +28,7 @@ RUN: %link %linkopts -o %t1.1.2.elf %t1.1.o -T %p/Inputs/script2.t --reproduce % RUN: %mkdir %t1.1.2.reproduce RUN: %tar %gnutaropts -xf %t1.1.2.reproduce.tar -C %t1.1.2.reproduce --strip-components=1 RUN: cd %t1.1.2.reproduce -RUN: sed -i '$s|$|'" -o %t1.1.rep.elf"'|' %t1.1.2.reproduce/response.txt +RUN: sed -i.bak '$s|$|'" -o %t1.1.rep.elf"'|' %t1.1.2.reproduce/response.txt RUN: %link @%t1.1.2.reproduce/response.txt -o %t1.1.2.rep.elf RUN: %readelf -S %t1.1.2.rep.elf 2>&1 | %filecheck %s --check-prefix=MULTIPLE_OSD RUN: %objdump -d %t1.1.2.rep.elf --section .five | %filecheck %s --check-prefix=FIVE_MULTIPLE_OSD diff --git a/test/Common/standalone/YAMLMapFile/EmptyArchiveFile/EmptyArchiveFile.test b/test/Common/standalone/YAMLMapFile/EmptyArchiveFile/EmptyArchiveFile.test index fc4561e22a..6732fdbf8e 100644 --- a/test/Common/standalone/YAMLMapFile/EmptyArchiveFile/EmptyArchiveFile.test +++ b/test/Common/standalone/YAMLMapFile/EmptyArchiveFile/EmptyArchiveFile.test @@ -6,7 +6,7 @@ #END_COMMENT #START_TEST RUN: %clang %clangopts -o %t1.1.o %p/Inputs/1.c -c -RUN: %ar cr %t1.lib.a +RUN: %ar --format=gnu cr %t1.lib.a RUN: %link %linkopts -o %t1.1.out %t1.1.o %t1.lib.a -MapStyle yaml \ RUN: -Map %t1.1.map.yaml 2>&1 | %filecheck %s RUN: %filecheck %s --check-prefix=MAP < %t1.1.map.yaml diff --git a/test/Hexagon/Plugin/FileSize/FileSize.test b/test/Hexagon/Plugin/FileSize/FileSize.test index edcd91c649..f22577e73a 100644 --- a/test/Hexagon/Plugin/FileSize/FileSize.test +++ b/test/Hexagon/Plugin/FileSize/FileSize.test @@ -11,10 +11,10 @@ RUN: %readelf -S -W %t2.out | %filecheck %s RUN: %link %linkopts %t1.1.o -T %p/Inputs/onlyscript.t --plugin-config %p/Inputs/plugin.config --trace=plugin -o %t2.out.1 --emit-timing-stats=%t.time.stats 2>&1 | %filecheck %s -check-prefix=PLUGINTRACE RUN: %readelf -S -W %t2.out.1 | %filecheck %s -#PLUGINTRACE: Note: Registration function found RegisterAll in Library {{.*}}{{[.sodll]}} -#PLUGINTRACE: Note: Plugin handler getPlugin found in Library {{.*}}{{[.sodll]}} +#PLUGINTRACE: Note: Registration function found RegisterAll in Library {{.*}}{{(so|dll|dylib)}} +#PLUGINTRACE: Note: Plugin handler getPlugin found in Library {{.*}}{{(so|dll|dylib)}} #PLUGINTRACE: Note: Registering all plugin handlers for plugin types -#PLUGINTRACE: Note: Found plugin handler for plugin type COPYBLOCKS in Library {{.*}}{{[.sodll]}} +#PLUGINTRACE: Note: Found plugin handler for plugin type COPYBLOCKS in Library {{.*}}{{(so|dll|dylib)}} #PLUGINTRACE: Note: Creating MemoryBlock sized {{.*}} for output section .foo #PLUGINTRACE: Note: Applying relocations for section .foo #PLUGINTRACE: Note: Syncing relocations for section .foo diff --git a/test/Hexagon/Plugin/MatchAndDiscardSections/MatchAndDiscardSections.test b/test/Hexagon/Plugin/MatchAndDiscardSections/MatchAndDiscardSections.test index e55ced96e7..b38243c18a 100644 --- a/test/Hexagon/Plugin/MatchAndDiscardSections/MatchAndDiscardSections.test +++ b/test/Hexagon/Plugin/MatchAndDiscardSections/MatchAndDiscardSections.test @@ -12,10 +12,10 @@ RUN: %clang %clangopts -c %p/Inputs/b.s -o %t1.2.o -ffunction-sections RUN: %link %linkopts %t1.2.o -M -T %p/Inputs/script.t --trace=plugin -o %t2.out.err --noinhibit-exec 2>&1 | %filecheck %s -check-prefix=PLUGINTRACE RUN: %readelf -s %t2.out.err 2>&1 | %filecheck %s -check-prefix=SYM -#PLUGINTRACE: Note: Registration function found RegisterAll in Library {{.*}}{{[.sodll]}} -#PLUGINTRACE: Note: Plugin handler getPlugin found in Library {{.*}}{{[.sodll]}} +#PLUGINTRACE: Note: Registration function found RegisterAll in Library {{.*}}{{(so|dll|dylib)}} +#PLUGINTRACE: Note: Plugin handler getPlugin found in Library {{.*}}{{(so|dll|dylib)}} #PLUGINTRACE: Note: Registering all plugin handlers for plugin types -#PLUGINTRACE: Note: Found plugin handler for plugin type MATCHANDDISCARDSECTIONS in Library {{.*}}{{[.sodll]}} +#PLUGINTRACE: Note: Found plugin handler for plugin type MATCHANDDISCARDSECTIONS in Library {{.*}}{{(so|dll|dylib)}} #PLUGINTRACE: MATCHANDDISCARDSECTIONS #CHECK-NOT: .ignoreme #SYM-NOT: goo diff --git a/test/Hexagon/Plugin/MatchSectionsAndGetRawData/MatchSectionsAndGetRawData.test b/test/Hexagon/Plugin/MatchSectionsAndGetRawData/MatchSectionsAndGetRawData.test index 6cff4efe42..9c82c4c8f3 100644 --- a/test/Hexagon/Plugin/MatchSectionsAndGetRawData/MatchSectionsAndGetRawData.test +++ b/test/Hexagon/Plugin/MatchSectionsAndGetRawData/MatchSectionsAndGetRawData.test @@ -8,10 +8,10 @@ RUN: %clang %clangopts -c %p/Inputs/1.s -o %t1.1.o -ffunction-sections %clangg0opts RUN: %link %linkopts %t1.1.o -T %p/Inputs/script.t --trace=plugin -o %t2.out 2>&1 | %filecheck %s -check-prefix=PLUGINTRACE -#PLUGINTRACE-DAG: Note: Registration function found RegisterAll in Library {{.*}}{{[.sodll]}} -#PLUGINTRACE-DAG: Note: Plugin handler getPlugin found in Library {{.*}}{{[.sodll]}} +#PLUGINTRACE-DAG: Note: Registration function found RegisterAll in Library {{.*}}{{(so|dll|dylib)}} +#PLUGINTRACE-DAG: Note: Plugin handler getPlugin found in Library {{.*}}{{(so|dll|dylib)}} #PLUGINTRACE-DAG: Note: Registering all plugin handlers for plugin types -#PLUGINTRACE-DAG: Note: Found plugin handler for plugin type MATCHSECTIONSANDGETRAWDATA in Library {{.*}}{{[.sodll]}} +#PLUGINTRACE-DAG: Note: Found plugin handler for plugin type MATCHSECTIONSANDGETRAWDATA in Library {{.*}}{{(so|dll|dylib)}} #PLUGINTRACE-DAG: HelloWorld #END_TEST diff --git a/test/Hexagon/Plugin/SignalHandling/SignalHandling.test b/test/Hexagon/Plugin/SignalHandling/SignalHandling.test index 2c4f484469..61e1235d00 100644 --- a/test/Hexagon/Plugin/SignalHandling/SignalHandling.test +++ b/test/Hexagon/Plugin/SignalHandling/SignalHandling.test @@ -9,7 +9,6 @@ UNSUPPORTED: sanitize RUN: %clang %clangopts -c %p/Inputs/1.c -o %t1.1.o -ffunction-sections RUN: %not %not %link %linkopts %t1.1.o -T %p/Inputs/script.t -o %t2.out 2>&1 | %filecheck %s CHECK-NOT: !!!UNEXPECTED LINKER BEHAVIOR!!! -CHECK-DAG: LinkerCrashPlugin::Init CHECK-DAG: Please rerun link with CHECK-DAG: .sh CHECK-DAG: !!!PLUGIN CRASHED!!! diff --git a/test/UnitTests/lit.cfg b/test/UnitTests/lit.cfg index 6e5e9a3ed6..4affe231b6 100644 --- a/test/UnitTests/lit.cfg +++ b/test/UnitTests/lit.cfg @@ -47,9 +47,13 @@ if eld_obj_root is not None: llvm_libs_dir = getattr(config, 'llvm_libs_dir', None) if not llvm_libs_dir: lit_config.fatal('No LLVM libs dir set!') - path = os.path.pathsep.join((llvm_libs_dir, - config.environment.get('LD_LIBRARY_PATH',''))) - config.environment['LD_LIBRARY_PATH'] = path + + if platform.system() == 'Darwin': + config.environment['DYLD_LIBRARY_PATH'] = os.path.pathsep.join( + (llvm_libs_dir, config.environment.get('DYLD_LIBRARY_PATH', ''))) + elif platform.system() != 'Windows': + config.environment['LD_LIBRARY_PATH'] = os.path.pathsep.join( + (llvm_libs_dir, config.environment.get('LD_LIBRARY_PATH', ''))) # Propagate LLVM_SRC_ROOT into the environment. config.environment['LLVM_SRC_ROOT'] = getattr(config, 'llvm_src_root', '') diff --git a/test/lit.cfg b/test/lit.cfg index 2e69384524..700522fcc6 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -93,6 +93,13 @@ if eld_obj_root is not None: if not llvm_libs_dir: lit_config.fatal('No LLVM libs dir set!') + if platform.system() == 'Darwin': + config.environment['DYLD_LIBRARY_PATH'] = os.path.pathsep.join( + (llvm_libs_dir, config.environment.get('DYLD_LIBRARY_PATH', ''))) + elif platform.system() != 'Windows': + config.environment['LD_LIBRARY_PATH'] = os.path.pathsep.join( + (llvm_libs_dir, config.environment.get('LD_LIBRARY_PATH', ''))) + # Propagate LLVM_SRC_ROOT into the environment. config.environment['LLVM_SRC_ROOT'] = getattr(config, 'llvm_src_root', '') @@ -238,11 +245,15 @@ if platform.system() == 'Windows': # equivalent, so that tests using '-o /dev/null' work correctly under # lit's internal shell. config.substitutions.insert(0, ('/dev/null', 'NUL')) -elif platform.system() == 'Linux': +else: rm = 'rm -rf' mkdir = 'mkdir -p' grep = 'grep' - config.available_features.add('linux') + if platform.system() == 'Linux': + config.available_features.add('linux') + elif platform.system() == 'Darwin': + config.available_features.add('darwin') + config.available_features.add('system-darwin') if config.eld_option_name != "": config.available_features.add(config.eld_option_name) @@ -356,8 +367,11 @@ if config.test_target == 'ARM': config.available_features.add('windows') elif platform.system() == 'Linux': config.available_features.add('arm-linux') + elif platform.system() == 'Darwin': + config.available_features.add('arm-darwin') if ('arm-windows' in config.available_features or - 'arm-linux' in config.available_features): + 'arm-linux' in config.available_features or + 'arm-darwin' in config.available_features): config.available_features.add('arm') link = 'ld.eld' linkopts = '--thread-count 4 --threads' @@ -387,8 +401,11 @@ if config.test_target == 'AArch64': config.available_features.add('aarch64-windows') elif platform.system() == 'Linux': config.available_features.add('aarch64-linux') + elif platform.system() == 'Darwin': + config.available_features.add('aarch64-darwin') if ('aarch64-windows' in config.available_features or - 'aarch64-linux' in config.available_features): + 'aarch64-linux' in config.available_features or + 'aarch64-darwin' in config.available_features): config.available_features.add('aarch64') xlen = 8 config.emulation = '-m aarch64elf' @@ -503,10 +520,14 @@ yaml2obj = which(yaml2obj) filecheck = which(filecheck) + ' ' + checkopts if platform.system() == 'Windows': python = which(python) -elif platform.system() == 'Linux': +else: python = which("python3") -tar = which(tar) + ' --force-local' +tar = which(tar) +# GNU tar needs --force-local so Windows drive-letter paths are not parsed as +# remote hosts. BSD tar on Darwin does not accept that flag. +if platform.system() != 'Darwin': + tar = tar + ' --force-local' mv = which(mv) diff = which(diff) touch = which(touch) @@ -705,7 +726,19 @@ config.substitutions.append( ("%mv","".join(mv)) ) config.substitutions.append( ("%echo","".join(echo)) ) config.substitutions.append( ("%diff","".join(diff)) ) config.substitutions.append( ("%touch","".join(touch)) ) -config.substitutions.append( ("%cppcompiler","".join(config.cpp_compiler)) ) +cppcompiler = config.cpp_compiler +if platform.system() == 'Darwin': + try: + sdk = subprocess.check_output( + ['xcrun', '--show-sdk-path'], + stderr=subprocess.DEVNULL, + text=True, + ).strip() + if sdk: + cppcompiler = '{} -isysroot {}'.format(cppcompiler, sdk) + except (OSError, subprocess.CalledProcessError): + pass +config.substitutions.append( ("%cppcompiler","".join(cppcompiler)) ) config.substitutions.append( ("%cmake", cmake) ) config.substitutions.append( ("%git", git)) config.substitutions.append( ("%cp", cp)) diff --git a/test/x86_64/linux/DefaultImageBase/DefaultImageBase.test b/test/x86_64/linux/DefaultImageBase/DefaultImageBase.test index 26232b238d..62d239de3c 100644 --- a/test/x86_64/linux/DefaultImageBase/DefaultImageBase.test +++ b/test/x86_64/linux/DefaultImageBase/DefaultImageBase.test @@ -1,4 +1,4 @@ -#UNSUPPORTED: windows +#UNSUPPORTED: windows, darwin #---DefaultImageBase.test-----Executable--------# BEGIN_COMMENT # Test x86_64 default image address diff --git a/test/x86_64/linux/DynamicDataCall/DynamicDataCall.test b/test/x86_64/linux/DynamicDataCall/DynamicDataCall.test index 2d93e23c2f..7370fd7f88 100644 --- a/test/x86_64/linux/DynamicDataCall/DynamicDataCall.test +++ b/test/x86_64/linux/DynamicDataCall/DynamicDataCall.test @@ -1,4 +1,4 @@ -#UNSUPPORTED: windows +#UNSUPPORTED: windows, darwin #--DynamicDataCall.test-------Executable--# #BEGIN_COMMENT #Verifies data accesses are handled correctly for dynamic linking scenarios. diff --git a/test/x86_64/linux/EmulationSupport/EmulationOption.test b/test/x86_64/linux/EmulationSupport/EmulationOption.test index 8bef5b10d7..39a236e661 100644 --- a/test/x86_64/linux/EmulationSupport/EmulationOption.test +++ b/test/x86_64/linux/EmulationSupport/EmulationOption.test @@ -1,4 +1,4 @@ -#UNSUPPORTED: windows +#UNSUPPORTED: windows, darwin #---x86_64_Emulation.test----------------- Executable --------------------# BEGIN_COMMENT diff --git a/test/x86_64/linux/TlsGDnonpreemptible/TlsGDnonpreemptible.test b/test/x86_64/linux/TlsGDnonpreemptible/TlsGDnonpreemptible.test index fd71c117e4..5f2458bda4 100644 --- a/test/x86_64/linux/TlsGDnonpreemptible/TlsGDnonpreemptible.test +++ b/test/x86_64/linux/TlsGDnonpreemptible/TlsGDnonpreemptible.test @@ -1,5 +1,5 @@ #------TlsGDnonpreemptible.test-------Executable------# -#UNSUPPORTED: windows +#UNSUPPORTED: windows, darwin #BEGIN_COMMENT # Verifies TLS General Dynamic (GD) model with non-preemptible symbols. # When TLS variables are defined and used in the same shared library diff --git a/test/x86_64/linux/TlsGDpreemptible/TlsGDpreemptible.test b/test/x86_64/linux/TlsGDpreemptible/TlsGDpreemptible.test index d5866af731..7185c2db64 100644 --- a/test/x86_64/linux/TlsGDpreemptible/TlsGDpreemptible.test +++ b/test/x86_64/linux/TlsGDpreemptible/TlsGDpreemptible.test @@ -1,5 +1,5 @@ #------TlsGDpreemptible.test-------Executable------# -#UNSUPPORTED: windows +#UNSUPPORTED: windows, darwin #BEGIN_COMMENT # Verifies TLS General Dynamic (GD) model when a TLS variable is defined in one # shared library (lib3.so) and accessed from another shared library (lib2.so). diff --git a/test/x86_64/linux/TlsIEModel/TlsIEModel.test b/test/x86_64/linux/TlsIEModel/TlsIEModel.test index 306ed41de8..0de1ce5ca1 100644 --- a/test/x86_64/linux/TlsIEModel/TlsIEModel.test +++ b/test/x86_64/linux/TlsIEModel/TlsIEModel.test @@ -1,5 +1,5 @@ #------TlsIEModel.test-------Executable------# -#UNSUPPORTED: windows +#UNSUPPORTED: windows, darwin #BEGIN_COMMENT # Verifies TLS Initial Exec (IE) model when a TLS variable is referenced in the # main executable and defined in a shared library. The linker should emit an diff --git a/test/x86_64/linux/TlsLDModel/TlsLDModel.test b/test/x86_64/linux/TlsLDModel/TlsLDModel.test index 4b871206ed..1f1336fb2e 100644 --- a/test/x86_64/linux/TlsLDModel/TlsLDModel.test +++ b/test/x86_64/linux/TlsLDModel/TlsLDModel.test @@ -1,4 +1,4 @@ -#UNSUPPORTED: windows +#UNSUPPORTED: windows, darwin #------TlsLDModel.test-------Shared Object------# #BEGIN_COMMENT # Verifies TLS Local Dynamic (LD) model for static thread-local variables. diff --git a/test/x86_64/linux/relocCOPY/relocCOPY.test b/test/x86_64/linux/relocCOPY/relocCOPY.test index a10a89e804..eb22245561 100644 --- a/test/x86_64/linux/relocCOPY/relocCOPY.test +++ b/test/x86_64/linux/relocCOPY/relocCOPY.test @@ -1,4 +1,4 @@ -#UNSUPPORTED: windows +#UNSUPPORTED: windows, darwin #------CopyReloc.test-------Copy Relocations------# #BEGIN_COMMENT # Verifies copy relocations for data symbols in non-PIC executables. diff --git a/test/x86_64/linux/relocGOTPCREL/relocGOTPCREL.test b/test/x86_64/linux/relocGOTPCREL/relocGOTPCREL.test index b76428897d..7c4623b01f 100644 --- a/test/x86_64/linux/relocGOTPCREL/relocGOTPCREL.test +++ b/test/x86_64/linux/relocGOTPCREL/relocGOTPCREL.test @@ -1,4 +1,4 @@ -#UNSUPPORTED: windows +#UNSUPPORTED: windows, darwin #--relocGOTPCRELStatic.test----------Executable--------# BEGIN_COMMENT # Test R_X86_64_GOTPCREL relocation type support. diff --git a/test/x86_64/linux/relocIRELATIVE/relocIRELATIVE.test b/test/x86_64/linux/relocIRELATIVE/relocIRELATIVE.test index f2469b66bc..5452c00133 100644 --- a/test/x86_64/linux/relocIRELATIVE/relocIRELATIVE.test +++ b/test/x86_64/linux/relocIRELATIVE/relocIRELATIVE.test @@ -1,4 +1,4 @@ -#UNSUPPORTED: windows +#UNSUPPORTED: windows, darwin #------IRelativeStatic.test-------IRELATIVE Relocations in Static Executables------# #BEGIN_COMMENT # Verifies IRELATIVE relocations (R_X86_64_IRELATIVE) are generated when diff --git a/test/x86_64/linux/relocPLT32Static/relocPLT32Static.test b/test/x86_64/linux/relocPLT32Static/relocPLT32Static.test index 0f094ae914..902b75ff86 100644 --- a/test/x86_64/linux/relocPLT32Static/relocPLT32Static.test +++ b/test/x86_64/linux/relocPLT32Static/relocPLT32Static.test @@ -1,4 +1,4 @@ -#UNSUPPORTED: windows +#UNSUPPORTED: windows, darwin #--PLT32Static.test----------Executable--------# BEGIN_COMMENT diff --git a/test/x86_64/linux/relocPLT32dynamic/relocPLT32dynamic.test b/test/x86_64/linux/relocPLT32dynamic/relocPLT32dynamic.test index 144b1e2f72..d7c30ef4be 100644 --- a/test/x86_64/linux/relocPLT32dynamic/relocPLT32dynamic.test +++ b/test/x86_64/linux/relocPLT32dynamic/relocPLT32dynamic.test @@ -1,4 +1,4 @@ -#UNSUPPORTED: windows +#UNSUPPORTED: windows, darwin #--relocPLT32dynamic.test-------Executable--# #BEGIN_COMMENT # Verifies R_X86_64_PLT32 relocations redirect external function calls From b68b5d62e4973b264dcd8989b3184152bd7ecd2c Mon Sep 17 00:00:00 2001 From: Dhruv Menon Date: Thu, 3 Sep 2026 01:29:37 +0530 Subject: [PATCH 4/7] [docs] Document macOS as a supported host macOS is a host for the ELF linker, not a Mach-O target. Document .dylib plugin naming and DYLD_LIBRARY_PATH search. Signed-off-by: Dhruv Menon --- README.md | 6 +++++- docs/userguide/documentation/linker_faq.rst | 1 + .../documentation/linker_plugins/linker_plugins.rst | 13 ++++++++----- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index eb6f2b1fb0..43f0d17de5 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,11 @@ and is designed for easy addition of more backends. ## Building ELD and running tests -ELD supports building and running tests on Linux and Windows utilizing LLVM. +ELD supports building and running tests on Linux, Windows, and macOS (Darwin) +utilizing LLVM. macOS is supported as a **host** (Apple Silicon and Intel); +ELD still produces ELF images and does not link Mach-O. On macOS the linker +binary is built natively for the host architecture (`arm64` or `x86_64`); +universal binaries are not required. ELD depends on LLVM. You can build ELD either: - Integrated into an `llvm-project` build (recommended for running tests), or diff --git a/docs/userguide/documentation/linker_faq.rst b/docs/userguide/documentation/linker_faq.rst index dcfc533320..d580623f69 100644 --- a/docs/userguide/documentation/linker_faq.rst +++ b/docs/userguide/documentation/linker_faq.rst @@ -3157,6 +3157,7 @@ Step 2 Check to see if there any system environment variables set. Important variables to note are :- * LD_LIBRARY_PATH +* DYLD_LIBRARY_PATH (macOS) * PATH (Windows) Remove the values set and see if the error disappears diff --git a/docs/userguide/documentation/linker_plugins/linker_plugins.rst b/docs/userguide/documentation/linker_plugins/linker_plugins.rst index 7d0f1d4441..9f7054f931 100644 --- a/docs/userguide/documentation/linker_plugins/linker_plugins.rst +++ b/docs/userguide/documentation/linker_plugins/linker_plugins.rst @@ -235,8 +235,8 @@ For example:: load. - Finds the library in the same search paths as if the library was passed as an input to the linker. - - Uses the name of the library without the lib prefix on Linux and without - the .so/.dll suffix on Linux/Windows, respectively + - Uses the name of the library without the lib prefix on Linux/macOS and + without the .so/.dll/.dylib suffix on Linux/Windows/macOS, respectively - **PluginName** @@ -276,8 +276,8 @@ Plugin configuration file format should be as follows::: :code:`GlobalPlugins` list can specify any number of elements. :code:`Options` member is optional. -:code:`Library` name should be specified without the lib prefix on Linux -and without the .so/.dll suffix on Linux/Windows +:code:`Library` name should be specified without the lib prefix on Linux/macOS +and without the .so/.dll/.dylib suffix on Linux/Windows/macOS :code:`ControlMemorySizePlugin` and :code:`ControlFileSizePlugin` are output section plugins. Therefore, in the plugin configuration file, they need to be @@ -340,6 +340,7 @@ The following steps describe how to develop a plugin: clang++ -c -I${HEXAGON_TOOLCHAIN_ROOT}/Tools/include ${SOURCE_BASENAME}.cpp -fPIC -stdlib=libc++ # Link the plugin library with linker wrapper library, LW. + # Linux: lib${SOURCE_BASENAME}.so macOS: lib${SOURCE_BASENAME}.dylib clang++ -shared ./${SOURCE_BASENAME}.o -L${HEXAGON_TOOLCHAIN_ROOT}/Tools/lib -lLW -stdlib=libc++ -o lib${SOURCE_BASENAME}.so 7) Define :code:`RegisterAll` function in C linkage. @@ -405,7 +406,9 @@ Linker performs the following operations to load, run and unload plugins. 2) Loads all the specified plugin libraries. - #. To find plugin libraries, :code:`LD_LIBRARY_PATH` environment variable is used on unix environment. + #. To find plugin libraries, :code:`LD_LIBRARY_PATH` is used on Linux. + On macOS, :code:`DYLD_LIBRARY_PATH` is searched first, then + :code:`LD_LIBRARY_PATH`. #. Standard method for searching dynamic libraries is used in Windows. 3) Calls :code:`RegisterAll` function from each plugin library. This function From f7dfd82384f372eff2a6f934d67173b624264045 Mon Sep 17 00:00:00 2001 From: Dhruv Menon Date: Thu, 3 Sep 2026 02:16:52 +0530 Subject: [PATCH 5/7] [workflow] Add GitHub-hosted macOS CI for Darwin host builds Test ld.eld on macos-latest so PRs get a Mac host build without changing the Linux self-hosted job. Signed-off-by: Dhruv Menon --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f712c0401f..0d3b1c29c5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,6 +11,7 @@ on: - '.github/workflows/docs.yaml' - '.github/workflows/docs-multiversion.yaml' - '.github/workflows/ci-win.yml' + - '.github/workflows/ci-macos.yml' - '.github/workflows/clang-cross-schedule.yml' - '.github/workflows/DownloadClangCrossToolchain/action.yaml' - '.github/workflows/DownloadLatestBusybox/action.yaml' From 7ee80fad18a4fb72fc1aa3612d2687d868e99063 Mon Sep 17 00:00:00 2001 From: Dhruv Menon Date: Thu, 3 Sep 2026 09:52:39 +0530 Subject: [PATCH 6/7] [workflow] Refactor non-doc change checks in CI workflows Replaced inline scripts for checking non-documentation changes with a reusable action in ci.yml, ci-macos.yml, and ci-win.yml. This improves maintainability and consistency across workflows. The new action fetches the base branch from the Qualcomm repository and determines if the changes are solely documentation-related. Signed-off-by: Dhruv Menon --- .../workflows/CheckNonDocChanges/action.yaml | 60 +++++++++++++++++++ .github/workflows/ci-win.yml | 13 ++++ .github/workflows/ci.yml | 20 ++----- 3 files changed, 77 insertions(+), 16 deletions(-) create mode 100644 .github/workflows/CheckNonDocChanges/action.yaml diff --git a/.github/workflows/CheckNonDocChanges/action.yaml b/.github/workflows/CheckNonDocChanges/action.yaml new file mode 100644 index 0000000000..58812e4796 --- /dev/null +++ b/.github/workflows/CheckNonDocChanges/action.yaml @@ -0,0 +1,60 @@ +name: Check for non-doc changes +description: > + Compare the ELD checkout to qualcomm/eld's PR base and set skip_build when + the PR only touches docs/. Shared by ci.yml, ci-macos.yml, and ci-win.yml. + +inputs: + base-branch: + description: "Base branch on qualcomm/eld (e.g. main)" + required: true + base-sha: + description: "github.event.pull_request.base.sha — the base commit GitHub already resolved" + required: true + +outputs: + skip_build: + description: "true if only docs changed; false otherwise" + value: ${{ steps.file-check.outputs.skip_build }} + +runs: + using: composite + steps: + - name: Check for non-doc changes + id: file-check + shell: bash + env: + BASE_BRANCH_NAME: ${{ inputs.base-branch }} + BASE_SHA: ${{ inputs.base-sha }} + # Action lives at /.github/workflows/CheckNonDocChanges. + working-directory: ${{ github.action_path }}/../../.. + run: | + set -euo pipefail + # We need the base commit from qualcomm/eld, not from the fork. + git remote add QC https://github.com/qualcomm/eld.git + # Prefer the event SHA (one commit, no history walk). Fall back to the + # branch tip if the remote will not serve a raw SHA. + git fetch --no-tags --depth=1 QC "${BASE_SHA}" || \ + git fetch --no-tags --depth=1 QC "${BASE_BRANCH_NAME}" + if git cat-file -e "${BASE_SHA}^{commit}" 2>/dev/null; then + BASE="${BASE_SHA}" + elif git rev-parse --verify "QC/${BASE_BRANCH_NAME}^{commit}" >/dev/null 2>&1; then + BASE="QC/${BASE_BRANCH_NAME}" + else + echo "::error::Could not resolve base ${BASE_SHA} or QC/${BASE_BRANCH_NAME}" + git rev-parse HEAD + git remote -v + exit 1 + fi + # Two-dot tree diff: both objects exist after the fetch, so this does + # not need merge-base (which fails on a depth-1 QC/main vs a fork HEAD). + CHANGED_FILES=$(git diff --name-only "${BASE}" HEAD) + echo "diff-base: ${BASE}" + echo "Changed files: ${CHANGED_FILES}" + for file in $CHANGED_FILES; do + if [[ ! "$file" =~ ^docs/ && ! "$file" =~ \.md$ ]]; then + echo "skip_build=false" >> "$GITHUB_OUTPUT" + exit 0 + fi + done + echo "Only docs changed. Skipping build." + echo "skip_build=true" >> "$GITHUB_OUTPUT" diff --git a/.github/workflows/ci-win.yml b/.github/workflows/ci-win.yml index 916105e159..6ab974e10b 100644 --- a/.github/workflows/ci-win.yml +++ b/.github/workflows/ci-win.yml @@ -65,6 +65,14 @@ jobs: path: nightly/llvm-project/llvm/tools/eld fetch-depth: 0 + - name: Check for non-doc changes + id: file-check + if: github.event_name == 'pull_request' + uses: ./nightly/llvm-project/llvm/tools/eld/.github/workflows/CheckNonDocChanges + with: + base-branch: ${{ env.BASE_BRANCH_NAME }} + base-sha: ${{ github.event.pull_request.base.sha }} + - name: Record pre-build entry if: github.event_name == 'schedule' uses: ./nightly/llvm-project/llvm/tools/eld/.github/workflows/BuildStatusDataRecorder @@ -80,6 +88,7 @@ jobs: branch-name: "${{ env.ELD_REF }}" - name: Configure CMake + if: github.event_name != 'pull_request' || steps.file-check.outputs.skip_build == 'false' working-directory: nightly shell: bash run: | @@ -95,22 +104,26 @@ jobs: ../llvm-project/llvm - name: Build + if: github.event_name != 'pull_request' || steps.file-check.outputs.skip_build == 'false' working-directory: nightly/obj shell: bash run: cmake --build . --config Release - name: Install PyYAML + if: github.event_name != 'pull_request' || steps.file-check.outputs.skip_build == 'false' shell: bash run: | echo "Installing dependencies using $(python --version) at $(which python)" python -m pip install pyyaml psutil - name: Run tests + if: github.event_name != 'pull_request' || steps.file-check.outputs.skip_build == 'false' working-directory: nightly/obj shell: bash run: cmake --build . --config Release --target check-eld - name: Summarize test results + if: github.event_name != 'pull_request' || steps.file-check.outputs.skip_build == 'false' working-directory: nightly/obj shell: bash run: cmake --build . --config Release --target check-eld-summary diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0d3b1c29c5..f012388d90 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -77,22 +77,10 @@ jobs: - name: Check for non-doc changes id: file-check - working-directory: pr-${{ env.PR_NUMBER }}/llvm-project/llvm/tools/eld - run: | - # We need to use base branch from qualcomm/eld - git remote add QC https://github.com/qualcomm/eld.git - git fetch QC ${{ env.BASE_BRANCH_NAME }} --depth=1 - MERGE_BASE=$(git merge-base QC/${{ env.BASE_BRANCH_NAME }} HEAD) - CHANGED_FILES=$(git diff --name-only "$MERGE_BASE" HEAD) - echo "Changed files: $CHANGED_FILES" - for file in $CHANGED_FILES; do - if [[ ! "$file" =~ ^docs/ && ! "$file" =~ \.md$ ]]; then - echo "skip_build=false" >> "$GITHUB_OUTPUT" - exit 0 - fi - done - echo "Only docs changed. Skipping build." - echo "skip_build=true" >> "$GITHUB_OUTPUT" + uses: ./pr-${{ github.event.number }}/llvm-project/llvm/tools/eld/.github/workflows/CheckNonDocChanges + with: + base-branch: ${{ env.BASE_BRANCH_NAME }} + base-sha: ${{ github.event.pull_request.base.sha }} - name: Run CMake if: steps.file-check.outputs.skip_build == 'false' From 4e355bf0fa2ca0c94aed1b0ad04668a02faddeca Mon Sep 17 00:00:00 2001 From: Dhruv Menon Date: Sun, 6 Sep 2026 10:37:24 +0530 Subject: [PATCH 7/7] [workflow] Enhance CheckNonDocChanges action and CI configuration Updated the CI workflow to stage the CheckNonDocChanges action at the workspace root, allowing for better path management. Added an optional input for the eld-root to support staging the action awa from its original location. Introduced a new lit configuration file for Linux x86_64 binaries to ensure compatibility with libc headers. Signed-off-by: Dhruv Menon --- .github/workflows/CheckNonDocChanges/action.yaml | 12 ++++++++++-- .github/workflows/ci.yml | 12 ++++++++++-- test/x86_64/linux/SymbolVersioning/lit.local.cfg | 4 ++++ 3 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 test/x86_64/linux/SymbolVersioning/lit.local.cfg diff --git a/.github/workflows/CheckNonDocChanges/action.yaml b/.github/workflows/CheckNonDocChanges/action.yaml index 58812e4796..ccbcb10654 100644 --- a/.github/workflows/CheckNonDocChanges/action.yaml +++ b/.github/workflows/CheckNonDocChanges/action.yaml @@ -10,6 +10,13 @@ inputs: base-sha: description: "github.event.pull_request.base.sha — the base commit GitHub already resolved" required: true + eld-root: + description: > + ELD checkout root (the directory that contains .git). Required when this + action is staged away from /.github/workflows/CheckNonDocChanges, + because uses: cannot interpolate github/env into a local path. + required: false + default: '' outputs: skip_build: @@ -25,8 +32,9 @@ runs: env: BASE_BRANCH_NAME: ${{ inputs.base-branch }} BASE_SHA: ${{ inputs.base-sha }} - # Action lives at /.github/workflows/CheckNonDocChanges. - working-directory: ${{ github.action_path }}/../../.. + # Default: action lives at /.github/workflows/CheckNonDocChanges. + # ci.yml stages a copy at the workspace root, so it passes eld-root. + working-directory: ${{ inputs.eld-root || format('{0}/../../..', github.action_path) }} run: | set -euo pipefail # We need the base commit from qualcomm/eld, not from the fork. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f012388d90..7cb6ee688a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -75,12 +75,20 @@ jobs: - name: Setup musl environment run: echo "/opt/musl/bin" >> $GITHUB_PATH + # uses: cannot contain ${{ github.* }} or ${{ env.* }}; stage a static path. + - name: Stage CheckNonDocChanges + run: | + rm -rf CheckNonDocChanges + cp -R "pr-${PR_NUMBER}/llvm-project/llvm/tools/eld/.github/workflows/CheckNonDocChanges" \ + CheckNonDocChanges + - name: Check for non-doc changes id: file-check - uses: ./pr-${{ github.event.number }}/llvm-project/llvm/tools/eld/.github/workflows/CheckNonDocChanges + uses: ./CheckNonDocChanges with: base-branch: ${{ env.BASE_BRANCH_NAME }} base-sha: ${{ github.event.pull_request.base.sha }} + eld-root: ${{ github.workspace }}/pr-${{ env.PR_NUMBER }}/llvm-project/llvm/tools/eld - name: Run CMake if: steps.file-check.outputs.skip_build == 'false' @@ -205,4 +213,4 @@ jobs: - name: Clean up if: always() run: | - rm -rf "pr-${PR_NUMBER}" + rm -rf "pr-${PR_NUMBER}" CheckNonDocChanges diff --git a/test/x86_64/linux/SymbolVersioning/lit.local.cfg b/test/x86_64/linux/SymbolVersioning/lit.local.cfg new file mode 100644 index 0000000000..e27199fc14 --- /dev/null +++ b/test/x86_64/linux/SymbolVersioning/lit.local.cfg @@ -0,0 +1,4 @@ +# Compile and run Linux x86_64 binaries with libc headers. Host clang +# -target x86_64-linux-gnu has no glibc sysroot on Darwin or Windows. +if 'linux' not in config.available_features: + config.unsupported = True