From a9cb354225d7f8941de26c3ae9b593cc275423a8 Mon Sep 17 00:00:00 2001 From: "Markus F.X.J. Oberhumer" Date: Wed, 7 Aug 2024 13:37:38 +0200 Subject: [PATCH] CI and cmake updates --- .github/workflows/ci.yml | 36 ++++++++++++------------ CMakeLists.txt | 13 +++++---- misc/cmake/functions.cmake | 55 +++++++++++++++++++------------------ misc/cmake/print_info.cmake | 2 +- misc/make/Makefile-extra.mk | 4 +++ src/Makefile | 2 +- src/check/dt_check.cpp | 2 ++ src/util/util.cpp | 15 +++++----- src/util/util.h | 4 +++ src/util/xspan.cpp | 7 +---- 10 files changed, 75 insertions(+), 65 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c63be46a..9bf3c80c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,11 +15,12 @@ env: DEBIAN_FRONTEND: noninteractive UPX_CMAKE_BUILD_FLAGS: --verbose UPX_CMAKE_CONFIG_FLAGS: -Wdev --warn-uninitialized + UPX_CONFIG_HAVE_WORKING_BUILD_RPATH: 'ON' UPX_DEBUG_TEST_FLOAT_DIVISION_BY_ZERO: 1 UPX_DEBUG_TEST_LIBC_QSORT: 1 ZSTD_CLEVEL: 9 - # 2024-06-07 - ZIG_DIST_VERSION: 0.13.0 + # 2024-08-03 + ZIG_DIST_VERSION: 0.14.0-dev.839+a931bfada jobs: job-rebuild-and-verify-stubs: @@ -76,8 +77,6 @@ jobs: job-linux-cmake: # uses cmake + make if: true needs: [ job-rebuild-and-verify-stubs ] - name: ${{ format('{0}', matrix.os) }} - runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: @@ -87,6 +86,8 @@ jobs: # GitHub ubuntu-24.04 is BETA; BUG: currently i386 programs can abort with "The futex facility returned an unexpected error code" # THIS IS A KNOWN ISSUE: https://github.com/actions/runner-images/issues/9848 - { os: ubuntu-24.04 } # TODO later: enable extra+wine once the GitHub VM is fixed + name: ${{ format('{0}', matrix.os) }} + runs-on: ${{ matrix.os }} steps: - name: Install extra 32-bit and MinGW packages if: ${{ matrix.use_extra }} @@ -206,8 +207,6 @@ jobs: job-macos-cmake: # uses cmake + make if: true needs: [ job-rebuild-and-verify-stubs ] - name: ${{ format('{0} {1}{2}', matrix.os, matrix.xcode_version && 'xcode-' || '', matrix.xcode_version) }} - runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: @@ -222,6 +221,8 @@ jobs: # { os: macos-14, gcc: gcc-13, gxx: g++-13, testsuite: true } # gcc-13: INTERNAL ERROR in ld64 # { os: macos-14, gcc: gcc-13, gxx: g++-13, testsuite: true, xcode_version: 14.3.1 } # gcc-13: MISSING HEADER FILES - { os: macos-14, gcc: gcc-12, gxx: g++-12, testsuite: true } # => use gcc-12 for now + name: ${{ format('{0} {1}{2}', matrix.os, matrix.xcode_version && 'xcode-' || '', matrix.xcode_version) }} + runs-on: ${{ matrix.os }} steps: - uses: maxim-lobanov/setup-xcode@v1 if: ${{ matrix.xcode_version }} @@ -327,14 +328,14 @@ jobs: job-windows-cmake: # uses cmake + msbuild if: true needs: [ job-rebuild-and-verify-stubs ] - name: ${{ format('{0}', matrix.name) }} - runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: include: - { name: windows-2019-amd64, os: windows-2019, vsversion: 2019, vsarch: amd64 } - { name: windows-2022-amd64, os: windows-2022, vsversion: 2022, vsarch: amd64 } + name: ${{ format('{0}', matrix.name) }} + runs-on: ${{ matrix.os }} steps: - run: git config --global core.autocrlf false - uses: actions/checkout@v4 @@ -379,11 +380,6 @@ jobs: job-windows-toolchains: # build "by hand" using cmd.exe if: github.repository_owner == 'upx' needs: [ job-rebuild-and-verify-stubs ] - name: ${{ format('windows {0}', matrix.name) }} - runs-on: ${{ matrix.os }} - env: - C: ${{ matrix.name }} - B: release strategy: fail-fast: false matrix: @@ -396,6 +392,11 @@ jobs: # { name: arm64x-win64-vs2022, os: windows-2022, vsversion: 2022, vsarch: amd64_arm64, cl_machine_flags: -arm64EC, link_machine_flags: '/machine:arm64x' } - { name: i386-win32-vs2019, os: windows-2019, vsversion: 2019, vsarch: amd64_x86 } - { name: i386-win32-vs2022, os: windows-2022, vsversion: 2022, vsarch: amd64_x86 } + name: ${{ format('windows {0}', matrix.name) }} + runs-on: ${{ matrix.os }} + env: + C: ${{ matrix.name }} + B: release steps: - run: git config --global core.autocrlf false - uses: actions/checkout@v4 @@ -483,9 +484,6 @@ jobs: job-linux-zigcc: # uses cmake + make if: github.repository_owner == 'upx' needs: [ job-rebuild-and-verify-stubs ] - name: ${{ format('zigcc {0} {1}', matrix.zig_target, matrix.zig_pic) }} - runs-on: ubuntu-latest - container: alpine:3.20 strategy: fail-fast: false matrix: @@ -519,9 +517,13 @@ jobs: # { zig_target: x86_64-macos.12.0-none } # { zig_target: x86_64-macos.13.0-none } - { zig_target: x86_64-windows-gnu } + name: ${{ format('zigcc {0} {1}', matrix.zig_target, matrix.zig_pic) }} + runs-on: ubuntu-latest + container: alpine:3.20 env: # zig is currently missing winpthreads; see https://github.com/ziglang/zig/issues/10989 UPX_CONFIG_EXPECT_THREADS: ${{ contains(matrix.zig_target, '-windows') && 'OFF' || 'ON' }} + UPX_CONFIG_HAVE_WORKING_BUILD_RPATH: '' # for zig-cc wrapper scripts (see below): ZIG_CPPFLAGS: -DUPX_DOCTEST_CONFIG_MULTITHREADING ZIG_FLAGS: ${{ matrix.zig_flags }} @@ -545,7 +547,7 @@ jobs: rev=$(git rev-parse --short=7 HEAD) echo "UPX_GITREV_SHORT=$rev" >> $GITHUB_ENV if [[ "${{ matrix.zig_target }}" == i386-linux-gnu.2.3.4 ]]; then - echo "UPX_CONFIG_DISABLE_SHARED_LIBS=ON" >> $GITHUB_ENV # zig problem + echo "UPX_CONFIG_DISABLE_SHARED_LIBS=ON" >> $GITHUB_ENV # zig problem when linking in Debug mode fi if [[ "${{ matrix.zig_target }}" == x86_64-linux-gnu.2.3.4 ]]; then echo "NEED_GCOMPAT=1" >> $GITHUB_ENV diff --git a/CMakeLists.txt b/CMakeLists.txt index 873e5a10..fd62bede 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -78,7 +78,7 @@ upx_cache_bool_vars(ON CMAKE_C_STANDARD_REQUIRED CMAKE_CXX_STANDARD_REQUIRED CMAKE_EXPORT_COMPILE_COMMANDS CMAKE_REQUIRED_QUIET ) -# internal UPX settings +# internal UPX settings; useful for CI jobs upx_cache_bool_vars(OFF UPX_CONFIG_CMAKE_DISABLE_TEST UPX_CONFIG_CMAKE_DISABLE_INSTALL UPX_CONFIG_CMAKE_DISABLE_PRINT_INFO UPX_CONFIG_CMAKE_DISABLE_PLATFORM_CHECK @@ -133,14 +133,17 @@ endif() # CMake init upx_set_default_build_type(Release) # default is CMAKE_BUILD_TYPE=Release -upx_set_default_rpath() project(upx VERSION "${UPX_VERSION_STRING}" LANGUAGES C CXX) upx_apply_build_type() -upx_apply_rpath() +upx_set_global_vars() +upx_check_working_build_rpath(UPX_CONFIG_HAVE_WORKING_BUILD_RPATH) if(DEFINED UPX_CONFIG_CMAKE_EXECUTABLE_SUFFIX) set(CMAKE_EXECUTABLE_SUFFIX "${UPX_CONFIG_CMAKE_EXECUTABLE_SUFFIX}") endif() +if(NOT UPX_CONFIG_CMAKE_DISABLE_INSTALL AND CMAKE_INSTALL_PREFIX) + include(GNUInstallDirs) +endif() #*********************************************************************** # common compilation flags @@ -479,9 +482,6 @@ if(NOT CMAKE_INSTALL_PREFIX) #message(FATAL_ERROR "ERROR: CMAKE_INSTALL_PREFIX is not defined") message(WARNING "WARNING: CMAKE_INSTALL_PREFIX is not defined") endif() -if(CMAKE_INSTALL_PREFIX) - include(GNUInstallDirs) -endif() # install files if(CMAKE_INSTALL_PREFIX AND DEFINED CMAKE_INSTALL_BINDIR) install(TARGETS upx DESTINATION "${CMAKE_INSTALL_BINDIR}") @@ -522,6 +522,7 @@ endif() # extra sanity checks to detect incompatible C vs CXX settings if(NOT UPX_CONFIG_CMAKE_DISABLE_PLATFORM_CHECK) upx_platform_check_mismatch(CMAKE_C_PLATFORM_ID CMAKE_CXX_PLATFORM_ID) + upx_platform_check_mismatch(CMAKE_C_SIMULATE_ID CMAKE_CXX_SIMULATE_ID) upx_platform_check_mismatch(CMAKE_C_COMPILER_ABI CMAKE_CXX_COMPILER_ABI) upx_platform_check_mismatch(CMAKE_C_COMPILER_FRONTEND_VARIANT CMAKE_CXX_COMPILER_FRONTEND_VARIANT) endif() diff --git a/misc/cmake/functions.cmake b/misc/cmake/functions.cmake index bf72e121..a31daf68 100644 --- a/misc/cmake/functions.cmake +++ b/misc/cmake/functions.cmake @@ -35,6 +35,15 @@ macro(upx_disallow_in_source_build) endif() endmacro() +# ternary conditional operator +macro(upx_ternary result_var_name condition true_value false_value) + if(${condition}) + set(${result_var_name} "${true_value}") + else() + set(${result_var_name} "${false_value}") + endif() +endmacro() + # set the default build type; must be called BEFORE project() cmake init macro(upx_set_default_build_type type) set(upx_global_default_build_type "${type}") @@ -73,41 +82,35 @@ macro(upx_apply_build_type) set(CMAKE_TRY_COMPILE_CONFIGURATION "${upx_global_default_build_type}") endif() endif() - # and also set MSVC_FRONTEND, GNU_FRONTEND and MINGW +endmacro() + +# set MINGW, MSVC_FRONTEND, GNU_FRONTEND and MSVC_SIMULATE +macro(upx_set_global_vars) + if(NOT DEFINED MINGW AND CMAKE_C_PLATFORM_ID MATCHES "^MinGW") + set(MINGW 1) + endif() if(NOT DEFINED MSVC_FRONTEND AND (MSVC OR CMAKE_C_COMPILER_FRONTEND_VARIANT MATCHES "^MSVC")) set(MSVC_FRONTEND 1) elseif(NOT DEFINED GNU_FRONTEND AND (CMAKE_C_COMPILER_FRONTEND_VARIANT MATCHES "^GNU" OR CMAKE_C_COMPILER_ID MATCHES "(Clang|GNU|LLVM)")) set(GNU_FRONTEND 1) endif() - if(NOT DEFINED MINGW AND CMAKE_C_PLATFORM_ID MATCHES "^MinGW") - set(MINGW 1) + if(NOT DEFINED MSVC_SIMULATE AND (CMAKE_C_SIMULATE_ID MATCHES "^MSVC")) + set(MSVC_SIMULATE 1) endif() endmacro() -# handle the default RPATH settings; must be called BEFORE project() cmake init -macro(upx_set_default_rpath) -endmacro() - -# handle the default RPATH settings; must be called AFTER project() cmake init -macro(upx_apply_rpath) - if(NOT DEFINED CMAKE_BUILD_WITH_INSTALL_RPATH) - if(APPLE) # macOS - set(CMAKE_BUILD_WITH_INSTALL_RPATH ON) - set(CMAKE_BUILD_WITH_INSTALL_NAME_DIR ON) - set(CMAKE_INSTALL_NAME_DIR "@rpath") - elseif(CMAKE_GENERATOR MATCHES "Ninja" AND NOT CMAKE_EXECUTABLE_FORMAT MATCHES "^ELF") - # info: needed by Ninja generator unless on an ELF-based or XCOFF-based platform - set(CMAKE_BUILD_WITH_INSTALL_RPATH ON) - endif() - endif() -endmacro() - -# ternary conditional operator -macro(upx_ternary result_var_name condition true_value false_value) - if(${condition}) - set(${result_var_name} "${true_value}") +# useful for CI jobs: check for working BUILD_RPATH +macro(upx_check_working_build_rpath var_name) + if(WIN32 OR MINGW OR CYGWIN) + # always works; DLLs reside next to the executables + upx_cache_bool_vars(ON ${var_name}) + elseif(CMAKE_BUILD_WITH_INSTALL_RPATH OR CMAKE_SKIP_RPATH OR CMAKE_SKIP_BUILD_RPATH) + # cannot work; BUILD_RPATH is disabled by global CMake settings + set(${var_name} OFF) + upx_cache_bool_vars(OFF ${var_name}) else() - set(${result_var_name} "${false_value}") + # we do not know if/how the BUILD_RPATH is set; be cautious by default + upx_cache_bool_vars(OFF ${var_name}) endif() endmacro() diff --git a/misc/cmake/print_info.cmake b/misc/cmake/print_info.cmake index 3bedd097..407af753 100644 --- a/misc/cmake/print_info.cmake +++ b/misc/cmake/print_info.cmake @@ -56,7 +56,7 @@ function(upx_print_info) # ARGV upx_print_var(UPX_CONFIG_SANITIZE_FLAGS_DEBUG UPX_CONFIG_SANITIZE_FLAGS_RELEASE) # shortcuts - upx_print_var(APPLE CLANG CYGWIN GNU_FRONTEND GNUC MINGW MSVC MSVC_FRONTEND MSVC_IDE MSVC_TOOLSET_VERSION MSVC_VERSION MSYS UNIX WIN32 WIN64) + upx_print_var(APPLE CLANG CYGWIN GNU_FRONTEND GNUC MINGW MSVC MSVC_FRONTEND MSVC_IDE MSVC_SIMULATE MSVC_TOOLSET_VERSION MSVC_VERSION MSYS UNIX WIN32 WIN64) endfunction() # vim:set ft=cmake ts=4 sw=4 tw=0 et: diff --git a/misc/make/Makefile-extra.mk b/misc/make/Makefile-extra.mk index 18f93bca..e1f23a07 100644 --- a/misc/make/Makefile-extra.mk +++ b/misc/make/Makefile-extra.mk @@ -302,6 +302,10 @@ endif # it easy to set other variables like CMAKE_AR or CMAKE_RANLIB #*********************************************************************** +UPX_CMAKE_CONFIG_FLAGS += $(UPX_CMAKE_CONFIG_FLAGS_GENERATOR) +UPX_CMAKE_CONFIG_FLAGS += $(UPX_CMAKE_CONFIG_FLAGS_TOOLSET) +UPX_CMAKE_CONFIG_FLAGS += $(UPX_CMAKE_CONFIG_FLAGS_PLATFORM) + $(call check_undefined,__add_cmake_config) # promote an environment or Make variable to a CMake cache entry: __add_cmake_config = $(and $($1),-D$1="$($1)") diff --git a/src/Makefile b/src/Makefile index 02801898..bd1a8c80 100644 --- a/src/Makefile +++ b/src/Makefile @@ -87,7 +87,7 @@ endif # /usr/bin/env # make clang-format #*********************************************************************** -# automatically format some C++ source code files +# automatically format most C++ source code files ifneq ($(wildcard /usr/bin/env),) ifeq ($(shell uname),Linux) diff --git a/src/check/dt_check.cpp b/src/check/dt_check.cpp index 7000b799..e528629e 100644 --- a/src/check/dt_check.cpp +++ b/src/check/dt_check.cpp @@ -1117,8 +1117,10 @@ void upx_compiler_sanity_check(void) noexcept { 0, 0, 0, 0, 0, 0, 0, 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0, 0, 0, 0, 0x7f, 0x7e, 0x7d, 0x7c, 0x7b, 0x7a, 0x79, 0x78, 0, 0, 0, 0, 0}; constexpr const byte *d = dd + 7; +#if !defined(upx_fake_alignas_16) assert_noexcept(ptr_is_aligned<16>(dd)); assert_noexcept(ptr_is_aligned(dd, 16)); +#endif static_assert(upx::compile_time::get_be16(d) == 0xfffe); static_assert(upx::compile_time::get_be24(d) == 0xfffefd); static_assert(upx::compile_time::get_be32(d) == 0xfffefdfc); diff --git a/src/util/util.cpp b/src/util/util.cpp index d60c3a19..047791fa 100644 --- a/src/util/util.cpp +++ b/src/util/util.cpp @@ -106,14 +106,12 @@ TEST_CASE("mem_size") { // ptr util **************************************************************************/ -int ptr_diff_bytes(const void *a, const void *b) { - if very_unlikely (a == nullptr) { +int ptr_diff_bytes(const void *a, const void *b) may_throw { + if very_unlikely (a == nullptr) throwCantPack("ptr_diff_bytes null 1; take care"); - } - if very_unlikely (b == nullptr) { + if very_unlikely (b == nullptr) throwCantPack("ptr_diff_bytes null 2; take care"); - } - ptrdiff_t d = (const charptr) a - (const charptr) b; + upx_sptraddr_t d = ptraddr_diff(a, b); if (a >= b) { if very_unlikely (!mem_size_valid_bytes(d)) throwCantPack("ptr_diff_bytes-1; take care"); @@ -121,10 +119,11 @@ int ptr_diff_bytes(const void *a, const void *b) { if very_unlikely (!mem_size_valid_bytes(0ll - d)) throwCantPack("ptr_diff_bytes-2; take care"); } + assert_noexcept(d == ((const charptr) a - (const charptr) b)); return ACC_ICONV(int, d); } -unsigned ptr_udiff_bytes(const void *a, const void *b) { +unsigned ptr_udiff_bytes(const void *a, const void *b) may_throw { int d = ptr_diff_bytes(a, b); if very_unlikely (d < 0) throwCantPack("ptr_udiff_bytes; take care"); @@ -1026,7 +1025,7 @@ TEST_CASE("get_ratio") { // compat **************************************************************************/ -#if defined(__wasi__) && 1 // TODO later - wait for wasm/wasi exception handling proposal +#if defined(__wasi__) && 1 // TODO later: wait for wasm/wasi exception handling proposal extern "C" { void *__cxa_allocate_exception(std::size_t thrown_size) throw() { return ::malloc(thrown_size); } void __cxa_throw(void *thrown_exception, /*std::type_info*/ void *tinfo, void (*dest)(void *)) { diff --git a/src/util/util.h b/src/util/util.h index 71df9bda..bb4bed62 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -105,6 +105,10 @@ forceinline upx_ptraddr_t ptr_get_address(const void *p) noexcept { return (upx_ forceinline upx_ptraddr_t ptr_get_address(upx_uintptr_t p) noexcept { return p; } #endif +forceinline upx_sptraddr_t ptraddr_diff(const void *a, const void *b) noexcept { + return ptr_get_address(a) - ptr_get_address(b); +} + template forceinline bool ptr_is_aligned(const void *p) noexcept { static_assert(upx::has_single_bit(Alignment)); diff --git a/src/util/xspan.cpp b/src/util/xspan.cpp index e971996b..3e5a2497 100644 --- a/src/util/xspan.cpp +++ b/src/util/xspan.cpp @@ -76,12 +76,7 @@ void xspan_check_range(const void *ptr, const void *base, ptrdiff_t size_in_byte xspan_fail_range_nullptr(); if very_unlikely (base == nullptr) xspan_fail_range_nullbase(); -#if defined(__SANITIZE_ADDRESS__) || 1 - // info: pointers are out of range deliberately during internal doctest checks; see dt_xspan.cpp - const upx_sptraddr_t off = ptr_get_address(ptr) - ptr_get_address(base); -#else - const ptrdiff_t off = (const charptr) ptr - (const charptr) base; -#endif + upx_sptraddr_t off = ptraddr_diff(ptr, base); if very_unlikely (off < 0 || off > size_in_bytes || size_in_bytes > UPX_RSIZE_MAX) xspan_fail_range_range(); NO_fprintf(stderr, "xspan_check_range done\n");