diff --git a/.github/workflows/built_test.yml b/.github/workflows/built_test.yml new file mode 100644 index 000000000..17d42d1cd --- /dev/null +++ b/.github/workflows/built_test.yml @@ -0,0 +1,160 @@ +# Documentation: https://wiki.unvanquished.net/wiki/Continuous_integration + +name: Build + +on: + push: + branches: + - master + - 'for-*.*.*/sync' # Next-release branch + pull_request: + branches: + - '**' + paths: + - '.github/workflows/build_test.yml' + - '.gitmodules' + # 'android/**' + - 'autotools/**' + - 'compat/**' + - configure.ac + - DEPS + - fetch-externals + - 'm4/**' + - Makefile.am + - 'src/**' + - 'test/**' + - 'wine/**' + +jobs: + build: + name: ${{ matrix.name }} + runs-on: ${{ matrix.vm_image }} + + strategy: + fail-fast: false + matrix: + include: + - name: Linux amd64 GCC + vm_image: ubuntu-22.04 + apt_packages: g++-12 libcurl4-openssl-dev + env_commands: export CC=gcc-12 CXX=g++-12 + - name: Linux i686 GCC + # This platform reliably caught in CI the random thread-related + # bug src/client/linux/linux_client_unittest, making it possible + # to track down and debug it. It also catches more pointer type + # mismatches, thanks to the different sizes. In the end it helps + # improving robustness. + vm_image: ubuntu-22.04 + apt_architecture: i386 + apt_packages: g++-i686-linux-gnu libcurl4-openssl-dev:i386 zlib1g-dev:i386 libzstd-dev:i386 + env_commands: export CC=i686-linux-gnu-gcc CXX=i686-linux-gnu-g++ + - name: Linux arm64 GCC + vm_image: ubuntu-22.04-arm + apt_packages: g++-12 libcurl4-openssl-dev binutils-x86-64-linux-gnu + env_commands: export CC=gcc-12 CXX=g++-12 + - name: Linux amd64 Clang + vm_image: ubuntu-22.04 + apt_packages: clang libcurl4-openssl-dev + env_commands: export CC=clang CXX=clang++ + - name: Windows amd64 MinGW + vm_image: ubuntu-26.04 + apt_packages: g++-mingw-w64-x86-64 mingw-w64-x86-64-dev gcc-mingw-w64-x86-64-posix-runtime wine libcurl4-openssl-dev libz-mingw-w64-dev + setup_commands: sudo update-alternatives --set x86_64-w64-mingw32-g++ /usr/bin/x86_64-w64-mingw32-g++-posix + env_commands: export TESTDRIVER_SHARED_TEMP_WINEPREFIX=true + # There is no libzstd-mingw-w64-dev. + configure_options: --host=x86_64-w64-mingw32 --enable-static-mingw --disable-zstd + - name: Windows arm64 MinGW + vm_image: windows-11-arm + shell: msys2 {0} + msystem: CLANGARM64 + pacman_packages: base-devel mingw-w64-clang-aarch64-clang mingw-w64-clang-aarch64-gcc-compat autoconf automake libtool + env_commands: export CC=aarch64-w64-mingw32-gcc CXX=aarch64-w64-mingw32-g++ + configure_options: --host=aarch64-w64-mingw32 --enable-static-mingw + - name: macOS amd64 AppleClang + vm_image: macos-15-intel + brew_packages: autoconf automake libtool zstd + nproc_command: sysctl -n hw.logicalcpu + - name: macOS arm64 AppleClang + vm_image: macos-15 + brew_packages: autoconf automake libtool zstd + nproc_command: sysctl -n hw.logicalcpu + + env: + APT_ARCHITECTURE: ${{ matrix.apt_architecture }} + APT_PACKAGES: ${{ matrix.apt_packages }} + BREW_PACKAGES: ${{ matrix.brew_packages }} + SETUP_COMMANDS: ${{ matrix.setup_commands }} + ENV_COMMANDS: ${{ matrix.env_commands }} + NPROC_COMMAND: ${{ matrix.nproc_command }} + CONFIGURE_OPTIONS: ${{ matrix.configure_options }} + + defaults: + run: + shell: ${{ matrix.shell || 'bash' }} + + steps: + - uses: actions/checkout@v5 + + - name: Checkout dependencies + # This doesn't require the MSYS2 shell, so we can run this before the MSYS2 setup, + # and we don't have to install fetch-externals' dependencies in MSYS2 environment + # like python and git which are already provided in the default Git bash environment. + shell: bash + run: | + # To fetch googletest. + ./fetch-externals + + - name: Setup MSYS2 packages + if: ${{ matrix.pacman_packages != '' }} + uses: msys2/setup-msys2@v2 + with: + msystem: ${{ matrix.msystem }} + install: ${{ matrix.pacman_packages }} + update: true + + - name: Setup Apt architecture + if: ${{ matrix.apt_architecture != '' }} + run: | + set -xue + sudo dpkg --add-architecture "${APT_ARCHITECTURE}" + + - name: Setup Apt packages + if: ${{ matrix.apt_packages != '' }} + run: | + set -xue + sudo apt-get update && sudo apt-get -y -q --no-install-recommends install ${APT_PACKAGES} + + - name: Setup Brew packages + if: ${{ matrix.brew_packages != '' }} + run: | + set -xue + brew update && brew install ${BREW_PACKAGES} + + - name: Setup commands + if: ${{ matrix.setup_commands != '' }} + run: | + set -xue + ${SETUP_COMMANDS} + + - name: Build + run: | + set -xue + ${ENV_COMMANDS} + parallelism="$(${NPROC_COMMAND:-nproc})" + echo "Build parallelism: ${parallelism}" + autoreconf -fvi + if ! ./configure --enable-zstd ${CONFIGURE_OPTIONS}; then + [ ! -f config.log ] || cat config.log + false + fi + make "-j${parallelism}" + + - name: Test + run: | + set -xue + ${ENV_COMMANDS} + parallelism="$(${NPROC_COMMAND:-nproc})" + if ! make "-j${parallelism}" check; then + [ ! -f test-suite.log ] || cat test-suite.log + false + fi diff --git a/Makefile.am b/Makefile.am index d1f508d4d..00e69e7e2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -258,6 +258,21 @@ check_SCRIPTS = \ src/processor/minidump_stackwalk_test \ src/processor/minidump_stackwalk_machine_readable_test +## dump_syms tests +check_DEPS = \ + src/tools/linux/dump_syms/dump_syms \ + src/tools/windows/dump_syms_dwarf/dump_syms_dwarf + +check_SCRIPTS += \ + src/tools/linux/dump_syms/dump_syms_test \ + src/tools/windows/dump_syms_dwarf/dump_syms_dwarf_test + +check_DEPS += \ + src/tools/mac/dump_syms/dump_syms_mac + +check_SCRIPTS += \ + src/tools/mac/dump_syms/dump_syms_mac_test + endif !DISABLE_PROCESSOR @@ -302,6 +317,12 @@ bin_PROGRAMS += \ check_PROGRAMS += \ src/common/dumper_unittest +bin_PROGRAMS += \ + src/tools/mac/dump_syms/dump_syms_mac + +check_PROGRAMS += \ + src/common/mac/macho_reader_unittest + if LINUX_HOST if ENABLE_UPLOAD_TOOLS @@ -315,9 +336,6 @@ bin_PROGRAMS += \ src/tools/linux/pid2md/pid2md \ src/tools/linux/md2core/minidump-2-core -bin_PROGRAMS += \ - src/tools/mac/dump_syms/dump_syms_mac - if HAVE_MEMFD_CREATE libexec_PROGRAMS += \ src/tools/linux/core_handler/core_handler @@ -326,9 +344,6 @@ endif check_PROGRAMS += \ src/tools/linux/md2core/minidump_2_core_unittest -check_PROGRAMS += \ - src/common/mac/macho_reader_unittest - endif LINUX_HOST endif !DISABLE_TOOLS @@ -723,12 +738,13 @@ src_tools_linux_dump_syms_dump_syms_SOURCES = \ src/tools/linux/dump_syms/dump_syms.cc src_tools_linux_dump_syms_dump_syms_CXXFLAGS = \ $(RUSTC_DEMANGLE_CFLAGS) \ - $(ZSTD_CFLAGS) + $(ZSTD_CFLAGS) \ + $(LIBZ_CFLAGS) src_tools_linux_dump_syms_dump_syms_LDADD = \ $(RUSTC_DEMANGLE_LIBS) \ - $(ZSTD_CFLAGS) \ - $(SOCKET_LIBS) \ - -lz + $(SOCKET_LIBS) \ + $(ZSTD_LIBS) \ + $(LIBZ_LIBS) src_tools_linux_md2core_minidump_2_core_SOURCES = \ src/common/linux/memory_mapped_file.cc \ @@ -788,8 +804,12 @@ src_tools_mac_dump_syms_dump_syms_mac_SOURCES = \ src/common/mac/macho_walker.cc \ src/common/mac/macho_walker.h \ src/tools/mac/dump_syms/dump_syms_tool.cc -src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS= \ - -I$(top_srcdir)/src/third_party/mac_headers \ +src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS = +if !MACOS_BUILD +src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS += \ + -I$(top_srcdir)/src/third_party/mac_headers +endif +src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS += \ $(RUSTC_DEMANGLE_CFLAGS) \ -DHAVE_MACH_O_NLIST_H src_tools_mac_dump_syms_dump_syms_mac_LDADD= \ @@ -912,8 +932,12 @@ src_common_mac_macho_reader_unittest_SOURCES = \ src/common/mac/macho_walker.cc \ src/common/tests/file_utils.cc src_common_mac_macho_reader_unittest_CPPFLAGS = \ - $(AM_CPPFLAGS) $(TEST_CFLAGS) \ - -I$(top_srcdir)/src/third_party/mac_headers \ + $(AM_CPPFLAGS) $(TEST_CFLAGS) +if !MACOS_BUILD +src_common_mac_macho_reader_unittest_CPPFLAGS += \ + -I$(top_srcdir)/src/third_party/mac_headers +endif +src_common_mac_macho_reader_unittest_CPPFLAGS += \ -DHAVE_MACH_O_NLIST_H \ $(PTHREAD_CFLAGS) src_common_mac_macho_reader_unittest_LDADD = \ diff --git a/configure.ac b/configure.ac index db62c8e4e..1232ba61f 100644 --- a/configure.ac +++ b/configure.ac @@ -142,20 +142,17 @@ esac AM_CONDITIONAL(ANDROID_HOST, test x$ANDROID_HOST = xtrue) case $build_os in + darwin*) + MACOS_BUILD=true + ;; mingw* | msys* | cygwin*) WINDOWS_BUILD=true ;; esac -AM_CONDITIONAL(WINE_HOST, test x$WINDOWS_HOST = xtrue -a x$WINDOWS_BUILD != xtrue) +AM_CONDITIONAL(MACOS_BUILD, test x$MACOS_BUILD = xtrue) -# Some tools (like mac ones) only support x86 currently. -case $host_cpu in - i?86|x86_64) - X86_HOST=true - ;; -esac -AM_CONDITIONAL(X86_HOST, test x$X86_HOST = xtrue) +AM_CONDITIONAL(WINE_HOST, test x$WINDOWS_HOST = xtrue -a x$WINDOWS_BUILD != xtrue) AC_ARG_ENABLE(processor, AS_HELP_STRING([--disable-processor], @@ -256,17 +253,84 @@ fi AC_ARG_VAR([RUSTC_DEMANGLE_CFLAGS], [Compiler flags for rustc-demangle]) AC_ARG_VAR([RUSTC_DEMANGLE_LIBS], [Linker flags for rustc-demangle]) -AC_ARG_ENABLE(zstd, - AS_HELP_STRING([--enable-zstd], - [Enable decompression of ELF sections with zstd]),, +PKG_PROG_PKG_CONFIG + +AC_ARG_ENABLE([zlib], + [AS_HELP_STRING([--disable-zlib], + [Disable decompression of ELF sections with zlib])], + [enable_zlib=$enableval], + [enable_zlib=yes]) + +if test "x${enable_zlib}" = "xyes"; then + have_zlib=no + LIBZ_CFLAGS="" + LIBZ_LIBS="" + + AC_CHECK_LIB([z], [uncompress], + [have_zlib=yes + LIBZ_LIBS="-lz"], + [have_zlib=no]) + + if test "x${have_zlib}" != "xyes"; then + PKG_CHECK_MODULES([LIBZ], [libz], + [have_zlib=yes], + [have_zlib=no]) + fi + + if test "x${have_zlib}" != "xyes"; then + AC_MSG_ERROR([zlib library not found.]) + fi + + save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $LIBZ_CFLAGS" + AC_CHECK_HEADER([zlib.h], [], + [AC_MSG_ERROR([zlib header not found.])]) + CPPFLAGS="$save_CPPFLAGS" +fi + +AC_SUBST([LIBZ_CFLAGS]) +AC_SUBST([LIBZ_LIBS]) +AM_CONDITIONAL([ENABLE_LIBZ], [test "x${enable_zlib}" = "xyes"]) + +PKG_PROG_PKG_CONFIG + +AC_ARG_ENABLE([zstd], + [AS_HELP_STRING([--enable-zstd], + [Enable decompression of ELF sections with zstd])], + [enable_zstd=$enableval], [enable_zstd=no]) -if test "x${enable_zstd}" != xno; then - AC_CHECK_LIB(zstd, ZSTD_decompress, [], - [AC_MSG_ERROR([zstd library not found.])]) - AC_CHECK_HEADER(zstd.h, [], + +if test "x${enable_zstd}" = "xyes"; then + have_zstd=no + ZSTD_CFLAGS="" + ZSTD_LIBS="" + + AC_CHECK_LIB([zstd], [ZSTD_decompress], + [have_zstd=yes + ZSTD_LIBS="-lzstd"], + [have_zstd=no]) + + if test "x${have_zstd}" != "xyes"; then + PKG_CHECK_MODULES([ZSTD], [libzstd], + [have_zstd=yes], + [have_zstd=no]) + fi + + if test "x${have_zstd}" != "xyes"; then + AC_MSG_ERROR([zstd library not found.]) + fi + + save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $ZSTD_CFLAGS" + AC_CHECK_HEADER([zstd.h], [], [AC_MSG_ERROR([zstd header not found.])]) + CPPFLAGS="$save_CPPFLAGS" fi +AC_SUBST([ZSTD_CFLAGS]) +AC_SUBST([ZSTD_LIBS]) +AM_CONDITIONAL([ENABLE_ZSTD], [test "x${enable_zstd}" = "xyes"]) + AC_ARG_WITH(tests-as-root, AS_HELP_STRING([--with-tests-as-root], [Run the tests as root. Use this on platforms] diff --git a/m4/pkg.m4 b/m4/pkg.m4 new file mode 100644 index 000000000..c88ef6ffe --- /dev/null +++ b/m4/pkg.m4 @@ -0,0 +1,343 @@ +# pkg.m4 - Macros to locate and use pkg-config. -*- Autoconf -*- +# serial 12 (pkg-config-0.29.2) + +dnl Copyright © 2004 Scott James Remnant . +dnl Copyright © 2012-2015 Dan Nicholson +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +dnl 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a +dnl configuration script generated by Autoconf, you may include it under +dnl the same distribution terms that you use for the rest of that +dnl program. + +dnl PKG_PREREQ(MIN-VERSION) +dnl ----------------------- +dnl Since: 0.29 +dnl +dnl Verify that the version of the pkg-config macros are at least +dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's +dnl installed version of pkg-config, this checks the developer's version +dnl of pkg.m4 when generating configure. +dnl +dnl To ensure that this macro is defined, also add: +dnl m4_ifndef([PKG_PREREQ], +dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) +dnl +dnl See the "Since" comment for each macro you use to see what version +dnl of the macros you require. +m4_defun([PKG_PREREQ], +[m4_define([PKG_MACROS_VERSION], [0.29.2]) +m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, + [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) +])dnl PKG_PREREQ + +dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) +dnl ---------------------------------- +dnl Since: 0.16 +dnl +dnl Search for the pkg-config tool and set the PKG_CONFIG variable to +dnl first found in the path. Checks that the version of pkg-config found +dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is +dnl used since that's the first version where most current features of +dnl pkg-config existed. +AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) +m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) +AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) +AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi +fi[]dnl +])dnl PKG_PROG_PKG_CONFIG + +dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------------------------------- +dnl Since: 0.18 +dnl +dnl Check to see whether a particular set of modules exists. Similar to +dnl PKG_CHECK_MODULES(), but does not set variables or print errors. +dnl +dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +dnl only at the first occurrence in configure.ac, so if the first place +dnl it's called might be skipped (such as if it is within an "if", you +dnl have to call PKG_CHECK_EXISTS manually +AC_DEFUN([PKG_CHECK_EXISTS], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +if test -n "$PKG_CONFIG" && \ + AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then + m4_default([$2], [:]) +m4_ifvaln([$3], [else + $3])dnl +fi]) + +dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +dnl --------------------------------------------- +dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting +dnl pkg_failed based on the result. +m4_define([_PKG_CONFIG], +[if test -n "$$1"; then + pkg_cv_[]$1="$$1" + elif test -n "$PKG_CONFIG"; then + PKG_CHECK_EXISTS([$3], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes ], + [pkg_failed=yes]) + else + pkg_failed=untried +fi[]dnl +])dnl _PKG_CONFIG + +dnl _PKG_SHORT_ERRORS_SUPPORTED +dnl --------------------------- +dnl Internal check to see if pkg-config supports short errors. +AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi[]dnl +])dnl _PKG_SHORT_ERRORS_SUPPORTED + + +dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl -------------------------------------------------------------- +dnl Since: 0.4.0 +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES might not happen, you should be sure to include an +dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +AC_DEFUN([PKG_CHECK_MODULES], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl + +pkg_failed=no +AC_MSG_CHECKING([for $2]) + +_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) +_PKG_CONFIG([$1][_LIBS], [libs], [$2]) + +m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS +and $1[]_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details.]) + +if test $pkg_failed = yes; then + AC_MSG_RESULT([no]) + _PKG_SHORT_ERRORS_SUPPORTED + if test $_pkg_short_errors_supported = yes; then + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + + m4_default([$4], [AC_MSG_ERROR( +[Package requirements ($2) were not met: + +$$1_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +_PKG_TEXT])[]dnl + ]) +elif test $pkg_failed = untried; then + AC_MSG_RESULT([no]) + m4_default([$4], [AC_MSG_FAILURE( +[The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +_PKG_TEXT + +To get pkg-config, see .])[]dnl + ]) +else + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + AC_MSG_RESULT([yes]) + $3 +fi[]dnl +])dnl PKG_CHECK_MODULES + + +dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl --------------------------------------------------------------------- +dnl Since: 0.29 +dnl +dnl Checks for existence of MODULES and gathers its build flags with +dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags +dnl and VARIABLE-PREFIX_LIBS from --libs. +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to +dnl include an explicit call to PKG_PROG_PKG_CONFIG in your +dnl configure.ac. +AC_DEFUN([PKG_CHECK_MODULES_STATIC], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +_save_PKG_CONFIG=$PKG_CONFIG +PKG_CONFIG="$PKG_CONFIG --static" +PKG_CHECK_MODULES($@) +PKG_CONFIG=$_save_PKG_CONFIG[]dnl +])dnl PKG_CHECK_MODULES_STATIC + + +dnl PKG_INSTALLDIR([DIRECTORY]) +dnl ------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable pkgconfigdir as the location where a module +dnl should install pkg-config .pc files. By default the directory is +dnl $libdir/pkgconfig, but the default can be changed by passing +dnl DIRECTORY. The user can override through the --with-pkgconfigdir +dnl parameter. +AC_DEFUN([PKG_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([pkgconfigdir], + [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, + [with_pkgconfigdir=]pkg_default) +AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_INSTALLDIR + + +dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) +dnl -------------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable noarch_pkgconfigdir as the location where a +dnl module should install arch-independent pkg-config .pc files. By +dnl default the directory is $datadir/pkgconfig, but the default can be +dnl changed by passing DIRECTORY. The user can override through the +dnl --with-noarch-pkgconfigdir parameter. +AC_DEFUN([PKG_NOARCH_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([noarch-pkgconfigdir], + [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, + [with_noarch_pkgconfigdir=]pkg_default) +AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_NOARCH_INSTALLDIR + + +dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, +dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------- +dnl Since: 0.28 +dnl +dnl Retrieves the value of the pkg-config variable for the given module. +AC_DEFUN([PKG_CHECK_VAR], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl + +_PKG_CONFIG([$1], [variable="][$3]["], [$2]) +AS_VAR_COPY([$1], [pkg_cv_][$1]) + +AS_VAR_IF([$1], [""], [$5], [$4])dnl +])dnl PKG_CHECK_VAR + +dnl PKG_WITH_MODULES(VARIABLE-PREFIX, MODULES, +dnl [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND], +dnl [DESCRIPTION], [DEFAULT]) +dnl ------------------------------------------ +dnl +dnl Prepare a "--with-" configure option using the lowercase +dnl [VARIABLE-PREFIX] name, merging the behaviour of AC_ARG_WITH and +dnl PKG_CHECK_MODULES in a single macro. +AC_DEFUN([PKG_WITH_MODULES], +[ +m4_pushdef([with_arg], m4_tolower([$1])) + +m4_pushdef([description], + [m4_default([$5], [build with ]with_arg[ support])]) + +m4_pushdef([def_arg], [m4_default([$6], [auto])]) +m4_pushdef([def_action_if_found], [AS_TR_SH([with_]with_arg)=yes]) +m4_pushdef([def_action_if_not_found], [AS_TR_SH([with_]with_arg)=no]) + +m4_case(def_arg, + [yes],[m4_pushdef([with_without], [--without-]with_arg)], + [m4_pushdef([with_without],[--with-]with_arg)]) + +AC_ARG_WITH(with_arg, + AS_HELP_STRING(with_without, description[ @<:@default=]def_arg[@:>@]),, + [AS_TR_SH([with_]with_arg)=def_arg]) + +AS_CASE([$AS_TR_SH([with_]with_arg)], + [yes],[PKG_CHECK_MODULES([$1],[$2],$3,$4)], + [auto],[PKG_CHECK_MODULES([$1],[$2], + [m4_n([def_action_if_found]) $3], + [m4_n([def_action_if_not_found]) $4])]) + +m4_popdef([with_arg]) +m4_popdef([description]) +m4_popdef([def_arg]) + +])dnl PKG_WITH_MODULES + +dnl PKG_HAVE_WITH_MODULES(VARIABLE-PREFIX, MODULES, +dnl [DESCRIPTION], [DEFAULT]) +dnl ----------------------------------------------- +dnl +dnl Convenience macro to trigger AM_CONDITIONAL after PKG_WITH_MODULES +dnl check._[VARIABLE-PREFIX] is exported as make variable. +AC_DEFUN([PKG_HAVE_WITH_MODULES], +[ +PKG_WITH_MODULES([$1],[$2],,,[$3],[$4]) + +AM_CONDITIONAL([HAVE_][$1], + [test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"]) +])dnl PKG_HAVE_WITH_MODULES + +dnl PKG_HAVE_DEFINE_WITH_MODULES(VARIABLE-PREFIX, MODULES, +dnl [DESCRIPTION], [DEFAULT]) +dnl ------------------------------------------------------ +dnl +dnl Convenience macro to run AM_CONDITIONAL and AC_DEFINE after +dnl PKG_WITH_MODULES check. HAVE_[VARIABLE-PREFIX] is exported as make +dnl and preprocessor variable. +AC_DEFUN([PKG_HAVE_DEFINE_WITH_MODULES], +[ +PKG_HAVE_WITH_MODULES([$1],[$2],[$3],[$4]) + +AS_IF([test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"], + [AC_DEFINE([HAVE_][$1], 1, [Enable ]m4_tolower([$1])[ support])]) +])dnl PKG_HAVE_DEFINE_WITH_MODULES diff --git a/src/client/linux/minidump_writer/minidump_writer_unittest.cc b/src/client/linux/minidump_writer/minidump_writer_unittest.cc index 449ac189d..5f74dc0a8 100644 --- a/src/client/linux/minidump_writer/minidump_writer_unittest.cc +++ b/src/client/linux/minidump_writer/minidump_writer_unittest.cc @@ -270,12 +270,44 @@ TEST(MinidumpWriterTest, MinidumpStacksSkippedIfRequested) { // current executable). This thread should not be captured in the minidump. pthread_t thread; pthread_attr_t thread_attributes; - pthread_attr_init(&thread_attributes); - pthread_attr_setdetachstate(&thread_attributes, PTHREAD_CREATE_DETACHED); + if (pthread_attr_init(&thread_attributes) != 0) { + syscall(__NR_exit_group, 1); + } + if (pthread_attr_setdetachstate( + &thread_attributes, PTHREAD_CREATE_DETACHED) != 0) { + pthread_attr_destroy(&thread_attributes); + syscall(__NR_exit_group, 1); + } + + const size_t stack_size = 1024 * 1024; + void* thread_stack = mmap(nullptr, stack_size, + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, + -1, 0); + if (thread_stack == MAP_FAILED) { + pthread_attr_destroy(&thread_attributes); + syscall(__NR_exit_group, 1); + } + memset(thread_stack, 0, stack_size); + + if (pthread_attr_setstack( + &thread_attributes, thread_stack, stack_size) != 0) { + munmap(thread_stack, stack_size); + pthread_attr_destroy(&thread_attributes); + syscall(__NR_exit_group, 1); + } + sigset_t sigset; sigemptyset(&sigset); - pthread_create(&thread, &thread_attributes, - reinterpret_cast(&sigsuspend), &sigset); + const int create_result = + pthread_create(&thread, &thread_attributes, + reinterpret_cast(&sigsuspend), + &sigset); + pthread_attr_destroy(&thread_attributes); + if (create_result != 0) { + munmap(thread_stack, stack_size); + syscall(__NR_exit_group, 1); + } char b; IGNORE_RET(HANDLE_EINTR(read(fds[0], &b, sizeof(b)))); diff --git a/src/common/linux/dump_symbols.cc b/src/common/linux/dump_symbols.cc index 744064563..668607965 100644 --- a/src/common/linux/dump_symbols.cc +++ b/src/common/linux/dump_symbols.cc @@ -52,7 +52,9 @@ #include #include #include +#ifdef HAVE_LIBZ #include +#endif #ifdef HAVE_LIBZSTD #include #endif @@ -314,6 +316,7 @@ uint32_t GetCompressionHeader( return sizeof (*header); } +#ifdef HAVE_LIBZ std::pair UncompressZlibSectionContents( const uint8_t* compressed_buffer, uint64_t compressed_size, uint64_t uncompressed_size) { google_breakpad::scoped_array uncompressed_buffer( @@ -328,6 +331,7 @@ std::pair UncompressZlibSectionContents( ? std::make_pair(nullptr, 0) : std::make_pair(uncompressed_buffer.release(), uncompressed_size); } +#endif #ifdef HAVE_LIBZSTD std::pair UncompressZstdSectionContents( @@ -347,9 +351,12 @@ std::pair UncompressZstdSectionContents( std::pair UncompressSectionContents( uint64_t compression_type, const uint8_t* compressed_buffer, uint64_t compressed_size, uint64_t uncompressed_size) { + +#ifdef HAVE_LIBZ if (compression_type == ELFCOMPRESS_ZLIB) { return UncompressZlibSectionContents(compressed_buffer, compressed_size, uncompressed_size); } +#endif #ifdef HAVE_LIBZSTD if (compression_type == ELFCOMPRESS_ZSTD) { diff --git a/src/common/mac/byteswap.h b/src/common/mac/byteswap.h index c4c7e6178..39a342c34 100644 --- a/src/common/mac/byteswap.h +++ b/src/common/mac/byteswap.h @@ -35,6 +35,8 @@ #ifndef COMMON_MAC_BYTESWAP_H_ #define COMMON_MAC_BYTESWAP_H_ +#include "compat/linux.h" + #ifdef __APPLE__ #include @@ -45,12 +47,19 @@ static inline int16_t ByteSwap(int16_t v) { return OSSwapInt16(v); } static inline int32_t ByteSwap(int32_t v) { return OSSwapInt32(v); } static inline int64_t ByteSwap(int64_t v) { return OSSwapInt64(v); } -#elif defined(__linux__) +#else // For NXByteOrder #include #include +#if defined(__MINGW32__) || defined(__MINGW64__) +#include +#define bswap_16(x) __builtin_bswap16(x) +#define bswap_32(x) __builtin_bswap32(x) +#define bswap_64(x) __builtin_bswap64(x) +#else #include #include_next +#endif static inline uint16_t ByteSwap(uint16_t v) { return bswap_16(v); } static inline uint32_t ByteSwap(uint32_t v) { return bswap_32(v); } diff --git a/src/common/memory_allocator.h b/src/common/memory_allocator.h index 5760b0c75..2d7082351 100644 --- a/src/common/memory_allocator.h +++ b/src/common/memory_allocator.h @@ -76,7 +76,8 @@ class PageAllocator { template static T AlignUp(T offset, size_t alignment) { assert(alignment > 0 && ((alignment - 1) & alignment) == 0); - return (offset + (alignment - 1)) & ~(alignment - 1); + const T mask = static_cast(alignment - 1); + return (offset + mask) & ~mask; } // Allocates an array with requested amount of `bytes` and at a location with diff --git a/src/common/windows/http_upload.cc b/src/common/windows/http_upload.cc index 76363398b..c6612fa6a 100644 --- a/src/common/windows/http_upload.cc +++ b/src/common/windows/http_upload.cc @@ -41,7 +41,7 @@ #include #include -#if defined(HAVE_ZLIB) +#if defined(HAVE_LIBZ) #include #endif @@ -67,7 +67,7 @@ namespace { // or in case of any error. The contents of `deflated` are undefined in the // latter case. bool Deflate(const string& data, string& deflated) { -#if defined(HAVE_ZLIB) +#if defined(HAVE_LIBZ) z_stream stream{}; // Start with an output buffer sufficient for 75% compression to avoid @@ -109,7 +109,7 @@ namespace { return result == Z_STREAM_END; #else return false; -#endif // defined(HAVE_ZLIB) +#endif // defined(HAVE_LIBZ) } // Restore C4100 to its previous state. diff --git a/src/tools/linux/dump_syms/dump_syms_test b/src/tools/linux/dump_syms/dump_syms_test new file mode 100755 index 000000000..a7a8bedba --- /dev/null +++ b/src/tools/linux/dump_syms/dump_syms_test @@ -0,0 +1,20 @@ +#!/bin/sh + +set -eu + +list_targets() +{ +cat <<\EOF +freebsd15-amd64-clang17 +linuxdebian12-amd64-gcc12 +linuxdebian12-arm64-gcc12 +linuxdebian12-armhf-gcc12 +linuxdebian12-ppc64el-gcc12 +linuxdebian13-riscv64-gcc14 +nacl-amd64-saigoclang21 +nacl-armhf-saigoclang21 +nacl-i686-saigoclang21 +EOF +} + +tests/dump_syms_test 'src/tools/linux/dump_syms/dump_syms' $(list_targets) diff --git a/src/tools/mac/dump_syms/dump_syms_mac_test b/src/tools/mac/dump_syms/dump_syms_mac_test new file mode 100755 index 000000000..ef3e10bd5 --- /dev/null +++ b/src/tools/mac/dump_syms/dump_syms_mac_test @@ -0,0 +1,13 @@ +#!/bin/sh + +set -eu + +list_targets() +{ +cat <<\EOF +macos10.12-amd64-appleclang21 +macos11.7-arm64-appleclang21 +EOF +} + +tests/dump_syms_test 'src/tools/mac/dump_syms/dump_syms_mac' $(list_targets) diff --git a/src/tools/windows/dump_syms_dwarf/dump_syms_dwarf_test b/src/tools/windows/dump_syms_dwarf/dump_syms_dwarf_test new file mode 100755 index 000000000..4ef9df86f --- /dev/null +++ b/src/tools/windows/dump_syms_dwarf/dump_syms_dwarf_test @@ -0,0 +1,13 @@ +#!/bin/sh + +set -eu + +list_targets() +{ +cat <<\EOF +windows7-amd64-mingwgcc14.exe +windows7-i686-mingwgcc14.exe +EOF +} + +tests/dump_syms_test 'src/tools/windows/dump_syms_dwarf/dump_syms_dwarf' $(list_targets) diff --git a/tests/HOWTO.md b/tests/HOWTO.md new file mode 100644 index 000000000..8fadb2558 --- /dev/null +++ b/tests/HOWTO.md @@ -0,0 +1,38 @@ +## Debian Bookworm + +```bash +CXX='x86_64-linux-gnu-g++' make SUFFIX='linuxdebian12-amd64-gcc12-dynamic' +CXX='i686-w64-mingw32-g++' make SUFFIX='linuxdebian12-i686-gcc12-dynamic' +CXX='aarch64-linux-gnu-g++' make SUFFIX='linuxdebian12-arm64-gcc12-dynamic' +CXX='arm-linux-gnueabihf-g++' make SUFFIX='linuxdebian12-armhf-gcc12-dynamic' +CXX='powerpc64le-linux-gnu-g++' make SUFFIX='linuxdebian12-ppc64el-gcc12-dynamic' +``` + +## Debian Trixie + +```bash +CXX='riscv64-linux-gnu-g++' make SUFFIX='linuxdebian13-riscv64-gcc14-dynamic' +CXX='x86_64-w64-mingw32-g++-posix' CXXFLAGS='-static -static-libstdc++ -static-libgcc -D_WIN32_WINNT=0x0601 -DWINVER=0x0601' make SUFFIX='windows7-amd64-mingwgcc14-static' +CXX='i686-w64-mingw32-g++-posix' CXXFLAGS='-static -static-libstdc++ -static-libgcc -D_WIN32_WINNT=0x0601 -DWINVER=0x0601' make SUFFIX='windows7-i686-mingwgcc14-static' +``` + +# macOS + +```bash +CXX='clang' CXXFLAGS='-target x86_64-apple-darwin -mmacos-version-min=10.12' make SUFFIX='macos10.12-amd64-appleclang21-dynamic' +CXX='clang' CXXFLAGS='-target arm64-apple-darwin -mmacos-version-min=11.7' make SUFFIX='macos11.7-arm64-appleclang21-dynamic' +``` + +## FreeBSD 15 + +```bash +CXX='clang' CXXFLAGS='-target x86_64-unknown-freebsd' gmake SUFFIX='freebsd15-amd64-clang17-dynamic' +``` + +## Saigo + +```bash +CXX='x86_64-nacl-clang++' make SUFFIX='nacl-amd64-saigoclang21-static' +CXX='i686-nacl-clang++' make SUFFIX='nacl-i686-saigoclang21-static' +CXX='arm-nacl-clang++' make SUFFIX='nacl-armhf-saigoclang21-static' +``` diff --git a/tests/Makefile b/tests/Makefile new file mode 100644 index 000000000..1e1e36a6b --- /dev/null +++ b/tests/Makefile @@ -0,0 +1,25 @@ +.DEFAULT_GOAL := all + +CXX ?= g++ +CXXFLAGS += -Wall -Wextra -Werror -O0 -g +LDLIBS ?= -lm + +SUFFIX ?= unknown +BASE_TARGETS := test-math +TARGETS := $(addsuffix _$(SUFFIX),$(BASE_TARGETS)) + +.PHONY: all clean + +%_${SUFFIX}: %.cpp + $(CXX) $(CXXFLAGS) $< -o $@ $(LDLIBS) + rm -rf ${@}.dSYM + +all: $(TARGETS) + +clean: + rm -fv $(TARGETS) + +fullclean: + @for target in $(BASE_TARGETS); do \ + rm -fv "$$target"_*; \ + done diff --git a/tests/dump_syms_test b/tests/dump_syms_test new file mode 100755 index 000000000..0911b8042 --- /dev/null +++ b/tests/dump_syms_test @@ -0,0 +1,38 @@ +#!/bin/sh + +dump_syms="${1}${EXE_EXT:-}"; shift + +printf 'Print file type for: %s\n' "${dump_syms}" +file "${dump_syms}" + +success='true' + +while [ -n "${1:-}" ] +do + target="${1}"; shift + + for source in test-math + do + sample="tests/${source}_${target}" + + if [ -f "${sample}" ] + then + printf 'Let %s symbolize %s:' "${dump_syms}" "${sample}" + + error_log="$(mktemp)" + + if ${EXE_LAUNCHER:-} "${dump_syms}" "${sample}" >/dev/null 2>"${error_log}" + then + printf ' OK\n' + else + printf ' FAILED\n' + cat "${error_log}" + success='false' + fi + + rm "${error_log}" + fi + done +done + +"${success}" diff --git a/tests/test-math.cpp b/tests/test-math.cpp new file mode 100644 index 000000000..e8674f77e --- /dev/null +++ b/tests/test-math.cpp @@ -0,0 +1,54 @@ + +#include +#include + +double calculate_identity(double x) +{ + return std::sin(x) * std::sin(x) + std::cos(x) * std::cos(x); +} + +double calculate_distance(double x1, double y1, double x2, double y2) +{ + double dx = x2 - x1; + double dy = y2 - y1; + + return std::sqrt(dx * dx + dy * dy); +} + +void print_result(const char* name, double result) +{ + printf("%-30s = %.6f\n", name, result); +} + +int main() +{ + double a = 12.5; + double b = 4.0; + + printf("=== Arithmetic ===\n\n"); + + print_result("Addition", a + b); + print_result("Subtraction", a - b); + print_result("Multiplication", a * b); + print_result("Division", a / b); + + printf("\n=== Math Functions ===\n\n"); + + print_result("Square root", std::sqrt(a)); + print_result("Power", std::pow(b, 3)); + + double angle = 0.75; + + print_result("Sinus", std::sin(angle)); + print_result("Cosinus", std::cos(angle)); + print_result("Pythagorean identity", calculate_identity(angle)); + + printf("\n=== Geometry ===\n\n"); + + print_result( + "Distance", + calculate_distance(1.0, 2.0, 4.0, 6.0) + ); + + return 0; +} diff --git a/tests/test-math_freebsd15-amd64-clang17-dynamic b/tests/test-math_freebsd15-amd64-clang17-dynamic new file mode 100755 index 000000000..5b9a51628 Binary files /dev/null and b/tests/test-math_freebsd15-amd64-clang17-dynamic differ diff --git a/tests/test-math_linuxdebian12-amd64-gcc12-dynamic b/tests/test-math_linuxdebian12-amd64-gcc12-dynamic new file mode 100755 index 000000000..3bbf2a013 Binary files /dev/null and b/tests/test-math_linuxdebian12-amd64-gcc12-dynamic differ diff --git a/tests/test-math_linuxdebian12-arm64-gcc12-dynamic b/tests/test-math_linuxdebian12-arm64-gcc12-dynamic new file mode 100755 index 000000000..ca1e55b65 Binary files /dev/null and b/tests/test-math_linuxdebian12-arm64-gcc12-dynamic differ diff --git a/tests/test-math_linuxdebian12-armhf-gcc12-dynamic b/tests/test-math_linuxdebian12-armhf-gcc12-dynamic new file mode 100755 index 000000000..1f487419e Binary files /dev/null and b/tests/test-math_linuxdebian12-armhf-gcc12-dynamic differ diff --git a/tests/test-math_linuxdebian12-ppc64el-gcc12-dynamic b/tests/test-math_linuxdebian12-ppc64el-gcc12-dynamic new file mode 100755 index 000000000..2d3379e6e Binary files /dev/null and b/tests/test-math_linuxdebian12-ppc64el-gcc12-dynamic differ diff --git a/tests/test-math_linuxdebian13-riscv64-gcc14-dynamic b/tests/test-math_linuxdebian13-riscv64-gcc14-dynamic new file mode 100755 index 000000000..c0debfaf8 Binary files /dev/null and b/tests/test-math_linuxdebian13-riscv64-gcc14-dynamic differ diff --git a/tests/test-math_macos10.12-amd64-appleclang21-dynamic b/tests/test-math_macos10.12-amd64-appleclang21-dynamic new file mode 100755 index 000000000..3896cbd6d Binary files /dev/null and b/tests/test-math_macos10.12-amd64-appleclang21-dynamic differ diff --git a/tests/test-math_macos11.7-arm64-appleclang21-dynamic b/tests/test-math_macos11.7-arm64-appleclang21-dynamic new file mode 100755 index 000000000..2e967cf20 Binary files /dev/null and b/tests/test-math_macos11.7-arm64-appleclang21-dynamic differ diff --git a/tests/test-math_nacl-amd64-saigoclang21-static b/tests/test-math_nacl-amd64-saigoclang21-static new file mode 100755 index 000000000..e9d444e98 Binary files /dev/null and b/tests/test-math_nacl-amd64-saigoclang21-static differ diff --git a/tests/test-math_nacl-armhf-saigoclang21-static b/tests/test-math_nacl-armhf-saigoclang21-static new file mode 100755 index 000000000..ecdf21ca6 Binary files /dev/null and b/tests/test-math_nacl-armhf-saigoclang21-static differ diff --git a/tests/test-math_nacl-i686-saigoclang21-static b/tests/test-math_nacl-i686-saigoclang21-static new file mode 100755 index 000000000..972b3bfee Binary files /dev/null and b/tests/test-math_nacl-i686-saigoclang21-static differ diff --git a/tests/test-math_windows7-amd64-mingwgcc14-static.exe b/tests/test-math_windows7-amd64-mingwgcc14-static.exe new file mode 100755 index 000000000..d9659e8f5 Binary files /dev/null and b/tests/test-math_windows7-amd64-mingwgcc14-static.exe differ diff --git a/tests/test-math_windows7-i686-mingwgcc14-static.exe b/tests/test-math_windows7-i686-mingwgcc14-static.exe new file mode 100755 index 000000000..545b40a4f Binary files /dev/null and b/tests/test-math_windows7-i686-mingwgcc14-static.exe differ