# SPDX-License-Identifier: GPL-3.0-or-later include_guard(GLOBAL) include(CheckCCompilerFlag) include(CheckCSourceCompiles) include(CheckCXXCompilerFlag) include(CheckCXXSourceCompiles) include(CMakePushCheckState) include(CheckLinkerFlag) include(CheckSymbolExists) function(rcc_append_flags value) foreach(variable IN LISTS ARGN) set(${variable} "${${variable}} ${value}" PARENT_SCOPE) endforeach() endfunction() macro(rcc_add_supported_warning flag name) check_c_compiler_flag("-Werror ${flag}" RCC_C_SUPPORTS_${name}) if(RCC_C_SUPPORTS_${name}) rcc_append_flags("${flag}" CMAKE_C_FLAGS) endif() check_cxx_compiler_flag("-Werror ${flag}" RCC_CXX_SUPPORTS_${name}) if(RCC_CXX_SUPPORTS_${name}) rcc_append_flags("${flag}" CMAKE_CXX_FLAGS) endif() endmacro() macro(rcc_configure_job_pools) set(RCC_PARALLEL_COMPILE_JOBS "" CACHE STRING "Maximum concurrent compilation jobs (Ninja only)") set(RCC_PARALLEL_LINK_JOBS "" CACHE STRING "Maximum concurrent link jobs (Ninja only)") if(RCC_RAM_PER_COMPILE_JOB OR RCC_RAM_PER_LINK_JOB) cmake_host_system_information(RESULT rccAvailableMemory QUERY AVAILABLE_PHYSICAL_MEMORY) cmake_host_system_information(RESULT rccLogicalCores QUERY NUMBER_OF_LOGICAL_CORES) endif() foreach(rccJobKind COMPILE LINK) if(RCC_RAM_PER_${rccJobKind}_JOB) math(EXPR rccMemoryJobs "${rccAvailableMemory} / ${RCC_RAM_PER_${rccJobKind}_JOB}" OUTPUT_FORMAT DECIMAL) if(rccMemoryJobs LESS 1) set(rccMemoryJobs 1) endif() if(rccMemoryJobs LESS rccLogicalCores) set(RCC_PARALLEL_${rccJobKind}_JOBS "${rccMemoryJobs}") else() set(RCC_PARALLEL_${rccJobKind}_JOBS "${rccLogicalCores}") endif() endif() endforeach() if(RCC_PARALLEL_COMPILE_JOBS) if(CMAKE_GENERATOR MATCHES "Ninja") set_property(GLOBAL APPEND PROPERTY JOB_POOLS compile_job_pool=${RCC_PARALLEL_COMPILE_JOBS}) set(CMAKE_JOB_POOL_COMPILE compile_job_pool) else() message(WARNING "Job pooling is only available with Ninja generators.") endif() endif() if(CMAKE_GENERATOR MATCHES "Ninja") if(NOT RCC_PARALLEL_LINK_JOBS AND rccLTOMode STREQUAL "THIN") message(STATUS "ThinLTO provides its own parallel linking - limiting parallel link jobs to 2.") set(RCC_PARALLEL_LINK_JOBS 2) endif() if(RCC_PARALLEL_LINK_JOBS) set_property(GLOBAL APPEND PROPERTY JOB_POOLS link_job_pool=${RCC_PARALLEL_LINK_JOBS}) set(CMAKE_JOB_POOL_LINK link_job_pool) endif() elseif(RCC_PARALLEL_LINK_JOBS) message(WARNING "Job pooling is only available with Ninja generators.") endif() endmacro() macro(rcc_configure_platform_checks) if(UNIX AND CMAKE_SYSTEM_NAME MATCHES "AIX") list(APPEND CMAKE_REQUIRED_DEFINITIONS "-D_XOPEN_SOURCE=700" "-D_LARGE_FILE_API") endif() if(UNIX AND CMAKE_SYSTEM_NAME MATCHES "SunOS") list(APPEND CMAKE_REQUIRED_DEFINITIONS "-D_FILE_OFFSET_BITS=64") endif() check_symbol_exists(__GLIBC__ stdio.h RCC_USING_GLIBC) if(RCC_USING_GLIBC OR CYGWIN) add_compile_definitions(_GNU_SOURCE) list(APPEND CMAKE_REQUIRED_DEFINITIONS "-D_GNU_SOURCE") endif() if(RCC_USING_GLIBC AND CMAKE_SIZEOF_VOID_P EQUAL 4) add_compile_definitions(_FILE_OFFSET_BITS=64) list(APPEND CMAKE_REQUIRED_DEFINITIONS "-D_FILE_OFFSET_BITS=64") endif() if(NOT RCC_ENABLE_PIC) rcc_append_flags("-fno-pie" CMAKE_EXE_LINKER_FLAGS) endif() endmacro() macro(rcc_configure_platform_link_options) if(APPLE) rcc_append_flags("-Wl,-flat_namespace -Wl,-undefined -Wl,dynamic_lookup" CMAKE_MODULE_LINKER_FLAGS) endif() if(CMAKE_SYSTEM_NAME MATCHES "AIX") if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") rcc_append_flags("-mcmodel=large" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) rcc_append_flags("-Wl,-bglink=large" CMAKE_EXE_LINKER_FLAGS CMAKE_MODULE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS) elseif(CMAKE_CXX_COMPILER_ID MATCHES "XL") rcc_append_flags("-Wl,-bbigtoc -bcdtors:mbr" CMAKE_EXE_LINKER_FLAGS CMAKE_MODULE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS) endif() if(BUILD_SHARED_LIBS) message(WARNING "Build and install environment path info may be exposed; binaries will also be unrelocatable.") endif() endif() if(CMAKE_SYSTEM_NAME MATCHES "OS390") rcc_append_flags("-Wl,-bcompress=yes" CMAKE_EXE_LINKER_FLAGS CMAKE_MODULE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS) endif() if(NOT (CMAKE_SYSTEM_NAME MATCHES "Darwin|FreeBSD|OpenBSD|DragonFly|AIX|OS390|Emscripten" OR WIN32 OR CYGWIN) AND NOT RCC_USE_SANITIZER) rcc_append_flags("-Wl,-z,defs" CMAKE_SHARED_LINKER_FLAGS) endif() endmacro() macro(rcc_configure_platform_definitions) if(UNIX AND CMAKE_SYSTEM_NAME MATCHES "AIX") add_compile_definitions(_XOPEN_SOURCE=700 _LARGE_FILE_API) add_compile_options(-pthread) rcc_append_flags("-shared -Wl,-G" CMAKE_MODULE_LINKER_FLAGS) rcc_append_flags("-shared" CMAKE_SHARED_LINKER_FLAGS) endif() if(CMAKE_SYSTEM_NAME MATCHES "OS390") add_compile_definitions(_XOPEN_SOURCE=600 _XPLATFORM_SOURCE _OPEN_SYS _OPEN_SYS_FILE_EXT _EXT) rcc_append_flags("-fzos-le-char-mode=ascii -m64" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() if(UNIX AND CMAKE_SYSTEM_NAME MATCHES "SunOS") add_compile_definitions(_FILE_OFFSET_BITS=64) endif() endmacro() macro(rcc_configure_warning_options) if(MSVC) if(RCC_ENABLE_WERROR) rcc_append_flags("/WX" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() if(RCC_ENABLE_WARNINGS) string(REGEX REPLACE " /W[0-4]" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") string(REGEX REPLACE " /W[0-4]" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") rcc_append_flags("/W4" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() if(NOT RCC_CLANG_CL) if(RCC_ENABLE_WARNING_SUPPRESSIONS) rcc_append_flags( "-wd4146 -wd4244 -wd4267 -wd4456 -wd4457 -wd4458 -wd4459 -wd4624 -wd4100 -wd4127 -wd4505 -wd4702 -wd4245 -wd4310 -wd4701 -wd4703 -wd4389 -wd4805 -wd4577 -wd4319 -wd4324 -wd4251 -wd4275" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() rcc_append_flags("-w14062 -we4238" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() endif() if(RCC_GCC_COMPATIBLE AND RCC_ENABLE_WERROR) rcc_append_flags("-Werror" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) rcc_append_flags("-Wno-error" CMAKE_REQUIRED_FLAGS) endif() if(RCC_GCC_COMPATIBLE OR CMAKE_CXX_COMPILER_ID MATCHES "XL") rcc_append_flags("-Werror=date-time" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") rcc_append_flags("-Werror=unguarded-availability-new" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() set(rccInitialCFlags "${CMAKE_C_FLAGS}") set(rccInitialCXXFlags "${CMAKE_CXX_FLAGS}") if(RCC_ENABLE_WARNINGS AND (RCC_GCC_COMPATIBLE OR RCC_CLANG_CL)) if(NOT RCC_CLANG_CL) rcc_append_flags("-Wall" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() rcc_append_flags("-Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") rcc_append_flags("-Wno-missing-field-initializers" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) else() rcc_append_flags("-Wmissing-field-initializers" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() if(RCC_ENABLE_PEDANTIC AND RCC_GCC_COMPATIBLE) rcc_append_flags("-pedantic -Wno-long-long" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) rcc_add_supported_warning("-Wc++98-compat-extra-semi" CXX98_COMPAT_EXTRA_SEMI) endif() rcc_append_flags("-Wimplicit-fallthrough" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") rcc_append_flags("-Wcovered-switch-default" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") # Match LLVM's GCC warning suppression policy and version conditions. if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 15.0) rcc_append_flags("-Wno-uninitialized" CMAKE_CXX_FLAGS) else() rcc_append_flags("-Wno-maybe-uninitialized" CMAKE_CXX_FLAGS) endif() rcc_append_flags("-Wno-nonnull" CMAKE_CXX_FLAGS) if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 8.1) rcc_append_flags("-Wno-class-memaccess" CMAKE_CXX_FLAGS) endif() if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 13.1) rcc_append_flags("-Wno-dangling-reference" CMAKE_CXX_FLAGS) endif() if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 9.1) rcc_append_flags("-Wno-redundant-move -Wno-pessimizing-move" CMAKE_CXX_FLAGS) endif() rcc_append_flags("-Wno-array-bounds" CMAKE_CXX_FLAGS) if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 11.1) rcc_append_flags("-Wno-stringop-overread" CMAKE_CXX_FLAGS) endif() if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 12.1) rcc_append_flags("-Wno-dangling-pointer" CMAKE_CXX_FLAGS) endif() if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 14.0) rcc_append_flags("-Wno-unused-but-set-parameter" CMAKE_CXX_FLAGS) endif() endif() rcc_append_flags("-Wno-noexcept-type" CMAKE_CXX_FLAGS) if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") rcc_append_flags("-Wnon-virtual-dtor" CMAKE_CXX_FLAGS) endif() rcc_append_flags("-Wdelete-non-virtual-dtor" CMAKE_CXX_FLAGS) check_cxx_compiler_flag("-Wsuggest-override" RCC_SUPPORTS_SUGGEST_OVERRIDE) if(RCC_SUPPORTS_SUGGEST_OVERRIDE) cmake_push_check_state() string(APPEND CMAKE_REQUIRED_FLAGS " -Werror=suggest-override") check_cxx_source_compiles([=[ class Base { public: virtual void anchor(); }; class Derived : Base { public: void anchor() final; }; int main() { return 0; } ]=] RCC_SUGGEST_OVERRIDE_ACCEPTS_FINAL) cmake_pop_check_state() if(RCC_SUGGEST_OVERRIDE_ACCEPTS_FINAL) rcc_append_flags("-Wsuggest-override" CMAKE_CXX_FLAGS) endif() endif() cmake_push_check_state() string(APPEND CMAKE_REQUIRED_FLAGS " -Werror -Wcomment") check_c_source_compiles("// \\\\\\n//\\nint main(void) { return 0; }" RCC_C_WCOMMENT_ACCEPTS_LINE_WRAP) cmake_pop_check_state() if(NOT RCC_C_WCOMMENT_ACCEPTS_LINE_WRAP) rcc_append_flags("-Wno-comment" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") rcc_append_flags("-Wstring-conversion" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) rcc_append_flags("-Wno-pass-failed" CMAKE_CXX_FLAGS) endif() if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") rcc_append_flags("-Wno-misleading-indentation" CMAKE_CXX_FLAGS) else() rcc_add_supported_warning("-Wmisleading-indentation" MISLEADING_INDENTATION) endif() rcc_add_supported_warning("-Wctad-maybe-unsupported" CTAD_MAYBE_UNSUPPORTED) elseif(RCC_GCC_COMPATIBLE AND NOT RCC_ENABLE_WARNINGS) rcc_append_flags("-w" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() if(NOT RCC_ENABLE_WARNING_SUPPRESSIONS AND (RCC_GCC_COMPATIBLE OR RCC_CLANG_CL)) foreach(rccLanguage C CXX) string(LENGTH "${rccInitial${rccLanguage}Flags}" rccInitialLength) string(SUBSTRING "${CMAKE_${rccLanguage}_FLAGS}" ${rccInitialLength} -1 rccAddedFlags) string(REGEX REPLACE "(^| +)-Wno-[a-zA-Z0-9_-]+" "" rccAddedFlags "${rccAddedFlags}") set(CMAKE_${rccLanguage}_FLAGS "${rccInitial${rccLanguage}Flags}${rccAddedFlags}") endforeach() endif() endmacro() # Configure in the caller's directory scope, as LLVM's option modules do. macro(rcc_configure_options) if(DEFINED CMAKE_CXX_STANDARD AND CMAKE_CXX_STANDARD LESS 23) message(FATAL_ERROR "RCC requires CMAKE_CXX_STANDARD to be at least 23") endif() set(CMAKE_CXX_STANDARD 23 CACHE STRING "C++ standard to conform to") set(CMAKE_CXX_STANDARD_REQUIRED YES) set(CMAKE_CXX_EXTENSIONS NO) if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) message(WARNING "No build type selected. Defaulted CMAKE_BUILD_TYPE=Release.") set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type: Debug, Release, RelWithDebInfo, MinSizeRel" FORCE) endif() if(CMAKE_DEFAULT_BUILD_TYPE) set(CMAKE_TRY_COMPILE_CONFIGURATION "${CMAKE_DEFAULT_BUILD_TYPE}") elseif(CMAKE_CONFIGURATION_TYPES) list(GET CMAKE_CONFIGURATION_TYPES 0 CMAKE_TRY_COMPILE_CONFIGURATION) elseif(CMAKE_BUILD_TYPE) set(CMAKE_TRY_COMPILE_CONFIGURATION "${CMAKE_BUILD_TYPE}") endif() set(RCC_ADDITIONAL_BUILD_TYPES "" CACHE STRING "Additional allowed CMake build types") set(rccAllowedBuildTypes DEBUG RELEASE RELWITHDEBINFO MINSIZEREL ${RCC_ADDITIONAL_BUILD_TYPES}) string(REPLACE ";" "|" rccAllowedBuildTypes "${rccAllowedBuildTypes}") string(TOUPPER "${rccAllowedBuildTypes}" rccAllowedBuildTypes) set(assertionsDefault OFF) string(TOUPPER "${CMAKE_BUILD_TYPE}" buildType) if(CMAKE_BUILD_TYPE AND NOT buildType MATCHES "^(${rccAllowedBuildTypes})$") message(FATAL_ERROR "Unknown value for CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}") endif() if(buildType STREQUAL "DEBUG") set(assertionsDefault ON) endif() option(RCC_ENABLE_WARNINGS "Enable compiler warnings" ON) option(RCC_ENABLE_WARNING_SUPPRESSIONS "Suppress compiler warnings" ON) option(RCC_ENABLE_PEDANTIC "Compile with pedantic enabled" ON) option(RCC_ENABLE_WERROR "Treat compiler warnings as errors" OFF) option(RCC_ENABLE_ASSERTIONS "Enable assertions" "${assertionsDefault}") option(RCC_ENABLE_EH "Enable C++ exceptions" OFF) option(RCC_ENABLE_RTTI "Enable C++ runtime type information" OFF) option(RCC_ENABLE_UNWIND_TABLES "Emit unwind tables for the libraries" ON) set(RCC_USE_SANITIZER "" CACHE STRING "Sanitizer used to build binaries; use LLVM's platform-specific combinations") option(RCC_OPTIMIZE_SANITIZED_BUILDS "Use -O1 for Debug sanitizer builds" ON) set(RCC_UBSAN_FLAGS "-fsanitize=undefined -fno-sanitize=vptr,function -fno-sanitize-recover=all" CACHE STRING "Compiler flags for the Undefined sanitizer") if(RCC_ENABLE_EH AND NOT RCC_ENABLE_RTTI) message(FATAL_ERROR "RCC_ENABLE_EH requires RCC_ENABLE_RTTI.") endif() if(NOT DEFINED RCC_GCC_COMPATIBLE) if(CMAKE_COMPILER_IS_GNUCXX) set(RCC_GCC_COMPATIBLE ON) elseif(MSVC) set(RCC_GCC_COMPATIBLE OFF) elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang|Intel") set(RCC_GCC_COMPATIBLE ON) endif() endif() set(RCC_CLANG_CL OFF) if(MSVC AND CMAKE_CXX_COMPILER_ID MATCHES "Clang") set(RCC_CLANG_CL ON) endif() if(WIN32) set(RCC_ON_UNIX OFF) elseif(FUCHSIA OR UNIX OR CYGWIN) set(RCC_ON_UNIX ON) elseif(CMAKE_SYSTEM_NAME STREQUAL "Generic") set(RCC_ON_UNIX OFF) else() message(SEND_ERROR "Unable to determine platform") endif() rcc_configure_additional_options() rcc_configure_standard_library() rcc_configure_platform_checks() rcc_configure_job_pools() if(RCC_ENABLE_ASSERTIONS) if(NOT WIN32 OR MINGW) add_compile_definitions(_DEBUG) endif() if(NOT buildType STREQUAL "DEBUG") add_compile_options("$<$:-UNDEBUG>") if(MSVC) foreach(rccFlagsVariable CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELWITHDEBINFO CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_RELWITHDEBINFO CMAKE_C_FLAGS_MINSIZEREL) string(REGEX REPLACE "(^| )[/-]D *NDEBUG($| )" " " ${rccFlagsVariable} "${${rccFlagsVariable}}") endforeach() endif() endif() add_compile_definitions(_GLIBCXX_ASSERTIONS) check_cxx_source_compiles([=[ #define _LIBCPP_HARDENING_MODE _LIBCPP_HARDENING_MODE_EXTENSIVE #include int main() { return 0; } ]=] RCC_SUPPORTS_LIBCXX_HARDENING_MODE) if(RCC_SUPPORTS_LIBCXX_HARDENING_MODE) add_compile_definitions(_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE) endif() endif() rcc_configure_standard_library_abi() rcc_configure_platform_link_options() rcc_configure_linker() rcc_configure_platform_options() rcc_configure_warning_options() if(RCC_USE_SANITIZER) rcc_configure_sanitizer_options() endif() rcc_configure_debug_options() rcc_configure_sections() if(MSVC) string(REGEX REPLACE "(^| ) */EH[-cs]+ *( |$)" "\\1 \\2" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") string(REGEX REPLACE "(^| ) */GR-? *( |$)" "\\1 \\2" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") endif() rcc_configure_profile_options() rcc_configure_pch_and_cache() rcc_configure_lto() rcc_configure_relative_paths() rcc_configure_platform_definitions() endmacro() macro(rcc_configure_sanitizer_options) set(ubsanFlags "${RCC_UBSAN_FLAGS}") set(sanitizerFlags) set(commonFlags ON) if(RCC_ON_UNIX) if(RCC_USE_SANITIZER STREQUAL "Address") list(APPEND sanitizerFlags -fsanitize=address) elseif(RCC_USE_SANITIZER STREQUAL "HWAddress") list(APPEND sanitizerFlags -fsanitize=hwaddress) elseif(RCC_USE_SANITIZER MATCHES "Memory(WithOrigins)?") list(APPEND sanitizerFlags -fsanitize=memory) if(RCC_USE_SANITIZER STREQUAL "MemoryWithOrigins") list(APPEND sanitizerFlags -fsanitize-memory-track-origins) endif() elseif(RCC_USE_SANITIZER STREQUAL "Undefined") list(APPEND sanitizerFlags ${ubsanFlags}) elseif(RCC_USE_SANITIZER STREQUAL "Thread") list(APPEND sanitizerFlags -fsanitize=thread) elseif(RCC_USE_SANITIZER STREQUAL "DataFlow") list(APPEND sanitizerFlags -fsanitize=dataflow) set(commonFlags OFF) elseif(RCC_USE_SANITIZER STREQUAL "Address;Undefined" OR RCC_USE_SANITIZER STREQUAL "Undefined;Address") list(APPEND sanitizerFlags -fsanitize=address ${ubsanFlags}) elseif(RCC_USE_SANITIZER STREQUAL "Leaks") list(APPEND sanitizerFlags -fsanitize=leak) else() message(FATAL_ERROR "Unsupported RCC_USE_SANITIZER value: ${RCC_USE_SANITIZER}") endif() elseif(MINGW OR MSVC) if(NOT RCC_USE_SANITIZER MATCHES "^(Address|Undefined|Address;Undefined|Undefined;Address)$") message(FATAL_ERROR "Unsupported sanitizer in this Windows environment: ${RCC_USE_SANITIZER}") endif() if("Address" IN_LIST RCC_USE_SANITIZER) if(MSVC AND NOT RCC_CLANG_CL) list(APPEND sanitizerFlags /fsanitize=address) else() list(APPEND sanitizerFlags -fsanitize=address) endif() endif() if("Undefined" IN_LIST RCC_USE_SANITIZER) if(MSVC AND NOT RCC_CLANG_CL) message(FATAL_ERROR "Undefined sanitizer requires clang-cl in the MSVC environment") endif() list(APPEND sanitizerFlags ${ubsanFlags}) endif() else() message(FATAL_ERROR "RCC_USE_SANITIZER is not supported on this platform") endif() if(commonFlags) if(MSVC AND NOT RCC_CLANG_CL) rcc_append_flags("/Z7" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) rcc_append_flags("/debug" CMAKE_EXE_LINKER_FLAGS CMAKE_MODULE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS) foreach(rccFlagsVariable CMAKE_EXE_LINKER_FLAGS CMAKE_MODULE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS) string(REGEX REPLACE "(^| )/INCREMENTAL($| )" " /INCREMENTAL:NO " ${rccFlagsVariable} "${${rccFlagsVariable}}") endforeach() if(CMAKE_C_COMPILER_ARCHITECTURE_ID STREQUAL "X86") rcc_append_flags("/Oy-" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() else() rcc_append_flags("-fno-omit-frame-pointer" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) if(NOT buildType STREQUAL "DEBUG" AND NOT buildType STREQUAL "RELWITHDEBINFO" AND CMAKE_CXX_COMPILER_ID MATCHES "Clang") rcc_append_flags("-gline-tables-only" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() if(buildType STREQUAL "DEBUG" AND RCC_OPTIMIZE_SANITIZED_BUILDS) rcc_append_flags("-O1" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() endif() endif() string(JOIN " " rccSanitizerFlags ${sanitizerFlags}) rcc_append_flags("${rccSanitizerFlags}" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) if(MSVC) if(NOT RCC_CLANG_CL AND "Address" IN_LIST RCC_USE_SANITIZER) foreach(rccFlagsVariable CMAKE_CXX_FLAGS_${buildType} CMAKE_C_FLAGS_${buildType}) string(REGEX REPLACE "(^| )/RTC[1csu]*($| )" " " ${rccFlagsVariable} "${${rccFlagsVariable}}") endforeach() endif() if(RCC_LINKER_IS_LLD_LINK AND "Address" IN_LIST RCC_USE_SANITIZER) if(CMAKE_C_COMPILER_ARCHITECTURE_ID STREQUAL "X86") set(runtimeArch i386) else() set(runtimeArch x86_64) endif() rcc_append_flags("/opt:nolldtailmerge clang_rt.asan_dynamic-${runtimeArch}.lib" CMAKE_EXE_LINKER_FLAGS CMAKE_MODULE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS) if(CMAKE_MSVC_RUNTIME_LIBRARY MATCHES "^(MultiThreaded|MultiThreadedDebug)$") set(rccRuntimeThunk "clang_rt.asan_static_runtime_thunk-${runtimeArch}.lib") else() set(rccRuntimeThunk "clang_rt.asan_dynamic_runtime_thunk-${runtimeArch}.lib") endif() rcc_append_flags("/wholearchive:${rccRuntimeThunk}" CMAKE_EXE_LINKER_FLAGS CMAKE_MODULE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS) endif() endif() if(RCC_USE_SANITIZE_COVERAGE) rcc_append_flags("-fsanitize=fuzzer-no-link" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() if(RCC_USE_SANITIZER MATCHES ".*Undefined.*") set(rccIgnorelist "${PROJECT_SOURCE_DIR}/utils/sanitizers/ubsan_ignorelist.txt") if(EXISTS "${rccIgnorelist}") rcc_append_flags("-fsanitize-ignorelist=\"${rccIgnorelist}\"" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() endif() endmacro() macro(rcc_configure_compiler_rt_path) if(RCC_CLANG_CL AND (RCC_BUILD_INSTRUMENTED OR RCC_USE_SANITIZER)) execute_process( COMMAND "${CMAKE_CXX_COMPILER}" /clang:-print-libgcc-file-name /clang:--rtlib=compiler-rt OUTPUT_VARIABLE rccCompilerRTFile ERROR_VARIABLE rccClangCLError RESULT_VARIABLE rccClangCLResult OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_STRIP_TRAILING_WHITESPACE) if(NOT rccClangCLResult STREQUAL "0") message(FATAL_ERROR "Unable to invoke clang-cl to find resource dir: ${rccClangCLError}") endif() file(TO_CMAKE_PATH "${rccCompilerRTFile}" rccCompilerRTFile) get_filename_component(rccRuntimeDir "${rccCompilerRTFile}" DIRECTORY) foreach(rccFlagsVariable CMAKE_EXE_LINKER_FLAGS CMAKE_MODULE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS) set(${rccFlagsVariable} "${CMAKE_CXX_LINKER_WRAPPER_FLAG}/libpath:\"${rccRuntimeDir}\" ${${rccFlagsVariable}}") endforeach() endif() endmacro() function(rcc_apply_options target) set(enableEH ${RCC_ENABLE_EH}) set(enableRTTI ${RCC_ENABLE_RTTI}) if(RCC_REQUIRES_EH) set(enableEH ON) endif() if(RCC_REQUIRES_RTTI) set(enableRTTI ON) endif() if(enableEH AND NOT enableRTTI) message(AUTHOR_WARNING "Exception handling requires RTTI; enabling RTTI for ${target}") set(enableRTTI ON) endif() set(cxxFlags) if(MSVC) if(enableEH) list(APPEND cxxFlags /EHsc) else() list(APPEND cxxFlags /EHs-c-) target_compile_definitions(${target} PRIVATE _HAS_EXCEPTIONS=0) endif() if(enableRTTI) list(APPEND cxxFlags /GR) else() list(APPEND cxxFlags /GR-) endif() elseif(RCC_GCC_COMPATIBLE) if(NOT enableEH) list(APPEND cxxFlags -fno-exceptions) if(RCC_ENABLE_UNWIND_TABLES) list(APPEND cxxFlags -funwind-tables) else() list(APPEND cxxFlags -fno-unwind-tables -fno-asynchronous-unwind-tables) endif() endif() if(NOT enableRTTI) list(APPEND cxxFlags -fno-rtti) endif() elseif(CMAKE_CXX_COMPILER_ID MATCHES "XL") if(NOT enableEH) list(APPEND cxxFlags -qnoeh) endif() if(NOT enableRTTI) list(APPEND cxxFlags -qnortti) endif() endif() target_compile_options(${target} PRIVATE "$<$:${cxxFlags}>") rcc_apply_link_options(${target}) endfunction() macro(rcc_configure_additional_options) option(BUILD_SHARED_LIBS "Build libraries as shared libraries instead of static" OFF) if(NOT CMAKE_SYSTEM_NAME MATCHES "OS390") option(RCC_ENABLE_PIC "Build position-independent code" ON) endif() option(RCC_ENABLE_LIBCXX "Use libc++ if available" OFF) option(RCC_STATIC_LINK_CXX_STDLIB "Statically link the C++ standard library" OFF) option(RCC_ENABLE_LLD "Use lld as the linker" OFF) set(RCC_USE_LINKER "" CACHE STRING "Linker to select through the compiler driver") set(RCC_ENABLE_LTO OFF CACHE STRING "Enable LTO; use Thin or Full to select its mode") string(TOUPPER "${RCC_ENABLE_LTO}" rccLTOMode) option(RCC_ENABLE_FATLTO "Build with fat LTO objects" OFF) set(RCC_THINLTO_CACHE_PATH "${PROJECT_BINARY_DIR}/lto.cache" CACHE STRING "ThinLTO cache directory") option(RCC_NO_DEAD_STRIP "Disable removal of unused sections" OFF) option(RCC_USE_SPLIT_DWARF "Use split DWARF in debug builds" OFF) option(RCC_USE_SANITIZE_COVERAGE "Enable sanitizer coverage without the fuzzer main function" OFF) set(RCC_BUILD_INSTRUMENTED OFF CACHE STRING "PGO instrumentation: IR, Frontend, CSIR, CSSPGO") option(RCC_BUILD_INSTRUMENTED_COVERAGE "Build with code coverage instrumentation" OFF) mark_as_advanced(RCC_BUILD_INSTRUMENTED RCC_BUILD_INSTRUMENTED_COVERAGE) set(RCC_PROFDATA_FILE "" CACHE FILEPATH "Instrumentation profile to use when compiling") set(RCC_SPROFDATA_FILE "" CACHE FILEPATH "Sampling profile to use when compiling") set(RCC_CCACHE_BUILD OFF CACHE BOOL "Enable ccache for compilation") set(RCC_SOURCE_PREFIX "" CACHE STRING "Source prefix in mapped paths") option(RCC_USE_RELATIVE_PATHS_IN_DEBUG_INFO "Use relative paths in debug information" OFF) option(RCC_USE_RELATIVE_PATHS_IN_FILES "Use relative paths in source and debug information" OFF) if(CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT (WIN32 OR CMAKE_SYSTEM_NAME MATCHES "AIX")) option(RCC_BUILD_32_BITS "Build 32-bit binaries on a 64-bit platform" OFF) endif() endmacro() macro(rcc_configure_standard_library) set(RCC_LIBCXX_USED OFF) if(RCC_ENABLE_LIBCXX) if(RCC_GCC_COMPATIBLE) check_cxx_compiler_flag("-stdlib=libc++" RCC_COMPILER_SUPPORTS_LIBCXX) check_linker_flag(CXX "-stdlib=libc++" RCC_LINKER_SUPPORTS_LIBCXX) if(RCC_COMPILER_SUPPORTS_LIBCXX AND RCC_LINKER_SUPPORTS_LIBCXX) rcc_append_flags("-stdlib=libc++" CMAKE_CXX_FLAGS CMAKE_EXE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS CMAKE_MODULE_LINKER_FLAGS) set(RCC_LIBCXX_USED ON) else() message(WARNING "Cannot select libc++ with -stdlib=") endif() else() message(WARNING "No libc++ selection flag is known for this compiler") endif() endif() if(RCC_STATIC_LINK_CXX_STDLIB) if(RCC_GCC_COMPATIBLE) check_cxx_compiler_flag("-static-libstdc++" RCC_COMPILER_SUPPORTS_STATIC_STDLIB) check_linker_flag(CXX "-static-libstdc++" RCC_LINKER_SUPPORTS_STATIC_STDLIB) if(RCC_COMPILER_SUPPORTS_STATIC_STDLIB AND RCC_LINKER_SUPPORTS_STATIC_STDLIB) rcc_append_flags("-static-libstdc++" CMAKE_EXE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS CMAKE_MODULE_LINKER_FLAGS) else() message(WARNING "Cannot select static linking for the C++ standard library") endif() else() message(WARNING "No static C++ standard library selection flag is known for this compiler") endif() endif() endmacro() macro(rcc_configure_standard_library_abi) check_cxx_source_compiles([=[ #include #if !defined(__GLIBCXX__) #error Not libstdc++ #endif int main() { return 0; } ]=] RCC_USES_LIBSTDCXX) check_cxx_source_compiles([=[ #include #if _GLIBCXX_USE_CXX11_ABI == 0 #error C++11 ABI not active #endif int main() { return 0; } ]=] RCC_DEFAULT_GLIBCXX_CXX11_ABI) option(GLIBCXX_USE_CXX11_ABI "Use the libstdc++ C++11 ABI" ${RCC_DEFAULT_GLIBCXX_CXX11_ABI}) if(RCC_USES_LIBSTDCXX) if(GLIBCXX_USE_CXX11_ABI) add_compile_definitions(_GLIBCXX_USE_CXX11_ABI=1) else() add_compile_definitions(_GLIBCXX_USE_CXX11_ABI=0) endif() endif() endmacro() macro(rcc_configure_linker) if(RCC_ENABLE_LLD) if(RCC_USE_LINKER) message(FATAL_ERROR "RCC_ENABLE_LLD and RCC_USE_LINKER cannot be set together") endif() if(MSVC) if(NOT CMAKE_LINKER MATCHES "lld-link") get_filename_component(rccCXXCompilerDir "${CMAKE_CXX_COMPILER}" DIRECTORY) get_filename_component(rccCCompilerDir "${CMAKE_C_COMPILER}" DIRECTORY) find_program(RCC_LLD_LINK NAMES lld-link lld-link.exe HINTS "${rccCXXCompilerDir}" "${rccCCompilerDir}") if(NOT RCC_LLD_LINK) message(FATAL_ERROR "RCC_ENABLE_LLD requires lld-link; set CMAKE_LINKER to its path") endif() set(CMAKE_LINKER "${RCC_LLD_LINK}") endif() else() set(RCC_USE_LINKER lld) endif() endif() if(RCC_USE_LINKER) check_cxx_source_compiles("int main() { return 0; }" RCC_CAN_LINK_EXECUTABLE) rcc_append_flags("-fuse-ld=${RCC_USE_LINKER}" CMAKE_EXE_LINKER_FLAGS CMAKE_MODULE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS) if(RCC_CAN_LINK_EXECUTABLE) check_cxx_source_compiles("int main() { return 0; }" RCC_SUPPORTS_CUSTOM_LINKER) if(NOT RCC_SUPPORTS_CUSTOM_LINKER) message(FATAL_ERROR "The compiler cannot link with -fuse-ld=${RCC_USE_LINKER}") endif() else() message(STATUS "Skipping custom linker check: the target cannot link an executable") endif() endif() set(RCC_LINKER_IS_LLD OFF) set(RCC_LINKER_IS_LLD_LINK OFF) if(CMAKE_LINKER MATCHES ".*lld" OR RCC_USE_LINKER STREQUAL "lld" OR RCC_ENABLE_LLD) set(RCC_LINKER_IS_LLD ON) endif() if(CMAKE_LINKER MATCHES "lld-link" OR (MSVC AND (RCC_USE_LINKER STREQUAL "lld" OR RCC_ENABLE_LLD))) set(RCC_LINKER_IS_LLD_LINK ON) endif() if(NOT WIN32) if(APPLE) set(rccLinkerVersionFlag "-Wl,-v") else() set(rccLinkerVersionFlag "-Wl,--version") endif() if(CMAKE_HOST_WIN32) set(rccLinkerDevNull "NUL") else() set(rccLinkerDevNull "/dev/null") endif() if(RCC_USE_LINKER) set(rccLinkerCommand ${CMAKE_C_COMPILER} -fuse-ld=${RCC_USE_LINKER} ${rccLinkerVersionFlag} -o ${rccLinkerDevNull}) else() separate_arguments(rccLinkerFlags UNIX_COMMAND "${CMAKE_EXE_LINKER_FLAGS}") set(rccLinkerCommand ${CMAKE_C_COMPILER} ${rccLinkerFlags} ${rccLinkerVersionFlag} -o ${rccLinkerDevNull}) endif() execute_process(COMMAND ${rccLinkerCommand} OUTPUT_VARIABLE rccLinkerOutput ERROR_VARIABLE rccLinkerError) set(RCC_LINKER_IS_SOLARISLD OFF) set(RCC_LINKER_IS_GNULD OFF) if(rccLinkerOutput MATCHES "GNU ld") set(RCC_LINKER_IS_GNULD ON) endif() if(rccLinkerOutput MATCHES "Solaris Link Editors" OR rccLinkerError MATCHES "Solaris Link Editors") set(RCC_LINKER_IS_SOLARISLD ON) endif() endif() if(APPLE) if(NOT RCC_USE_LINKER) check_linker_flag(C "-Wl,-no_warn_duplicate_libraries" RCC_LINKER_SUPPORTS_NO_WARN_DUPLICATE_LIBRARIES) else() set(RCC_LINKER_SUPPORTS_NO_WARN_DUPLICATE_LIBRARIES OFF CACHE INTERNAL "") endif() endif() endmacro() function(rcc_has_no_incremental flags output) set(${output} OFF PARENT_SCOPE) string(FIND "${flags}" "/INCREMENTAL" position REVERSE) if(position GREATER -1) string(SUBSTRING "${flags}" ${position} 15 option) if(option MATCHES "/INCREMENTAL:NO") set(${output} ON PARENT_SCOPE) endif() endif() endfunction() macro(rcc_configure_msvc_options) add_compile_definitions(_CRT_SECURE_NO_DEPRECATE _CRT_SECURE_NO_WARNINGS _CRT_NONSTDC_NO_DEPRECATE _CRT_NONSTDC_NO_WARNINGS _SCL_SECURE_NO_DEPRECATE _SCL_SECURE_NO_WARNINGS UNICODE _UNICODE) rcc_append_flags("/Zc:inline /Oi /permissive-" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") rcc_append_flags("/Zc:preprocessor" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() rcc_append_flags("/Zc:__cplusplus /bigobj" CMAKE_CXX_FLAGS) set(RCC_WINSYSROOT "" CACHE STRING "Argument to clang-cl's /winsysroot") if(RCC_WINSYSROOT) if(NOT RCC_CLANG_CL) message(FATAL_ERROR "RCC_WINSYSROOT requires clang-cl") endif() rcc_append_flags("/winsysroot\"${RCC_WINSYSROOT}\"" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) if(RCC_LINKER_IS_LLD_LINK) rcc_append_flags("/winsysroot:\"${RCC_WINSYSROOT}\"" CMAKE_EXE_LINKER_FLAGS CMAKE_MODULE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS) endif() endif() option(RCC_ENABLE_PDB "Generate PDB files in Release builds" OFF) if(RCC_ENABLE_PDB AND buildType STREQUAL "RELEASE") rcc_append_flags("/Zi" CMAKE_C_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELEASE) rcc_append_flags("/DEBUG /OPT:REF /OPT:ICF" CMAKE_EXE_LINKER_FLAGS CMAKE_MODULE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS) endif() set(rccAllLinkerFlags "") foreach(rccKind EXE MODULE SHARED) string(APPEND rccAllLinkerFlags " ${CMAKE_${rccKind}_LINKER_FLAGS_${buildType}} ${CMAKE_${rccKind}_LINKER_FLAGS}") endforeach() string(TOUPPER "${rccAllLinkerFlags}" rccAllLinkerFlags) if(RCC_CLANG_CL AND RCC_LINKER_IS_LLD AND rccAllLinkerFlags MATCHES "/DEBUG") rcc_add_supported_warning("-gcodeview-ghash" GCODEVIEW_GHASH) endif() if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT RCC_ENABLE_LTO) foreach(rccKind EXE MODULE SHARED) rcc_has_no_incremental( "${CMAKE_${rccKind}_LINKER_FLAGS_${buildType}} ${CMAKE_${rccKind}_LINKER_FLAGS}" rccNoIncremental${rccKind}) endforeach() if(rccNoIncrementalEXE AND rccNoIncrementalMODULE AND rccNoIncrementalSHARED) add_compile_options("$<$:/Brepro>") add_link_options("LINKER:/Brepro") else() message(WARNING "/Brepro is incompatible with incremental linking; output will not be deterministic") endif() endif() endmacro() macro(rcc_configure_platform_options) if(RCC_ENABLE_PIC) if(XCODE) message(WARNING "-fPIC is not supported with Xcode") elseif(NOT (WIN32 OR CYGWIN)) check_c_compiler_flag("-Werror -fPIC" RCC_C_SUPPORTS_FPIC) check_cxx_compiler_flag("-Werror -fPIC" RCC_CXX_SUPPORTS_FPIC) if(RCC_C_SUPPORTS_FPIC AND RCC_CXX_SUPPORTS_FPIC) message(STATUS "Building with -fPIC") rcc_append_flags("-fPIC" CMAKE_C_FLAGS CMAKE_CXX_FLAGS CMAKE_ASM_FLAGS) else() message(WARNING "-fPIC is not supported") endif() if(NOT CMAKE_SYSTEM_NAME MATCHES "AIX" AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") rcc_add_supported_warning("-fno-semantic-interposition" FNO_SEMANTIC_INTERPOSITION) endif() endif() endif() if(NOT CMAKE_SYSTEM_NAME MATCHES "AIX" AND (NOT (WIN32 OR CYGWIN) OR ((MINGW OR CYGWIN) AND CMAKE_CXX_COMPILER_ID MATCHES "Clang"))) check_cxx_compiler_flag("-fvisibility-inlines-hidden" RCC_SUPPORTS_HIDDEN_INLINES) if(RCC_SUPPORTS_HIDDEN_INLINES) rcc_append_flags("-fvisibility-inlines-hidden" CMAKE_CXX_FLAGS) endif() endif() if((CMAKE_SIZEOF_VOID_P EQUAL 8 AND MINGW) OR CMAKE_SIZEOF_VOID_P EQUAL 4) add_compile_definitions(_FILE_OFFSET_BITS=64) endif() if(CMAKE_SIZEOF_VOID_P EQUAL 4) add_compile_definitions(_LARGEFILE_SOURCE) endif() if(CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT WIN32 AND RCC_BUILD_32_BITS) message(STATUS "Building 32 bits executables and libraries.") rcc_append_flags("-m32" CMAKE_C_FLAGS CMAKE_CXX_FLAGS CMAKE_EXE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS CMAKE_MODULE_LINKER_FLAGS) add_compile_definitions(_LARGEFILE_SOURCE _FILE_OFFSET_BITS=64) endif() if(MSVC OR CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC") add_link_options("$<$,EXECUTABLE>:LINKER:/STACK:10000000>") elseif(MINGW OR CYGWIN) add_link_options("$<$,EXECUTABLE>:LINKER:--stack,16777216>") if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang") rcc_append_flags("-Wa,-mbig-obj" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() endif() if(MSVC) rcc_configure_msvc_options() endif() if(XCODE) foreach(rccWarning GCC_WARN_ABOUT_RETURN_TYPE GCC_WARN_ABOUT_MISSING_NEWLINE GCC_WARN_UNUSED_VALUE GCC_WARN_UNUSED_VARIABLE GCC_WARN_SIGN_COMPARE GCC_WARN_UNUSED_FUNCTION GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS GCC_WARN_UNINITIALIZED_AUTOS CLANG_WARN_BOOL_CONVERSION CLANG_WARN_EMPTY_BODY CLANG_WARN_ENUM_CONVERSION CLANG_WARN_INT_CONVERSION CLANG_WARN_CONSTANT_CONVERSION GCC_WARN_NON_VIRTUAL_DESTRUCTOR) set(CMAKE_XCODE_ATTRIBUTE_${rccWarning} YES) endforeach() endif() if(MSVC_IDE) set(RCC_COMPILER_JOBS "0" CACHE STRING "Parallel compiler jobs; 0 uses all processors") if(RCC_COMPILER_JOBS STREQUAL "0") add_compile_options(/MP) elseif(NOT RCC_COMPILER_JOBS STREQUAL "1") message(STATUS "Number of parallel compiler jobs set to ${RCC_COMPILER_JOBS}") add_compile_options("/MP${RCC_COMPILER_JOBS}") else() message(STATUS "Parallel compilation disabled") endif() endif() endmacro() macro(rcc_configure_sections) if(NOT CYGWIN AND NOT MSVC) if(NOT CMAKE_SYSTEM_NAME MATCHES "Darwin" AND NOT buildType STREQUAL "DEBUG") if(CMAKE_CXX_COMPILER_ID MATCHES "XL") rcc_append_flags("-qfuncsect" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) else() rcc_append_flags("-ffunction-sections" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() rcc_append_flags("-fdata-sections" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() elseif(MSVC AND NOT buildType STREQUAL "DEBUG") rcc_append_flags("/Gw" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() endmacro() macro(rcc_configure_debug_options) if(RCC_USE_SPLIT_DWARF AND (buildType STREQUAL "DEBUG" OR buildType STREQUAL "RELWITHDEBINFO") AND CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU") add_compile_options("$<$:-gsplit-dwarf>") check_linker_flag(CXX "-Wl,--gdb-index" RCC_LINKER_SUPPORTS_GDB_INDEX) if(RCC_LINKER_SUPPORTS_GDB_INDEX) rcc_append_flags("-Wl,--gdb-index" CMAKE_EXE_LINKER_FLAGS CMAKE_MODULE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS) endif() endif() if(RCC_ENABLE_PIC AND RCC_USING_GLIBC) check_cxx_source_compiles([=[ #include #if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 36) #error RELR requires glibc 2.36 #endif int main() { return 0; } ]=] RCC_GLIBC_SUPPORTS_RELR) if(RCC_GLIBC_SUPPORTS_RELR) check_linker_flag(CXX "-Wl,-z,pack-relative-relocs" RCC_LINKER_SUPPORTS_RELR) if(RCC_LINKER_SUPPORTS_RELR) rcc_append_flags("-Wl,-z,pack-relative-relocs" CMAKE_EXE_LINKER_FLAGS CMAKE_MODULE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS) endif() endif() endif() add_compile_definitions(__STDC_CONSTANT_MACROS __STDC_FORMAT_MACROS __STDC_LIMIT_MACROS) if(UNIX AND CMAKE_GENERATOR MATCHES "Ninja") if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU") rcc_append_flags("-fdiagnostics-color" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() check_linker_flag(CXX "-Wl,--color-diagnostics" RCC_LINKER_SUPPORTS_COLOR_DIAGNOSTICS) if(RCC_LINKER_SUPPORTS_COLOR_DIAGNOSTICS) rcc_append_flags("-Wl,--color-diagnostics" CMAKE_EXE_LINKER_FLAGS CMAKE_MODULE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS) endif() endif() endmacro() macro(rcc_configure_profile_options) string(TOUPPER "${RCC_BUILD_INSTRUMENTED}" rccProfileMode) if(RCC_BUILD_INSTRUMENTED OR RCC_BUILD_INSTRUMENTED_COVERAGE) if(NOT RCC_PROFILE_MERGE_POOL_SIZE) set(RCC_PROFILE_MERGE_POOL_SIZE 4) endif() if(NOT RCC_PROFILE_FILE_PATTERN) if(NOT RCC_PROFILE_DATA_DIR) file(TO_NATIVE_PATH "${PROJECT_BINARY_DIR}/profiles" RCC_PROFILE_DATA_DIR) endif() file(TO_NATIVE_PATH "${RCC_PROFILE_DATA_DIR}/%${RCC_PROFILE_MERGE_POOL_SIZE}m.profraw" RCC_PROFILE_FILE_PATTERN) endif() if(NOT RCC_CSPROFILE_FILE_PATTERN) if(NOT RCC_CSPROFILE_DATA_DIR) file(TO_NATIVE_PATH "${PROJECT_BINARY_DIR}/csprofiles" RCC_CSPROFILE_DATA_DIR) endif() file(TO_NATIVE_PATH "${RCC_CSPROFILE_DATA_DIR}/%${RCC_PROFILE_MERGE_POOL_SIZE}m.profraw" RCC_CSPROFILE_FILE_PATTERN) endif() endif() if(RCC_BUILD_INSTRUMENTED AND RCC_BUILD_INSTRUMENTED_COVERAGE) message(FATAL_ERROR "PGO instrumentation and coverage instrumentation cannot both be enabled") endif() if(RCC_BUILD_INSTRUMENTED) if(rccProfileMode STREQUAL "IR") set(rccProfileFlags "-fprofile-generate=\"${RCC_PROFILE_DATA_DIR}\"") elseif(rccProfileMode STREQUAL "CSIR") set(rccProfileFlags "-fcs-profile-generate=\"${RCC_CSPROFILE_DATA_DIR}\"") elseif(rccProfileMode STREQUAL "CSSPGO") if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang") message(FATAL_ERROR "RCC_BUILD_INSTRUMENTED=CSSPGO requires Clang") endif() set(rccProfileFlags "-fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -fno-optimize-sibling-calls -fpseudo-probe-for-profiling -fdebug-info-for-profiling") else() set(rccProfileFlags "-fprofile-instr-generate=\"${RCC_PROFILE_FILE_PATTERN}\"") endif() rcc_append_flags("${rccProfileFlags}" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) if(NOT RCC_LINKER_IS_LLD_LINK) rcc_append_flags("${rccProfileFlags}" CMAKE_EXE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS) endif() endif() rcc_configure_compiler_rt_path() if(RCC_PROFDATA_FILE AND EXISTS "${RCC_PROFDATA_FILE}") if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang") message(FATAL_ERROR "RCC_PROFDATA_FILE requires Clang") endif() rcc_append_flags("-fprofile-instr-use=\"${RCC_PROFDATA_FILE}\"" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) if(NOT RCC_LINKER_IS_LLD_LINK) rcc_append_flags("-fprofile-instr-use=\"${RCC_PROFDATA_FILE}\"" CMAKE_EXE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS) endif() elseif(RCC_PROFDATA_FILE) message(WARNING "RCC_PROFDATA_FILE does not exist: ${RCC_PROFDATA_FILE}") endif() if(RCC_SPROFDATA_FILE AND EXISTS "${RCC_SPROFDATA_FILE}") if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang") message(FATAL_ERROR "RCC_SPROFDATA_FILE requires Clang") endif() set(rccSampleFlags "-fpseudo-probe-for-profiling -fprofile-sample-use=\"${RCC_SPROFDATA_FILE}\"") rcc_append_flags("${rccSampleFlags}" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) if(NOT RCC_LINKER_IS_LLD_LINK) rcc_append_flags("${rccSampleFlags}" CMAKE_EXE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS) endif() endif() if(RCC_BUILD_INSTRUMENTED_COVERAGE) rcc_append_flags("-fprofile-instr-generate=\"${RCC_PROFILE_FILE_PATTERN}\" -fcoverage-mapping" CMAKE_C_FLAGS CMAKE_CXX_FLAGS CMAKE_EXE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS) endif() endmacro() macro(rcc_configure_lto) if(RCC_ENABLE_LTO AND WIN32 AND NOT RCC_LINKER_IS_LLD_LINK AND NOT MINGW) message(FATAL_ERROR "LTO on Windows requires lld-link; set CMAKE_LINKER to its path") endif() if(RCC_ENABLE_LTO) if(rccLTOMode STREQUAL "THIN") set(rccLTOFlag "-flto=thin") elseif(rccLTOMode STREQUAL "FULL") set(rccLTOFlag "-flto=full") else() set(rccLTOFlag "-flto") endif() rcc_append_flags("${rccLTOFlag}" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) if(NOT RCC_LINKER_IS_LLD_LINK) rcc_append_flags("${rccLTOFlag}" CMAKE_EXE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS) endif() endif() if(rccLTOMode STREQUAL "THIN") if(APPLE) rcc_append_flags("-Wl,-cache_path_lto,${RCC_THINLTO_CACHE_PATH}" CMAKE_EXE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS) elseif(CMAKE_SYSTEM_NAME MATCHES "AIX") rcc_append_flags("-bplugin_opt:-legacy-thinlto-cache-dir=${RCC_THINLTO_CACHE_PATH}" CMAKE_EXE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS) elseif((UNIX OR MINGW) AND RCC_USE_LINKER STREQUAL "lld") rcc_append_flags("-Wl,--thinlto-cache-dir=${RCC_THINLTO_CACHE_PATH}" CMAKE_EXE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS) elseif(RCC_USE_LINKER STREQUAL "gold") rcc_append_flags("-Wl,--plugin-opt,cache-dir=${RCC_THINLTO_CACHE_PATH}" CMAKE_EXE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS) elseif(RCC_LINKER_IS_LLD_LINK) rcc_append_flags("/lldltocache:${RCC_THINLTO_CACHE_PATH}" CMAKE_EXE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS) endif() endif() if(RCC_ENABLE_FATLTO AND ((UNIX AND NOT APPLE) OR FUCHSIA)) rcc_append_flags("-ffat-lto-objects" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) if(NOT RCC_LINKER_IS_LLD_LINK) rcc_append_flags("-ffat-lto-objects" CMAKE_EXE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS CMAKE_MODULE_LINKER_FLAGS) endif() endif() endmacro() macro(rcc_configure_pch_and_cache) if(NOT DEFINED CMAKE_DISABLE_PRECOMPILE_HEADERS) if(CMAKE_SYSTEM_NAME MATCHES "OS390") message(NOTICE "Precompiled headers are disabled by default on z/OS. " "Pass -DCMAKE_DISABLE_PRECOMPILE_HEADERS=OFF to override.") set(CMAKE_DISABLE_PRECOMPILE_HEADERS ON) endif() if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") message(NOTICE "Precompiled headers are disabled by default with GCC. " "Pass -DCMAKE_DISABLE_PRECOMPILE_HEADERS=OFF to override.") set(CMAKE_DISABLE_PRECOMPILE_HEADERS ON) endif() if(CMAKE_CXX_COMPILER_LAUNCHER MATCHES "sccache") message(NOTICE "Precompiled headers are disabled by default with sccache. " "Pass -DCMAKE_DISABLE_PRECOMPILE_HEADERS=OFF to override.") set(CMAKE_DISABLE_PRECOMPILE_HEADERS ON) elseif(CMAKE_CXX_COMPILER_LAUNCHER MATCHES "clang-cache") message(NOTICE "Precompiled headers are disabled by default with clang-cache. " "Pass -DCMAKE_DISABLE_PRECOMPILE_HEADERS=OFF to override.") set(CMAKE_DISABLE_PRECOMPILE_HEADERS ON) elseif(RCC_CCACHE_BUILD OR CMAKE_CXX_COMPILER_LAUNCHER MATCHES "ccache") if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang") message(WARNING "Using ccache with precompiled headers with non-Clang " "compilers is not supported and may lead to false positives. " "Set CMAKE_DISABLE_PRECOMPILE_HEADERS to ON/OFF to silence this warning.") set(CMAKE_DISABLE_PRECOMPILE_HEADERS ON) endif() if(CMAKE_HOST_WIN32) message(WARNING "Using ccache with precompiled headers on Windows is " "currently not supported. " "Pass -DCMAKE_DISABLE_PRECOMPILE_HEADERS=OFF to override.") set(CMAKE_DISABLE_PRECOMPILE_HEADERS ON) endif() endif() endif() if(NOT CMAKE_DISABLE_PRECOMPILE_HEADERS) message(STATUS "Precompiled headers enabled.") set(CMAKE_PCH_PROLOGUE "") if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") rcc_append_flags("-Xclang -fno-pch-timestamp" CMAKE_CXX_FLAGS) elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") rcc_append_flags("-fpch-preprocess" CMAKE_CXX_FLAGS) endif() else() message(STATUS "Precompiled headers disabled.") endif() if(RCC_CCACHE_BUILD) find_program(RCC_CCACHE_PROGRAM ccache) if(NOT RCC_CCACHE_PROGRAM) message(FATAL_ERROR "ccache was not found; install it or disable RCC_CCACHE_BUILD") endif() set(RCC_CCACHE_MAXSIZE "" CACHE STRING "ccache size limit") set(RCC_CCACHE_DIR "" CACHE STRING "ccache storage directory") set(RCC_CCACHE_PARAMS "CCACHE_CPP2=yes CCACHE_HASHDIR=yes CCACHE_SLOPPINESS=pch_defines,time_macros" CACHE STRING "Environment assignments for ccache") if(NOT CMAKE_HOST_WIN32) set(rccCacheCommand "${RCC_CCACHE_PARAMS} \"${RCC_CCACHE_PROGRAM}\"") if(NOT CMAKE_DISABLE_PRECOMPILE_HEADERS) set(rccCacheCommand "CCACHE_DEPEND=1 ${rccCacheCommand}") endif() if(RCC_CCACHE_MAXSIZE) set(rccCacheCommand "CCACHE_MAXSIZE=${RCC_CCACHE_MAXSIZE} ${rccCacheCommand}") endif() if(RCC_CCACHE_DIR) set(rccCacheCommand "CCACHE_DIR=\"${RCC_CCACHE_DIR}\" ${rccCacheCommand}") endif() set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${rccCacheCommand}") message(STATUS "ccache program: ${rccCacheCommand}") else() if(RCC_CCACHE_MAXSIZE OR RCC_CCACHE_DIR OR NOT RCC_CCACHE_PARAMS MATCHES "CCACHE_CPP2=yes CCACHE_HASHDIR=yes CCACHE_SLOPPINESS=pch_defines,time_macros") message(FATAL_ERROR "Configure ccache through environment variables on Windows") endif() set(CMAKE_C_COMPILER_LAUNCHER "${RCC_CCACHE_PROGRAM}") set(CMAKE_CXX_COMPILER_LAUNCHER "${RCC_CCACHE_PROGRAM}") message(STATUS "ccache program: ${RCC_CCACHE_PROGRAM}") endif() endif() endmacro() macro(rcc_configure_relative_paths) if(RCC_USE_RELATIVE_PATHS_IN_DEBUG_INFO OR RCC_USE_RELATIVE_PATHS_IN_FILES) if(RCC_ENABLE_PROJECTS) get_filename_component(rccSourceRoot "${PROJECT_SOURCE_DIR}/.." ABSOLUTE) else() set(rccSourceRoot "${PROJECT_SOURCE_DIR}") endif() file(RELATIVE_PATH rccRelativeRoot "${CMAKE_BINARY_DIR}" "${rccSourceRoot}") endif() if(RCC_USE_RELATIVE_PATHS_IN_DEBUG_INFO) check_c_compiler_flag("-fdebug-prefix-map=foo=bar" RCC_SUPPORTS_FDEBUG_PREFIX_MAP) if(RCC_SUPPORTS_FDEBUG_PREFIX_MAP) rcc_append_flags("-fdebug-prefix-map=\"${CMAKE_BINARY_DIR}=${rccRelativeRoot}\" -fdebug-prefix-map=\"${rccSourceRoot}/=${RCC_SOURCE_PREFIX}\"" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() if(RCC_GCC_COMPATIBLE) rcc_append_flags("-no-canonical-prefixes" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() endif() if(RCC_USE_RELATIVE_PATHS_IN_FILES) check_c_compiler_flag("-ffile-prefix-map=foo=bar" RCC_SUPPORTS_FFILE_PREFIX_MAP) if(RCC_SUPPORTS_FFILE_PREFIX_MAP) rcc_append_flags("-ffile-prefix-map=\"${CMAKE_BINARY_DIR}=${rccRelativeRoot}\" -ffile-prefix-map=\"${rccSourceRoot}/=${RCC_SOURCE_PREFIX}\"" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() if(RCC_GCC_COMPATIBLE) rcc_append_flags("-no-canonical-prefixes" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() endif() endmacro() function(rcc_apply_link_options target) if(NOT buildType STREQUAL "DEBUG") if(NOT RCC_NO_DEAD_STRIP) if(CMAKE_SYSTEM_NAME MATCHES "Darwin") target_link_options(${target} PRIVATE "LINKER:-dead_strip") elseif(CMAKE_SYSTEM_NAME STREQUAL "SunOS" AND RCC_LINKER_IS_SOLARISLD) check_linker_flag(CXX "-Wl,-z,discard-unused=sections" RCC_LINKER_SUPPORTS_DISCARD_UNUSED) if(RCC_LINKER_SUPPORTS_DISCARD_UNUSED) target_link_options(${target} PRIVATE "LINKER:-z,discard-unused=sections") endif() elseif(NOT MSVC AND NOT CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC" AND NOT CMAKE_SYSTEM_NAME MATCHES "AIX|OS390") target_link_options(${target} PRIVATE "LINKER:--gc-sections") endif() elseif(CMAKE_SYSTEM_NAME MATCHES "AIX") target_link_options(${target} PRIVATE "LINKER:-bnogc") endif() endif() if(RCC_LINKER_SUPPORTS_NO_WARN_DUPLICATE_LIBRARIES) target_link_options(${target} PRIVATE "LINKER:-no_warn_duplicate_libraries") endif() endfunction()