cmake update

This commit is contained in:
Markus F.X.J. Oberhumer 2023-12-20 12:16:25 +01:00
parent 51a6a5cca5
commit 1236776aa2
2 changed files with 215 additions and 189 deletions

View File

@ -25,11 +25,8 @@ else()
cmake_minimum_required(VERSION "3.8" FATAL_ERROR) # CMake >= 3.8 is needed for CXX_STANDARD 17 cmake_minimum_required(VERSION "3.8" FATAL_ERROR) # CMake >= 3.8 is needed for CXX_STANDARD 17
endif() endif()
# support config hooks; developer convenience # support functions
macro(upx_cmake_include_hook section) include("${CMAKE_CURRENT_SOURCE_DIR}/misc/cmake/functions.cmake")
include("${CMAKE_CURRENT_SOURCE_DIR}/misc/cmake/hooks/CMakeLists.${section}.txt" OPTIONAL)
include("${CMAKE_CURRENT_SOURCE_DIR}/maint/make/CMakeLists.${section}.txt" OPTIONAL)
endmacro()
#*********************************************************************** #***********************************************************************
# options # options
@ -75,55 +72,6 @@ if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/.git")
endif() endif()
endif() endif()
# util
function(upx_print_var) # ARGV
foreach(var_name ${ARGV})
if(DEFINED ${var_name} AND NOT ",${${var_name}}," STREQUAL ",,")
if(${var_name})
message(STATUS "${var_name} = ${${var_name}}")
endif()
endif()
endforeach()
endfunction()
function(upx_print_have_symbol) # ARGV
foreach(symbol ${ARGV})
set(cache_var_name "HAVE_symbol_${symbol}")
check_symbol_exists(${symbol} "limits.h;stddef.h;stdint.h" ${cache_var_name})
if(${cache_var_name})
message(STATUS "HAVE ${symbol}")
endif()
endforeach()
endfunction()
# useful for CI jobs: allow settings via environment and cache result
function(upx_cache_bool_vars) # ARGV
set(default_value "${ARGV0}")
list(REMOVE_AT ARGV 0)
foreach(var_name ${ARGV})
set(value ${default_value})
if(DEFINED UPX_CACHE_VALUE_${var_name}) # check cache
set(value "${UPX_CACHE_VALUE_${var_name}}")
elseif(DEFINED ${var_name}) # defined via "cmake -DXXX=YYY"
set(value "${${var_name}}")
elseif("$ENV{${var_name}}" MATCHES "^(0|1|OFF|ON|FALSE|TRUE)$") # check environment
set(value "$ENV{${var_name}}")
set(UPX_CACHE_ORIGIN_FROM_ENV_${var_name} TRUE CACHE INTERNAL "" FORCE) # for info below
endif()
# convert to bool
if(value)
set(value ON)
else()
set(value OFF)
endif()
# store result
if(UPX_CACHE_ORIGIN_FROM_ENV_${var_name})
message(STATUS "setting from environment: ${var_name} = ${value}")
endif()
set(${var_name} "${value}" PARENT_SCOPE) # store result
set(UPX_CACHE_VALUE_${var_name} "${value}" CACHE INTERNAL "" FORCE) # and store in cache
endforeach()
endfunction()
# global settings # global settings
if(${CMAKE_VERSION} VERSION_GREATER "3.14.99" AND NOT DEFINED CMAKE_MSVC_RUNTIME_LIBRARY) if(${CMAKE_VERSION} VERSION_GREATER "3.14.99" AND NOT DEFINED CMAKE_MSVC_RUNTIME_LIBRARY)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded") set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded")
@ -277,38 +225,6 @@ if(MSVC_FRONTEND)
set(warn_WX -wd5105 ${warn_WX}) set(warn_WX -wd5105 ${warn_WX})
endif() endif()
function(upx_add_definitions_with_prefix) # ARGV
set(flag_prefix "${ARGV0}")
if(flag_prefix MATCHES "^empty$") # need "empty" to work around bug in old CMake versions
set(flag_prefix "")
endif()
list(REMOVE_AT ARGV 0)
set(failed "")
foreach(f ${ARGV})
set(flag "${flag_prefix}${f}")
string(REGEX REPLACE "[^0-9a-zA-Z_]" "_" cache_var_name "HAVE_CFLAG_${flag}")
check_c_compiler_flag("${flag}" ${cache_var_name})
if(${cache_var_name})
#message(STATUS "add_definitions: ${flag}")
add_definitions("${flag}")
else()
list(APPEND failed "${f}")
endif()
endforeach()
set(failed_flags "${failed}" PARENT_SCOPE) # return value
endfunction()
function(upx_add_definitions) # ARGV
set(failed_flags "")
if(MSVC_FRONTEND AND CMAKE_C_COMPILER_ID MATCHES "Clang")
# for clang-cl try "-clang:" flag prefix first
upx_add_definitions_with_prefix("-clang:" ${ARGV})
upx_add_definitions_with_prefix("empty" ${failed_flags})
else()
upx_add_definitions_with_prefix("empty" ${ARGV})
endif()
endfunction()
if(NOT CMAKE_C_COMPILER_ID MATCHES "^MSVC") if(NOT CMAKE_C_COMPILER_ID MATCHES "^MSVC")
# use -O2 instead of -O3 to reduce code size # use -O2 instead of -O3 to reduce code size
string(REGEX REPLACE "(^| )-O3( |$$)" "\\1-O2\\2" a "${CMAKE_C_FLAGS_RELEASE}") string(REGEX REPLACE "(^| )-O3( |$$)" "\\1-O2\\2" a "${CMAKE_C_FLAGS_RELEASE}")
@ -344,93 +260,9 @@ if(NOT CMAKE_C_COMPILER_ID MATCHES "^MSVC")
endif() endif()
endif() endif()
# compile a target with -O2 optimization even in Debug build
function(upx_compile_target_debug_with_O2) # ARGV
foreach(t ${ARGV})
if(MSVC_FRONTEND)
# MSVC uses some Debug compilation options like -RTC1 that are incompatible with -O2
else()
target_compile_options(${t} PRIVATE $<$<CONFIG:Debug>:-O2>)
endif()
endforeach()
endfunction()
# compile a source file with -O2 optimization even in Debug build; messy because of CMake limitations
function(upx_compile_source_debug_with_O2) # ARGV
set(flags "$<$<CONFIG:Debug>:-O2>")
if(${CMAKE_VERSION} VERSION_LESS "3.8")
# 3.8: The COMPILE_FLAGS source file property learned to support generator expressions
if(is_multi_config OR NOT CMAKE_BUILD_TYPE MATCHES "^Debug$")
return()
endif()
set(flags "-O2")
endif()
if(CMAKE_GENERATOR MATCHES "Xcode") # multi-config
# NOTE: Xcode does not support per-config per-source COMPILE_FLAGS (as of CMake 3.27.7)
return()
endif()
foreach(source ${ARGV})
if(MSVC_FRONTEND)
# MSVC uses some Debug compilation options like -RTC1 that are incompatible with -O2
else()
get_source_file_property(prop "${source}" COMPILE_FLAGS)
if(prop MATCHES "^(NOTFOUND)?$")
set_source_files_properties("${source}" PROPERTIES COMPILE_FLAGS "${flags}")
else()
set_source_files_properties("${source}" PROPERTIES COMPILE_FLAGS "${prop} ${flags}")
endif()
endif()
endforeach()
endfunction()
# sanitize a target: this needs proper support from your compiler AND toolchain
function(upx_sanitize_target) # ARGV
foreach(t ${ARGV})
if(UPX_CONFIG_DISABLE_SANITIZE)
# no-op
elseif(MSVC_FRONTEND)
# MSVC uses -GS (similar to -fstack-protector) by default
elseif(MINGW OR CYGWIN)
# avoid link errors with current MinGW-w64 versions
# see https://www.mingw-w64.org/contribute/#sanitizers-asan-tsan-usan
elseif(CMAKE_C_COMPILER_ID MATCHES "^GNU" AND CMAKE_C_COMPILER_VERSION VERSION_LESS "8.0")
# unsupported compiler; unreliable/broken sanitize implementation
else()
# default sanitizer for Debug builds
target_compile_options(${t} PRIVATE $<$<CONFIG:Debug>:-fsanitize=undefined -fsanitize-undefined-trap-on-error -fstack-protector-all>)
# default sanitizer for Release builds
target_compile_options(${t} PRIVATE $<$<CONFIG:MinSizeRel>:-fstack-protector>)
target_compile_options(${t} PRIVATE $<$<CONFIG:Release>:-fstack-protector>)
target_compile_options(${t} PRIVATE $<$<CONFIG:RelWithDebInfo>:-fstack-protector>)
endif()
endforeach()
endfunction()
# util to add wildcard expansions to a variable
function(upx_add_glob_files) # ARGV
set(var_name ${ARGV0})
list(REMOVE_AT ARGV 0)
file(GLOB files ${ARGV})
set(result "${${var_name}}")
list(APPEND result "${files}")
list(SORT result)
list(REMOVE_DUPLICATES result)
##message(STATUS "upx_add_glob_files: ${var_name} = ${result}")
set(${var_name} "${result}" PARENT_SCOPE) # return value
endfunction()
# examine MinGW/Cygwin compiler configuration # examine MinGW/Cygwin compiler configuration
if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/.git") if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/.git")
if(WIN32 OR MINGW OR CYGWIN) upx_print_mingw_symbols()
if(CMAKE_C_COMPILER_ID MATCHES "(Clang|GNU)")
# runtime library: msvcrt vs ucrt vs cygwin
upx_print_have_symbol(__CRTDLL__ __CYGWIN__ __CYGWIN32__ __CYGWIN64__ __MINGW32__ __MINGW64__ __MINGW64_VERSION_MAJOR __MSVCRT__ _UCRT _WIN32 _WIN64)
# exception handing: SJLJ (setjmp/longjmp) vs DWARF vs SEH
upx_print_have_symbol(__GCC_HAVE_DWARF2_CFI_ASM __SEH__ __USING_SJLJ_EXCEPTIONS__)
# threads: win32 vs posix/pthread/winpthreads vs mcfgthread
upx_print_have_symbol(_REENTRANT __USING_MCFGTHREAD__)
endif()
endif()
endif() endif()
#*********************************************************************** #***********************************************************************
@ -613,13 +445,6 @@ upx_cmake_include_hook(6_test)
if(NOT UPX_CONFIG_CMAKE_DISABLE_TEST) if(NOT UPX_CONFIG_CMAKE_DISABLE_TEST)
function(upx_add_test) # ARGV
set(name "${ARGV0}")
list(REMOVE_AT ARGV 0)
add_test(NAME "${name}" COMMAND ${ARGV})
set_tests_properties("${name}" PROPERTIES RUN_SERIAL TRUE) # run these tests sequentially
endfunction()
include(CTest) include(CTest)
if(NOT CMAKE_CROSSCOMPILING OR CMAKE_CROSSCOMPILING_EMULATOR) if(NOT CMAKE_CROSSCOMPILING OR CMAKE_CROSSCOMPILING_EMULATOR)
add_test(NAME upx-version COMMAND upx --version) add_test(NAME upx-version COMMAND upx --version)
@ -630,17 +455,17 @@ if(NOT UPX_CONFIG_DISABLE_SELF_PACK_TEST)
set(exe "${CMAKE_EXECUTABLE_SUFFIX}") set(exe "${CMAKE_EXECUTABLE_SUFFIX}")
set(upx_self_exe "$<TARGET_FILE:upx>") set(upx_self_exe "$<TARGET_FILE:upx>")
set(fo "--force-overwrite") set(fo "--force-overwrite")
upx_add_test(upx-self-pack upx -3 "${upx_self_exe}" ${fo} -o upx-packed${exe}) upx_add_serial_test(upx-self-pack upx -3 "${upx_self_exe}" ${fo} -o upx-packed${exe})
upx_add_test(upx-self-pack-n2b upx -3 --nrv2b "${upx_self_exe}" ${fo} -o upx-packed-n2b${exe}) upx_add_serial_test(upx-self-pack-n2b upx -3 --nrv2b "${upx_self_exe}" ${fo} -o upx-packed-n2b${exe})
upx_add_test(upx-self-pack-n2d upx -3 --nrv2d "${upx_self_exe}" ${fo} -o upx-packed-n2d${exe}) upx_add_serial_test(upx-self-pack-n2d upx -3 --nrv2d "${upx_self_exe}" ${fo} -o upx-packed-n2d${exe})
upx_add_test(upx-self-pack-n2e upx -3 --nrv2e "${upx_self_exe}" ${fo} -o upx-packed-n2e${exe}) upx_add_serial_test(upx-self-pack-n2e upx -3 --nrv2e "${upx_self_exe}" ${fo} -o upx-packed-n2e${exe})
upx_add_test(upx-self-pack-lzma upx -1 --lzma "${upx_self_exe}" ${fo} -o upx-packed-lzma${exe}) upx_add_serial_test(upx-self-pack-lzma upx -1 --lzma "${upx_self_exe}" ${fo} -o upx-packed-lzma${exe})
upx_add_test(upx-list upx -l upx-packed${exe} upx-packed-n2b${exe} upx-packed-n2d${exe} upx-packed-n2e${exe} upx-packed-lzma${exe}) upx_add_serial_test(upx-list upx -l upx-packed${exe} upx-packed-n2b${exe} upx-packed-n2d${exe} upx-packed-n2e${exe} upx-packed-lzma${exe})
upx_add_test(upx-fileinfo upx --fileinfo upx-packed${exe} upx-packed-n2b${exe} upx-packed-n2d${exe} upx-packed-n2e${exe} upx-packed-lzma${exe}) upx_add_serial_test(upx-fileinfo upx --fileinfo upx-packed${exe} upx-packed-n2b${exe} upx-packed-n2d${exe} upx-packed-n2e${exe} upx-packed-lzma${exe})
upx_add_test(upx-test upx -t upx-packed${exe} upx-packed-n2b${exe} upx-packed-n2d${exe} upx-packed-n2e${exe} upx-packed-lzma${exe}) upx_add_serial_test(upx-test upx -t upx-packed${exe} upx-packed-n2b${exe} upx-packed-n2d${exe} upx-packed-n2e${exe} upx-packed-lzma${exe})
upx_add_test(upx-unpack upx -d upx-packed${exe} ${fo} -o upx-unpacked${exe}) upx_add_serial_test(upx-unpack upx -d upx-packed${exe} ${fo} -o upx-unpacked${exe})
upx_add_test(upx-run-unpacked ${CMAKE_CROSSCOMPILING_EMULATOR} ./upx-unpacked${exe} --version-short) upx_add_serial_test(upx-run-unpacked ${CMAKE_CROSSCOMPILING_EMULATOR} ./upx-unpacked${exe} --version-short)
upx_add_test(upx-run-packed ${CMAKE_CROSSCOMPILING_EMULATOR} ./upx-packed${exe} --version-short) upx_add_serial_test(upx-run-packed ${CMAKE_CROSSCOMPILING_EMULATOR} ./upx-packed${exe} --version-short)
endif() # UPX_CONFIG_DISABLE_SELF_PACK_TEST endif() # UPX_CONFIG_DISABLE_SELF_PACK_TEST
endif() endif()

201
misc/cmake/functions.cmake Normal file
View File

@ -0,0 +1,201 @@
#
# UPX "CMake" build file; see https://cmake.org/
# Copyright (C) Markus Franz Xaver Johannes Oberhumer
#
#***********************************************************************
# util
#***********************************************************************
# support config hooks; developer convenience
macro(upx_cmake_include_hook section)
include("${CMAKE_CURRENT_SOURCE_DIR}/misc/cmake/hooks/CMakeLists.${section}.txt" OPTIONAL)
include("${CMAKE_CURRENT_SOURCE_DIR}/maint/make/CMakeLists.${section}.txt" OPTIONAL)
endmacro()
function(upx_print_var) # ARGV
foreach(var_name ${ARGV})
if(DEFINED ${var_name} AND NOT ",${${var_name}}," STREQUAL ",,")
if(${var_name})
message(STATUS "${var_name} = ${${var_name}}")
endif()
endif()
endforeach()
endfunction()
function(upx_print_have_symbol) # ARGV
foreach(symbol ${ARGV})
set(cache_var_name "HAVE_symbol_${symbol}")
check_symbol_exists(${symbol} "limits.h;stddef.h;stdint.h" ${cache_var_name})
if(${cache_var_name})
message(STATUS "HAVE ${symbol}")
endif()
endforeach()
endfunction()
# examine MinGW/Cygwin compiler configuration
function(upx_print_mingw_symbols)
if(WIN32 OR MINGW OR CYGWIN)
if(CMAKE_C_COMPILER_ID MATCHES "(Clang|GNU)")
# runtime library: msvcrt vs ucrt vs cygwin
upx_print_have_symbol(__CRTDLL__ __CYGWIN__ __CYGWIN32__ __CYGWIN64__ __MINGW32__ __MINGW64__ __MINGW64_VERSION_MAJOR __MSVCRT__ _UCRT _WIN32 _WIN64)
# exception handing: SJLJ (setjmp/longjmp) vs DWARF vs SEH
upx_print_have_symbol(__GCC_HAVE_DWARF2_CFI_ASM __SEH__ __USING_SJLJ_EXCEPTIONS__)
# threads: win32 vs posix/pthread/winpthreads vs mcfgthread
upx_print_have_symbol(_REENTRANT __USING_MCFGTHREAD__)
endif()
endif()
endfunction()
# add wildcard expansions to a variable
function(upx_add_glob_files) # ARGV
set(var_name ${ARGV0})
list(REMOVE_AT ARGV 0)
file(GLOB files ${ARGV})
set(result "${${var_name}}")
list(APPEND result "${files}")
list(SORT result)
list(REMOVE_DUPLICATES result)
##message(STATUS "upx_add_glob_files: ${var_name} = ${result}")
set(${var_name} "${result}" PARENT_SCOPE) # return value
endfunction()
# useful for CI jobs: allow settings via environment and cache result
function(upx_cache_bool_vars) # ARGV
set(default_value "${ARGV0}")
list(REMOVE_AT ARGV 0)
foreach(var_name ${ARGV})
set(value ${default_value})
if(DEFINED UPX_CACHE_VALUE_${var_name}) # check cache
set(value "${UPX_CACHE_VALUE_${var_name}}")
elseif(DEFINED ${var_name}) # defined via "cmake -DXXX=YYY"
set(value "${${var_name}}")
elseif("$ENV{${var_name}}" MATCHES "^(0|1|OFF|ON|FALSE|TRUE)$") # check environment
set(value "$ENV{${var_name}}")
set(UPX_CACHE_ORIGIN_FROM_ENV_${var_name} TRUE CACHE INTERNAL "" FORCE) # for info below
endif()
# convert to bool
if(value)
set(value ON)
else()
set(value OFF)
endif()
# store result
if(UPX_CACHE_ORIGIN_FROM_ENV_${var_name})
message(STATUS "setting from environment: ${var_name} = ${value}")
endif()
set(${var_name} "${value}" PARENT_SCOPE) # store result
set(UPX_CACHE_VALUE_${var_name} "${value}" CACHE INTERNAL "" FORCE) # and store in cache
endforeach()
endfunction()
#***********************************************************************
# compilation flags
#***********************************************************************
function(upx_internal_add_definitions_with_prefix) # ARGV
set(flag_prefix "${ARGV0}")
if(flag_prefix MATCHES "^empty$") # need "empty" to work around bug in old CMake versions
set(flag_prefix "")
endif()
list(REMOVE_AT ARGV 0)
set(failed "")
foreach(f ${ARGV})
set(flag "${flag_prefix}${f}")
string(REGEX REPLACE "[^0-9a-zA-Z_]" "_" cache_var_name "HAVE_CFLAG_${flag}")
check_c_compiler_flag("${flag}" ${cache_var_name})
if(${cache_var_name})
#message(STATUS "add_definitions: ${flag}")
add_definitions("${flag}")
else()
list(APPEND failed "${f}")
endif()
endforeach()
set(failed_flags "${failed}" PARENT_SCOPE) # return value
endfunction()
function(upx_add_definitions) # ARGV
set(failed_flags "")
if(MSVC_FRONTEND AND CMAKE_C_COMPILER_ID MATCHES "Clang")
# for clang-cl try "-clang:" flag prefix first
upx_internal_add_definitions_with_prefix("-clang:" ${ARGV})
upx_internal_add_definitions_with_prefix("empty" ${failed_flags})
else()
upx_internal_add_definitions_with_prefix("empty" ${ARGV})
endif()
endfunction()
# compile a target with -O2 optimization even in Debug build
function(upx_compile_target_debug_with_O2) # ARGV
foreach(t ${ARGV})
if(MSVC_FRONTEND)
# MSVC uses some Debug compilation options like -RTC1 that are incompatible with -O2
else()
target_compile_options(${t} PRIVATE $<$<CONFIG:Debug>:-O2>)
endif()
endforeach()
endfunction()
# compile a source file with -O2 optimization even in Debug build; messy because of CMake limitations
function(upx_compile_source_debug_with_O2) # ARGV
set(flags "$<$<CONFIG:Debug>:-O2>")
if(${CMAKE_VERSION} VERSION_LESS "3.8")
# 3.8: The COMPILE_FLAGS source file property learned to support generator expressions
if(is_multi_config OR NOT CMAKE_BUILD_TYPE MATCHES "^Debug$")
return()
endif()
set(flags "-O2")
endif()
if(CMAKE_GENERATOR MATCHES "Xcode") # multi-config
# NOTE: Xcode does not support per-config per-source COMPILE_FLAGS (as of CMake 3.27.7)
return()
endif()
foreach(source ${ARGV})
if(MSVC_FRONTEND)
# MSVC uses some Debug compilation options like -RTC1 that are incompatible with -O2
else()
get_source_file_property(prop "${source}" COMPILE_FLAGS)
if(prop MATCHES "^(NOTFOUND)?$")
set_source_files_properties("${source}" PROPERTIES COMPILE_FLAGS "${flags}")
else()
set_source_files_properties("${source}" PROPERTIES COMPILE_FLAGS "${prop} ${flags}")
endif()
endif()
endforeach()
endfunction()
# sanitize a target: this needs proper support from your compiler AND toolchain
function(upx_sanitize_target) # ARGV
foreach(t ${ARGV})
if(UPX_CONFIG_DISABLE_SANITIZE)
# no-op
elseif(MSVC_FRONTEND)
# MSVC uses -GS (similar to -fstack-protector) by default
elseif(MINGW OR CYGWIN)
# avoid link errors with current MinGW-w64 versions
# see https://www.mingw-w64.org/contribute/#sanitizers-asan-tsan-usan
elseif(CMAKE_C_COMPILER_ID MATCHES "^GNU" AND CMAKE_C_COMPILER_VERSION VERSION_LESS "8.0")
# unsupported compiler; unreliable/broken sanitize implementation
else()
# default sanitizer for Debug builds
target_compile_options(${t} PRIVATE $<$<CONFIG:Debug>:-fsanitize=undefined -fsanitize-undefined-trap-on-error -fstack-protector-all>)
# default sanitizer for Release builds
target_compile_options(${t} PRIVATE $<$<CONFIG:MinSizeRel>:-fstack-protector>)
target_compile_options(${t} PRIVATE $<$<CONFIG:Release>:-fstack-protector>)
target_compile_options(${t} PRIVATE $<$<CONFIG:RelWithDebInfo>:-fstack-protector>)
endif()
endforeach()
endfunction()
#***********************************************************************
# test
#***********************************************************************
function(upx_add_serial_test) # ARGV
set(name "${ARGV0}")
list(REMOVE_AT ARGV 0)
add_test(NAME "${name}" COMMAND ${ARGV})
set_tests_properties("${name}" PROPERTIES RUN_SERIAL TRUE) # run these tests sequentially
endfunction()
# vim:set ft=cmake ts=4 sw=4 tw=0 et: