We are catching errors in our CMake makefiles due to lack of -fPIC
. Her's one from a ci20 MIPS dev-board:
...
[ 92%] Built target cryptopp-object
Scanning dependencies of target cryptopp-shared
Scanning dependencies of target cryptopp-static
Linking CXX static library libcryptopp.a
Linking CXX shared library libcryptopp.so
/usr/bin/ld: CMakeFiles/cryptopp-object.dir/cryptlib.cpp.o: relocation R_MIPS_HI16 against
`a local symbol' can not be used when making a shared object; recompile with -fPIC
CMakeFiles/cryptopp-object.dir/cryptlib.cpp.o: could not read symbols: Bad value
collect2: ld returned 1 exit status
The project's policy is to us PIC everywhere except 32-bit x86 due to register pressures. That means x86_64, ARM-32, Aarch32, Aarch64, MIPS, MIPS64, UltraSparc, etc get PIC.
I believe the target processor is provided in CMAKE_SYSTEM_PROCESSOR
. The problem I am having is the docs don't tell me the values, so I can't figure out how to craft a "not 32-bit x86" test.
How do I detect 32-bit x86 processor in CMakeList.txt?
Even better, I would like to see a comprehensive list of processors that CMake sets CMAKE_SYSTEM_PROCESSOR
to. If anyone has the list, then it would be great to provide it.
I probably would build something around the compiler.
A close approximation using existing variables/modules would be:
include(TestBigEndian)
if (NOT WIN32)
TEST_BIG_ENDIAN(_bigendian)
if((CMAKE_SIZEOF_VOID_P GREATER 4) OR (_bigendian))
message(
STATUS "Setting ${CMAKE_CXX_COMPILE_OPTIONS_PIC} "
"for machine ${CMAKE_HOST_SYSTEM_PROCESSOR}"
)
set(CMAKE_POSITION_INDEPENDENT_CODE 1)
endif()
endif()
In short what I have done:
WIN32
is also valid for 64 Bit Windows compilers/environmentsCMAKE_SIZEOF_VOID_P GREATER 4
checks for "greater then 32 Bit"CMAKE_POSITION_INDEPENDENT_CODE
to set -fPIC
I admit a more accurate method would be to build something around a pre-defined macros test.
Edit: Added "Predefined Macros Check" Alternative
Here is the more precise check for predefined macros:
include(CheckCXXSourceCompiles)
if (CMAKE_CXX_COMPILE_OPTIONS_PIC)
set(
_preDefMacrosX86
__i386 __i386__ __i486__ __i586__ __i686__
_M_I86 _M_IX86 __X86__ _X86_ __THW_INTEL__
__I86__ __INTEL__ __386
)
set(_code "void main() {}")
foreach(_macro IN LISTS _preDefMacrosX86)
set(
_code
"${_code}\n\#ifdef ${_macro}\n\#error ${_macro} is defined\n\#endif"
)
endforeach()
CHECK_CXX_SOURCE_COMPILES("${_code}" _canCompileX86DoesFailCheck)
if((CMAKE_SIZEOF_VOID_P GREATER 4) OR (_canCompileX86DoesFailCheck))
message(STATUS "Setting ${CMAKE_CXX_COMPILE_OPTIONS_PIC}")
set(CMAKE_POSITION_INDEPENDENT_CODE 1)
endif()
endif()
References