recursive_library.cmake 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. function(add_recursive_library Target)
  2. if (${CMAKE_VERSION} VERSION_LESS "3.21.0")
  3. message(FATAL_ERROR "add_recursive_library requires at least cmake 3.21.0 (because it uses CXX_LINKER_LAUNCHER)")
  4. endif()
  5. if (CMAKE_GENERATOR MATCHES "Visual.Studio.*")
  6. message(FATAL_ERROR "add_recursive_library is incompatible with Visual Studio generators")
  7. endif()
  8. find_package(Python3 REQUIRED)
  9. # this is not really an executable but we will use it to make CMake collect all dependencies to pass to the custom linking command (because there's no proper way to do it otherwise)
  10. add_executable(${Target} EXCLUDE_FROM_ALL)
  11. if (NOT (DEFINED CMAKE_POSITION_INDEPENDENT_CODE))
  12. # default should be the same as for usual static libraries - https://cmake.org/cmake/help/latest/prop_tgt/POSITION_INDEPENDENT_CODE.html
  13. set_property(TARGET ${Target} PROPERTY POSITION_INDEPENDENT_CODE Off)
  14. endif()
  15. set_property(TARGET ${Target} PROPERTY PREFIX ${CMAKE_STATIC_LIBRARY_PREFIX})
  16. set_property(TARGET ${Target} PROPERTY SUFFIX ${CMAKE_STATIC_LIBRARY_SUFFIX})
  17. # the result will consist of two files at most (if there are no input files of particular type the resulting output files won't be created):
  18. # ${PREFIX}${Target}${SUFFIX} - for objects not requiring global initialization
  19. # ${PREFIX}${Target}${GLOBAL_PART_SUFFIX}${SUFFIX} - for objects requiring global initialization
  20. set(GLOBAL_PART_SUFFIX ".global")
  21. if (MSVC)
  22. # if this is not disabled CMake generates additional call to mt.exe after the linking command, manifests are needed only for real executables and dlls
  23. target_link_options(${Target} PRIVATE "/MANIFEST:NO")
  24. endif()
  25. string(CONCAT CXX_LINKER_LAUNCHER_CMD "${Python3_EXECUTABLE}"
  26. ";${CMAKE_SOURCE_DIR}/build/scripts/create_recursive_library_for_cmake.py"
  27. ";--cmake-binary-dir;${CMAKE_BINARY_DIR}"
  28. ";--cmake-ar;${CMAKE_AR}"
  29. ";--cmake-ranlib;${CMAKE_RANLIB}"
  30. ";--cmake-host-system-name;${CMAKE_HOST_SYSTEM_NAME}"
  31. ";--global-part-suffix;${GLOBAL_PART_SUFFIX}"
  32. )
  33. if (CMAKE_CXX_STANDARD_LIBRARIES)
  34. # because they have to be excluded from input
  35. string(APPEND CXX_LINKER_LAUNCHER_CMD ";--cmake-cxx-standard-libraries;${CMAKE_CXX_STANDARD_LIBRARIES}")
  36. endif()
  37. string(APPEND CXX_LINKER_LAUNCHER_CMD ";--linking-cmdline") # this must be the last argument
  38. set_property(TARGET ${Target} PROPERTY CXX_LINKER_LAUNCHER ${CXX_LINKER_LAUNCHER_CMD})
  39. set_property(TARGET ${Target} PROPERTY LINK_DEPENDS
  40. "${CMAKE_SOURCE_DIR}/build/scripts/create_recursive_library_for_cmake.py"
  41. ";${CMAKE_SOURCE_DIR}/build/scripts/link_lib.py"
  42. )
  43. endfunction()