From c479fe32b3bba70cd7f652e2b36a19a67c731783 Mon Sep 17 00:00:00 2001 From: "Markus F.X.J. Oberhumer" Date: Mon, 13 Nov 2023 11:29:17 +0100 Subject: [PATCH] cmake update --- CMakeLists.txt | 130 +++++++++++++++++++++++++++--------------- src/check/dt_impl.cpp | 4 +- src/conf.h | 2 +- src/headers.h | 3 - src/options.h | 6 +- src/util/xspan.h | 8 +-- src/work.cpp | 4 +- 7 files changed, 98 insertions(+), 59 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 25b45d48..254f5c19 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,11 @@ else() cmake_minimum_required(VERSION "3.8" FATAL_ERROR) # CMake >= 3.8 is needed for CXX_STANDARD 17 endif() +macro(upx_cmake_include_hook section) # developer convenience + include("${CMAKE_CURRENT_SOURCE_DIR}/misc/cmake/hooks/CMakeLists.${section}.txt" OPTIONAL) + include("${CMAKE_CURRENT_SOURCE_DIR}/maint/make/CMakeLists.${section}.txt" OPTIONAL) +endmacro() + # Sections of this CMakeLists.txt: # - options # - init @@ -28,6 +33,8 @@ endif() # options #*********************************************************************** +upx_cmake_include_hook(1_options) + # compilation config options if(NOT IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/.git") # permissive config defaults when building from source code tarball @@ -52,6 +59,8 @@ option(UPX_CONFIG_DISABLE_SELF_PACK_TEST "Do not test packing UPX with itself" O # init #*********************************************************************** +upx_cmake_include_hook(2_init_begin) + # Disallow in-source builds. Note that you will still have to manually # clean up a few files if you accidentally try an in-source build. if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/.git") @@ -62,30 +71,41 @@ if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/.git") endif() endif() +# util +function(print_var) + 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() + # useful for CI jobs: allow settings via environment and cache result function(upx_cache_bool_vars) set(default_value "${ARGV0}") list(REMOVE_AT ARGV 0) - foreach(var ${ARGV}) + foreach(var_name ${ARGV}) set(value ${default_value}) - if(DEFINED UPX_CACHE_${var}) # cached - set(value "${UPX_CACHE_${var}}") - elseif(DEFINED ${var}) # defined via "cmake -DXXX=YYY" - set(value "${${var}}") - elseif("$ENV{${var}}" MATCHES "^(0|1|OFF|ON|FALSE|TRUE)$") # environment - set(value "$ENV{${var}}") - set(UPX_CACHE_ORIGIN_FROM_ENV_${var} TRUE CACHE INTERNAL "" FORCE) + if(DEFINED UPX_CACHE_${var_name}) # cached + set(value "${UPX_CACHE_${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)$") # environment + set(value "$ENV{${var_name}}") + set(UPX_CACHE_ORIGIN_FROM_ENV_${var_name} TRUE CACHE INTERNAL "" FORCE) endif() if(value) set(value ON) else() set(value OFF) endif() - if(UPX_CACHE_ORIGIN_FROM_ENV_${var}) - message(STATUS "setting from environment: ${var} = ${value}") + if(UPX_CACHE_ORIGIN_FROM_ENV_${var_name}) + message(STATUS "setting from environment: ${var_name} = ${value}") endif() - set(${var} "${value}" PARENT_SCOPE) - set(UPX_CACHE_${var} "${value}" CACHE INTERNAL "" FORCE) + set(${var_name} "${value}" PARENT_SCOPE) + set(UPX_CACHE_${var_name} "${value}" CACHE INTERNAL "" FORCE) endforeach() endfunction() @@ -169,6 +189,15 @@ if(is_multi_config) set(CMAKE_CONFIGURATION_TYPES "${c}" CACHE STRING "List of supported configuration types." FORCE) endif() +# set the build type for use in try_compile() +if(NOT CMAKE_TRY_COMPILE_CONFIGURATION) + if(CMAKE_BUILD_TYPE) + set(CMAKE_TRY_COMPILE_CONFIGURATION "${CMAKE_BUILD_TYPE}") + else() + set(CMAKE_TRY_COMPILE_CONFIGURATION "Release") + endif() +endif() + # set MSVC_FRONTEND and MINGW if(NOT DEFINED MSVC_FRONTEND AND (MSVC OR CMAKE_C_COMPILER_FRONTEND_VARIANT MATCHES "^MSVC")) set(MSVC_FRONTEND 1) @@ -177,6 +206,8 @@ if(NOT DEFINED MINGW AND CMAKE_C_PLATFORM_ID MATCHES "^MinGW") set(MINGW 1) endif() +upx_cmake_include_hook(2_init_end) + #*********************************************************************** # common compilation flags #*********************************************************************** @@ -187,12 +218,7 @@ include(CheckIncludeFile) include(CheckStructHasMember) include(CheckSymbolExists) -# TODO later: use pledge() -# https://justine.lol/pledge/ -# https://github.com/jart/cosmopolitan -# https://news.ycombinator.com/item?id=32096801 -##find_package(PkgConfig QUIET) -##pkg_check_modules(PKG_libseccomp QUIET libseccomp) +upx_cmake_include_hook(3_common_compilation_flags_begin) if(NOT DEFINED HAVE_UNISTD_H) check_include_file("unistd.h" HAVE_UNISTD_H) @@ -328,15 +354,15 @@ function(upx_compile_source_debug_with_O2) # NOTE: Xcode does not support per-config per-source COMPILE_FLAGS (as of CMake 3.27.7) return() endif() - foreach(t ${ARGV}) + 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 ${t} COMPILE_FLAGS) + get_source_file_property(prop "${source}" COMPILE_FLAGS) if(prop MATCHES "^(NOTFOUND)?$") - set_source_files_properties(${t} PROPERTIES COMPILE_FLAGS "${flags}") + set_source_files_properties("${source}" PROPERTIES COMPILE_FLAGS "${flags}") else() - set_source_files_properties(${t} PROPERTIES COMPILE_FLAGS "${prop} ${flags}") + set_source_files_properties("${source}" PROPERTIES COMPILE_FLAGS "${prop} ${flags}") endif() endif() endforeach() @@ -363,6 +389,21 @@ function(upx_sanitize_target) endforeach() endfunction() +# util to add wildcard expansions to a variable +function(upx_add_glob_files) + 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() + +upx_cmake_include_hook(3_common_compilation_flags_end) + #*********************************************************************** # targets #*********************************************************************** @@ -372,44 +413,41 @@ set(UPX_CONFIG_DISABLE_THREADS ON) # multithreading is currently not used; maybe set(UPX_CONFIG_DISABLE_BZIP2 ON) # bzip2 is currently not used; we might need it to decompress linux kernels set(UPX_CONFIG_DISABLE_ZSTD ON) # zstd is currently not used; maybe in UPX version 5 +upx_cmake_include_hook(4_targets_begin) + if(NOT UPX_CONFIG_DISABLE_THREADS) find_package(Threads) endif() if(NOT UPX_CONFIG_DISABLE_BZIP2) -file(GLOB bzip2_SOURCES "vendor/bzip2/*.c") -list(SORT bzip2_SOURCES) +upx_add_glob_files(bzip2_SOURCES "vendor/bzip2/*.c") add_library(upx_vendor_bzip2 STATIC ${bzip2_SOURCES}) if(NOT UPX_CONFIG_DISABLE_C_STANDARD) set_property(TARGET upx_vendor_bzip2 PROPERTY C_STANDARD 11) endif() endif() # UPX_CONFIG_DISABLE_BZIP2 -file(GLOB ucl_SOURCES "vendor/ucl/src/*.c") -list(SORT ucl_SOURCES) +upx_add_glob_files(ucl_SOURCES "vendor/ucl/src/*.c") add_library(upx_vendor_ucl STATIC ${ucl_SOURCES}) if(NOT UPX_CONFIG_DISABLE_C_STANDARD) set_property(TARGET upx_vendor_ucl PROPERTY C_STANDARD 11) endif() -file(GLOB zlib_SOURCES "vendor/zlib/*.c") -list(SORT zlib_SOURCES) +upx_add_glob_files(zlib_SOURCES "vendor/zlib/*.c") add_library(upx_vendor_zlib STATIC ${zlib_SOURCES}) if(NOT UPX_CONFIG_DISABLE_C_STANDARD) set_property(TARGET upx_vendor_zlib PROPERTY C_STANDARD 11) endif() if(NOT UPX_CONFIG_DISABLE_ZSTD) -file(GLOB zstd_SOURCES "vendor/zstd/lib/*/*.c") -list(SORT zstd_SOURCES) +upx_add_glob_files(zstd_SOURCES "vendor/zstd/lib/*/*.c") add_library(upx_vendor_zstd STATIC ${zstd_SOURCES}) if(NOT UPX_CONFIG_DISABLE_C_STANDARD) set_property(TARGET upx_vendor_zstd PROPERTY C_STANDARD 11) endif() endif() # UPX_CONFIG_DISABLE_ZSTD -file(GLOB upx_SOURCES "src/*.cpp" "src/[cfu]*/*.cpp") -list(SORT upx_SOURCES) +upx_add_glob_files(upx_SOURCES "src/*.cpp" "src/[cfu]*/*.cpp") add_executable(upx ${upx_SOURCES}) if(NOT UPX_CONFIG_DISABLE_CXX_STANDARD) set_property(TARGET upx PROPERTY CXX_STANDARD 17) @@ -425,10 +463,14 @@ if(Threads_FOUND) target_link_libraries(upx Threads::Threads) endif() +upx_cmake_include_hook(4_targets_end) + #*********************************************************************** # target compilation flags #*********************************************************************** +upx_cmake_include_hook(5_target_compilation_flags_begin) + if(NOT UPX_CONFIG_DISABLE_BZIP2) set(t upx_vendor_bzip2) upx_compile_target_debug_with_O2(${t}) @@ -518,6 +560,8 @@ else() target_compile_options(${t} PRIVATE ${warn_Wall} ${warn_Werror}) endif() +upx_cmake_include_hook(5_target_compilation_flags_end) + #*********************************************************************** # test # ctest @@ -525,6 +569,8 @@ endif() # ninja test #*********************************************************************** +upx_cmake_include_hook(6_test) + if(NOT UPX_CONFIG_CMAKE_DISABLE_TEST) include(CTest) @@ -567,6 +613,8 @@ endif() # UPX_CONFIG_CMAKE_DISABLE_TEST # ninja install #*********************************************************************** +upx_cmake_include_hook(7_install) + if(NOT UPX_CONFIG_CMAKE_DISABLE_INSTALL) # installation prefix and directories @@ -593,19 +641,7 @@ endif() # UPX_CONFIG_CMAKE_DISABLE_INSTALL # print some info about the build configuration #*********************************************************************** -function(print_var) - foreach(var ${ARGV}) - if(DEFINED ${var} AND NOT ",${${var}}," STREQUAL ",,") - if(${var}) - message(STATUS "${var} = ${${var}}") - endif() - endif() - endforeach() -endfunction() - -if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/maint/make/CMakeLists.maint.txt") -include("${CMAKE_CURRENT_SOURCE_DIR}/maint/make/CMakeLists.maint.txt") -endif() +upx_cmake_include_hook(8_summary) print_var(CMAKE_VERSION UPX_CONFIG_CMAKE_MINIMUM_REQUIRED_VERSION CMAKE_GENERATOR) if(NOT UPX_CONFIG_CMAKE_DISABLE_PRINT_INFO) @@ -613,7 +649,7 @@ print_var(CMAKE_HOST_SYSTEM_NAME CMAKE_HOST_SYSTEM_VERSION) print_var(CMAKE_SYSTEM_NAME CMAKE_SYSTEM_VERSION CMAKE_CROSSCOMPILING) print_var(CMAKE_C_COMPILER_ID CMAKE_C_COMPILER_VERSION CMAKE_C_COMPILER_FRONTEND_VARIANT CMAKE_C_COMPILER_ARCHITECTURE_ID CMAKE_C_PLATFORM_ID CMAKE_C_COMPILER_ABI) print_var(CMAKE_CXX_COMPILER_ID CMAKE_CXX_COMPILER_VERSION CMAKE_CXX_COMPILER_FRONTEND_VARIANT CMAKE_CXX_COMPILER_ARCHITECTURE_ID CMAKE_CXX_PLATFORM_ID CMAKE_CXX_COMPILER_ABI) -print_var(CMAKE_POSITION_INDEPENDENT_CODE) +print_var(CMAKE_CROSSCOMPILING_EMULATOR CMAKE_INTERPROCEDURAL_OPTIMIZATION CMAKE_POSITION_INDEPENDENT_CODE CMAKE_TRY_COMPILE_CONFIGURATION) print_var(CYGWIN GNUC MINGW MSVC MSVC_FRONTEND MSVC_IDE WIN32 WIN64) endif() # UPX_CONFIG_CMAKE_DISABLE_PRINT_INFO print_var(CMAKE_INSTALL_PREFIX CMAKE_CONFIGURATION_TYPES CMAKE_BUILD_TYPE) @@ -634,4 +670,6 @@ if(NOT ",${CMAKE_C_COMPILER_FRONTEND_VARIANT}," STREQUAL ",${CMAKE_CXX_COMPILER_ endif() endif() # UPX_CONFIG_CMAKE_DISABLE_PLATFORM_CHECK +upx_cmake_include_hook(9_finish) + # vim:set ft=cmake ts=4 sw=4 tw=0 et: diff --git a/src/check/dt_impl.cpp b/src/check/dt_impl.cpp index 477729ba..dfe1b660 100644 --- a/src/check/dt_impl.cpp +++ b/src/check/dt_impl.cpp @@ -43,9 +43,11 @@ #pragma GCC diagnostic ignored "-Wshadow" #endif -#if !defined(UPX_DOCTEST_CONFIG_MULTITHREADING) +#if !defined(UPX_DOCTEST_CONFIG_MULTITHREADING) && !(WITH_THREADS) +#ifndef DOCTEST_CONFIG_NO_MULTITHREADING #define DOCTEST_CONFIG_NO_MULTITHREADING #endif +#endif #if defined(__clang__) && defined(__FAST_MATH__) && defined(__INTEL_LLVM_COMPILER) // warning: comparison with NaN always evaluates to false in fast floating point modes diff --git a/src/conf.h b/src/conf.h index 0f1c960b..1aca6443 100644 --- a/src/conf.h +++ b/src/conf.h @@ -197,7 +197,7 @@ typedef upx_int64_t upx_off_t; // portab **************************************************************************/ -// some system headers may define these, so undef just in case +// some platform system headers may pre-define these, so undef to avoid conflicts #undef _ #undef __ #undef ___ diff --git a/src/headers.h b/src/headers.h index 14b904c8..3e0973ae 100644 --- a/src/headers.h +++ b/src/headers.h @@ -113,9 +113,6 @@ static_assert(sizeof(void *) == 8); #include // C++ multithreading (UPX currently does not use multithreading) -#ifndef WITH_THREADS -#define WITH_THREADS 0 -#endif #if __STDC_NO_ATOMICS__ #undef WITH_THREADS #endif diff --git a/src/options.h b/src/options.h index ab949a33..46c57fcc 100644 --- a/src/options.h +++ b/src/options.h @@ -67,9 +67,9 @@ struct Options final { int level; // compression level 1..10 int filter; // preferred filter from Packer::getFilters() bool ultra_brute; - bool all_methods; // try all available compression methods ? + bool all_methods; // try all available compression methods int all_methods_use_lzma; - bool all_filters; // try all available filters ? + bool all_filters; // try all available filters bool no_filter; // force no filter bool prefer_ucl; // prefer UCL bool exact; // user requires byte-identical decompression @@ -120,11 +120,13 @@ struct Options final { // CRP - Compression Runtime Parameters (undocumented and subject to change) struct { + bzip2_compress_config_t crp_bzip2; lzma_compress_config_t crp_lzma; ucl_compress_config_t crp_ucl; zlib_compress_config_t crp_zlib; zstd_compress_config_t crp_zstd; void reset() noexcept { + crp_bzip2.reset(); crp_lzma.reset(); crp_ucl.reset(); crp_zlib.reset(); diff --git a/src/util/xspan.h b/src/util/xspan.h index 9750824f..6db76fec 100644 --- a/src/util/xspan.h +++ b/src/util/xspan.h @@ -36,14 +36,14 @@ #if WITH_XSPAN -// automatic conversion to underlying pointer; do NOT enable this config as this +// Automatic conversion to underlying pointer; do NOT enable this config as this // defeats the main purpose of a checked pointer => use raw_bytes() as needed; -// and see xspan_fwd.h how to make this more convenient +// and see xspan_fwd.h how to make this more convenient. #ifndef XSPAN_CONFIG_ENABLE_IMPLICIT_CONVERSION #define XSPAN_CONFIG_ENABLE_IMPLICIT_CONVERSION 0 #endif -// allow automatic conversion PtrOrSpanOrNull => PtrOrSpan => Span (with run-time checks) -// choose between compile-time safety vs. possible run-time exceptions +// Allow automatic conversion PtrOrSpanOrNull => PtrOrSpan => Span (with run-time checks). +// Choose between compile-time safety vs. possible run-time exceptions. #ifndef XSPAN_CONFIG_ENABLE_SPAN_CONVERSION #define XSPAN_CONFIG_ENABLE_SPAN_CONVERSION 1 #endif diff --git a/src/work.cpp b/src/work.cpp index bd8c7e38..de318d5d 100644 --- a/src/work.cpp +++ b/src/work.cpp @@ -62,7 +62,7 @@ #endif /************************************************************************* -// util +// file util **************************************************************************/ namespace { @@ -100,7 +100,7 @@ static void set_fd_timestamp(int fd, const XStat *xst) noexcept { BOOL r = SetFileTime((HANDLE) _get_osfhandle(fd), nullptr, &xst->ft_atime, &xst->ft_mtime); IGNORE_ERROR(r); #elif USE_FTIME - auto ft_ftime = xst->ft_ftime; // djgpp2 libc bug: not const, so use a copy + struct ftime ft_ftime = xst->ft_ftime; // djgpp2 libc bug/feature: not const, so use a copy int r = setftime(fd, &ft_ftime); IGNORE_ERROR(r); #elif USE__FUTIME