I have been using a check like this to check for the requirement to link with libm:
check_symbol_exists(pow "math.h" CMath_HAVE_LIBC_POW)
if (NOT CMath_HAVE_LIBC_POW)
set(CMAKE_REQUIRED_LIBRARIES_SAVE ${CMAKE_REQUIRED_LIBRARIES})
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} m)
check_symbol_exists(pow "math.h" CMath_HAVE_LIBM_POW)
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES_SAVE})
endif ()
set(CMath_pow FALSE)
if (CMath_HAVE_LIBC_POW OR CMath_HAVE_LIBM_POW)
set(CMath_pow TRUE)
endif ()
Overall, this has worked OK for years.
However, it doesn’t work when I start to build the same project with an embedded toolchain. In this case I have a toolchain file containing the following:
set(ARM_TOOLCHAIN_ROOT "D:/ARM/Arm GNU Toolchain arm-none-eabi/${CMAKE_SYSTEM_VERSION}")
set(CMAKE_SYSROOT "${ARM_TOOLCHAIN_ROOT}/arm-none-eabi")
set(CMAKE_FIND_ROOT_PATH "${ARM_TOOLCHAIN_ROOT}")
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
With this toolchain file, the requirement to link with libm is never satisfied and the build will fail due to a failing link step with missing math symbols.
The reason for this is that the first symbol check always succeeds, i.e. is a false positive. The test module compiles successfully, but there’s no link step to make the first check fail and the second check pass.
I’ve seen some historical discussion of undesirable false positives when using CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY
, but I haven’t seen any solutions. It’s clearly possible to directly hardcode linking to libm in the project and this does work, but since the project should work portably on many platforms I can’t hardcode assumptions about the toolchain and its libraries into the project. If anyone has any suggestions for how to do this, that would be much appreciated.
As an aside, I was wondering if the various try_compile-based tests could be a bit cleverer and permit linking with some extra source files such as startup assembly/C and a linker script. E.g. CMAKE_TRY_COMPILE_EXTRA_SOURCES and CMAKE_TRY_COMPILE_LINKER_FLAGS This would enable full executable generation on embedded platforms, making the STATIC_LIBRARY
setting unnecessary. Combined with CMAKE_CROSSCOMPILING_EMULATOR
, it could even run them. Or, could these tests use a sub-CMake to compile, link and run the test using a self-contained CMake project generated on the fly? This would get around the limitation of not being able to link with CMake targets at configuration time, as well as lifting a good bit of complexity out of CMake and unifying how programs are compiled and linked at configuration time and build time.
Thanks,
Roger