diff options
author | Alex Richardson <Alexander.Richardson@cl.cam.ac.uk> | 2021-06-23 08:24:04 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2021-06-24 14:57:51 (GMT) |
commit | 5dfa3ddbe592add43e2985dad772f6aa44d37c0b (patch) | |
tree | 0e49df76386e2c3399e6f34ecefc8ad35dd718d5 | |
parent | 0da1540aaa8d36145329572938aeec6c86fb1ee7 (diff) | |
download | CMake-5dfa3ddbe592add43e2985dad772f6aa44d37c0b.zip CMake-5dfa3ddbe592add43e2985dad772f6aa44d37c0b.tar.gz CMake-5dfa3ddbe592add43e2985dad772f6aa44d37c0b.tar.bz2 |
cmELF: Allow building without system ELF headers
Use ELF headers vendored in `Utilities/cmelf` to get the ELF constants
and types. Using the same ELF definition header for all compilation
targets allows removing some #ifdefs depending on the host OS since we
know all required ELF constants will always be present. To reduce the
size of this commit, the CMake_USE_ELF_PARSER definite will be removed
in a separate commit.
This allows me to use CMAKE_BUILD_WITH_INSTALL_RPATH=False and the Ninja
generator on macOS, whereas before it would always give me the following
error message (despite cross-compiling for an ELF-based platform):
```
The install of the <name> target requires changing an RPATH from
the build tree, but this is not supported with the Ninja generator unless
on an ELF-based platform. The CMAKE_BUILD_WITH_INSTALL_RPATH variable may
be set to avoid this relinking step.
```
-rw-r--r-- | Source/CMakeLists.txt | 32 | ||||
-rw-r--r-- | Source/cmELF.cxx | 65 | ||||
-rw-r--r-- | Tests/RunCMake/CMakeLists.txt | 4 | ||||
-rw-r--r-- | Tests/RunCMake/file-RPATH/RunCMakeTest.cmake | 2 |
4 files changed, 10 insertions, 93 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 9a18184..39e4a9d 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -10,36 +10,8 @@ if (NOT CMAKE_SYSTEM_NAME STREQUAL "QNX") endif() include(CheckIncludeFile) -# Check if we can build support for ELF parsing. -if(WIN32) - set(HAVE_ELF_H 0) -elseif(CMAKE_CXX_PLATFORM_ID MATCHES "OpenBSD") - CHECK_INCLUDE_FILES("stdint.h;elf_abi.h" HAVE_ELF_H) -else() - CHECK_INCLUDE_FILE("elf.h" HAVE_ELF_H) -endif() -if(HAVE_ELF_H) - set(CMake_USE_ELF_PARSER 1) -elseif(HAIKU) - # On Haiku, we need to include elf32.h from the private headers - set(CMake_HAIKU_INCLUDE_DIRS - /boot/system/develop/headers/private/system - /boot/system/develop/headers/private/system/arch/x86 - ) - - set(CMAKE_REQUIRED_INCLUDES ${CMake_HAIKU_INCLUDE_DIRS}) - CHECK_INCLUDE_FILE("elf32.h" HAVE_ELF32_H) - unset(CMAKE_REQUIRED_INCLUDES) - if(HAVE_ELF32_H) - set(CMake_USE_ELF_PARSER 1) - else() - unset(CMake_HAIKU_INCLUDE_DIRS) - set(CMake_USE_ELF_PARSER) - endif() -else() - set(CMake_USE_ELF_PARSER) -endif() +set(CMake_USE_ELF_PARSER 1) if(NOT CMake_DEFAULT_RECURSION_LIMIT) if(DEFINED ENV{DASHBOARD_TEST_FROM_CTEST}) @@ -111,7 +83,7 @@ include_directories( ${CMake_HAIKU_INCLUDE_DIRS} ) -# Check if we can build the ELF parser. +# The ELF parser can be built on all platforms. if(CMake_USE_ELF_PARSER) set(ELF_SRCS cmELF.h cmELF.cxx) endif() diff --git a/Source/cmELF.cxx b/Source/cmELF.cxx index d96644b..cde7cdf 100644 --- a/Source/cmELF.cxx +++ b/Source/cmELF.cxx @@ -17,41 +17,9 @@ #include "cmsys/FStream.hxx" -// Include the ELF format information system header. -#if defined(__OpenBSD__) -# include <elf_abi.h> -#elif defined(__HAIKU__) -# include <elf32.h> -# include <elf64.h> -using Elf32_Ehdr = struct Elf32_Ehdr; -using Elf32_Shdr = struct Elf32_Shdr; -using Elf32_Sym = struct Elf32_Sym; -using Elf32_Rel = struct Elf32_Rel; -using Elf32_Rela = struct Elf32_Rela; -# define ELFMAG0 0x7F -# define ELFMAG1 'E' -# define ELFMAG2 'L' -# define ELFMAG3 'F' -# define ET_NONE 0 -# define ET_REL 1 -# define ET_EXEC 2 -# define ET_DYN 3 -# define ET_CORE 4 -# define EM_386 3 -# define EM_SPARC 2 -# define EM_PPC 20 -#else -# include <elf.h> -#endif -#if defined(__sun) -# include <sys/link.h> // For dynamic section information -#endif -#ifdef _SCO_DS -# include <link.h> // For DT_SONAME etc. -#endif -#ifndef DT_RUNPATH -# define DT_RUNPATH 29 -#endif +#include "cmelf/elf32.h" +#include "cmelf/elf64.h" +#include "cmelf/elf_common.h" // Low-level byte swapping implementation. template <size_t s> @@ -213,7 +181,6 @@ struct cmELFTypes32 }; // Configure the implementation template for 64-bit ELF files. -#ifndef _SCO_DS struct cmELFTypes64 { using ELF_Ehdr = Elf64_Ehdr; @@ -223,7 +190,6 @@ struct cmELFTypes64 using tagtype = ::uint64_t; static const char* GetName() { return "64-bit"; } }; -#endif // Parser implementation template. template <class Types> @@ -257,11 +223,7 @@ public: // Lookup a string from the dynamic section with the given tag. StringEntry const* GetDynamicSectionString(unsigned int tag) override; -#ifdef EM_MIPS bool IsMips() const override { return this->ELFHeader.e_machine == EM_MIPS; } -#else - bool IsMips() const override { false; } -#endif // Print information about the ELF file. void PrintInfo(std::ostream& os) const override @@ -346,16 +308,12 @@ private: eti == ET_CORE) { return true; } -#if defined(ET_LOOS) && defined(ET_HIOS) if (eti >= ET_LOOS && eti <= ET_HIOS) { return true; } -#endif -#if defined(ET_LOPROC) && defined(ET_HIPROC) if (eti >= ET_LOPROC && eti <= ET_HIPROC) { return true; } -#endif return false; } @@ -466,18 +424,14 @@ cmELFInternalImpl<Types>::cmELFInternalImpl(cmELF* external, break; default: { unsigned int eti = static_cast<unsigned int>(this->ELFHeader.e_type); -#if defined(ET_LOOS) && defined(ET_HIOS) if (eti >= ET_LOOS && eti <= ET_HIOS) { this->ELFType = cmELF::FileTypeSpecificOS; break; } -#endif -#if defined(ET_LOPROC) && defined(ET_HIPROC) if (eti >= ET_LOPROC && eti <= ET_HIPROC) { this->ELFType = cmELF::FileTypeSpecificProc; break; } -#endif std::ostringstream e; e << "Unknown ELF file type " << eti; this->SetErrorMessage(e.str().c_str()); @@ -680,12 +634,7 @@ cmELF::StringEntry const* cmELFInternalImpl<Types>::GetDynamicSectionString( const long cmELF::TagRPath = DT_RPATH; const long cmELF::TagRunPath = DT_RUNPATH; - -#ifdef DT_MIPS_RLD_MAP_REL const long cmELF::TagMipsRldMapRel = DT_MIPS_RLD_MAP_REL; -#else -const long cmELF::TagMipsRldMapRel = 0; -#endif cmELF::cmELF(const char* fname) { @@ -735,15 +684,11 @@ cmELF::cmELF(const char* fname) // 32-bit ELF this->Internal = cm::make_unique<cmELFInternalImpl<cmELFTypes32>>( this, std::move(fin), order); - } -#ifndef _SCO_DS - else if (ident[EI_CLASS] == ELFCLASS64) { + } else if (ident[EI_CLASS] == ELFCLASS64) { // 64-bit ELF this->Internal = cm::make_unique<cmELFInternalImpl<cmELFTypes64>>( this, std::move(fin), order); - } -#endif - else { + } else { this->ErrorMessage = "ELF file class is not 32-bit or 64-bit."; return; } diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index dafb174..256c8a6 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -377,8 +377,8 @@ add_RunCMake_test(ctest_upload) add_RunCMake_test(ctest_fixtures) add_RunCMake_test(file -DMSYS=${MSYS}) add_RunCMake_test(file-CHMOD -DMSYS=${MSYS}) -if(HAVE_ELF_H OR CMAKE_SYSTEM_NAME STREQUAL "AIX") - add_RunCMake_test(file-RPATH -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME} -DHAVE_ELF_H=${HAVE_ELF_H}) +if(CMake_USE_ELF_PARSER) + add_RunCMake_test(file-RPATH -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME} -DCMake_USE_ELF_PARSER=${CMake_USE_ELF_PARSER}) endif() add_RunCMake_test(find_file) add_RunCMake_test(find_library -DCYGWIN=${CYGWIN} -DMSYS=${MSYS}) diff --git a/Tests/RunCMake/file-RPATH/RunCMakeTest.cmake b/Tests/RunCMake/file-RPATH/RunCMakeTest.cmake index eb7b497..e209f35 100644 --- a/Tests/RunCMake/file-RPATH/RunCMakeTest.cmake +++ b/Tests/RunCMake/file-RPATH/RunCMakeTest.cmake @@ -1,6 +1,6 @@ include(RunCMake) -if(HAVE_ELF_H) +if(CMake_USE_ELF_PARSER) run_cmake_command(ELF ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/ELF.cmake) endif() |