aboutsummaryrefslogtreecommitdiff
path: root/rcc/cmake/modules/AddRCC.cmake
diff options
context:
space:
mode:
authorRichard Qin <richard.qin.x@gmail.com>2026-10-20 01:29:21 +0800
committerRichard Qin <richard.qin.x@gmail.com>2026-10-20 01:29:21 +0800
commita59ba0e3eda5381623a4929486b2f673a883d8d8 (patch)
treead7af8234e12bd5ca27bcf61385705f8465de556 /rcc/cmake/modules/AddRCC.cmake
parentf20fef9298247bae52cfc8e879d24a29d190aae9 (diff)
downloadrcc-project-a59ba0e3eda5381623a4929486b2f673a883d8d8.tar.gz
rcc-project-a59ba0e3eda5381623a4929486b2f673a883d8d8.tar.xz
[CMake] Add compiler options and target helpers
Diffstat (limited to 'rcc/cmake/modules/AddRCC.cmake')
-rw-r--r--rcc/cmake/modules/AddRCC.cmake184
1 files changed, 184 insertions, 0 deletions
diff --git a/rcc/cmake/modules/AddRCC.cmake b/rcc/cmake/modules/AddRCC.cmake
new file mode 100644
index 0000000..11bd92e
--- /dev/null
+++ b/rcc/cmake/modules/AddRCC.cmake
@@ -0,0 +1,184 @@
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+include_guard(GLOBAL)
+include(GNUInstallDirs)
+include(HandleRCCOptions)
+
+macro(rcc_configure_output_directories)
+ set(RCC_RUNTIME_OUTPUT_INTDIR "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin")
+ set(RCC_LIBRARY_OUTPUT_INTDIR "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib")
+ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${RCC_RUNTIME_OUTPUT_INTDIR}")
+ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${RCC_LIBRARY_OUTPUT_INTDIR}")
+ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${RCC_LIBRARY_OUTPUT_INTDIR}")
+endmacro()
+
+function(rcc_set_output_directory target)
+ if(WIN32 OR CYGWIN)
+ set(moduleDir "${RCC_RUNTIME_OUTPUT_INTDIR}")
+ else()
+ set(moduleDir "${RCC_LIBRARY_OUTPUT_INTDIR}")
+ endif()
+ if(NOT CMAKE_CFG_INTDIR STREQUAL ".")
+ foreach(buildMode IN LISTS CMAKE_CONFIGURATION_TYPES)
+ string(TOUPPER "${buildMode}" configSuffix)
+ if(RCC_RUNTIME_OUTPUT_INTDIR)
+ string(REPLACE "${CMAKE_CFG_INTDIR}" "${buildMode}" binaryDir "${RCC_RUNTIME_OUTPUT_INTDIR}")
+ set_target_properties(${target} PROPERTIES RUNTIME_OUTPUT_DIRECTORY_${configSuffix} "${binaryDir}")
+ endif()
+ if(RCC_LIBRARY_OUTPUT_INTDIR)
+ string(REPLACE "${CMAKE_CFG_INTDIR}" "${buildMode}" libraryDir "${RCC_LIBRARY_OUTPUT_INTDIR}")
+ set_target_properties(${target} PROPERTIES ARCHIVE_OUTPUT_DIRECTORY_${configSuffix} "${libraryDir}")
+ endif()
+ if(moduleDir)
+ string(REPLACE "${CMAKE_CFG_INTDIR}" "${buildMode}" configModuleDir "${moduleDir}")
+ set_target_properties(${target} PROPERTIES LIBRARY_OUTPUT_DIRECTORY_${configSuffix} "${configModuleDir}")
+ endif()
+ endforeach()
+ else()
+ if(RCC_RUNTIME_OUTPUT_INTDIR)
+ set_target_properties(${target} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${RCC_RUNTIME_OUTPUT_INTDIR}")
+ endif()
+ if(RCC_LIBRARY_OUTPUT_INTDIR)
+ set_target_properties(${target} PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "${RCC_LIBRARY_OUTPUT_INTDIR}")
+ endif()
+ if(moduleDir)
+ set_target_properties(${target} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${moduleDir}")
+ endif()
+ endif()
+endfunction()
+
+function(rcc_update_pch target)
+ if(RCC_REQUIRES_RTTI OR RCC_REQUIRES_EH)
+ set(arg_DISABLE_PCH_REUSE ON)
+ endif()
+ get_target_property(sources ${target} SOURCES)
+ foreach(source IN LISTS sources)
+ get_filename_component(extension "${source}" EXT)
+ if(extension STREQUAL ".c" AND NOT arg_PRECOMPILE_HEADERS)
+ set(arg_DISABLE_PCH_REUSE ON)
+ elseif(extension STREQUAL ".mm")
+ set(arg_DISABLE_PCH_REUSE ON)
+ endif()
+ endforeach()
+ get_target_property(targetType ${target} TYPE)
+ if(targetType STREQUAL "EXECUTABLE")
+ get_target_property(positionIndependent ${target} POSITION_INDEPENDENT_CODE)
+ if(positionIndependent)
+ set(arg_DISABLE_PCH_REUSE ON)
+ endif()
+ endif()
+
+ set(pchPriority 0)
+ foreach(library IN LISTS arg_LINK_LIBS)
+ if(TARGET ${library})
+ get_target_property(libraryPriority ${library} RCC_PCH_PRIORITY)
+ get_target_property(libraryPCHDisabled ${library} DISABLE_PRECOMPILE_HEADERS)
+ if(libraryPriority GREATER pchPriority AND NOT libraryPCHDisabled)
+ set(pchPriority "${libraryPriority}")
+ set(pchReuse "${library}")
+ endif()
+ endif()
+ endforeach()
+ if(arg_PRECOMPILE_HEADERS)
+ message(DEBUG "Adding PCH ${arg_PRECOMPILE_HEADERS} for ${target} (prio ${pchPriority})")
+ target_precompile_headers(${target} PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:${arg_PRECOMPILE_HEADERS}>")
+ if(NOT arg_DISABLE_PCH_REUSE)
+ math(EXPR pchPriority "${pchPriority} + 1")
+ set_target_properties(${target} PROPERTIES RCC_PCH_PRIORITY "${pchPriority}")
+ endif()
+ elseif(pchReuse AND NOT arg_DISABLE_PCH_REUSE)
+ message(DEBUG "Using PCH ${pchReuse} for ${target} (prio ${pchPriority})")
+ target_precompile_headers(${target} REUSE_FROM ${pchReuse})
+ else()
+ message(DEBUG "Using NO PCH for ${target}")
+ endif()
+endfunction()
+
+function(rcc_setup_rpath target)
+ if(CMAKE_INSTALL_RPATH)
+ return()
+ endif()
+ set(extraLibraryDir "")
+ if(RCC_INSTALL_PREFIX AND NOT RCC_INSTALL_PREFIX STREQUAL CMAKE_INSTALL_PREFIX)
+ set(extraLibraryDir "${RCC_LIBRARY_DIR}")
+ elseif(RCC_BUILD_LIBRARY_DIR)
+ set(extraLibraryDir "${RCC_LIBRARY_DIR}")
+ endif()
+ get_target_property(targetType ${target} TYPE)
+ if(targetType STREQUAL "EXECUTABLE")
+ set(installDirectory "${CMAKE_INSTALL_FULL_BINDIR}")
+ else()
+ set(installDirectory "${CMAKE_INSTALL_FULL_LIBDIR}")
+ endif()
+ file(RELATIVE_PATH relativeLibraryDir "${installDirectory}" "${CMAKE_INSTALL_FULL_LIBDIR}")
+
+ if(APPLE)
+ set(installName INSTALL_NAME_DIR "@rpath")
+ set(installRpath "@loader_path/${relativeLibraryDir}" ${extraLibraryDir})
+ elseif(CMAKE_SYSTEM_NAME MATCHES "AIX" AND BUILD_SHARED_LIBS)
+ set(installRpath "${RCC_LIBRARY_OUTPUT_INTDIR}" "${CMAKE_INSTALL_FULL_LIBDIR}" ${extraLibraryDir})
+ elseif(UNIX)
+ set(buildRpath "\$ORIGIN/../lib" ${extraLibraryDir})
+ set(installRpath "\$ORIGIN/${relativeLibraryDir}")
+ if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD|DragonFly")
+ target_link_options(${target} PRIVATE "LINKER:-z,origin")
+ endif()
+ if(RCC_LINKER_IS_GNULD AND RCC_LIBRARY_OUTPUT_INTDIR)
+ target_link_options(${target} PRIVATE "LINKER:-rpath-link,${RCC_LIBRARY_OUTPUT_INTDIR}")
+ endif()
+ else()
+ return()
+ endif()
+ if("${CMAKE_BUILD_RPATH}" STREQUAL "")
+ if(CMAKE_SYSTEM_NAME MATCHES "Darwin|AIX")
+ set_target_properties(${target} PROPERTIES BUILD_WITH_INSTALL_RPATH ON)
+ else()
+ set_property(TARGET ${target} APPEND PROPERTY BUILD_RPATH "${buildRpath}")
+ endif()
+ endif()
+ set_target_properties(${target} PROPERTIES INSTALL_RPATH "${installRpath}" ${installName})
+endfunction()
+
+function(rcc_configure_target target)
+ rcc_apply_options(${target})
+ rcc_set_output_directory(${target})
+ rcc_update_pch(${target})
+ get_target_property(targetType ${target} TYPE)
+ if(targetType MATCHES "^(EXECUTABLE|SHARED_LIBRARY|MODULE_LIBRARY)$" AND NOT arg_NO_INSTALL_RPATH)
+ rcc_setup_rpath(${target})
+ endif()
+ if(targetType STREQUAL "SHARED_LIBRARY")
+ if(MSVC)
+ set_target_properties(${target} PROPERTIES PREFIX "")
+ endif()
+ if(UNIX)
+ set_target_properties(${target} PROPERTIES
+ VERSION "${RCC_VERSION_MAJOR}.${RCC_VERSION_MINOR}"
+ SOVERSION "${RCC_VERSION_MAJOR}.${RCC_VERSION_MINOR}")
+ endif()
+ endif()
+endfunction()
+
+function(add_rcc_library name)
+ cmake_parse_arguments(PARSE_ARGV 1 arg "DISABLE_PCH_REUSE;NO_INSTALL_RPATH" "" "LINK_LIBS;PRECOMPILE_HEADERS")
+ add_library(${name} ${arg_UNPARSED_ARGUMENTS})
+ target_link_libraries(${name} PUBLIC RCCHeaders ${arg_LINK_LIBS})
+ rcc_configure_target(${name})
+ install(TARGETS ${name} EXPORT RCCTargets
+ ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
+ LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
+ RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
+endfunction()
+
+function(add_rcc_executable name)
+ cmake_parse_arguments(PARSE_ARGV 1 arg "DISABLE_PCH_REUSE;NO_INSTALL_RPATH" "" "LINK_LIBS;PRECOMPILE_HEADERS")
+ add_executable(${name} ${arg_UNPARSED_ARGUMENTS})
+ target_link_libraries(${name} PRIVATE RCCHeaders ${arg_LINK_LIBS})
+ rcc_configure_target(${name})
+endfunction()
+
+function(add_rcc_tool name)
+ add_rcc_executable(${name} ${ARGN})
+ install(TARGETS ${name} EXPORT RCCTargets
+ RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
+endfunction()