From bac5a060d26c6e2e6ccca1f85f3aa36e805dec0e Mon Sep 17 00:00:00 2001 From: RedbeanW Date: Sat, 10 May 2025 22:38:39 +0800 Subject: [PATCH] feat: build for win32 and osx. (#7) --- .../{build-linux.yml => build_linux.yml} | 37 ++---- .github/workflows/build_macos.yml | 55 ++++++++ .github/workflows/build_windows.yml | 55 ++++++++ src/data_format/bound_symbol_list.h | 2 +- src/data_format/magic_blob.h | 2 +- src/data_format/type/magic_entry.h | 4 + src/data_format/type/typed_symbol.h | 6 + src/data_format/typed_symbol_list.h | 2 +- src/nonstd.h | 12 ++ src/tools/extractsym/main.cpp | 2 - src/util/llvm_error.h | 6 +- xmake.lua | 121 ++++++++++-------- 12 files changed, 219 insertions(+), 85 deletions(-) rename .github/workflows/{build-linux.yml => build_linux.yml} (50%) create mode 100644 .github/workflows/build_macos.yml create mode 100644 .github/workflows/build_windows.yml diff --git a/.github/workflows/build-linux.yml b/.github/workflows/build_linux.yml similarity index 50% rename from .github/workflows/build-linux.yml rename to .github/workflows/build_linux.yml index 2108e25..d0b8ef4 100644 --- a/.github/workflows/build-linux.yml +++ b/.github/workflows/build_linux.yml @@ -3,7 +3,7 @@ name: Build (Linux) on: push: paths: - - .github/workflows/build-linux.yml + - .github/workflows/build_linux.yml - src/** - xmake.lua workflow_dispatch: @@ -18,11 +18,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 -# - name: Prepare works -# run: | -# mkdir ./.xmake-dest - - - name: Restore build cache + - name: Restore xmake cache uses: actions/cache@v4 with: path: | @@ -32,35 +28,26 @@ jobs: restore-keys: | xmake-linux- - - name: Setup XMake + - name: Setup xmake uses: xmake-io/github-action-setup-xmake@v1 with: - xmake-version: '2.9.8' - actions-cache-folder: './.xmake-dest' - - - name: Install build dependencies - run: | - sudo apt install -y build-essential llvm-19-dev libclang-19-dev - - # workaround to switch llvm version. - sudo mv /usr/include/clang /usr/include/clang-compiler - sudo ln -s /usr/lib/llvm-19/bin/llvm-config /usr/bin/llvm-config - sudo ln -s /usr/include/llvm-19/llvm /usr/include/llvm - sudo ln -s /usr/include/llvm-c-19/llvm-c /usr/include/llvm-c - sudo ln -s /usr/lib/llvm-19/include/clang /usr/include/clang - sudo ln -s /usr/lib/llvm-19/include/clang-c /usr/include/clang-c - + xmake-version: "2.9.9" + actions-cache-folder: "./.xmake-dest" - name: Configure run: | # c++23 requires gcc 14. - xmake f -a x64 -m ${{ matrix.mode }} -p linux --toolchain=gcc-14 -v -y + xmake f -a x64 -m ${{ matrix.mode }} -p linux --toolchain=gcc-14 -vD -y - name: Build run: | - xmake -v -y + xmake -vD -y - - name: Upload Artifact + - name: Cleanup + run: | + xrepo clean + + - name: Upload artifact uses: actions/upload-artifact@v4 with: name: debuginfo-${{ matrix.mode }}-linux-x64-${{ github.sha }} diff --git a/.github/workflows/build_macos.yml b/.github/workflows/build_macos.yml new file mode 100644 index 0000000..613a08d --- /dev/null +++ b/.github/workflows/build_macos.yml @@ -0,0 +1,55 @@ +name: Build (MacOS) + +on: + push: + paths: + - .github/workflows/build_macos.yml + - src/** + - xmake.lua + workflow_dispatch: + +jobs: + build: + strategy: + matrix: + mode: [release, debug] + arch: [arm64] + runs-on: macos-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Restore xmake cache + uses: actions/cache@v4 + with: + path: | + ~/.xmake + ./.xmake-dest + key: xmake-macos-${{ hashFiles('xmake.lua') }} + restore-keys: | + xmake-macos- + + - name: Setup xmake + uses: xmake-io/github-action-setup-xmake@v1 + with: + xmake-version: "2.9.9" + actions-cache-folder: "./.xmake-dest" + + - name: Configure + run: | + xmake f -a ${{ matrix.arch }} -m ${{ matrix.mode }} -p macosx -vD -y + + - name: Build + run: | + xmake -vD -y + + - name: Cleanup + run: | + xrepo clean + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: debuginfo-macosx-${{ matrix.arch }}-${{ matrix.mode }} + path: | + build/macosx/${{ matrix.arch }}/${{ matrix.mode }} diff --git a/.github/workflows/build_windows.yml b/.github/workflows/build_windows.yml new file mode 100644 index 0000000..9474dae --- /dev/null +++ b/.github/workflows/build_windows.yml @@ -0,0 +1,55 @@ +name: Build (Windows) + +on: + push: + paths: + - .github/workflows/build_windows.yml + - src/** + - xmake.lua + workflow_dispatch: + +jobs: + build: + strategy: + matrix: + mode: [release, debug] + arch: [x64] + runs-on: windows-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup xmake + uses: xmake-io/github-action-setup-xmake@v1 + with: + xmake-version: "2.9.9" + actions-cache-folder: "./.xmake-dest" + + - name: Restore xmake cache + uses: actions/cache@v4 + with: + path: | + ~/AppData/Local/.xmake + ./.xmake-dest + key: xmake-windows-${{ matrix.arch }}-${{ hashFiles('xmake.lua') }} + restore-keys: | + xmake-windows-${{ matrix.arch }}- + + - name: Configure + run: | + xmake f -a ${{ matrix.arch }} -m ${{ matrix.mode }} -p windows -vD -y --toolchain=clang + + - name: Build + run: | + xmake -vD -y + + - name: Cleanup + run: | + xrepo clean + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: debuginfo-windows-${{ matrix.arch }}-${{ matrix.mode }} + path: | + build/windows/${{ matrix.arch }}/${{ matrix.mode }} diff --git a/src/data_format/bound_symbol_list.h b/src/data_format/bound_symbol_list.h index 7938aef..5e68ceb 100644 --- a/src/data_format/bound_symbol_list.h +++ b/src/data_format/bound_symbol_list.h @@ -14,7 +14,7 @@ public: void record(const std::string& symbol, rva_t rva, bool is_function); - constexpr void for_each(const for_each_callback_t& callback) const { + DI_CONSTEXPR void for_each(const for_each_callback_t& callback) const { for (const auto& entity : m_entities) callback(entity); } diff --git a/src/data_format/magic_blob.h b/src/data_format/magic_blob.h index 629df8f..bfa54d3 100644 --- a/src/data_format/magic_blob.h +++ b/src/data_format/magic_blob.h @@ -11,7 +11,7 @@ public: void read(const fs::path& path) override; - void for_each(const for_each_callback_t& callback) const { + DI_CONSTEXPR void for_each(const for_each_callback_t& callback) const { for (const auto& [hash, entry] : m_entries) callback(hash, *entry); } diff --git a/src/data_format/type/magic_entry.h b/src/data_format/type/magic_entry.h index 450de4e..26ad3d3 100644 --- a/src/data_format/type/magic_entry.h +++ b/src/data_format/type/magic_entry.h @@ -5,6 +5,10 @@ namespace di { struct MagicEntry { +#if __cpp_aggregate_paren_init < 201902L + MagicEntry(std::bitset<64> flags, rva_t rva) : flags(flags), rva(rva) {} +#endif + std::bitset<64> flags; // What is stored in the original format is not the RVA itself, but the // difference with the previous entry (in MagicBlob, RVA is sorted from diff --git a/src/data_format/type/typed_symbol.h b/src/data_format/type/typed_symbol.h index 046c31c..73d8261 100644 --- a/src/data_format/type/typed_symbol.h +++ b/src/data_format/type/typed_symbol.h @@ -5,6 +5,12 @@ namespace di { struct TypedSymbol { +#if __cpp_aggregate_paren_init < 201902L + TypedSymbol(std::string_view name, DeclType type) + : m_name(name), + m_type(type) {} +#endif + std::string m_name; DeclType m_type; diff --git a/src/data_format/typed_symbol_list.h b/src/data_format/typed_symbol_list.h index 9b44285..1547ae8 100644 --- a/src/data_format/typed_symbol_list.h +++ b/src/data_format/typed_symbol_list.h @@ -20,7 +20,7 @@ public: constexpr size_t count() const { return m_data.size(); } - constexpr void for_each(const for_each_callback_t& callback) const { + DI_CONSTEXPR void for_each(const for_each_callback_t& callback) const { for (const auto& entity : m_data) callback(entity); } diff --git a/src/nonstd.h b/src/nonstd.h index 97db061..edfe711 100644 --- a/src/nonstd.h +++ b/src/nonstd.h @@ -13,6 +13,18 @@ constexpr auto underlying_value(T v) { return static_cast>(v); } +#if __cpp_constexpr >= 202211L // complete c++23 constexpr +#define DI_CONSTEXPR constexpr +#else +#define DI_CONSTEXPR inline +#endif + +// a clang bug +#if __clang_major__ < 19 +#undef DI_CONSTEXPR +#define DI_CONSTEXPR inline +#endif + // From: // https://stackoverflow.com/questions/7110301/generic-hash-for-tuples-in-unordered-map-unordered-set diff --git a/src/tools/extractsym/main.cpp b/src/tools/extractsym/main.cpp index 92a2b8e..37d89e1 100644 --- a/src/tools/extractsym/main.cpp +++ b/src/tools/extractsym/main.cpp @@ -1,7 +1,5 @@ #include -#include - #include "data_format/typed_symbol_list.h" #include "object_file/pdb.h" diff --git a/src/util/llvm_error.h b/src/util/llvm_error.h index 19874e7..6cbfe5c 100644 --- a/src/util/llvm_error.h +++ b/src/util/llvm_error.h @@ -20,7 +20,7 @@ public: constexpr std::string category() const { return "exception.llvm"; } }; -constexpr void check_llvm_result(Error err, std::string_view msg = "") { +DI_CONSTEXPR void check_llvm_result(Error err, std::string_view msg = "") { if (err) { std::string err_detail; raw_string_ostream os(err_detail); @@ -30,7 +30,7 @@ constexpr void check_llvm_result(Error err, std::string_view msg = "") { } template -constexpr T +DI_CONSTEXPR T check_llvm_result(Expected val_or_err, std::string_view msg = "") { if (val_or_err) return std::move(*val_or_err); else { @@ -43,7 +43,7 @@ check_llvm_result(Expected val_or_err, std::string_view msg = "") { } template -constexpr T& +DI_CONSTEXPR T& check_llvm_result(Expected val_or_err, std::string_view msg = "") { if (val_or_err) return *val_or_err; else { diff --git a/xmake.lua b/xmake.lua index 1b3ac7c..b8035ac 100644 --- a/xmake.lua +++ b/xmake.lua @@ -1,8 +1,11 @@ add_rules('mode.debug', 'mode.release') +add_repositories('rbw-testing https://github.com/Redbeanw44602/xmake-repo-testing') + add_requires('argparse 3.1') add_requires('nlohmann_json 3.11.3') add_requires('xxhash 0.8.3') +add_requires('libllvm 19.1.7') add_requires('boost 1.87.0', { system = false, configs = { @@ -11,8 +14,6 @@ add_requires('boost 1.87.0', { } }) -add_requires('llvm') - --- options option('symbol-resolver') @@ -36,35 +37,11 @@ end --- global settings -set_policy("build.optimization.lto", true) - set_languages('c23', 'c++23') set_warnings('all') -add_includedirs('src') - --- now use boost::stacktrace, due to MacOSX (libc++) compatibility issues. --- ~~workaround to fix std::stacktrace link problem~~ --- --- for gcc == 14 --- see https://gcc.gnu.org/onlinedocs/gcc-14.2.0/libstdc++/manual/manual/using.html --- for gcc == 13 --- see https://gcc.gnu.org/onlinedocs/gcc-13.2.0/libstdc++/manual/manual/using.html --- if is_plat('linux') then --- add_links('stdc++exp') --- end - if is_mode('debug') then add_defines('DI_DEBUG') - - -- to fix llvm link problem - -- see https://stackoverflow.com/questions/53805007/compilation-failing-on-enableabibreakingchecks - add_defines('LLVM_DISABLE_ABI_BREAKING_CHECKS_ENFORCING=1') -end - -add_packages('boost') -if is_plat('linux') or is_plat('macosx') then - add_defines('BOOST_STACKTRACE_USE_ADDR2LINE=1') end --- targets @@ -78,25 +55,75 @@ target('libdi') set_basename('di') if is_plat('linux') then - add_ldflags('$(shell llvm-config --libs)') -- xrepo llvm bug? + add_cxflags('-fPIC') end + add_packages('xxhash') add_packages( - 'xxhash', + 'libllvm', + 'boost', 'nlohmann_json', - 'llvm' + {public = true} ) + add_includedirs('src', {public = true}) + + -- now use boost::stacktrace, due to MacOSX (libc++) compatibility issues. + -- ~~workaround to fix std::stacktrace link problem~~ + -- + -- for gcc == 14 + -- see https://gcc.gnu.org/onlinedocs/gcc-14.2.0/libstdc++/manual/manual/using.html + -- for gcc == 13 + -- see https://gcc.gnu.org/onlinedocs/gcc-13.2.0/libstdc++/manual/manual/using.html + -- if is_plat('linux') then + -- add_links('stdc++exp') + -- end + + if is_plat('linux') or is_plat('macosx') then + add_defines('BOOST_STACKTRACE_USE_ADDR2LINE=1', {public = true}) + end + + on_load(function (target) -- bug in libllvm package, TODO: remove it. + if target:is_plat('windows') then + local vcvars = target:toolchains()[1]:config("vcvars") + if not vcvars then + vcvars = import("core.tool.toolchain").load("msvc"):config("vcvars") + end + local vs_install_dir = vcvars["BUILD_TOOLS_ROOT"] or vcvars["VSInstallDir"] + local vc_install_dir = vcvars["VCToolsInstallDir"] + local arch = target:arch() + local target_arch = { + x64 = "amd64", + arm = "arm", + arm64 = "arm64" + } + if target_arch[arch] == nil then + raise("DIA SDK does not currently support " .. arch) + end + local dia_sdkdir = path.join(vs_install_dir, "DIA SDK", "lib", target_arch[arch]) + local atl_sdkdir = path.join(vc_install_dir, "atlmfc", "lib", arch) + target:add("linkdirs", dia_sdkdir, atl_sdkdir) + target:add("syslinks", "diaguids") + end + end) + + -- workaround to fix boost problem + -- see https://github.com/boostorg/stacktrace/issues/88 + if is_plat('macosx') then + add_defines('_GNU_SOURCE', {public = true}) + end + + -- to fix llvm link problem + -- see https://stackoverflow.com/questions/53805007/compilation-failing-on-enableabibreakingchecks + add_defines('LLVM_DISABLE_ABI_BREAKING_CHECKS_ENFORCING=1', {public = true}) + target('askrva') set_kind('binary') - add_deps('libdi') add_files('src/tools/askrva/**.cpp') set_pcxxheader('src/pch.h') - add_packages( - 'argparse', - 'nlohmann_json' - ) + add_deps('libdi') + add_packages('argparse') if is_config('symbol-resolver', 'native') then add_packages('preloader') @@ -105,43 +132,33 @@ target('askrva') target('blob-extractor') set_kind('binary') - add_deps('libdi') add_files('src/tools/blob-extractor/**.cpp') set_pcxxheader('src/pch.h') + add_deps('libdi') add_packages( - 'nlohmann_json', - 'argparse' + 'argparse', + 'nlohmann_json' ) target('dumpsym') set_kind('shared') - add_deps('libdi') add_files('src/tools/dumpsym/**.cpp') set_pcxxheader('src/pch.h') - - add_packages( - 'llvm' - ) + add_deps('libdi') target('extractsym') set_kind('binary') - add_deps('libdi') add_files('src/tools/extractsym/**.cpp') set_pcxxheader('src/pch.h') - add_packages( - 'nlohmann_json', - 'argparse' - ) + add_deps('libdi') + add_packages('argparse') target('makepdb') set_kind('binary') - add_deps('libdi') add_files('src/tools/makepdb/**.cpp') set_pcxxheader('src/pch.h') - add_packages( - 'nlohmann_json', - 'argparse' - ) + add_deps('libdi') + add_packages('argparse')