diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5857753e14e1d..e69de29bb2d1d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,291 +0,0 @@ -# Copyright (c) 2023 The Bitcoin Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. - -name: CI -on: - # See: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request. - pull_request: - # See: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#push. - push: - branches: - - '**' - tags-ignore: - - '**' - -concurrency: - group: ${{ github.event_name != 'pull_request' && github.run_id || github.ref }} - cancel-in-progress: true - -env: - DANGER_RUN_CI_ON_HOST: 1 - CI_FAILFAST_TEST_LEAVE_DANGLING: 1 # GHA does not care about dangling processes and setting this variable avoids killing the CI script itself on error - MAKEJOBS: '-j10' - -jobs: - test-each-commit: - name: 'test each commit' - runs-on: ubuntu-22.04 - if: github.event_name == 'pull_request' && github.event.pull_request.commits != 1 - timeout-minutes: 360 # Use maximum time, see https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idtimeout-minutes. Assuming a worst case time of 1 hour per commit, this leads to a --max-count=6 below. - env: - MAX_COUNT: 6 - steps: - - name: Determine fetch depth - run: echo "FETCH_DEPTH=$((${{ github.event.pull_request.commits }} + 2))" >> "$GITHUB_ENV" - - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha }} - fetch-depth: ${{ env.FETCH_DEPTH }} - - name: Determine commit range - run: | - # Checkout HEAD~ and find the test base commit - # Checkout HEAD~ because it would be wasteful to rerun tests on the PR - # head commit that are already run by other jobs. - git checkout HEAD~ - # Figure out test base commit by listing ancestors of HEAD, excluding - # ancestors of the most recent merge commit, limiting the list to the - # newest MAX_COUNT ancestors, ordering it from oldest to newest, and - # taking the first one. - # - # If the branch contains up to MAX_COUNT ancestor commits after the - # most recent merge commit, all of those commits will be tested. If it - # contains more, only the most recent MAX_COUNT commits will be - # tested. - # - # In the command below, the ^@ suffix is used to refer to all parents - # of the merge commit as described in: - # https://git-scm.com/docs/git-rev-parse#_other_rev_parent_shorthand_notations - # and the ^ prefix is used to exclude these parents and all their - # ancestors from the rev-list output as described in: - # https://git-scm.com/docs/git-rev-list - echo "TEST_BASE=$(git rev-list -n$((${{ env.MAX_COUNT }} + 1)) --reverse HEAD ^$(git rev-list -n1 --merges HEAD)^@ | head -1)" >> "$GITHUB_ENV" - - run: | - sudo apt-get update - sudo apt-get install clang-15 ccache build-essential libtool autotools-dev automake pkg-config bsdmainutils python3-zmq libevent-dev libboost-dev libsqlite3-dev libdb++-dev systemtap-sdt-dev libminiupnpc-dev libnatpmp-dev libqt5gui5 libqt5core5a libqt5dbus5 qttools5-dev qttools5-dev-tools qtwayland5 libqrencode-dev -y - - name: Compile and run tests - run: | - # Run tests on commits after the last merge commit and before the PR head commit - # Use clang++, because it is a bit faster and uses less memory than g++ - git rebase --exec "echo Running test-one-commit on \$( git log -1 ) && ./autogen.sh && CC=clang-15 CXX=clang++-15 ./configure && make clean && make -j $(nproc) check && ./test/functional/test_runner.py -j $(( $(nproc) * 2 ))" ${{ env.TEST_BASE }} - - macos-native-x86_64: - name: 'macOS 13 native, x86_64, no depends, sqlite only, gui' - # Use latest image, but hardcode version to avoid silent upgrades (and breaks). - # See: https://github.com/actions/runner-images#available-images. - runs-on: macos-13 - - # No need to run on the read-only mirror, unless it is a PR. - if: github.repository != 'bitcoin-core/gui' || github.event_name == 'pull_request' - - timeout-minutes: 120 - - env: - FILE_ENV: './ci/test/00_setup_env_mac_native.sh' - BASE_ROOT_DIR: ${{ github.workspace }} - - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Clang version - run: | - sudo xcode-select --switch /Applications/Xcode_15.0.app - clang --version - - - name: Install Homebrew packages - env: - HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1 - run: brew install automake libtool pkg-config gnu-getopt ccache boost libevent miniupnpc libnatpmp zeromq qt@5 qrencode - - - name: Set Ccache directory - run: echo "CCACHE_DIR=${RUNNER_TEMP}/ccache_dir" >> "$GITHUB_ENV" - - - name: Restore Ccache cache - id: ccache-cache - uses: actions/cache/restore@v4 - with: - path: ${{ env.CCACHE_DIR }} - key: ${{ github.job }}-ccache-${{ github.run_id }} - restore-keys: ${{ github.job }}-ccache- - - - name: CI script - run: ./ci/test_run_all.sh - - - name: Save Ccache cache - uses: actions/cache/save@v4 - if: github.event_name != 'pull_request' && steps.ccache-cache.outputs.cache-hit != 'true' - with: - path: ${{ env.CCACHE_DIR }} - # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#update-a-cache - key: ${{ github.job }}-ccache-${{ github.run_id }} - - win64-native: - name: 'Win64 native, VS 2022' - # Use latest image, but hardcode version to avoid silent upgrades (and breaks). - # See: https://github.com/actions/runner-images#available-images. - runs-on: windows-2022 - - # No need to run on the read-only mirror, unless it is a PR. - if: github.repository != 'bitcoin-core/gui' || github.event_name == 'pull_request' - - env: - CCACHE_MAXSIZE: '200M' - CI_CCACHE_VERSION: '4.7.5' - CI_QT_CONF: '-release -silent -opensource -confirm-license -opengl desktop -static -static-runtime -mp -qt-zlib -qt-pcre -qt-libpng -nomake examples -nomake tests -nomake tools -no-angle -no-dbus -no-gif -no-gtk -no-ico -no-icu -no-libjpeg -no-libudev -no-sql-sqlite -no-sql-odbc -no-sqlite -no-vulkan -skip qt3d -skip qtactiveqt -skip qtandroidextras -skip qtcharts -skip qtconnectivity -skip qtdatavis3d -skip qtdeclarative -skip doc -skip qtdoc -skip qtgamepad -skip qtgraphicaleffects -skip qtimageformats -skip qtlocation -skip qtlottie -skip qtmacextras -skip qtmultimedia -skip qtnetworkauth -skip qtpurchasing -skip qtquick3d -skip qtquickcontrols -skip qtquickcontrols2 -skip qtquicktimeline -skip qtremoteobjects -skip qtscript -skip qtscxml -skip qtsensors -skip qtserialbus -skip qtserialport -skip qtspeech -skip qtsvg -skip qtvirtualkeyboard -skip qtwayland -skip qtwebchannel -skip qtwebengine -skip qtwebglplugin -skip qtwebsockets -skip qtwebview -skip qtx11extras -skip qtxmlpatterns -no-openssl -no-feature-bearermanagement -no-feature-printdialog -no-feature-printer -no-feature-printpreviewdialog -no-feature-printpreviewwidget -no-feature-sql -no-feature-sqlmodel -no-feature-textbrowser -no-feature-textmarkdownwriter -no-feature-textodfwriter -no-feature-xml' - CI_QT_DIR: 'qt-everywhere-src-5.15.11' - CI_QT_URL: 'https://download.qt.io/official_releases/qt/5.15/5.15.11/single/qt-everywhere-opensource-src-5.15.11.zip' - PYTHONUTF8: 1 - TEST_RUNNER_TIMEOUT_FACTOR: 40 - - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Configure Developer Command Prompt for Microsoft Visual C++ - # Using microsoft/setup-msbuild is not enough. - uses: ilammy/msvc-dev-cmd@v1 - with: - arch: x64 - - - name: Check MSBuild and Qt - run: | - msbuild -version | Out-File -FilePath "$env:GITHUB_WORKSPACE\msbuild_version" - Get-Content -Path "$env:GITHUB_WORKSPACE\msbuild_version" - $env:VCToolsVersion | Out-File -FilePath "$env:GITHUB_WORKSPACE\toolset_version" - Get-Content -Path "$env:GITHUB_WORKSPACE\toolset_version" - $env:CI_QT_URL | Out-File -FilePath "$env:GITHUB_WORKSPACE\qt_url" - $env:CI_QT_CONF | Out-File -FilePath "$env:GITHUB_WORKSPACE\qt_conf" - - - name: Restore static Qt cache - id: static-qt-cache - uses: actions/cache/restore@v4 - with: - path: C:\Qt_static - key: ${{ github.job }}-static-qt-${{ hashFiles('msbuild_version', 'qt_url', 'qt_conf') }} - - - name: Build static Qt. Download - if: steps.static-qt-cache.outputs.cache-hit != 'true' - shell: cmd - run: | - curl --location --output C:\qt-src.zip %CI_QT_URL% - choco install --yes --no-progress jom - - - name: Build static Qt. Expand source archive - if: steps.static-qt-cache.outputs.cache-hit != 'true' - shell: cmd - run: tar -xf C:\qt-src.zip -C C:\ - - - name: Build static Qt. Create build directory - if: steps.static-qt-cache.outputs.cache-hit != 'true' - run: | - Rename-Item -Path "C:\$env:CI_QT_DIR" -NewName "C:\qt-src" - New-Item -ItemType Directory -Path "C:\qt-src\build" - - - name: Build static Qt. Configure - if: steps.static-qt-cache.outputs.cache-hit != 'true' - working-directory: C:\qt-src\build - shell: cmd - run: ..\configure %CI_QT_CONF% -prefix C:\Qt_static - - - name: Build static Qt. Build - if: steps.static-qt-cache.outputs.cache-hit != 'true' - working-directory: C:\qt-src\build - shell: cmd - run: jom - - - name: Build static Qt. Install - if: steps.static-qt-cache.outputs.cache-hit != 'true' - working-directory: C:\qt-src\build - shell: cmd - run: jom install - - - name: Save static Qt cache - if: steps.static-qt-cache.outputs.cache-hit != 'true' - uses: actions/cache/save@v4 - with: - path: C:\Qt_static - key: ${{ github.job }}-static-qt-${{ hashFiles('msbuild_version', 'qt_url', 'qt_conf') }} - - - name: Ccache installation cache - id: ccache-installation-cache - uses: actions/cache@v4 - with: - path: | - C:\ProgramData\chocolatey\lib\ccache - C:\ProgramData\chocolatey\bin\ccache.exe - C:\ccache\cl.exe - key: ${{ github.job }}-ccache-installation-${{ env.CI_CCACHE_VERSION }} - - - name: Install Ccache - if: steps.ccache-installation-cache.outputs.cache-hit != 'true' - run: | - choco install --yes --no-progress ccache --version=$env:CI_CCACHE_VERSION - New-Item -ItemType Directory -Path "C:\ccache" - Copy-Item -Path "$env:ChocolateyInstall\lib\ccache\tools\ccache-$env:CI_CCACHE_VERSION-windows-x86_64\ccache.exe" -Destination "C:\ccache\cl.exe" - - - name: Restore Ccache cache - id: ccache-cache - uses: actions/cache/restore@v4 - with: - path: ~/AppData/Local/ccache - key: ${{ github.job }}-ccache-${{ github.run_id }} - restore-keys: ${{ github.job }}-ccache- - - - name: Using vcpkg with MSBuild - run: | - Set-Location "$env:VCPKG_INSTALLATION_ROOT" - Add-Content -Path "triplets\x64-windows-static.cmake" -Value "set(VCPKG_BUILD_TYPE release)" - Add-Content -Path "triplets\x64-windows-static.cmake" -Value "set(VCPKG_PLATFORM_TOOLSET_VERSION $env:VCToolsVersion)" - .\vcpkg.exe --vcpkg-root "$env:VCPKG_INSTALLATION_ROOT" integrate install - git rev-parse HEAD | Out-File -FilePath "$env:GITHUB_WORKSPACE\vcpkg_commit" - Get-Content -Path "$env:GITHUB_WORKSPACE\vcpkg_commit" - - - name: vcpkg tools cache - uses: actions/cache@v4 - with: - path: C:/vcpkg/downloads/tools - key: ${{ github.job }}-vcpkg-tools - - - name: vcpkg binary cache - uses: actions/cache@v4 - with: - path: ~/AppData/Local/vcpkg/archives - key: ${{ github.job }}-vcpkg-binary-${{ hashFiles('vcpkg_commit', 'msbuild_version', 'toolset_version', 'build_msvc/vcpkg.json') }} - - - name: Generate project files - run: py -3 build_msvc\msvc-autogen.py - - - name: Build - shell: cmd - run: | - ccache --zero-stats - msbuild build_msvc\bitcoin.sln -property:CLToolPath=C:\ccache;CLToolExe=cl.exe;UseMultiToolTask=true;Configuration=Release -maxCpuCount -verbosity:minimal -noLogo - - - name: Ccache stats - run: ccache --show-stats - - - name: Save Ccache cache - uses: actions/cache/save@v4 - if: github.event_name != 'pull_request' && steps.ccache-cache.outputs.cache-hit != 'true' - with: - path: ~/AppData/Local/ccache - # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#update-a-cache - key: ${{ github.job }}-ccache-${{ github.run_id }} - - - name: Run unit tests - run: src\test_bitcoin.exe -l test_suite - - - name: Run benchmarks - run: src\bench_bitcoin.exe -sanity-check - - - name: Run util tests - run: py -3 test\util\test_runner.py - - - name: Run rpcauth test - run: py -3 test\util\rpcauth-test.py - - - name: Run functional tests - env: - TEST_RUNNER_EXTRA: ${{ github.event_name != 'pull_request' && '--extended' || '' }} - run: py -3 test\functional\test_runner.py --jobs $env:NUMBER_OF_PROCESSORS --ci --quiet --tmpdirprefix=$env:RUNNER_TEMP --combinedlogslen=99999999 --timeout-factor=$env:TEST_RUNNER_TIMEOUT_FACTOR $env:TEST_RUNNER_EXTRA diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml new file mode 100644 index 0000000000000..f8205a82a5b73 --- /dev/null +++ b/.github/workflows/cmake.yml @@ -0,0 +1,513 @@ +# Copyright (c) 2023-present The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://opensource.org/license/mit/. + +name: CMake +on: + # Running for pushes is enough in the cmake-staging branch. + # pull_request: + push: + branches: + - '**' + tags-ignore: + - '**' + +concurrency: + group: ${{ github.workflow }}${{ github.event_name != 'pull_request' && github.run_id || github.ref }} + cancel-in-progress: true + +jobs: + build-info: + name: 'Test obj/build.h generation' + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - run: cp cmake/script/GenerateBuildInfo.cmake ${{ runner.temp }} + + - name: Test at HEAD + run: | + rm -rf src/obj build/src/obj + mkdir -p src/obj build/src/obj + ./share/genbuild.sh ${PWD}/src/obj/build.h ${PWD} + cmake -DBUILD_INFO_HEADER_PATH=${PWD}/build/src/obj/build.h -DSOURCE_DIR=${PWD} -P ${{ runner.temp }}/GenerateBuildInfo.cmake + cat src/obj/build.h + diff -u src/obj/build.h build/src/obj/build.h + + - name: Test out of tree + run: | + rm -rf src/obj build/src/obj + mkdir -p src/obj build/src/obj + ./share/genbuild.sh ${PWD}/src/obj/build.h ${{ runner.temp }} + cmake -DBUILD_INFO_HEADER_PATH=${PWD}/build/src/obj/build.h -DSOURCE_DIR=${{ runner.temp }} -P ${{ runner.temp }}/GenerateBuildInfo.cmake + cat src/obj/build.h + diff -u src/obj/build.h build/src/obj/build.h + + - name: Test at tag + run: | + rm -rf src/obj build/src/obj + mkdir -p src/obj build/src/obj + git -c advice.detachedHead=false checkout v25.1 + ./share/genbuild.sh ${PWD}/src/obj/build.h ${PWD} + cmake -DBUILD_INFO_HEADER_PATH=${PWD}/build/src/obj/build.h -DSOURCE_DIR=${PWD} -P ${{ runner.temp }}/GenerateBuildInfo.cmake + cat src/obj/build.h + diff -u src/obj/build.h build/src/obj/build.h + + - name: Test dirty tree + run: | + rm -rf src/obj build/src/obj + mkdir -p src/obj build/src/obj + echo "test" >> README.md + ./share/genbuild.sh ${PWD}/src/obj/build.h ${PWD} + cmake -DBUILD_INFO_HEADER_PATH=${PWD}/build/src/obj/build.h -DSOURCE_DIR=${PWD} -P ${{ runner.temp }}/GenerateBuildInfo.cmake + cat src/obj/build.h + diff -u src/obj/build.h build/src/obj/build.h + + - name: Test BITCOIN_GENBUILD_NO_GIT + env: + BITCOIN_GENBUILD_NO_GIT: '1' + run: | + rm -rf src/obj build/src/obj + mkdir -p src/obj build/src/obj + ./share/genbuild.sh ${PWD}/src/obj/build.h ${PWD} + cmake -DBUILD_INFO_HEADER_PATH=${PWD}/build/src/obj/build.h -DSOURCE_DIR=${PWD} -P ${{ runner.temp }}/GenerateBuildInfo.cmake + cat src/obj/build.h + diff -u src/obj/build.h build/src/obj/build.h + + + deps-search: + name: 'Test dependency search' + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + conf: + # Boost: Header-only. Using CMake's FindBoost module. + # Libevent: Using CMake's FindPkgConfig module. + - system_packages: '' + depends_options: 'NO_BOOST=1 NO_LIBEVENT=1 NO_WALLET=1 NO_USDT=1' + build_options: '' + expected: 'fail' + - system_packages: 'libboost-dev libevent-dev' + depends_options: 'NO_BOOST=1 NO_LIBEVENT=1 NO_WALLET=1 NO_USDT=1' + build_options: '' + expected: 'fail' + - system_packages: 'libboost-dev libevent-dev' + depends_options: 'NO_LIBEVENT=1 NO_WALLET=1 NO_USDT=1' + build_options: '' + expected: 'fail' + - system_packages: 'libboost-dev libevent-dev' + depends_options: 'NO_BOOST=1 NO_WALLET=1 NO_USDT=1' + build_options: '' + expected: 'fail' + - system_packages: 'libboost-dev libevent-dev' + depends_options: 'NO_WALLET=1 NO_USDT=1' + build_options: '' + expected: 'pass' + + # BerkeleyDB: Using our own FindBerkeleyDB module. + - system_packages: 'libboost-dev libevent-dev' + depends_options: 'NO_BDB=1 NO_SQLITE=1 NO_USDT=1' + build_options: '-DENABLE_WALLET=ON -DWITH_BDB=ON' + expected: 'fail' + - system_packages: 'libboost-dev libevent-dev libdb-dev libdb++-dev' + depends_options: 'NO_BDB=1 NO_SQLITE=1 NO_USDT=1' + build_options: '-DENABLE_WALLET=ON -DWITH_BDB=ON' + expected: 'fail' + - system_packages: 'libboost-dev libevent-dev' + depends_options: 'NO_SQLITE=1 NO_USDT=1' + build_options: '-DENABLE_WALLET=ON -DWITH_BDB=ON' + expected: 'pass' + + # SQLite: Using CMake's FindSQLite3 module. + - system_packages: 'libboost-dev libevent-dev' + depends_options: 'NO_BDB=1 NO_SQLITE=1 NO_USDT=1' + build_options: '-DENABLE_WALLET=ON -DWITH_SQLITE=ON' + expected: 'fail' + - system_packages: 'libboost-dev libevent-dev libsqlite3-dev' + depends_options: 'NO_BDB=1 NO_SQLITE=1 NO_USDT=1' + build_options: '-DENABLE_WALLET=ON -DWITH_SQLITE=ON' + expected: 'fail' + - system_packages: 'libboost-dev libevent-dev' + depends_options: 'NO_BDB=1 NO_USDT=1' + build_options: '-DENABLE_WALLET=ON -DWITH_SQLITE=ON' + expected: 'pass' + + # USDT: Header-only. Using CMake's find_path function. + - system_packages: 'libboost-dev libevent-dev' + depends_options: 'NO_WALLET=1 NO_USDT=1' + build_options: '-DWITH_USDT=ON' + expected: 'fail' + - system_packages: 'libboost-dev libevent-dev systemtap-sdt-dev' + depends_options: 'NO_WALLET=1 NO_USDT=1' + build_options: '-DWITH_USDT=ON' + expected: 'fail' + - system_packages: 'libboost-dev libevent-dev' + depends_options: 'NO_WALLET=1' + build_options: '-DWITH_USDT=ON' + expected: 'pass' + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install system packages + if: ${{ matrix.conf.system_packages != '' }} + run: | + sudo apt-get update + sudo apt-get install --no-install-recommends ${{ matrix.conf.system_packages }} + + - name: Build depends + working-directory: depends + run: | + make -j $(nproc) ${{ matrix.conf.depends_options }} NO_QT=1 NO_ZMQ=1 NO_UPNP=1 NO_NATPMP=1 LOG=1 + + - name: Generate build system. Expected to FAIL + if: ${{ matrix.conf.expected == 'fail' }} + run: | + ! cmake -B build -DCMAKE_TOOLCHAIN_FILE=depends/x86_64-pc-linux-gnu/share/toolchain.cmake ${{ matrix.conf.build_options }} + + - name: Generate build system. Expected to PASS + if: ${{ matrix.conf.expected == 'pass' }} + run: | + cmake -B build -DCMAKE_TOOLCHAIN_FILE=depends/x86_64-pc-linux-gnu/share/toolchain.cmake + + + ubuntu-focal-native: + name: 'Ubuntu 20.04, CMake 3.16, downloaded Boost' + runs-on: ubuntu-20.04 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Remove preinstalled CMake + run: | + sudo rm /usr/local/bin/cmake /usr/local/bin/ctest + + - name: Install packages + run: | + sudo apt-get update + sudo apt-get install --no-install-recommends curl g++10 cmake ccache libevent-dev libsqlite3-dev libdb-dev libdb++-dev libminiupnpc-dev libnatpmp-dev libzmq3-dev systemtap-sdt-dev libqt5gui5 libqt5core5a libqt5dbus5 qttools5-dev qttools5-dev-tools + echo "CCACHE_DIR=${{ runner.temp }}/ccache" >> "$GITHUB_ENV" + + - name: CMake version + run: | + cmake --version + ctest --version + + - name: Download Boost + run: | + curl --location --remote-name https://boostorg.jfrog.io/artifactory/main/release/1.84.0/source/boost_1_84_0.tar.gz + tar -xf boost_1_84_0.tar.gz + + - name: Restore Ccache cache + uses: actions/cache/restore@v3 + id: ccache-cache + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ github.job }}-ccache-${{ github.run_id }} + restore-keys: ${{ github.job }}-ccache- + + - name: Generate build system + run: > + cmake -B build \ + -DCMAKE_C_COMPILER=gcc-10 -DCMAKE_CXX_COMPILER=g++-10 \ + -DBoost_INCLUDE_DIR="${PWD}/boost_1_84_0" \ + -DENABLE_WALLET=ON -DWITH_SQLITE=ON -DWITH_BDB=ON \ + -DWITH_GUI=Qt5 \ + -DWITH_MINIUPNPC=ON \ + -DWITH_NATPMP=ON \ + -DWITH_ZMQ=ON \ + -DWITH_USDT=ON \ + -DWERROR=ON \ + -DCCACHE=ON + + - name: Build + working-directory: build + run: | + cmake --build . -j $(nproc) + + - name: Ccache stats + run: | + ccache --version | head -n 1 + ccache --show-stats + + - name: Save Ccache cache + uses: actions/cache/save@v3 + if: github.event_name != 'pull_request' && steps.ccache-cache.outputs.cache-hit != 'true' + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ github.job }}-ccache-${{ github.run_id }} + + - name: Test + working-directory: build + run: | + ctest -j $(nproc) + + - name: Install + run: | + cmake --install build --prefix install + tree install + + + cross-build: + name: ${{ matrix.host.name }} + runs-on: ubuntu-22.04 + + strategy: + fail-fast: false + matrix: + host: + - name: 'Linux 32-bit, Clang, link to libatomic' + triplet: 'i686-pc-linux-gnu' + packages: 'clang-14 g++-multilib' + c_compiler: 'clang-14 -m32' + cxx_compiler: 'clang++-14 -m32' + depends_options: '' + configure_options: '-DWERROR=ON' + - name: 'MinGW-w64' + triplet: 'x86_64-w64-mingw32' + packages: 'g++-mingw-w64-x86-64-posix' + depends_options: '' + exe_extension: '.exe' + - name: 'MinGW-w64, debug' + triplet: 'x86_64-w64-mingw32' + packages: 'g++-mingw-w64-x86-64-posix' + depends_options: 'DEBUG=1' + configure_options: '-DCMAKE_BUILD_TYPE=Debug' + cache_suffix: '-debug' + exe_extension: '.exe' + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install dependency packages + run: | + sudo apt-get update + sudo apt-get install --no-install-recommends ccache ${{ matrix.host.packages }} + echo "CCACHE_DIR=${{ runner.temp }}/ccache" >> "$GITHUB_ENV" + + - name: Depends fingerprint (1) + if: ${{ matrix.host.c_compiler != '' }} + run: | + ${{ matrix.host.c_compiler }} -v 2>&1 | tee depends/c_compiler_version + + - name: Depends fingerprint (2) + if: ${{ matrix.host.cxx_compiler != '' }} + run: | + ${{ matrix.host.cxx_compiler }} -v 2>&1 | tee depends/cxx_compiler_version + + - name: Depends fingerprint (3) + run: | + echo ${{ matrix.host.depends_options }} > depends/depends_options + + - name: Depends fingerprint (4) + id: depends_fingerprint + run: | + echo "hash=${{ hashFiles('depends/**') }}" >> "$GITHUB_OUTPUT" + + - name: Depends cache + id: depends_cache + uses: actions/cache@v3 + with: + path: | + depends/built + key: ${{ matrix.host.triplet }}${{ matrix.host.cache_suffix }}-depends-${{ steps.depends_fingerprint.outputs.hash }} + + - name: Build depends + working-directory: depends + env: + CC: ${{ matrix.host.c_compiler }} + CXX: ${{ matrix.host.cxx_compiler }} + run: | + make -j$(nproc) HOST=${{ matrix.host.triplet }} ${{ matrix.host.depends_options }} LOG=1 + + - name: Restore Ccache cache + uses: actions/cache/restore@v3 + id: ccache-cache + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ matrix.host.triplet }}${{ matrix.host.cache_suffix }}-ccache-${{ github.run_id }} + restore-keys: ${{ matrix.host.triplet }}${{ matrix.host.cache_suffix }}-ccache- + + - name: Generate build system + run: | + cmake -B build --toolchain depends/${{ matrix.host.triplet }}/share/toolchain.cmake ${{ matrix.host.configure_options }} + + - name: Build + run: | + ccache --zero-stats + cmake --build build -j $(nproc) + file build/src/bitcoind${{ matrix.host.exe_extension }} + + - name: Ccache stats + run: | + ccache --version | head -n 1 + ccache --show-stats --verbose + + - name: Save Ccache cache + uses: actions/cache/save@v3 + if: github.event_name != 'pull_request' && steps.ccache-cache.outputs.cache-hit != 'true' + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ matrix.host.triplet }}${{ matrix.host.cache_suffix }}-ccache-${{ github.run_id }} + + - name: Test + if: ${{ matrix.host.triplet == 'i686-pc-linux-gnu' }} + run: | + ctest --test-dir build -j $(nproc) + + - name: Install + run: | + cmake --install build --prefix install + tree install + + + win64-native-builtin-tools: + name: 'Win64 native, VS 2022, built-in tools' + runs-on: windows-2022 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Remove non-MSVC tool installations + run: | + Remove-Item -Path "$env:ProgramFiles/CMake" -Recurse -Force + Remove-Item -Path "$env:VCPKG_INSTALLATION_ROOT" -Recurse -Force + + - name: Configure Visual Studio Developer PowerShell + # Using microsoft/setup-msbuild is not enough as it does not add other Visual Studio tools to PATH. + uses: ilammy/msvc-dev-cmd@v1 + + - name: Check build tools + run: | + cmake --version | Out-File -FilePath "cmake_version" + Get-Content -Path "cmake_version" + Write-Output "---" + msbuild -version | Out-File -FilePath "msbuild_version" + Get-Content -Path "msbuild_version" + Write-Output "---" + $env:VCToolsVersion | Out-File -FilePath "toolset_version" + Get-Content -Path "toolset_version" + # GHA Windows images have different versions of MSVC toolsets being installed + # side-by-side. Therefore, the VCPKG_PLATFORM_TOOLSET_VERSION must be set explicitly + # to avoid linker errors when using vcpkg in the manifest mode. + # See: https://github.com/bitcoin/bitcoin/pull/28934 + Add-Content -Path "$env:VCPKG_ROOT\triplets\x64-windows-static.cmake" -Value "set(VCPKG_PLATFORM_TOOLSET_VERSION $env:VCToolsVersion)" + # Skip debug configuration to speed up build and minimize cache size. + Add-Content -Path "$env:VCPKG_ROOT\triplets\x64-windows.cmake" -Value "set(VCPKG_BUILD_TYPE release)" + Add-Content -Path "$env:VCPKG_ROOT\triplets\x64-windows-static.cmake" -Value "set(VCPKG_BUILD_TYPE release)" + + - name: Restore vcpkg binary cache + uses: actions/cache/restore@v3 + id: vcpkg-binary-cache + with: + path: ~/AppData/Local/vcpkg/archives + key: ${{ runner.os }}-${{ runner.arch }}-vcpkg-binary-${{ hashFiles('cmake_version', 'msbuild_version', 'toolset_version', 'vcpkg.json') }} + + - name: Generate build system + run: | + cmake -B build -A x64 --toolchain $env:VCPKG_ROOT\scripts\buildsystems\vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static -DWITH_NATPMP=OFF + + - name: Save vcpkg binary cache + uses: actions/cache/save@v3 + if: github.event_name != 'pull_request' && steps.vcpkg-binary-cache.outputs.cache-hit != 'true' + with: + path: ~/AppData/Local/vcpkg/archives + key: ${{ runner.os }}-${{ runner.arch }}-vcpkg-binary-${{ hashFiles('cmake_version', 'msbuild_version', 'toolset_version', 'vcpkg.json') }} + + - name: Build Release configuration + run: | + cmake --build build -j $env:NUMBER_OF_PROCESSORS --config Release + + - name: Test Release configuration + run: | + ctest --test-dir build -j $env:NUMBER_OF_PROCESSORS -C Release + + - name: Install Release configuration + run: | + cmake --install build --prefix install --config Release + tree /f install + + + macos-native-x86_64: + name: ${{ matrix.conf.name }} + runs-on: macos-13 + + strategy: + fail-fast: false + matrix: + conf: + - name: 'macOS 13 native, x86_64, Xcode 14.3.1' + xcode_path: '/Applications/Xcode_14.3.1.app' + ccache_id: 'macos-13-xcode-14.3.1' + - name: 'macOS 13 native, x86_64, Xcode 15.1' + xcode_path: '/Applications/Xcode_15.1.app' + ccache_id: 'macos-13-xcode-15.1' + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Clang version + run: | + sudo xcode-select --switch ${{ matrix.conf.xcode_path }} + clang --version + + - name: Install Homebrew packages + env: + HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1 + run: | + brew install ccache cmake pkg-config boost libevent berkeley-db@4 qt@5 libnatpmp miniupnpc zeromq tree + echo "CCACHE_DIR=${{ runner.temp }}/ccache" >> "$GITHUB_ENV" + + - name: CMake version + run: | + cmake --version + ctest --version + + - name: Restore Ccache cache + uses: actions/cache/restore@v3 + id: ccache-cache + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ matrix.conf.ccache_id }}-ccache-${{ github.run_id }} + restore-keys: ${{ matrix.conf.ccache_id }}-ccache- + + - name: Generate build system + run: | + cmake -B build + + - name: Build + run: | + ccache --zero-stats + cmake --build build -j $(sysctl -n hw.logicalcpu) + + - name: Ccache stats + run: | + ccache --version | head -n 1 + ccache --show-stats --verbose + + - name: Save Ccache cache + uses: actions/cache/save@v3 + if: github.event_name != 'pull_request' && steps.ccache-cache.outputs.cache-hit != 'true' + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ matrix.conf.ccache_id }}-ccache-${{ github.run_id }} + + - name: Test + run: | + ctest --test-dir build -j $(sysctl -n hw.logicalcpu) + + - name: Install + run: | + cmake --install build --prefix install + tree install diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000000..f63fad3bc8bc5 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,441 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# IMPORTANT: Changes which affect binary results may not be quietly gated +# by CMake version. +# +# Ubuntu 20.04 LTS Focal Fossa, https://wiki.ubuntu.com/Releases, EOSS in April 2025: +# - CMake 3.16.3, https://packages.ubuntu.com/focal/cmake +# +# Centos Stream 8, EOL in May 2024: +# - CMake 3.20.2, http://mirror.centos.org/centos/8-stream/AppStream/x86_64/os/Packages/ +# +# All policies known to the running version of CMake and introduced +# in the 3.28 version or earlier will be set to use NEW behavior. +# All policies introduced in later versions will be unset. +# See: https://cmake.org/cmake/help/latest/manual/cmake-policies.7.html +cmake_minimum_required(VERSION 3.16...3.28) + +project("Bitcoin Core" + VERSION 26.99.0 + DESCRIPTION "Bitcoin client software" + HOMEPAGE_URL "https://bitcoincore.org/" + LANGUAGES CXX ASM +) + +set(PACKAGE_NAME ${PROJECT_NAME}) +set(CLIENT_VERSION_IS_RELEASE "false") +set(COPYRIGHT_YEAR "2023") +set(COPYRIGHT_HOLDERS "The %s developers") +set(COPYRIGHT_HOLDERS_FINAL "The ${PROJECT_NAME} developers") +set(PACKAGE_BUGREPORT "https://github.com/bitcoin/bitcoin/issues") + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/module) + +# Configurable options. +# When adding a new option, end the with a full stop for consistency. +option(BUILD_DAEMON "Build bitcoind executable." ON) +option(BUILD_CLI "Build bitcoin-cli executable." ON) +option(BUILD_TX "Build bitcoin-tx executable." ON) +option(BUILD_UTIL "Build bitcoin-util executable." ON) +option(ASM "Use assembly routines." ON) + +option(ENABLE_WALLET "Enable wallet." OFF) +include(CMakeDependentOption) +cmake_dependent_option(WITH_SQLITE "Enable SQLite wallet support." OFF "ENABLE_WALLET" OFF) +cmake_dependent_option(WITH_BDB "Enable Berkeley DB (BDB) wallet support." OFF "ENABLE_WALLET" OFF) +cmake_dependent_option(WARN_INCOMPATIBLE_BDB "Warn when using a Berkeley DB (BDB) version other than 4.8." ON "WITH_BDB" OFF) +cmake_dependent_option(BUILD_WALLET_TOOL "Build bitcoin-wallet tool." ON "ENABLE_WALLET" OFF) + +option(THREADLOCAL "Enable features that depend on the C++ thread_local keyword (currently just thread names in debug logs)." ON) +option(HARDENING "Attempt to harden the resulting executables." ON) +option(REDUCE_EXPORTS "Attempt to reduce exported symbols in the resulting executables." OFF) +option(WERROR "Treat compiler warnings as errors." OFF) + +option(CCACHE "Use ccache for compiling." OFF) +option(WITH_NATPMP "Enable NAT-PMP." OFF) +option(WITH_MINIUPNPC "Enable UPnP." OFF) +option(WITH_ZMQ "Enable ZMQ notifications." OFF) +option(WITH_USDT "Enable tracepoints for Userspace, Statically Defined Tracing." OFF) + +option(BUILD_TESTS "Build test_bitcoin executable." ON) +option(BUILD_BENCH "Build bench_bitcoin executable." ON) +cmake_dependent_option(BUILD_FUZZ_BINARY "Build fuzz binary." ON "NOT MSVC" OFF) +cmake_dependent_option(FUZZ "Build for fuzzing. Enabling this will disable all other targets and override BUILD_FUZZ_BINARY." OFF "NOT MSVC" OFF) + +if(FUZZ) + message(WARNING "FUZZ=ON will disable all other targets and force BUILD_FUZZ_BINARY=ON.") + set(BUILD_DAEMON OFF) + set(BUILD_CLI OFF) + set(BUILD_TX OFF) + set(BUILD_UTIL OFF) + set(BUILD_UTIL_CHAINSTATE OFF) + set(BUILD_SHARED_LIBS OFF) + set(BUILD_WALLET_TOOL OFF) + set(WITH_NATPMP OFF) + set(WITH_MINIUPNPC OFF) + set(WITH_ZMQ OFF) + set(BUILD_TESTS OFF) + set(BUILD_BENCH OFF) + set(BUILD_FUZZ_BINARY ON) +endif() + +option(INSTALL_MAN "Install man pages." ON) + +set(configure_warnings) + +include(CheckPIESupported) +check_pie_supported(OUTPUT_VARIABLE check_pie_output LANGUAGES CXX) +if(CMAKE_CXX_LINK_PIE_SUPPORTED) + set(CMAKE_POSITION_INDEPENDENT_CODE ON) +elseif(NOT WIN32) + # The warning is superfluous for Windows. + message(WARNING "PIE is not supported at link time: ${check_pie_output}") + list(APPEND configure_warnings "Position independent code disabled.") +endif() +unset(check_pie_output) + +# The core_interface library aims to encapsulate common build flags. +# It is intended to be a usage requirement for all other targets. +add_library(core_interface INTERFACE) + +include(TryAppendCXXFlags) +include(TryAppendLinkerFlag) + +if(WIN32) + #[=[ + This build system supports two ways to build binaries for Windows. + + 1. Building on Windows using MSVC. + Implementation notes: + - /DWIN32 and /D_WINDOWS definitions are included into the CMAKE_CXX_FLAGS_INIT + and CMAKE_CXX_FLAGS_INIT variables by default. + - A run-time library is selected using the CMAKE_MSVC_RUNTIME_LIBRARY variable. + - MSVC-specific options, for example, /Zc:__cplusplus, are additionally required. + + 2. Cross-compiling using MinGW. + Implementation notes: + - WIN32 and _WINDOWS definitions must be provided explicitly. + - A run-time library must be specified explicitly using _MT definition. + ]=] + + target_compile_definitions(core_interface INTERFACE + _WIN32_WINNT=0x0601 + _WIN32_IE=0x0501 + WIN32_LEAN_AND_MEAN + NOMINMAX + ) + + if(MSVC) + target_compile_definitions(core_interface INTERFACE + _UNICODE;UNICODE + ) + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") + target_compile_options(core_interface INTERFACE + /utf-8 + /Zc:__cplusplus + ) + # Improve parallelism in MSBuild. + # See: https://devblogs.microsoft.com/cppblog/improved-parallelism-in-msbuild/. + list(APPEND CMAKE_VS_GLOBALS "UseMultiToolTask=true") + + try_append_cxx_flags("/W3" TARGET core_interface) + try_append_cxx_flags("/wd4018" TARGET core_interface) + try_append_cxx_flags("/wd4244" TARGET core_interface) + try_append_cxx_flags("/wd4267" TARGET core_interface) + try_append_cxx_flags("/wd4715" TARGET core_interface) + try_append_cxx_flags("/wd4805" TARGET core_interface) + target_compile_definitions(core_interface INTERFACE + _CRT_SECURE_NO_WARNINGS + _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING + ) + endif() + + if(MINGW) + target_compile_definitions(core_interface INTERFACE + WIN32 + _WINDOWS + _MT + ) + # Avoid the use of aligned vector instructions when building for Windows. + # See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54412. + try_append_cxx_flags("-Wa,-muse-unaligned-vector-move" TARGET core_interface) + try_append_linker_flag("-static" TARGET core_interface) + # We require Windows 7 (NT 6.1) or later. + try_append_linker_flag("-Wl,--major-subsystem-version,6" TARGET core_interface) + try_append_linker_flag("-Wl,--minor-subsystem-version,1" TARGET core_interface) + endif() +endif() + +# Use 64-bit off_t on 32-bit Linux. +if (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SIZEOF_VOID_P EQUAL 4) + # Ensure 64-bit offsets are used for filesystem accesses for 32-bit compilation. + target_compile_definitions(core_interface INTERFACE + _FILE_OFFSET_BITS=64 + ) +endif() + +if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + target_compile_definitions(core_interface INTERFACE + MAC_OSX + ) + # These flags are specific to ld64, and may cause issues with other linkers. + # For example: GNU ld will interpret -dead_strip as -de and then try and use + # "ad_strip" as the symbol for the entry point. + try_append_linker_flag("-Wl,-dead_strip" TARGET core_interface) + try_append_linker_flag("-Wl,-dead_strip_dylibs" TARGET core_interface) + try_append_linker_flag("-Wl,-headerpad_max_install_names" TARGET core_interface) +endif() + +if(CMAKE_CROSSCOMPILING) + target_compile_definitions(core_interface INTERFACE ${DEPENDS_COMPILE_DEFINITIONS}) + target_compile_options(core_interface INTERFACE "$<$:${DEPENDS_C_COMPILER_FLAGS}>") + target_compile_options(core_interface INTERFACE "$<$:${DEPENDS_CXX_COMPILER_FLAGS}>") +endif() + +include(AddThreadsIfNeeded) +add_threads_if_needed() + +add_library(sanitizing_interface INTERFACE) +target_link_libraries(core_interface INTERFACE sanitizing_interface) +if(SANITIZERS) + # First check if the compiler accepts flags. If an incompatible pair like + # -fsanitize=address,thread is used here, this check will fail. This will also + # fail if a bad argument is passed, e.g. -fsanitize=undfeined + try_append_cxx_flags("-fsanitize=${SANITIZERS}" TARGET sanitizing_interface + RESULT_VAR cxx_supports_sanitizers + ) + if(NOT cxx_supports_sanitizers) + message(FATAL_ERROR "Compiler did not accept requested flags.") + endif() + + # Some compilers (e.g. GCC) require additional libraries like libasan, + # libtsan, libubsan, etc. Make sure linking still works with the sanitize + # flag. This is a separate check so we can give a better error message when + # the sanitize flags are supported by the compiler but the actual sanitizer + # libs are missing. + try_append_linker_flag("-fsanitize=${SANITIZERS}" VAR SANITIZER_LDFLAGS + SOURCE " + #include + #include + extern \"C\" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { return 0; } + __attribute__((weak)) // allow for libFuzzer linking + int main() { return 0; } + " + RESULT_VAR linker_supports_sanitizers + ) + if(NOT linker_supports_sanitizers) + message(FATAL_ERROR "Linker did not accept requested flags, you are missing required libraries.") + endif() +endif() +target_link_options(sanitizing_interface INTERFACE ${SANITIZER_LDFLAGS}) + +include(AddBoostIfNeeded) +add_boost_if_needed() + +include(AddLibeventIfNeeded) +add_libevent_if_needed() + +include(cmake/introspection.cmake) + +include(cmake/crc32c.cmake) +include(cmake/leveldb.cmake) +include(cmake/minisketch.cmake) +include(cmake/secp256k1.cmake) + +include(ProcessConfigurations) +set_default_config(RelWithDebInfo) + +# Redefine configuration flags. +target_compile_definitions(core_interface INTERFACE + $<$:DEBUG> + $<$:DEBUG_LOCKORDER> + $<$:DEBUG_LOCKCONTENTION> + $<$:RPC_DOC_CHECK> + $<$:ABORT_ON_FAILED_ASSUME> +) +# We leave assertions on. +if(MSVC) + remove_c_flag_from_all_configs(/DNDEBUG) + remove_cxx_flag_from_all_configs(/DNDEBUG) +else() + remove_c_flag_from_all_configs(-DNDEBUG) + remove_cxx_flag_from_all_configs(-DNDEBUG) + + # Prefer -O2 optimization level. (-O3 is CMake's default for Release for many compilers.) + replace_c_flag_in_config(Release -O3 -O2) + replace_cxx_flag_in_config(Release -O3 -O2) + + set(debug_flags) + try_append_cxx_flags("-O0" VAR debug_flags) + try_append_cxx_flags("-g3" VAR debug_flags RESULT_VAR compiler_supports_g3) + if(NOT compiler_supports_g3) + try_append_cxx_flags("-g" VAR debug_flags) + endif() + set(CMAKE_C_FLAGS_DEBUG "${debug_flags}") + try_append_cxx_flags("-ftrapv" VAR debug_flags) + set(CMAKE_CXX_FLAGS_DEBUG "${debug_flags}") + unset(debug_flags) +endif() + +include(cmake/optional_qt.cmake) + +include(cmake/optional.cmake) + +# Don't allow extended (non-ASCII) symbols in identifiers. This is easier for code review. +try_append_cxx_flags("-fno-extended-identifiers" TARGET core_interface) + +# Currently all versions of gcc are subject to a class of bugs, see the +# gccbug_90348 test case (only reproduces on GCC 11 and earlier) and +# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111843. To work around that, set +# -fstack-reuse=none for all gcc builds. (Only gcc understands this flag). +try_append_cxx_flags("-fstack-reuse=none" TARGET core_interface) + +if(HARDENING) + add_library(hardening_interface INTERFACE) + target_link_libraries(core_interface INTERFACE hardening_interface) + if(MSVC) + try_append_linker_flag("/DYNAMICBASE" TARGET hardening_interface) + try_append_linker_flag("/HIGHENTROPYVA" TARGET hardening_interface) + try_append_linker_flag("/NXCOMPAT" TARGET hardening_interface) + else() + target_compile_options(hardening_interface INTERFACE + $<$>:-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=3> + ) + + try_append_cxx_flags("-Wstack-protector" TARGET hardening_interface) + try_append_cxx_flags("-fstack-protector-all" TARGET hardening_interface) + try_append_cxx_flags("-fcf-protection=full" TARGET hardening_interface) + + if(MINGW) + # stack-clash-protection doesn't compile with GCC 10 and earlier. + # In any case, it is a no-op for Windows. + # See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90458 for more details. + else() + try_append_cxx_flags("-fstack-clash-protection" TARGET hardening_interface) + endif() + + if(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64") + try_append_cxx_flags("-mbranch-protection=bti" TARGET hardening_interface) + endif() + + try_append_linker_flag("-Wl,--enable-reloc-section" TARGET hardening_interface) + try_append_linker_flag("-Wl,--dynamicbase" TARGET hardening_interface) + try_append_linker_flag("-Wl,--nxcompat" TARGET hardening_interface) + try_append_linker_flag("-Wl,--high-entropy-va" TARGET hardening_interface) + try_append_linker_flag("-Wl,-z,relro" TARGET hardening_interface) + try_append_linker_flag("-Wl,-z,now" TARGET hardening_interface) + try_append_linker_flag("-Wl,-z,separate-code" TARGET hardening_interface) + if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + try_append_linker_flag("-Wl,-bind_at_load" TARGET hardening_interface) + try_append_linker_flag("-Wl,-fixup_chains" TARGET hardening_interface) + endif() + endif() +endif() + +if(REDUCE_EXPORTS) + set(CMAKE_CXX_VISIBILITY_PRESET hidden) + set(CMAKE_VISIBILITY_INLINES_HIDDEN 1) + try_append_linker_flag("-Wl,--exclude-libs,ALL" TARGET core_interface) +endif() + +if(WERROR) + if(MSVC) + set(werror_flag "/WX") + else() + set(werror_flag "-Werror") + endif() + try_append_cxx_flags(${werror_flag} TARGET core_interface RESULT_VAR compiler_supports_werror) + if(NOT compiler_supports_werror) + message(FATAL_ERROR "WERROR set but ${werror_flag} is not usable.") + endif() + unset(werror_flag) +endif() + +find_package(Python3 3.9 COMPONENTS Interpreter) +if(Python3_EXECUTABLE) + set(PYTHON_COMMAND ${Python3_EXECUTABLE}) +else() + list(APPEND configure_warnings + "Minimum required Python not found. Utils and rpcauth tests are disabled." + ) +endif() + +add_subdirectory(src) +add_subdirectory(test) + +include(cmake/tests.cmake) + +include(Maintenance) +setup_split_debug_script() +add_maintenance_targets() + +get_target_property(definitions core_interface INTERFACE_COMPILE_DEFINITIONS) +separate_by_configs(definitions) + +message("\n") +message("Configure summary") +message("=================") +message("Executables:") +message(" bitcoind ............................ ${BUILD_DAEMON}") +message(" bitcoin-cli ......................... ${BUILD_CLI}") +message(" bitcoin-tx .......................... ${BUILD_TX}") +message(" bitcoin-util ........................ ${BUILD_UTIL}") +message(" bitcoin-wallet ...................... ${BUILD_WALLET_TOOL}") +message("Wallet support:") +message(" SQLite, descriptor wallets .......... ${WITH_SQLITE}") +message(" Berkeley DB, legacy wallets ......... ${WITH_BDB}") +message("Optional packages:") +message(" GUI ................................. ${WITH_GUI}") +message(" NAT-PMP ............................. ${WITH_NATPMP}") +message(" UPnP ................................ ${WITH_MINIUPNPC}") +message(" ZeroMQ .............................. ${WITH_ZMQ}") +message(" USDT tracing ........................ ${WITH_USDT}") +message("Tests:") +message(" test_bitcoin ........................ ${BUILD_TESTS}") +message(" bench_bitcoin ....................... ${BUILD_BENCH}") +message(" fuzz binary ......................... ${BUILD_FUZZ_BINARY}") +message("") +if(CMAKE_CROSSCOMPILING) + set(cross_status "TRUE, for ${CMAKE_SYSTEM_NAME}, ${CMAKE_SYSTEM_PROCESSOR}") +else() + set(cross_status "FALSE") +endif() +message("Cross compiling ....................... ${cross_status}") +message("Preprocessor defined macros ........... ${definitions_ALL}") +message("C compiler ............................ ${CMAKE_C_COMPILER}") +list(JOIN DEPENDS_C_COMPILER_FLAGS " " depends_c_flags) +string(STRIP "${CMAKE_C_FLAGS} ${depends_c_flags}" combined_c_flags) +message("CFLAGS ................................ ${combined_c_flags}") +message("C++ compiler .......................... ${CMAKE_CXX_COMPILER}") +list(JOIN DEPENDS_CXX_COMPILER_FLAGS " " depends_cxx_flags) +string(STRIP "${CMAKE_CXX_FLAGS} ${depends_cxx_flags}" combined_cxx_flags) +message("CXXFLAGS .............................. ${combined_cxx_flags}") +include(GetTargetInterface) +get_target_interface(common_compile_options core_interface COMPILE_OPTIONS) +message("Common compile options ................ ${common_compile_options}") +get_target_interface(common_link_options core_interface LINK_OPTIONS) +message("Common link options ................... ${common_link_options}") +message("Linker flags for executables .......... ${CMAKE_EXE_LINKER_FLAGS}") +message("Linker flags for shared libraries ..... ${CMAKE_SHARED_LINKER_FLAGS}") +print_config_flags() +message("Use assembly routines ................. ${ASM}") +message("Attempt to harden executables ......... ${HARDENING}") +message("Treat compiler warnings as errors ..... ${WERROR}") +message("Use ccache for compiling .............. ${CCACHE}") +message("\n") +if(configure_warnings) + message(" ******\n") + foreach(warning IN LISTS configure_warnings) + message(WARNING "${warning}") + endforeach() + message(" ******\n") +endif() + +# We want all build properties to be encapsulated properly. +include(WarnAboutGlobalProperties) diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 0000000000000..ed0a1936d2886 --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,25 @@ +{ + "cmakeMinimumRequired": {"major": 3, "minor": 21, "patch": 0}, + "version": 3, + "configurePresets": [ + { + "name": "dev-mode", + "displayName": "Development mode (intended only for Bitcoin Core developers)", + "cacheVariables": { + "ENABLE_WALLET": "ON", + "WITH_SQLITE": "ON", + "WITH_BDB": "ON", + "WERROR": "ON", + "CCACHE": "ON", + "WITH_NATPMP": "ON", + "WITH_MINIUPNPC": "ON", + "WITH_ZMQ": "ON", + "WITH_USDT": "ON" + }, + "warnings": { + "dev": true, + "uninitialized": false + } + } + ] +} diff --git a/cmake/bitcoin-config.h.in b/cmake/bitcoin-config.h.in new file mode 100644 index 0000000000000..ebbb97562cdb0 --- /dev/null +++ b/cmake/bitcoin-config.h.in @@ -0,0 +1,218 @@ +// Copyright (c) 2023 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_CONFIG_H + +#define BITCOIN_CONFIG_H + +/* Define this symbol if type char equals int8_t */ +#cmakedefine CHAR_EQUALS_INT8 1 + +/* Version Build */ +#define CLIENT_VERSION_BUILD @PROJECT_VERSION_PATCH@ + +/* Version is release */ +#define CLIENT_VERSION_IS_RELEASE @CLIENT_VERSION_IS_RELEASE@ + +/* Major version */ +#define CLIENT_VERSION_MAJOR @PROJECT_VERSION_MAJOR@ + +/* Minor version */ +#define CLIENT_VERSION_MINOR @PROJECT_VERSION_MINOR@ + +/* Copyright holder(s) before %s replacement */ +#define COPYRIGHT_HOLDERS "@COPYRIGHT_HOLDERS@" + +/* Copyright holder(s) */ +#define COPYRIGHT_HOLDERS_FINAL "@COPYRIGHT_HOLDERS_FINAL@" + +/* Replacement for %s in copyright holders string */ +#define COPYRIGHT_HOLDERS_SUBSTITUTION "@PROJECT_NAME@" + +/* Copyright year */ +#define COPYRIGHT_YEAR @COPYRIGHT_YEAR@ + +/* Define to 1 to enable tracepoints for Userspace, Statically Defined Tracing + */ +#cmakedefine ENABLE_TRACING 1 + +/* Define this symbol if you have __builtin_clzl */ +#cmakedefine HAVE_BUILTIN_CLZL 1 + +/* Define this symbol if you have __builtin_clzll */ +#cmakedefine HAVE_BUILTIN_CLZLL 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_BYTESWAP_H 1 + +/* Define to 1 if you have the declaration of `be16toh', and to 0 if you + don't. */ +#cmakedefine01 HAVE_DECL_BE16TOH + +/* Define to 1 if you have the declaration of `be32toh', and to 0 if you + don't. */ +#cmakedefine01 HAVE_DECL_BE32TOH + +/* Define to 1 if you have the declaration of `be64toh', and to 0 if you + don't. */ +#cmakedefine01 HAVE_DECL_BE64TOH + +/* Define to 1 if you have the declaration of `bswap_16', and to 0 if you + don't. */ +#cmakedefine01 HAVE_DECL_BSWAP_16 + +/* Define to 1 if you have the declaration of `bswap_32', and to 0 if you + don't. */ +#cmakedefine01 HAVE_DECL_BSWAP_32 + +/* Define to 1 if you have the declaration of `bswap_64', and to 0 if you + don't. */ +#cmakedefine01 HAVE_DECL_BSWAP_64 + +/* Define to 1 if you have the declaration of `fork', and to 0 if you don't. + */ +#cmakedefine01 HAVE_DECL_FORK + +/* Define to 1 if you have the declaration of `freeifaddrs', and to 0 if you + don't. */ +#cmakedefine01 HAVE_DECL_FREEIFADDRS + +/* Define to 1 if you have the declaration of `getifaddrs', and to 0 if you + don't. */ +#cmakedefine01 HAVE_DECL_GETIFADDRS + +/* Define to 1 if you have the declaration of `htobe16', and to 0 if you + don't. */ +#cmakedefine01 HAVE_DECL_HTOBE16 + +/* Define to 1 if you have the declaration of `htobe32', and to 0 if you + don't. */ +#cmakedefine01 HAVE_DECL_HTOBE32 + +/* Define to 1 if you have the declaration of `htobe64', and to 0 if you + don't. */ +#cmakedefine01 HAVE_DECL_HTOBE64 + +/* Define to 1 if you have the declaration of `htole16', and to 0 if you + don't. */ +#cmakedefine01 HAVE_DECL_HTOLE16 + +/* Define to 1 if you have the declaration of `htole32', and to 0 if you + don't. */ +#cmakedefine01 HAVE_DECL_HTOLE32 + +/* Define to 1 if you have the declaration of `htole64', and to 0 if you + don't. */ +#cmakedefine01 HAVE_DECL_HTOLE64 + +/* Define to 1 if you have the declaration of `le16toh', and to 0 if you + don't. */ +#cmakedefine01 HAVE_DECL_LE16TOH + +/* Define to 1 if you have the declaration of `le32toh', and to 0 if you + don't. */ +#cmakedefine01 HAVE_DECL_LE32TOH + +/* Define to 1 if you have the declaration of `le64toh', and to 0 if you + don't. */ +#cmakedefine01 HAVE_DECL_LE64TOH + +/* Define to 1 if you have the declaration of `pipe2', and to 0 if you don't. + */ +#cmakedefine01 HAVE_DECL_PIPE2 + +/* Define to 1 if you have the declaration of `setsid', and to 0 if you don't. + */ +#cmakedefine01 HAVE_DECL_SETSID + +/* Define if the visibility attribute is supported. */ +#cmakedefine HAVE_DEFAULT_VISIBILITY_ATTRIBUTE 1 + +/* Define if the dllexport attribute is supported. */ +#cmakedefine HAVE_DLLEXPORT_ATTRIBUTE 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ENDIAN_H 1 + +/* Define to 1 if fdatasync is available. */ +#cmakedefine HAVE_FDATASYNC 1 + +/* Define this symbol if the BSD getentropy system call is available with + sys/random.h */ +#cmakedefine HAVE_GETENTROPY_RAND 1 + +/* Define this symbol if gmtime_r is available */ +#cmakedefine HAVE_GMTIME_R 1 + +/* Define this symbol if you have malloc_info */ +#cmakedefine HAVE_MALLOC_INFO 1 + +/* Define this symbol if you have mallopt with M_ARENA_MAX */ +#cmakedefine HAVE_MALLOPT_ARENA_MAX 1 + +/* Define to 1 if O_CLOEXEC flag is available. */ +#cmakedefine01 HAVE_O_CLOEXEC + +/* Define this symbol if you have posix_fallocate */ +#cmakedefine HAVE_POSIX_FALLOCATE 1 + +/* Define this symbol to build code that uses getauxval) */ +#cmakedefine HAVE_STRONG_GETAUXVAL 1 + +/* Define this symbol if the BSD sysctl() is available */ +#cmakedefine HAVE_SYSCTL 1 + +/* Define this symbol if the BSD sysctl(KERN_ARND) is available */ +#cmakedefine HAVE_SYSCTL_ARND 1 + +/* Define to 1 if std::system or ::wsystem is available. */ +#cmakedefine HAVE_SYSTEM 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_ENDIAN_H 1 + +/* Define this symbol if the Linux getrandom system call is available */ +#cmakedefine HAVE_SYS_GETRANDOM 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_PRCTL_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_RESOURCES_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_VMMETER_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_VM_VM_PARAM_H 1 + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "@PROJECT_NAME@" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "@PROJECT_HOMEPAGE_URL@" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "@PROJECT_VERSION@" + +/* Define to 1 if strerror_r returns char *. */ +#cmakedefine STRERROR_R_CHAR_P 1 + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#cmakedefine WORDS_BIGENDIAN 1 + +/* Define to 1 to enable wallet functions. */ +#cmakedefine ENABLE_WALLET 1 + +/* Define if SQLite support should be compiled in. */ +#cmakedefine USE_SQLITE + +/* Define if Berkeley DB (BDB) support should be compiled in. */ +#cmakedefine USE_BDB + +#endif //BITCOIN_CONFIG_H diff --git a/cmake/crc32c.cmake b/cmake/crc32c.cmake new file mode 100644 index 0000000000000..dbe8e92d9558f --- /dev/null +++ b/cmake/crc32c.cmake @@ -0,0 +1,115 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# This file is part of the transition from Autotools to CMake. Once CMake +# support has been merged we should switch to using the upstream CMake +# buildsystem. + +include(CheckCXXSourceCompiles) + +# Check for __builtin_prefetch support in the compiler. +check_cxx_source_compiles(" + int main() { + char data = 0; + const char* address = &data; + __builtin_prefetch(address, 0, 0); + return 0; + } + " HAVE_BUILTIN_PREFETCH +) + +# Check for _mm_prefetch support in the compiler. +check_cxx_source_compiles(" + #if defined(_MSC_VER) + #include + #else + #include + #endif + + int main() { + char data = 0; + const char* address = &data; + _mm_prefetch(address, _MM_HINT_NTA); + return 0; + } + " HAVE_MM_PREFETCH +) + +# Check for SSE4.2 support in the compiler. +if(MSVC) + set(SSE42_CXXFLAGS /arch:AVX) +else() + set(SSE42_CXXFLAGS -msse4.2) +endif() +check_cxx_source_compiles_with_flags("${SSE42_CXXFLAGS}" " + #include + #if defined(_MSC_VER) + #include + #elif defined(__GNUC__) && defined(__SSE4_2__) + #include + #endif + + int main() { + uint64_t l = 0; + l = _mm_crc32_u8(l, 0); + l = _mm_crc32_u32(l, 0); + l = _mm_crc32_u64(l, 0); + return l; + } + " HAVE_SSE42 +) + +# Check for ARMv8 w/ CRC and CRYPTO extensions support in the compiler. +set(ARM_CRC_CXXFLAGS -march=armv8-a+crc+crypto) +check_cxx_source_compiles_with_flags("${ARM_CRC_CXXFLAGS}" " + #include + #include + + int main() { + #ifdef __aarch64__ + __crc32cb(0, 0); __crc32ch(0, 0); __crc32cw(0, 0); __crc32cd(0, 0); + vmull_p64(0, 0); + #else + #error crc32c library does not support hardware acceleration on 32-bit ARM + #endif + return 0; + } + " HAVE_ARM64_CRC32C +) + +add_library(crc32c STATIC EXCLUDE_FROM_ALL + ${PROJECT_SOURCE_DIR}/src/crc32c/src/crc32c.cc + ${PROJECT_SOURCE_DIR}/src/crc32c/src/crc32c_portable.cc +) + +target_compile_definitions(crc32c + PRIVATE + HAVE_BUILTIN_PREFETCH=$ + HAVE_MM_PREFETCH=$ + HAVE_STRONG_GETAUXVAL=$ + HAVE_SSE42=$ + HAVE_ARM64_CRC32C=$ + BYTE_ORDER_BIG_ENDIAN=${WORDS_BIGENDIAN} +) + +target_include_directories(crc32c + PUBLIC + $ +) + +if(HAVE_SSE42) + target_sources(crc32c PRIVATE ${PROJECT_SOURCE_DIR}/src/crc32c/src/crc32c_sse42.cc) + set_property(SOURCE ${PROJECT_SOURCE_DIR}/src/crc32c/src/crc32c_sse42.cc + APPEND PROPERTY COMPILE_OPTIONS ${SSE42_CXXFLAGS} + ) +endif() + +if(HAVE_ARM64_CRC32C) + target_sources(crc32c PRIVATE ${PROJECT_SOURCE_DIR}/src/crc32c/src/crc32c_arm64.cc) + set_property(SOURCE ${PROJECT_SOURCE_DIR}/src/crc32c/src/crc32c_arm64.cc + APPEND PROPERTY COMPILE_OPTIONS ${ARM_CRC_CXXFLAGS} + ) +endif() + +target_link_libraries(crc32c PRIVATE core_interface) diff --git a/cmake/introspection.cmake b/cmake/introspection.cmake new file mode 100644 index 0000000000000..d9865874901a2 --- /dev/null +++ b/cmake/introspection.cmake @@ -0,0 +1,252 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +include(CheckCXXSourceCompiles) +include(CheckCXXSymbolExists) +include(CheckIncludeFileCXX) +include(TestBigEndian) + +test_big_endian(WORDS_BIGENDIAN) + +# The following HAVE_{HEADER}_H variables go to the bitcoin-config.h header. +check_include_file_cxx(byteswap.h HAVE_BYTESWAP_H) +check_include_file_cxx(endian.h HAVE_ENDIAN_H) +check_include_file_cxx(sys/endian.h HAVE_SYS_ENDIAN_H) +check_include_file_cxx(sys/prctl.h HAVE_SYS_PRCTL_H) +check_include_file_cxx(sys/resources.h HAVE_SYS_RESOURCES_H) +check_include_file_cxx(sys/vmmeter.h HAVE_SYS_VMMETER_H) +check_include_file_cxx(vm/vm_param.h HAVE_VM_VM_PARAM_H) + +check_cxx_source_compiles(" + int main() + { + (void) __builtin_clzl(0); + } + " HAVE_BUILTIN_CLZL +) + +check_cxx_source_compiles(" + int main() + { + (void) __builtin_clzll(0); + } + " HAVE_BUILTIN_CLZLL +) + +check_cxx_symbol_exists(O_CLOEXEC "fcntl.h" HAVE_O_CLOEXEC) + +if(HAVE_BYTESWAP_H) + check_cxx_symbol_exists(bswap_16 "byteswap.h" HAVE_DECL_BSWAP_16) + check_cxx_symbol_exists(bswap_32 "byteswap.h" HAVE_DECL_BSWAP_32) + check_cxx_symbol_exists(bswap_64 "byteswap.h" HAVE_DECL_BSWAP_64) +endif() + +if(HAVE_ENDIAN_H OR HAVE_SYS_ENDIAN_H) + if(HAVE_ENDIAN_H) + set(ENDIAN_HEADER "endian.h") + else() + set(ENDIAN_HEADER "sys/endian.h") + endif() + check_cxx_symbol_exists(be16toh ${ENDIAN_HEADER} HAVE_DECL_BE16TOH) + check_cxx_symbol_exists(be32toh ${ENDIAN_HEADER} HAVE_DECL_BE32TOH) + check_cxx_symbol_exists(be64toh ${ENDIAN_HEADER} HAVE_DECL_BE64TOH) + check_cxx_symbol_exists(htobe16 ${ENDIAN_HEADER} HAVE_DECL_HTOBE16) + check_cxx_symbol_exists(htobe32 ${ENDIAN_HEADER} HAVE_DECL_HTOBE32) + check_cxx_symbol_exists(htobe64 ${ENDIAN_HEADER} HAVE_DECL_HTOBE64) + check_cxx_symbol_exists(htole16 ${ENDIAN_HEADER} HAVE_DECL_HTOLE16) + check_cxx_symbol_exists(htole32 ${ENDIAN_HEADER} HAVE_DECL_HTOLE32) + check_cxx_symbol_exists(htole64 ${ENDIAN_HEADER} HAVE_DECL_HTOLE64) + check_cxx_symbol_exists(le16toh ${ENDIAN_HEADER} HAVE_DECL_LE16TOH) + check_cxx_symbol_exists(le32toh ${ENDIAN_HEADER} HAVE_DECL_LE32TOH) + check_cxx_symbol_exists(le64toh ${ENDIAN_HEADER} HAVE_DECL_LE64TOH) +endif() + +check_include_file_cxx(unistd.h HAVE_UNISTD_H) +if(HAVE_UNISTD_H) + check_cxx_symbol_exists(fdatasync "unistd.h" HAVE_FDATASYNC) + check_cxx_symbol_exists(fork "unistd.h" HAVE_DECL_FORK) + check_cxx_symbol_exists(pipe2 "unistd.h" HAVE_DECL_PIPE2) + check_cxx_symbol_exists(setsid "unistd.h" HAVE_DECL_SETSID) +endif() + +check_include_file_cxx(sys/types.h HAVE_SYS_TYPES_H) +check_include_file_cxx(ifaddrs.h HAVE_IFADDRS_H) +if(HAVE_SYS_TYPES_H AND HAVE_IFADDRS_H) + check_cxx_symbol_exists(freeifaddrs "sys/types.h;ifaddrs.h" HAVE_DECL_FREEIFADDRS) + check_cxx_symbol_exists(getifaddrs "sys/types.h;ifaddrs.h" HAVE_DECL_GETIFADDRS) + if(HAVE_DECL_GETIFADDRS AND HAVE_DECL_FREEIFADDRS) + include(TestAppendRequiredLibraries) + test_append_socket_library(core_interface) + endif() +endif() + +include(TestAppendRequiredLibraries) +test_append_atomic_library(core_interface) + +# Check for gmtime_r(), fallback to gmtime_s() if that is unavailable. +# Fail if neither are available. +check_cxx_source_compiles(" + #include + + int main() + { + gmtime_r((const time_t*)nullptr, (struct tm*)nullptr); + } + " HAVE_GMTIME_R +) +if(NOT HAVE_GMTIME_R) + check_cxx_source_compiles(" + #include + + int main() + { + gmtime_s((struct tm*)nullptr, (const time_t*)nullptr); + } + " HAVE_GMTIME_S + ) + if(NOT HAVE_GMTIME_S) + message(FATAL_ERROR "Both gmtime_r and gmtime_s are unavailable.") + endif() +endif() + +check_cxx_symbol_exists(std::system "cstdlib" HAVE_STD_SYSTEM) +check_cxx_symbol_exists(::_wsystem "stdlib.h" HAVE__WSYSTEM) +if(HAVE_STD_SYSTEM OR HAVE__WSYSTEM) + set(HAVE_SYSTEM 1) +endif() + +check_include_file_cxx(string.h HAVE_STRING_H) +if(HAVE_STRING_H) + check_cxx_source_compiles(" + #include + + int main() + { + char buf[100]; + char* p{strerror_r(0, buf, sizeof buf)}; + (void)p; + } + " STRERROR_R_CHAR_P + ) +endif() + +# Check for malloc_info (for memory statistics information in getmemoryinfo). +check_cxx_symbol_exists(malloc_info "malloc.h" HAVE_MALLOC_INFO) + +# Check for mallopt(M_ARENA_MAX) (to set glibc arenas). +check_cxx_source_compiles(" + #include + + int main() + { + mallopt(M_ARENA_MAX, 1); + } + " HAVE_MALLOPT_ARENA_MAX +) + +# Check for posix_fallocate(). +check_cxx_source_compiles(" + // same as in src/util/fs_helpers.cpp + #ifdef __linux__ + #ifdef _POSIX_C_SOURCE + #undef _POSIX_C_SOURCE + #endif + #define _POSIX_C_SOURCE 200112L + #endif // __linux__ + #include + + int main() + { + return posix_fallocate(0, 0, 0); + } + " HAVE_POSIX_FALLOCATE +) + +# Check for strong getauxval() support in the system headers. +check_cxx_source_compiles(" + #include + + int main() + { + getauxval(AT_HWCAP); + } + " HAVE_STRONG_GETAUXVAL +) + +# Check for different ways of gathering OS randomness: +# - Linux getrandom() +check_cxx_source_compiles(" + #include + #include + #include + + int main() + { + syscall(SYS_getrandom, nullptr, 32, 0); + } + " HAVE_SYS_GETRANDOM +) + +# - BSD getentropy() +check_cxx_symbol_exists(getentropy "unistd.h;sys/random.h" HAVE_GETENTROPY_RAND) + +# - BSD sysctl() +check_cxx_source_compiles(" + #include + #include + + #ifdef __linux__ + #error Don't use sysctl on Linux, it's deprecated even when it works + #endif + + int main() + { + sysctl(nullptr, 2, nullptr, nullptr, nullptr, 0); + } + " HAVE_SYSCTL +) + +# - BSD sysctl(KERN_ARND) +check_cxx_source_compiles(" + #include + #include + + #ifdef __linux__ + #error Don't use sysctl on Linux, it's deprecated even when it works + #endif + + int main() + { + static int name[2] = {CTL_KERN, KERN_ARND}; + sysctl(name, 2, nullptr, nullptr, nullptr, 0); + } + " HAVE_SYSCTL_ARND +) + +check_cxx_source_compiles(" + #include + #include + + int main() + { + static_assert(std::is_same::value); + } + " CHAR_EQUALS_INT8 +) + +check_cxx_source_compiles(" + int foo(void) __attribute__((visibility(\"default\"))); + int main(){} + " HAVE_DEFAULT_VISIBILITY_ATTRIBUTE +) + +check_cxx_source_compiles(" + __declspec(dllexport) int foo(void); + int main(){} + " HAVE_DLLEXPORT_ATTRIBUTE +) + +if(CMAKE_HOST_APPLE) + find_program(BREW_COMMAND brew) +endif() diff --git a/cmake/leveldb.cmake b/cmake/leveldb.cmake new file mode 100644 index 0000000000000..8614365edad23 --- /dev/null +++ b/cmake/leveldb.cmake @@ -0,0 +1,94 @@ +# Copyright (c) 2023-present The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://opensource.org/license/mit/. + +# This file is part of the transition from Autotools to CMake. Once CMake +# support has been merged we should switch to using the upstream CMake +# buildsystem. + +include(CheckCXXSymbolExists) +check_cxx_symbol_exists(F_FULLFSYNC "fcntl.h" HAVE_FULLFSYNC) + +add_library(leveldb STATIC EXCLUDE_FROM_ALL + ${PROJECT_SOURCE_DIR}/src/leveldb/db/builder.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/db/c.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/db/db_impl.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/db/db_iter.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/db/dbformat.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/db/dumpfile.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/db/filename.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/db/log_reader.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/db/log_writer.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/db/memtable.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/db/repair.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/db/table_cache.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/db/version_edit.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/db/version_set.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/db/write_batch.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/table/block.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/table/block_builder.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/table/filter_block.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/table/format.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/table/iterator.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/table/merger.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/table/table.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/table/table_builder.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/table/two_level_iterator.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/util/arena.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/util/bloom.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/util/cache.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/util/coding.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/util/comparator.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/util/crc32c.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/util/env.cc + $<$>:${PROJECT_SOURCE_DIR}/src/leveldb/util/env_posix.cc> + $<$:${PROJECT_SOURCE_DIR}/src/leveldb/util/env_windows.cc> + ${PROJECT_SOURCE_DIR}/src/leveldb/util/filter_policy.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/util/hash.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/util/histogram.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/util/logging.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/util/options.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/util/status.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/helpers/memenv/memenv.cc +) + +target_compile_definitions(leveldb + PRIVATE + HAVE_SNAPPY=0 + HAVE_CRC32C=1 + HAVE_FDATASYNC=$ + HAVE_FULLFSYNC=$ + HAVE_O_CLOEXEC=$ + FALLTHROUGH_INTENDED=[[fallthrough]] + LEVELDB_IS_BIG_ENDIAN=${WORDS_BIGENDIAN} + $<$>:LEVELDB_PLATFORM_POSIX> + $<$:LEVELDB_PLATFORM_WINDOWS> + $<$:_UNICODE;UNICODE> + $<$:__USE_MINGW_ANSI_STDIO=1> +) + +target_include_directories(leveldb + PRIVATE + $ + PUBLIC + $ +) + +if(MSVC) + target_compile_options(leveldb + PRIVATE + /wd4244 + /wd4267 + $<$:/wd4722> + ) + target_compile_definitions(leveldb + PRIVATE + _CRT_NONSTDC_NO_DEPRECATE + _CRT_SECURE_NO_WARNINGS + ) +endif() + +#TODO: figure out how to filter out: +# -Wconditional-uninitialized -Werror=conditional-uninitialized -Wsuggest-override -Werror=suggest-override + +target_link_libraries(leveldb PRIVATE core_interface crc32c) diff --git a/cmake/minisketch.cmake b/cmake/minisketch.cmake new file mode 100644 index 0000000000000..63c5743742232 --- /dev/null +++ b/cmake/minisketch.cmake @@ -0,0 +1,85 @@ +# Copyright (c) 2023-present The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://opensource.org/license/mit/. + +# Check for clmul instructions support. +if(MSVC) + set(CLMUL_CXXFLAGS) +else() + set(CLMUL_CXXFLAGS -mpclmul) +endif() +check_cxx_source_compiles_with_flags("${CLMUL_CXXFLAGS}" " + #include + #include + + int main() + { + __m128i a = _mm_cvtsi64_si128((uint64_t)7); + __m128i b = _mm_clmulepi64_si128(a, a, 37); + __m128i c = _mm_srli_epi64(b, 41); + __m128i d = _mm_xor_si128(b, c); + uint64_t e = _mm_cvtsi128_si64(d); + return e == 0; + } + " HAVE_CLMUL +) + +add_library(minisketch_common INTERFACE) +target_compile_definitions(minisketch_common INTERFACE + DISABLE_DEFAULT_FIELDS + ENABLE_FIELD_32 + $<$,$>:HAVE_CLZ> +) +if(MSVC) + target_compile_options(minisketch_common INTERFACE + /wd4060 + /wd4065 + /wd4146 + /wd4244 + /wd4267 + ) +endif() + +if(HAVE_CLMUL) + add_library(minisketch_clmul OBJECT EXCLUDE_FROM_ALL + ${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/clmul_1byte.cpp + ${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/clmul_2bytes.cpp + ${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/clmul_3bytes.cpp + ${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/clmul_4bytes.cpp + ${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/clmul_5bytes.cpp + ${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/clmul_6bytes.cpp + ${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/clmul_7bytes.cpp + ${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/clmul_8bytes.cpp + ) + target_compile_definitions(minisketch_clmul PUBLIC HAVE_CLMUL) + target_compile_options(minisketch_clmul PRIVATE ${CLMUL_CXXFLAGS}) + target_link_libraries(minisketch_clmul + PRIVATE + core_interface + minisketch_common + ) +endif() + +add_library(minisketch STATIC EXCLUDE_FROM_ALL + ${PROJECT_SOURCE_DIR}/src/minisketch/src/minisketch.cpp + ${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/generic_1byte.cpp + ${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/generic_2bytes.cpp + ${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/generic_3bytes.cpp + ${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/generic_4bytes.cpp + ${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/generic_5bytes.cpp + ${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/generic_6bytes.cpp + ${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/generic_7bytes.cpp + ${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/generic_8bytes.cpp +) + +target_include_directories(minisketch + PUBLIC + $ +) + +target_link_libraries(minisketch + PRIVATE + core_interface + minisketch_common + $ +) diff --git a/cmake/module/AddBoostIfNeeded.cmake b/cmake/module/AddBoostIfNeeded.cmake new file mode 100644 index 0000000000000..179887d24bb15 --- /dev/null +++ b/cmake/module/AddBoostIfNeeded.cmake @@ -0,0 +1,52 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +function(add_boost_if_needed) + #[=[ + TODO: Not all targets, which will be added in the future, require + Boost. Therefore, a proper check will be appropriate here. + + Implementation notes: + Although only Boost headers are used to build Bitcoin Core, + we still leverage a standard CMake's approach to handle + dependencies, i.e., the Boost::headers "library". + A command target_link_libraries(target PRIVATE Boost::headers) + will propagate Boost::headers usage requirements to the target. + For Boost::headers such usage requirements is an include + directory and other added INTERFACE properties. + ]=] + + set(Boost_NO_BOOST_CMAKE ON) + find_package(Boost 1.73.0 REQUIRED) + set_target_properties(Boost::headers PROPERTIES IMPORTED_GLOBAL TRUE) + target_compile_definitions(Boost::headers INTERFACE + # We don't use multi_index serialization. + BOOST_MULTI_INDEX_DISABLE_SERIALIZATION + ) + + if(BUILD_TESTS) + include(CheckCXXSourceCompiles) + set(CMAKE_REQUIRED_INCLUDES ${Boost_INCLUDE_DIR}) + check_cxx_source_compiles(" + #define BOOST_TEST_MAIN + #include + " HAVE_BOOST_INCLUDED_UNIT_TEST_H + ) + if(NOT HAVE_BOOST_INCLUDED_UNIT_TEST_H) + message(FATAL_ERROR "Building test_bitcoin executable requested but boost/test/included/unit_test.hpp header not available.") + endif() + + check_cxx_source_compiles(" + #define BOOST_TEST_MAIN + #include + #include + " HAVE_BOOST_UNIT_TEST_H + ) + if(NOT HAVE_BOOST_UNIT_TEST_H) + message(FATAL_ERROR "Building test_bitcoin executable requested but boost/test/unit_test.hpp header not available.") + endif() + endif() + + mark_as_advanced(Boost_INCLUDE_DIR) +endfunction() diff --git a/cmake/module/AddLibeventIfNeeded.cmake b/cmake/module/AddLibeventIfNeeded.cmake new file mode 100644 index 0000000000000..3c8aee8a96edd --- /dev/null +++ b/cmake/module/AddLibeventIfNeeded.cmake @@ -0,0 +1,61 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# Check whether evhttp_connection_get_peer expects const char**. +# See https://github.com/libevent/libevent/commit/a18301a2bb160ff7c3ffaf5b7653c39ffe27b385 +macro(check_evhttp_connection_get_peer target) + include(CMakePushCheckState) + cmake_push_check_state(RESET) + set(CMAKE_REQUIRED_LIBRARIES ${target}) + check_cxx_source_compiles(" + #include + #include + + int main() + { + evhttp_connection* conn = (evhttp_connection*)1; + const char* host; + uint16_t port; + evhttp_connection_get_peer(conn, &host, &port); + } + " HAVE_EVHTTP_CONNECTION_GET_PEER_CONST_CHAR + ) + cmake_pop_check_state() + target_compile_definitions(${target} INTERFACE + $<$:HAVE_EVHTTP_CONNECTION_GET_PEER_CONST_CHAR=1> + ) +endmacro() + +function(add_libevent_if_needed) + # TODO: Not all targets, which will be added in the future, + # require libevent. Therefore, a proper check will be + # appropriate here. + + set(libevent_minimum_version 2.1.8) + + if(MSVC) + find_package(Libevent ${libevent_minimum_version} REQUIRED COMPONENTS extra CONFIG) + check_evhttp_connection_get_peer(libevent::extra) + add_library(libevent::libevent ALIAS libevent::extra) + return() + endif() + + include(CrossPkgConfig) + cross_pkg_check_modules(libevent + REQUIRED IMPORTED_TARGET GLOBAL + libevent>=${libevent_minimum_version} + ) + check_evhttp_connection_get_peer(PkgConfig::libevent) + target_link_libraries(PkgConfig::libevent INTERFACE + $<$:iphlpapi;ssp;ws2_32> + ) + add_library(libevent::libevent ALIAS PkgConfig::libevent) + + if(NOT WIN32) + cross_pkg_check_modules(libevent_pthreads + REQUIRED IMPORTED_TARGET GLOBAL + libevent_pthreads>=${libevent_minimum_version} + ) + endif() +endfunction() diff --git a/cmake/module/AddThreadsIfNeeded.cmake b/cmake/module/AddThreadsIfNeeded.cmake new file mode 100644 index 0000000000000..2939f1a0c6fcb --- /dev/null +++ b/cmake/module/AddThreadsIfNeeded.cmake @@ -0,0 +1,42 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +function(add_threads_if_needed) + # TODO: Not all targets, which will be added in the future, + # require Threads. Therefore, a proper check will be + # appropriate here. + + if(CMAKE_C_COMPILER_LOADED) + message(FATAL_ERROR [=[ + To make FindThreads check C++ language features, C language must be + disabled. This is essential, at least, when cross-compiling for MinGW-w64 + because two different threading models are available. + ]=] ) + endif() + + set(THREADS_PREFER_PTHREAD_FLAG ON) + find_package(Threads REQUIRED) + set_target_properties(Threads::Threads PROPERTIES IMPORTED_GLOBAL TRUE) + + set(thread_local) + if(MINGW) + #[=[ + mingw32's implementation of thread_local has been shown to behave + erroneously under concurrent usage. + See: + - https://github.com/bitcoin/bitcoin/pull/15849 + - https://gist.github.com/jamesob/fe9a872051a88b2025b1aa37bfa98605 + ]=] + elseif(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") + #[=[ + FreeBSD's implementation of thread_local is buggy. + See: + - https://github.com/bitcoin/bitcoin/pull/16059 + - https://groups.google.com/d/msg/bsdmailinglist/22ncTZAbDp4/Dii_pII5AwAJ + ]=] + elseif(THREADLOCAL) + set(thread_local "$<$:HAVE_THREAD_LOCAL>") + endif() + set(THREAD_LOCAL_IF_AVAILABLE "${thread_local}" PARENT_SCOPE) +endfunction() diff --git a/cmake/module/CheckSourceCompilesAndLinks.cmake b/cmake/module/CheckSourceCompilesAndLinks.cmake new file mode 100644 index 0000000000000..88c897d524330 --- /dev/null +++ b/cmake/module/CheckSourceCompilesAndLinks.cmake @@ -0,0 +1,39 @@ +# Copyright (c) 2023-present The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://opensource.org/license/mit/. + +include_guard(GLOBAL) +include(CheckCXXSourceCompiles) +include(CMakePushCheckState) + +# This avoids running the linker. +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + +macro(check_cxx_source_links source) + set(CMAKE_TRY_COMPILE_TARGET_TYPE EXECUTABLE) + check_cxx_source_compiles("${source}" ${ARGN}) + set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) +endmacro() + +macro(check_cxx_source_compiles_with_flags flags source) + cmake_push_check_state(RESET) + set(CMAKE_REQUIRED_FLAGS ${flags}) + list(JOIN CMAKE_REQUIRED_FLAGS " " CMAKE_REQUIRED_FLAGS) + check_cxx_source_compiles("${source}" ${ARGN}) + cmake_pop_check_state() +endmacro() + +macro(check_cxx_source_links_with_flags flags source) + cmake_push_check_state(RESET) + set(CMAKE_REQUIRED_FLAGS ${flags}) + list(JOIN CMAKE_REQUIRED_FLAGS " " CMAKE_REQUIRED_FLAGS) + check_cxx_source_links("${source}" ${ARGN}) + cmake_pop_check_state() +endmacro() + +macro(check_cxx_source_links_with_libs libs source) + cmake_push_check_state(RESET) + set(CMAKE_REQUIRED_LIBRARIES "${libs}") + check_cxx_source_links("${source}" ${ARGN}) + cmake_pop_check_state() +endmacro() diff --git a/cmake/module/CrossPkgConfig.cmake b/cmake/module/CrossPkgConfig.cmake new file mode 100644 index 0000000000000..cbd6f3c27b288 --- /dev/null +++ b/cmake/module/CrossPkgConfig.cmake @@ -0,0 +1,49 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +find_package(PkgConfig REQUIRED) + +function(remove_isystem_from_include_directories_internal target) + #[=[ + A workaround for https://gitlab.kitware.com/cmake/cmake/-/issues/20652. + + When the pkg-config provides CFLAGS with -isystem options, for instance: + + $ pkg-config --cflags-only-I libzmq + -isystem /usr/include/mit-krb5 -I/usr/include/pgm-5.3 -I/usr/include/libxml2 + + an old CMake fails to parse them properly and the INTERFACE_INCLUDE_DIRECTORIES + property contains "-isystem" as a separated element: + + -isystem;/usr/include/mit-krb5;/usr/include/pgm-5.3;/usr/include/libxml2 + + which ends with an error "Imported target includes non-existent path". + + Fixing by removing the "-isystem" element from the INTERFACE_INCLUDE_DIRECTORIES. + ]=] + + get_target_property(include_directories ${target} INTERFACE_INCLUDE_DIRECTORIES) + if(include_directories) + list(REMOVE_ITEM include_directories -isystem) + set_target_properties(${target} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${include_directories}") + endif() +endfunction() + +macro(cross_pkg_check_modules prefix) + if(CMAKE_CROSSCOMPILING) + set(pkg_config_path_saved "$ENV{PKG_CONFIG_PATH}") + set(pkg_config_libdir_saved "$ENV{PKG_CONFIG_LIBDIR}") + set(ENV{PKG_CONFIG_PATH} ${PKG_CONFIG_PATH}) + set(ENV{PKG_CONFIG_LIBDIR} ${PKG_CONFIG_LIBDIR}) + pkg_check_modules(${prefix} ${ARGN}) + set(ENV{PKG_CONFIG_PATH} ${pkg_config_path_saved}) + set(ENV{PKG_CONFIG_LIBDIR} ${pkg_config_libdir_saved}) + else() + pkg_check_modules(${prefix} ${ARGN}) + endif() + + if(CMAKE_VERSION VERSION_LESS 3.17.3 AND TARGET PkgConfig::${prefix}) + remove_isystem_from_include_directories_internal(PkgConfig::${prefix}) + endif() +endmacro() diff --git a/cmake/module/FindBerkeleyDB.cmake b/cmake/module/FindBerkeleyDB.cmake new file mode 100644 index 0000000000000..a858e4235588b --- /dev/null +++ b/cmake/module/FindBerkeleyDB.cmake @@ -0,0 +1,129 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#[=======================================================================[ +FindBerkeleyDB +-------------- + +Finds the Berkeley DB headers and library. + +Imported Targets +^^^^^^^^^^^^^^^^ + +This module provides imported target ``BerkeleyDB::BerkeleyDB``, if +Berkeley DB has been found. + +Result Variables +^^^^^^^^^^^^^^^^ + +This module defines the following variables: + +``BerkeleyDB_FOUND`` + "True" if Berkeley DB found. + +``BerkeleyDB_VERSION`` + The MAJOR.MINOR version of Berkeley DB found. + +#]=======================================================================] + +if(BREW_COMMAND) + # The Homebrew package manager installs the berkeley-db* packages as + # "keg-only", which means they are not symlinked into the default prefix. + # To find such a package, the find_path() and find_library() commands + # need additional path hints that are computed by Homebrew itself. + execute_process( + COMMAND ${BREW_COMMAND} --prefix berkeley-db@4 + OUTPUT_VARIABLE _BerkeleyDB_homebrew_prefix + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE + ) +endif() + +find_path(BerkeleyDB_INCLUDE_DIR + NAMES db_cxx.h + HINTS ${_BerkeleyDB_homebrew_prefix}/include + PATH_SUFFIXES 4.8 48 4 db4 5.3 5 db5 +) +mark_as_advanced(BerkeleyDB_INCLUDE_DIR) +unset(_BerkeleyDB_homebrew_prefix) + +if(NOT BerkeleyDB_LIBRARY) + if(VCPKG_TARGET_TRIPLET) + # The vcpkg package manager installs the berkeleydb package with the same name + # of release and debug libraries. Therefore, the default search paths set by + # vcpkg's toolchain file cannot be used to search libraries as the debug one + # will always be found. + set(CMAKE_FIND_USE_CMAKE_PATH FALSE) + endif() + + get_filename_component(_BerkeleyDB_lib_hint "${BerkeleyDB_INCLUDE_DIR}" DIRECTORY) + + find_library(BerkeleyDB_LIBRARY_RELEASE + NAMES db_cxx-4.8 db4_cxx db48 db_cxx-5.3 db_cxx-5 db_cxx libdb48 + NAMES_PER_DIR + HINTS ${_BerkeleyDB_lib_hint} + PATH_SUFFIXES lib + ) + mark_as_advanced(BerkeleyDB_LIBRARY_RELEASE) + + find_library(BerkeleyDB_LIBRARY_DEBUG + NAMES db_cxx-4.8 db4_cxx db48 db_cxx-5.3 db_cxx-5 db_cxx libdb48 + NAMES_PER_DIR + HINTS ${_BerkeleyDB_lib_hint} + PATH_SUFFIXES debug/lib + ) + mark_as_advanced(BerkeleyDB_LIBRARY_DEBUG) + + unset(_BerkeleyDB_lib_hint) + unset(CMAKE_FIND_USE_CMAKE_PATH) + + include(SelectLibraryConfigurations) + select_library_configurations(BerkeleyDB) + # The select_library_configurations() command sets BerkeleyDB_FOUND, but we + # want the one from the find_package_handle_standard_args() command below. + unset(BerkeleyDB_FOUND) +endif() + +if(BerkeleyDB_INCLUDE_DIR) + file(STRINGS "${BerkeleyDB_INCLUDE_DIR}/db.h" _BerkeleyDB_version_strings REGEX "^#define[\t ]+DB_VERSION_(MAJOR|MINOR|PATCH)[ \t]+[0-9]+.*") + string(REGEX REPLACE ".*#define[\t ]+DB_VERSION_MAJOR[ \t]+([0-9]+).*" "\\1" _BerkeleyDB_version_major "${_BerkeleyDB_version_strings}") + string(REGEX REPLACE ".*#define[\t ]+DB_VERSION_MINOR[ \t]+([0-9]+).*" "\\1" _BerkeleyDB_version_minor "${_BerkeleyDB_version_strings}") + string(REGEX REPLACE ".*#define[\t ]+DB_VERSION_PATCH[ \t]+([0-9]+).*" "\\1" _BerkeleyDB_version_patch "${_BerkeleyDB_version_strings}") + unset(_BerkeleyDB_version_strings) + # The MAJOR.MINOR.PATCH version will be logged in the following find_package_handle_standard_args() command. + set(_BerkeleyDB_full_version ${_BerkeleyDB_version_major}.${_BerkeleyDB_version_minor}.${_BerkeleyDB_version_patch}) + set(BerkeleyDB_VERSION ${_BerkeleyDB_version_major}.${_BerkeleyDB_version_minor}) + unset(_BerkeleyDB_version_major) + unset(_BerkeleyDB_version_minor) + unset(_BerkeleyDB_version_patch) +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(BerkeleyDB + REQUIRED_VARS BerkeleyDB_LIBRARY BerkeleyDB_INCLUDE_DIR + VERSION_VAR _BerkeleyDB_full_version +) +unset(_BerkeleyDB_full_version) + +if(BerkeleyDB_FOUND AND NOT TARGET BerkeleyDB::BerkeleyDB) + add_library(BerkeleyDB::BerkeleyDB UNKNOWN IMPORTED) + set_target_properties(BerkeleyDB::BerkeleyDB PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${BerkeleyDB_INCLUDE_DIR}" + ) + if(BerkeleyDB_LIBRARY_RELEASE) + set_property(TARGET BerkeleyDB::BerkeleyDB APPEND PROPERTY + IMPORTED_CONFIGURATIONS RELEASE + ) + set_target_properties(BerkeleyDB::BerkeleyDB PROPERTIES + IMPORTED_LOCATION_RELEASE "${BerkeleyDB_LIBRARY_RELEASE}" + ) + endif() + if(BerkeleyDB_LIBRARY_DEBUG) + set_property(TARGET BerkeleyDB::BerkeleyDB APPEND PROPERTY + IMPORTED_CONFIGURATIONS DEBUG) + set_target_properties(BerkeleyDB::BerkeleyDB PROPERTIES + IMPORTED_LOCATION_DEBUG "${BerkeleyDB_LIBRARY_DEBUG}" + ) + endif() +endif() diff --git a/cmake/module/FindMiniUPnPc.cmake b/cmake/module/FindMiniUPnPc.cmake new file mode 100644 index 0000000000000..dd3a223104b1c --- /dev/null +++ b/cmake/module/FindMiniUPnPc.cmake @@ -0,0 +1,84 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +if(NOT MSVC) + include(CrossPkgConfig) + cross_pkg_check_modules(PC_MiniUPnPc QUIET miniupnpc) +endif() + +find_path(MiniUPnPc_INCLUDE_DIR + NAMES miniupnpc/miniupnpc.h + PATHS ${PC_MiniUPnPc_INCLUDE_DIRS} +) + +if(MiniUPnPc_INCLUDE_DIR) + file( + STRINGS "${MiniUPnPc_INCLUDE_DIR}/miniupnpc/miniupnpc.h" version_strings + REGEX "^#define[\t ]+MINIUPNPC_API_VERSION[\t ]+[0-9]+" + ) + string(REGEX REPLACE "^#define[\t ]+MINIUPNPC_API_VERSION[\t ]+([0-9]+)" "\\1" MiniUPnPc_API_VERSION "${version_strings}") + + # The minimum supported miniUPnPc API version is set to 17. This excludes + # versions with known vulnerabilities. + if(MiniUPnPc_API_VERSION GREATER_EQUAL 17) + set(MiniUPnPc_API_VERSION_OK TRUE) + endif() +endif() + +if(MSVC) + cmake_path(GET MiniUPnPc_INCLUDE_DIR PARENT_PATH MiniUPnPc_IMPORTED_PATH) + find_library(MiniUPnPc_LIBRARY_DEBUG + NAMES miniupnpc PATHS ${MiniUPnPc_IMPORTED_PATH}/debug/lib + NO_DEFAULT_PATH + ) + find_library(MiniUPnPc_LIBRARY_RELEASE + NAMES miniupnpc PATHS ${MiniUPnPc_IMPORTED_PATH}/lib + NO_DEFAULT_PATH + ) + set(MiniUPnPc_required MiniUPnPc_IMPORTED_PATH) +else() + find_library(MiniUPnPc_LIBRARY + NAMES miniupnpc + PATHS ${PC_MiniUPnPc_LIBRARY_DIRS} + ) + set(MiniUPnPc_required MiniUPnPc_LIBRARY) +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(MiniUPnPc + REQUIRED_VARS ${MiniUPnPc_required} MiniUPnPc_INCLUDE_DIR MiniUPnPc_API_VERSION_OK +) + +if(MiniUPnPc_FOUND AND NOT TARGET MiniUPnPc::MiniUPnPc) + add_library(MiniUPnPc::MiniUPnPc UNKNOWN IMPORTED) + set_target_properties(MiniUPnPc::MiniUPnPc PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${MiniUPnPc_INCLUDE_DIR}" + ) + if(MSVC) + if(MiniUPnPc_LIBRARY_DEBUG) + set_property(TARGET MiniUPnPc::MiniUPnPc APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG) + set_target_properties(MiniUPnPc::MiniUPnPc PROPERTIES + IMPORTED_LOCATION_DEBUG "${MiniUPnPc_LIBRARY_DEBUG}" + ) + endif() + if(MiniUPnPc_LIBRARY_RELEASE) + set_property(TARGET MiniUPnPc::MiniUPnPc APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) + set_target_properties(MiniUPnPc::MiniUPnPc PROPERTIES + IMPORTED_LOCATION_RELEASE "${MiniUPnPc_LIBRARY_RELEASE}" + ) + endif() + else() + set_target_properties(MiniUPnPc::MiniUPnPc PROPERTIES + IMPORTED_LOCATION "${MiniUPnPc_LIBRARY}" + ) + endif() + set_property(TARGET MiniUPnPc::MiniUPnPc PROPERTY + INTERFACE_COMPILE_DEFINITIONS USE_UPNP=1 $<$:MINIUPNP_STATICLIB> + ) +endif() + +mark_as_advanced( + MiniUPnPc_INCLUDE_DIR + MiniUPnPc_LIBRARY +) diff --git a/cmake/module/FindNATPMP.cmake b/cmake/module/FindNATPMP.cmake new file mode 100644 index 0000000000000..973fb9b0d06cd --- /dev/null +++ b/cmake/module/FindNATPMP.cmake @@ -0,0 +1,32 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +find_path(NATPMP_INCLUDE_DIR + NAMES natpmp.h +) + +find_library(NATPMP_LIBRARY + NAMES natpmp +) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(NATPMP + REQUIRED_VARS NATPMP_LIBRARY NATPMP_INCLUDE_DIR +) + +if(NATPMP_FOUND AND NOT TARGET NATPMP::NATPMP) + add_library(NATPMP::NATPMP UNKNOWN IMPORTED) + set_target_properties(NATPMP::NATPMP PROPERTIES + IMPORTED_LOCATION "${NATPMP_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${NATPMP_INCLUDE_DIR}" + ) + set_property(TARGET NATPMP::NATPMP PROPERTY + INTERFACE_COMPILE_DEFINITIONS USE_NATPMP=1 $<$:NATPMP_STATICLIB> + ) +endif() + +mark_as_advanced( + NATPMP_INCLUDE_DIR + NATPMP_LIBRARY +) diff --git a/cmake/module/GenerateHeaders.cmake b/cmake/module/GenerateHeaders.cmake new file mode 100644 index 0000000000000..d8714771b4f6d --- /dev/null +++ b/cmake/module/GenerateHeaders.cmake @@ -0,0 +1,21 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +function(generate_header_from_json json_source_relpath) + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${json_source_relpath}.h + COMMAND ${CMAKE_COMMAND} -DJSON_SOURCE_PATH=${CMAKE_CURRENT_SOURCE_DIR}/${json_source_relpath} -DHEADER_PATH=${CMAKE_CURRENT_BINARY_DIR}/${json_source_relpath}.h -P ${CMAKE_SOURCE_DIR}/cmake/script/GenerateHeaderFromJson.cmake + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${json_source_relpath} ${CMAKE_SOURCE_DIR}/cmake/script/GenerateHeaderFromJson.cmake + VERBATIM + ) +endfunction() + +function(generate_header_from_raw raw_source_relpath) + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${raw_source_relpath}.h + COMMAND ${CMAKE_COMMAND} -DRAW_SOURCE_PATH=${CMAKE_CURRENT_SOURCE_DIR}/${raw_source_relpath} -DHEADER_PATH=${CMAKE_CURRENT_BINARY_DIR}/${raw_source_relpath}.h -P ${CMAKE_SOURCE_DIR}/cmake/script/GenerateHeaderFromRaw.cmake + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${raw_source_relpath} ${CMAKE_SOURCE_DIR}/cmake/script/GenerateHeaderFromRaw.cmake + VERBATIM + ) +endfunction() diff --git a/cmake/module/GetTargetInterface.cmake b/cmake/module/GetTargetInterface.cmake new file mode 100644 index 0000000000000..f55354fd61b2a --- /dev/null +++ b/cmake/module/GetTargetInterface.cmake @@ -0,0 +1,28 @@ +# Copyright (c) 2023-present The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://opensource.org/license/mit/. + +include_guard(GLOBAL) + +# Get target's interface properties recursively. +function(get_target_interface var target property) + get_target_property(result ${target} INTERFACE_${property}) + if(result) + string(GENEX_STRIP "${result}" result) + list(JOIN result " " result) + else() + set(result) + endif() + + get_target_property(dependencies ${target} INTERFACE_LINK_LIBRARIES) + if(dependencies) + foreach(dependency IN LISTS dependencies) + if(TARGET ${dependency}) + get_target_interface(dep_result ${dependency} ${property}) + string(STRIP "${result} ${dep_result}" result) + endif() + endforeach() + endif() + + set(${var} "${result}" PARENT_SCOPE) +endfunction() diff --git a/cmake/module/Maintenance.cmake b/cmake/module/Maintenance.cmake new file mode 100644 index 0000000000000..3f253b5aae335 --- /dev/null +++ b/cmake/module/Maintenance.cmake @@ -0,0 +1,74 @@ +# Copyright (c) 2023-present The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://opensource.org/license/mit/. + +include_guard(GLOBAL) + +function(setup_split_debug_script) + if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") + set(OBJCOPY ${CMAKE_OBJCOPY}) + set(STRIP ${CMAKE_STRIP}) + if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.20) + configure_file( + contrib/devtools/split-debug.sh.in split-debug.sh + FILE_PERMISSIONS OWNER_READ OWNER_EXECUTE + GROUP_READ GROUP_EXECUTE + WORLD_READ + @ONLY + ) + else() + configure_file( + contrib/devtools/split-debug.sh.in split-debug.sh + @ONLY + ) + endif() + endif() +endfunction() + +function(add_maintenance_targets) + if(NOT PYTHON_COMMAND) + return() + endif() + + if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + set(exe_format MACHO) + elseif(WIN32) + set(exe_format PE) + else() + set(exe_format ELF) + endif() + if(CMAKE_CROSSCOMPILING) + list(JOIN DEPENDS_C_COMPILER_WITH_LAUNCHER " " c_compiler_command) + else() + set(c_compiler_command ${CMAKE_C_COMPILER}) + endif() + add_custom_target(test-security-check + COMMAND ${CMAKE_COMMAND} -E env CC=${c_compiler_command} CFLAGS=${CMAKE_C_FLAGS} LDFLAGS=${CMAKE_EXE_LINKER_FLAGS} ${PYTHON_COMMAND} ${CMAKE_SOURCE_DIR}/contrib/devtools/test-security-check.py TestSecurityChecks.test_${exe_format} + COMMAND ${CMAKE_COMMAND} -E env CC=${c_compiler_command} CFLAGS=${CMAKE_C_FLAGS} LDFLAGS=${CMAKE_EXE_LINKER_FLAGS} ${PYTHON_COMMAND} ${CMAKE_SOURCE_DIR}/contrib/devtools/test-symbol-check.py TestSymbolChecks.test_${exe_format} + VERBATIM + ) + + foreach(target IN ITEMS bitcoind bitcoin-cli bitcoin-tx bitcoin-util bitcoin-wallet test_bitcoin bench_bitcoin) + if(TARGET ${target}) + # Not using the TARGET_FILE generator expression because it creates excessive + # target-level dependencies in the following custom targets. + list(APPEND executables $/$) + endif() + endforeach() + + add_custom_target(check-symbols + COMMAND ${CMAKE_COMMAND} -E echo "Running symbol and dynamic library checks..." + COMMAND ${PYTHON_COMMAND} ${CMAKE_SOURCE_DIR}/contrib/devtools/symbol-check.py ${executables} + VERBATIM + ) + + if(HARDENING) + add_custom_target(check-security + COMMAND ${CMAKE_COMMAND} -E echo "Checking binary security..." + COMMAND ${PYTHON_COMMAND} ${CMAKE_SOURCE_DIR}/contrib/devtools/security-check.py ${executables} + VERBATIM + ) + else() + add_custom_target(check-security) + endif() +endfunction() diff --git a/cmake/module/ProcessConfigurations.cmake b/cmake/module/ProcessConfigurations.cmake new file mode 100644 index 0000000000000..c8cd0635220d9 --- /dev/null +++ b/cmake/module/ProcessConfigurations.cmake @@ -0,0 +1,133 @@ +# Copyright (c) 2023-present The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://opensource.org/license/mit/. + +function(get_all_configs output) + get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) + if(is_multi_config) + set(all_configs ${CMAKE_CONFIGURATION_TYPES}) + else() + get_property(all_configs CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS) + if(NOT all_configs) + # See https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#default-and-custom-configurations + set(all_configs Debug Release RelWithDebInfo MinSizeRel) + endif() + endif() + set(${output} "${all_configs}" PARENT_SCOPE) +endfunction() + + +#[=[ +Set the default build configuration. + +See: https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#build-configurations. + +On single-configuration generators, this function sets the CMAKE_BUILD_TYPE variable to +the default build configuration, which can be overridden by the user at configure time if needed. + +On multi-configuration generators, this function rearranges the CMAKE_CONFIGURATION_TYPES list, +ensuring that the default build configuration appears first while maintaining the order of the +remaining configurations. The user can choose a build configuration at build time. +]=] +function(set_default_config config) + get_all_configs(all_configs) + if(NOT ${config} IN_LIST all_configs) + message(FATAL_ERROR "The default config is \"${config}\", but must be one of ${all_configs}.") + endif() + + list(REMOVE_ITEM all_configs ${config}) + list(PREPEND all_configs ${config}) + + get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) + if(is_multi_config) + get_property(help_string CACHE CMAKE_CONFIGURATION_TYPES PROPERTY HELPSTRING) + set(CMAKE_CONFIGURATION_TYPES "${all_configs}" CACHE STRING "${help_string}" FORCE) + else() + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY + STRINGS "${all_configs}" + ) + if(NOT CMAKE_BUILD_TYPE) + message(STATUS "Setting build type to \"${config}\" as none was specified") + get_property(help_string CACHE CMAKE_BUILD_TYPE PROPERTY HELPSTRING) + set(CMAKE_BUILD_TYPE "${config}" CACHE STRING "${help_string}" FORCE) + endif() + endif() +endfunction() + +function(remove_c_flag_from_all_configs flag) + get_all_configs(all_configs) + foreach(config IN LISTS all_configs) + string(TOUPPER "${config}" config_uppercase) + set(flags "${CMAKE_C_FLAGS_${config_uppercase}}") + separate_arguments(flags) + list(FILTER flags EXCLUDE REGEX "${flag}") + list(JOIN flags " " new_flags) + set(CMAKE_C_FLAGS_${config_uppercase} "${new_flags}" PARENT_SCOPE) + endforeach() +endfunction() + +function(remove_cxx_flag_from_all_configs flag) + get_all_configs(all_configs) + foreach(config IN LISTS all_configs) + string(TOUPPER "${config}" config_uppercase) + set(flags "${CMAKE_CXX_FLAGS_${config_uppercase}}") + separate_arguments(flags) + list(FILTER flags EXCLUDE REGEX "${flag}") + list(JOIN flags " " new_flags) + set(CMAKE_CXX_FLAGS_${config_uppercase} "${new_flags}" PARENT_SCOPE) + endforeach() +endfunction() + +function(replace_c_flag_in_config config old_flag new_flag) + string(TOUPPER "${config}" config_uppercase) + string(REGEX REPLACE "(^| )${old_flag}( |$)" "\\1${new_flag}\\2" new_flags "${CMAKE_C_FLAGS_${config_uppercase}}") + set(CMAKE_C_FLAGS_${config_uppercase} "${new_flags}" PARENT_SCOPE) +endfunction() + +function(replace_cxx_flag_in_config config old_flag new_flag) + string(TOUPPER "${config}" config_uppercase) + string(REGEX REPLACE "(^| )${old_flag}( |$)" "\\1${new_flag}\\2" new_flags "${CMAKE_CXX_FLAGS_${config_uppercase}}") + set(CMAKE_CXX_FLAGS_${config_uppercase} "${new_flags}" PARENT_SCOPE) +endfunction() + +function(separate_by_configs options) + list(JOIN ${options} " " ${options}_ALL) + string(GENEX_STRIP "${${options}_ALL}" ${options}_ALL) + string(STRIP "${${options}_ALL}" ${options}_ALL) + set(${options}_ALL "${${options}_ALL}" PARENT_SCOPE) + + get_all_configs(all_configs) + foreach(config IN LISTS all_configs) + string(REGEX MATCHALL "\\$<\\$:[^<>\n]*>" match "${${options}}") + list(JOIN match " " match) + string(REPLACE "\$<\$:" "" match "${match}") + string(REPLACE ">" "" match "${match}") + string(TOUPPER "${config}" conf_upper) + set(${options}_${conf_upper} "${match}" PARENT_SCOPE) + endforeach() +endfunction() + +function(print_config_flags) + macro(print_flags config) + string(TOUPPER "${config}" config_uppercase) + message(" - Preprocessor defined macros ........ ${definitions_${config_uppercase}}") + message(" - CFLAGS ............................. ${CMAKE_C_FLAGS_${config_uppercase}}") + message(" - CXXFLAGS ........................... ${CMAKE_CXX_FLAGS_${config_uppercase}}") + message(" - LDFLAGS for executables ............ ${CMAKE_EXE_LINKER_FLAGS_${config_uppercase}}") + message(" - LDFLAGS for shared libraries ....... ${CMAKE_SHARED_LINKER_FLAGS_${config_uppercase}}") + endmacro() + + get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) + if(is_multi_config) + list(JOIN CMAKE_CONFIGURATION_TYPES " " configs) + message("Available build types (configurations) ${configs}") + foreach(config IN LISTS CMAKE_CONFIGURATION_TYPES) + message("'${config}' build type (configuration):") + print_flags(${config}) + endforeach() + else() + message("Build type (configuration):") + message(" - CMAKE_BUILD_TYPE ................... ${CMAKE_BUILD_TYPE}") + print_flags(${CMAKE_BUILD_TYPE}) + endif() +endfunction() diff --git a/cmake/module/TestAppendRequiredLibraries.cmake b/cmake/module/TestAppendRequiredLibraries.cmake new file mode 100644 index 0000000000000..d15a93e6c7655 --- /dev/null +++ b/cmake/module/TestAppendRequiredLibraries.cmake @@ -0,0 +1,87 @@ +# Copyright (c) 2023-present The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://opensource.org/license/mit/. + +include_guard(GLOBAL) + +# Illumos/SmartOS requires linking with -lsocket if +# using getifaddrs & freeifaddrs. +# See: https://github.com/bitcoin/bitcoin/pull/21486 +function(test_append_socket_library target) + if (NOT TARGET ${target}) + message(FATAL_ERROR "test_append_socket_library() called with non-existent target \"${target}\".") + endif() + + set(check_socket_source " + #include + #include + + int main() { + struct ifaddrs* ifaddr; + getifaddrs(&ifaddr); + freeifaddrs(ifaddr); + } + ") + + include(CheckSourceCompilesAndLinks) + check_cxx_source_links("${check_socket_source}" IFADDR_LINKS_WITHOUT_LIBSOCKET) + if(IFADDR_LINKS_WITHOUT_LIBSOCKET) + return() + endif() + + check_cxx_source_links_with_libs(socket "${check_socket_source}" IFADDR_NEEDS_LINK_TO_LIBSOCKET) + if(IFADDR_NEEDS_LINK_TO_LIBSOCKET) + target_link_libraries(${target} INTERFACE socket) + else() + message(FATAL_ERROR "Cannot figure out how to use getifaddrs/freeifaddrs.") + endif() +endfunction() + +# Clang, when building for 32-bit, +# and linking against libstdc++, requires linking with +# -latomic if using the C++ atomic library. +# Can be tested with: clang++ test.cpp -m32 +# +# Sourced from http://bugs.debian.org/797228 +function(test_append_atomic_library target) + if (NOT TARGET ${target}) + message(FATAL_ERROR "test_append_atomic_library() called with non-existent target \"${target}\".") + endif() + + set(check_atomic_source " + #include + #include + #include + + using namespace std::chrono_literals; + + int main() { + std::atomic lock{true}; + lock.exchange(false); + + std::atomic t{0s}; + t.store(2s); + auto t1 = t.load(); + t.compare_exchange_strong(t1, 3s); + + std::atomic a{}; + + int64_t v = 5; + int64_t r = a.fetch_add(v); + return static_cast(r); + } + ") + + include(CheckSourceCompilesAndLinks) + check_cxx_source_links("${check_atomic_source}" STD_ATOMIC_LINKS_WITHOUT_LIBATOMIC) + if(STD_ATOMIC_LINKS_WITHOUT_LIBATOMIC) + return() + endif() + + check_cxx_source_links_with_libs(atomic "${check_atomic_source}" STD_ATOMIC_NEEDS_LINK_TO_LIBATOMIC) + if(STD_ATOMIC_NEEDS_LINK_TO_LIBATOMIC) + target_link_libraries(${target} INTERFACE atomic) + else() + message(FATAL_ERROR "Cannot figure out how to use std::atomic.") + endif() +endfunction() diff --git a/cmake/module/TryAppendCXXFlags.cmake b/cmake/module/TryAppendCXXFlags.cmake new file mode 100644 index 0000000000000..b14e00d9acb53 --- /dev/null +++ b/cmake/module/TryAppendCXXFlags.cmake @@ -0,0 +1,107 @@ +# Copyright (c) 2023-present The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://opensource.org/license/mit/. + +include_guard(GLOBAL) +include(CheckCXXSourceCompiles) + +#[=[ +Usage examples: + + try_append_cxx_flags("-Wformat -Wformat-security" VAR warn_cxx_flags) + + + try_append_cxx_flags("-Wsuggest-override" VAR warn_cxx_flags + SOURCE "struct A { virtual void f(); }; struct B : A { void f() final; };" + ) + + + try_append_cxx_flags("-fsanitize=${SANITIZERS}" TARGET core_interface + RESULT_VAR cxx_supports_sanitizers + ) + if(NOT cxx_supports_sanitizers) + message(FATAL_ERROR "Compiler did not accept requested flags.") + endif() + + + try_append_cxx_flags("-Wunused-parameter" TARGET core_interface + IF_CHECK_PASSED "-Wno-unused-parameter" + ) + + + try_append_cxx_flags("-Werror=return-type" TARGET core_interface + IF_CHECK_FAILED "-Wno-error=return-type" + SOURCE "#include \nint f(){ assert(false); }" + ) + + +In configuration output, this function prints a string by the following pattern: + + -- Performing Test CXX_SUPPORTS_[flags] + -- Performing Test CXX_SUPPORTS_[flags] - Success + +]=] +function(try_append_cxx_flags flags) + cmake_parse_arguments(PARSE_ARGV 1 + TACXXF # prefix + "" # options + "TARGET;VAR;SOURCE;RESULT_VAR" # one_value_keywords + "IF_CHECK_PASSED;IF_CHECK_FAILED" # multi_value_keywords + ) + + string(MAKE_C_IDENTIFIER "${flags}" result) + string(TOUPPER "${result}" result) + string(PREPEND result CXX_SUPPORTS_) + + set(source "int main() { return 0; }") + if(DEFINED TACXXF_SOURCE AND NOT TACXXF_SOURCE STREQUAL source) + set(source "${TACXXF_SOURCE}") + string(SHA256 source_hash "${source}") + string(SUBSTRING ${source_hash} 0 4 source_hash_head) + string(APPEND result _${source_hash_head}) + endif() + + # This avoids running a linker. + set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + set(CMAKE_REQUIRED_FLAGS "${flags} ${working_compiler_werror_flag}") + check_cxx_source_compiles("${source}" ${result}) + + if(${result}) + if(DEFINED TACXXF_IF_CHECK_PASSED) + if(DEFINED TACXXF_TARGET) + target_compile_options(${TACXXF_TARGET} INTERFACE ${TACXXF_IF_CHECK_PASSED}) + endif() + if(DEFINED TACXXF_VAR) + string(STRIP "${${TACXXF_VAR}} ${TACXXF_IF_CHECK_PASSED}" ${TACXXF_VAR}) + endif() + else() + if(DEFINED TACXXF_TARGET) + target_compile_options(${TACXXF_TARGET} INTERFACE ${flags}) + endif() + if(DEFINED TACXXF_VAR) + string(STRIP "${${TACXXF_VAR}} ${flags}" ${TACXXF_VAR}) + endif() + endif() + elseif(DEFINED TACXXF_IF_CHECK_FAILED) + if(DEFINED TACXXF_TARGET) + target_compile_options(${TACXXF_TARGET} INTERFACE ${TACXXF_IF_CHECK_FAILED}) + endif() + if(DEFINED TACXXF_VAR) + string(STRIP "${${TACXXF_VAR}} ${TACXXF_IF_CHECK_FAILED}" ${TACXXF_VAR}) + endif() + endif() + + if(DEFINED TACXXF_VAR) + set(${TACXXF_VAR} "${${TACXXF_VAR}}" PARENT_SCOPE) + endif() + + if(DEFINED TACXXF_RESULT_VAR) + set(${TACXXF_RESULT_VAR} "${${result}}" PARENT_SCOPE) + endif() +endfunction() + +if(MSVC) + try_append_cxx_flags("/WX /options:strict" VAR working_compiler_werror_flag) +else() + try_append_cxx_flags("-Werror" VAR working_compiler_werror_flag) +endif() diff --git a/cmake/module/TryAppendLinkerFlag.cmake b/cmake/module/TryAppendLinkerFlag.cmake new file mode 100644 index 0000000000000..749120d4458dd --- /dev/null +++ b/cmake/module/TryAppendLinkerFlag.cmake @@ -0,0 +1,85 @@ +# Copyright (c) 2023-present The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://opensource.org/license/mit/. + +include_guard(GLOBAL) +include(CheckCXXSourceCompiles) + +#[=[ +Usage example: + + try_append_linker_flag("-Wl,--major-subsystem-version,6" TARGET core_interface) + + +In configuration output, this function prints a string by the following pattern: + + -- Performing Test LINKER_SUPPORTS_[flag] + -- Performing Test LINKER_SUPPORTS_[flag] - Success + +]=] +function(try_append_linker_flag flag) + cmake_parse_arguments(PARSE_ARGV 1 + TALF # prefix + "" # options + "TARGET;VAR;SOURCE;RESULT_VAR" # one_value_keywords + "IF_CHECK_PASSED;IF_CHECK_FAILED" # multi_value_keywords + ) + + string(MAKE_C_IDENTIFIER "${flag}" result) + string(TOUPPER "${result}" result) + string(PREPEND result LINKER_SUPPORTS_) + + set(source "int main() { return 0; }") + if(DEFINED TALF_SOURCE AND NOT TALF_SOURCE STREQUAL source) + set(source "${TALF_SOURCE}") + string(SHA256 source_hash "${source}") + string(SUBSTRING ${source_hash} 0 4 source_hash_head) + string(APPEND result _${source_hash_head}) + endif() + + # This forces running a linker. + set(CMAKE_TRY_COMPILE_TARGET_TYPE EXECUTABLE) + set(CMAKE_REQUIRED_LINK_OPTIONS ${flag} ${working_linker_werror_flag}) + check_cxx_source_compiles("${source}" ${result}) + + if(${result}) + if(DEFINED TALF_IF_CHECK_PASSED) + if(DEFINED TALF_TARGET) + target_link_options(${TALF_TARGET} INTERFACE ${TALF_IF_CHECK_PASSED}) + endif() + if(DEFINED TALF_VAR) + string(STRIP "${${TALF_VAR}} ${TALF_IF_CHECK_PASSED}" ${TALF_VAR}) + endif() + else() + if(DEFINED TALF_TARGET) + target_link_options(${TALF_TARGET} INTERFACE ${flag}) + endif() + if(DEFINED TALF_VAR) + string(STRIP "${${TALF_VAR}} ${flag}" ${TALF_VAR}) + endif() + endif() + elseif(DEFINED TALF_IF_CHECK_FAILED) + if(DEFINED TALF_TARGET) + target_link_options(${TALF_TARGET} INTERFACE ${TACXXF_IF_CHECK_FAILED}) + endif() + if(DEFINED TALF_VAR) + string(STRIP "${${TALF_VAR}} ${TACXXF_IF_CHECK_FAILED}" ${TALF_VAR}) + endif() + endif() + + if(DEFINED TALF_VAR) + set(${TALF_VAR} "${${TALF_VAR}}" PARENT_SCOPE) + endif() + + if(DEFINED TALF_RESULT_VAR) + set(${TALF_RESULT_VAR} "${${result}}" PARENT_SCOPE) + endif() +endfunction() + +if(MSVC) + try_append_linker_flag("/WX" VAR working_linker_werror_flag) +elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + try_append_linker_flag("-Wl,-fatal_warnings" VAR working_linker_werror_flag) +else() + try_append_linker_flag("-Wl,--fatal-warnings" VAR working_linker_werror_flag) +endif() diff --git a/cmake/module/WarnAboutGlobalProperties.cmake b/cmake/module/WarnAboutGlobalProperties.cmake new file mode 100644 index 0000000000000..1cf3a6be86742 --- /dev/null +++ b/cmake/module/WarnAboutGlobalProperties.cmake @@ -0,0 +1,35 @@ +# Copyright (c) 2023-present The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://opensource.org/license/mit/. + +include_guard(GLOBAL) + +# Avoid the directory-wide add_definitions() and add_compile_definitions() commands. +# Instead, prefer the target-specific target_compile_definitions() one. +get_directory_property(global_compile_definitions COMPILE_DEFINITIONS) +if(global_compile_definitions) + message(AUTHOR_WARNING "The directory's COMPILE_DEFINITIONS property is not empty: ${global_compile_definitions}") +endif() + +# Avoid the directory-wide add_compile_options() command. +# Instead, prefer the target-specific target_compile_options() one. +get_directory_property(global_compile_options COMPILE_OPTIONS) +if(global_compile_options) + message(AUTHOR_WARNING "The directory's COMPILE_OPTIONS property is not empty: ${global_compile_options}") +endif() + +# Avoid the directory-wide add_link_options() command. +# Instead, prefer the target-specific target_link_options() one. +get_directory_property(global_link_options LINK_OPTIONS) +if(global_link_options) + message(AUTHOR_WARNING "The directory's LINK_OPTIONS property is not empty: ${global_link_options}") +endif() + +# Avoid the directory-wide link_libraries() command. +# Instead, prefer the target-specific target_link_libraries() one. +file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/dummy_cxx_source.cpp "#error") +add_library(check_loose_linked_libraries OBJECT EXCLUDE_FROM_ALL ${CMAKE_CURRENT_BINARY_DIR}/dummy_cxx_source.cpp) +get_target_property(global_linked_libraries check_loose_linked_libraries LINK_LIBRARIES) +if(global_linked_libraries) + message(AUTHOR_WARNING "There are libraries linked with `link_libraries` commands: ${global_linked_libraries}") +endif() diff --git a/cmake/optional.cmake b/cmake/optional.cmake new file mode 100644 index 0000000000000..76ebe4af70e28 --- /dev/null +++ b/cmake/optional.cmake @@ -0,0 +1,120 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# Optional features and packages. + +if(CCACHE) + find_program(CCACHE_COMMAND ccache) + mark_as_advanced(CCACHE_COMMAND) + if(CCACHE_COMMAND) + if(MSVC) + if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.24) + # ccache >= 4.8 requires compile batching turned off that is available since CMake 3.24. + # See https://github.com/ccache/ccache/wiki/MS-Visual-Studio + set(MSVC_CCACHE_WRAPPER_CONTENT "\"${CCACHE_COMMAND}\" \"${CMAKE_CXX_COMPILER}\"") + set(MSVC_CCACHE_WRAPPER_FILENAME wrapped-cl.bat) + file(WRITE ${CMAKE_BINARY_DIR}/${MSVC_CCACHE_WRAPPER_FILENAME} "${MSVC_CCACHE_WRAPPER_CONTENT} %*") + list(APPEND CMAKE_VS_GLOBALS + "CLToolExe=${MSVC_CCACHE_WRAPPER_FILENAME}" + "CLToolPath=${CMAKE_BINARY_DIR}" + "DebugInformationFormat=OldStyle" + ) + set(CMAKE_VS_NO_COMPILE_BATCHING ON) + else() + message(FATAL_ERROR "ccache requested and found, but CMake >= 3.24 is required to use it properly.") + endif() + else() + list(APPEND CMAKE_C_COMPILER_LAUNCHER ${CCACHE_COMMAND}) + list(APPEND CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE_COMMAND}) + endif() + else() + message(FATAL_ERROR "ccache requested, but not found.") + endif() +endif() + +if(WITH_NATPMP) + find_package(NATPMP MODULE REQUIRED) +endif() + +if(WITH_MINIUPNPC) + find_package(MiniUPnPc MODULE REQUIRED) +endif() + +if(WITH_ZMQ) + if(MSVC) + find_package(ZeroMQ CONFIG REQUIRED) + else() + # The ZeroMQ project has provided config files since v4.2.2. + # TODO: Switch to find_package(ZeroMQ) at some point in the future. + include(CrossPkgConfig) + cross_pkg_check_modules(libzmq REQUIRED IMPORTED_TARGET libzmq>=4) + target_compile_definitions(PkgConfig::libzmq INTERFACE + $<$:ZMQ_STATIC> + ) + target_link_libraries(PkgConfig::libzmq INTERFACE + $<$:iphlpapi;ws2_32> + ) + endif() +endif() + +if(WITH_USDT) + find_path(SystemTap_INCLUDE_DIR + NAMES sys/sdt.h + REQUIRED + ) + mark_as_advanced(SystemTap_INCLUDE_DIR) + + include(CMakePushCheckState) + cmake_push_check_state(RESET) + include(CheckCXXSourceCompiles) + set(CMAKE_REQUIRED_INCLUDES ${SystemTap_INCLUDE_DIR}) + check_cxx_source_compiles(" + #include + + int main() + { + DTRACE_PROBE(context, event); + int a, b, c, d, e, f, g; + DTRACE_PROBE7(context, event, a, b, c, d, e, f, g); + } + " HAVE_USDT_H + ) + cmake_pop_check_state() + + if(HAVE_USDT_H) + target_include_directories(core_interface INTERFACE + ${SystemTap_INCLUDE_DIR} + ) + set(ENABLE_TRACING TRUE) + else() + message(FATAL_ERROR "sys/sdt.h found, but could not be compiled.") + endif() +endif() + +if(ENABLE_WALLET) + if(WITH_SQLITE) + if(VCPKG_TARGET_TRIPLET) + # Use of the `unofficial::` namespace is a vcpkg package manager convention. + find_package(unofficial-sqlite3 CONFIG REQUIRED) + else() + find_package(SQLite3 3.7.17 REQUIRED) + endif() + set(USE_SQLITE ON) + endif() + + if(WITH_BDB) + find_package(BerkeleyDB 4.8 MODULE REQUIRED) + set(USE_BDB ON) + if(NOT BerkeleyDB_VERSION VERSION_EQUAL 4.8) + message(WARNING "Found Berkeley DB (BDB) other than 4.8.") + if(WARN_INCOMPATIBLE_BDB) + message(WARNING "BDB (legacy) wallets opened by this build would not be portable!\n" + "If this is intended, pass \"-DWARN_INCOMPATIBLE_BDB=OFF\".\n" + "Passing \"-DWITH_BDB=OFF\" will suppress this warning.\n") + else() + message(WARNING "BDB (legacy) wallets opened by this build will not be portable!") + endif() + endif() + endif() +endif() diff --git a/cmake/optional_qt.cmake b/cmake/optional_qt.cmake new file mode 100644 index 0000000000000..bf46f8413b13b --- /dev/null +++ b/cmake/optional_qt.cmake @@ -0,0 +1,46 @@ +# Copyright (c) 2023-present The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://opensource.org/license/mit/. + +set(WITH_GUI "AUTO" CACHE STRING "Build GUI ([AUTO], Qt5, OFF)") +set(with_gui_values AUTO Qt5 OFF) +if(NOT WITH_GUI IN_LIST with_gui_values) + message(FATAL_ERROR "WITH_GUI value is \"${WITH_GUI}\", but must be one of \"AUTO\", \"Qt5\" or \"OFF\".") +endif() + +if(WITH_GUI) + set(QT_NO_CREATE_VERSIONLESS_FUNCTIONS ON) + set(QT_NO_CREATE_VERSIONLESS_TARGETS ON) + + if(BREW_COMMAND) + execute_process( + COMMAND ${BREW_COMMAND} --prefix qt@5 + OUTPUT_VARIABLE qt5_brew_prefix + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + endif() + + if(WITH_GUI STREQUAL "AUTO") + # The PATH_SUFFIXES option is required on OpenBSD systems. + find_package(QT NAMES Qt5 + COMPONENTS Core + HINTS ${qt5_brew_prefix} + PATH_SUFFIXES Qt5 + ) + if(QT_FOUND) + set(WITH_GUI Qt${QT_VERSION_MAJOR}) + if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + enable_language(OBJCXX) + set(CMAKE_OBJCXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") + set(CMAKE_OBJCXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") + set(CMAKE_OBJCXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") + set(CMAKE_OBJCXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL}") + endif() + else() + message(WARNING "Qt not found, disabling.\n" + "To skip this warning check, use \"-DWITH_GUI=OFF\".\n") + set(WITH_GUI OFF) + endif() + endif() +endif() diff --git a/cmake/script/GenerateBuildInfo.cmake b/cmake/script/GenerateBuildInfo.cmake new file mode 100644 index 0000000000000..74221c789e600 --- /dev/null +++ b/cmake/script/GenerateBuildInfo.cmake @@ -0,0 +1,115 @@ +# Copyright (c) 2023-present The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://opensource.org/license/mit/. + +# This script is a multiplatform port of the share/genbuild.sh shell script. + +macro(fatal_error) + message(FATAL_ERROR "\n" + "Usage:\n" + " cmake -D BUILD_INFO_HEADER_PATH= [-D SOURCE_DIR=] -P ${CMAKE_CURRENT_LIST_FILE}\n" + "All specified paths must be absolute ones.\n" + ) +endmacro() + +if(DEFINED BUILD_INFO_HEADER_PATH AND IS_ABSOLUTE "${BUILD_INFO_HEADER_PATH}") + if(EXISTS "${BUILD_INFO_HEADER_PATH}") + file(STRINGS ${BUILD_INFO_HEADER_PATH} INFO LIMIT_COUNT 1) + endif() +else() + fatal_error() +endif() + +if(DEFINED SOURCE_DIR) + if(IS_ABSOLUTE "${SOURCE_DIR}" AND IS_DIRECTORY "${SOURCE_DIR}") + set(WORKING_DIR ${SOURCE_DIR}) + else() + fatal_error() + endif() +else() + set(WORKING_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +endif() + +set(GIT_TAG) +set(GIT_COMMIT) +if(NOT "$ENV{BITCOIN_GENBUILD_NO_GIT}" STREQUAL "1") + find_package(Git QUIET) + if(Git_FOUND) + execute_process( + COMMAND ${GIT_EXECUTABLE} rev-parse --is-inside-work-tree + WORKING_DIRECTORY ${WORKING_DIR} + OUTPUT_VARIABLE IS_INSIDE_WORK_TREE + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + ) + if(IS_INSIDE_WORK_TREE) + # Clean 'dirty' status of touched files that haven't been modified. + execute_process( + COMMAND ${GIT_EXECUTABLE} diff + WORKING_DIRECTORY ${WORKING_DIR} + OUTPUT_QUIET + ERROR_QUIET + ) + + execute_process( + COMMAND ${GIT_EXECUTABLE} describe --abbrev=0 + WORKING_DIRECTORY ${WORKING_DIR} + OUTPUT_VARIABLE MOST_RECENT_TAG + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + ) + + execute_process( + COMMAND ${GIT_EXECUTABLE} rev-list -1 ${MOST_RECENT_TAG} + WORKING_DIRECTORY ${WORKING_DIR} + OUTPUT_VARIABLE MOST_RECENT_TAG_COMMIT + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + ) + + execute_process( + COMMAND ${GIT_EXECUTABLE} rev-parse HEAD + WORKING_DIRECTORY ${WORKING_DIR} + OUTPUT_VARIABLE HEAD_COMMIT + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + ) + + execute_process( + COMMAND ${GIT_EXECUTABLE} diff-index --quiet HEAD -- + WORKING_DIRECTORY ${WORKING_DIR} + RESULT_VARIABLE IS_DIRTY + ) + + if(HEAD_COMMIT STREQUAL MOST_RECENT_TAG_COMMIT AND NOT IS_DIRTY) + # If latest commit is tagged and not dirty, then use the tag name. + set(GIT_TAG ${MOST_RECENT_TAG}) + else() + # Otherwise, generate suffix from git, i.e. string like "0e0a5173fae3-dirty". + execute_process( + COMMAND ${GIT_EXECUTABLE} rev-parse --short=12 HEAD + WORKING_DIRECTORY ${WORKING_DIR} + OUTPUT_VARIABLE GIT_COMMIT + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + ) + if(IS_DIRTY) + string(APPEND GIT_COMMIT "-dirty") + endif() + endif() + endif() + endif() +endif() + +if(GIT_TAG) + set(NEWINFO "#define BUILD_GIT_TAG \"${GIT_TAG}\"\n") +elseif(GIT_COMMIT) + set(NEWINFO "#define BUILD_GIT_COMMIT \"${GIT_COMMIT}\"\n") +else() + set(NEWINFO "// No build information available\n") +endif() + +# Only update the header if necessary. +if(NOT "${INFO}" STREQUAL "${NEWINFO}") + file(WRITE ${BUILD_INFO_HEADER_PATH} ${NEWINFO}) +endif() diff --git a/cmake/script/GenerateHeaderFromJson.cmake b/cmake/script/GenerateHeaderFromJson.cmake new file mode 100644 index 0000000000000..c13c9b1d40b7d --- /dev/null +++ b/cmake/script/GenerateHeaderFromJson.cmake @@ -0,0 +1,24 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +file(READ ${JSON_SOURCE_PATH} hex_content HEX) +string(REGEX MATCHALL "([A-Za-z0-9][A-Za-z0-9])" bytes "${hex_content}") + +file(WRITE ${HEADER_PATH} "#include \n") +file(APPEND ${HEADER_PATH} "namespace json_tests{\n") +get_filename_component(json_source_basename ${JSON_SOURCE_PATH} NAME_WE) +file(APPEND ${HEADER_PATH} "static const std::string ${json_source_basename}{\n") + +set(i 0) +foreach(byte ${bytes}) + math(EXPR i "${i} + 1") + math(EXPR remainder "${i} % 8") + if(remainder EQUAL 0) + file(APPEND ${HEADER_PATH} "0x${byte},\n") + else() + file(APPEND ${HEADER_PATH} "0x${byte}, ") + endif() +endforeach() + +file(APPEND ${HEADER_PATH} "\n};};") diff --git a/cmake/script/GenerateHeaderFromRaw.cmake b/cmake/script/GenerateHeaderFromRaw.cmake new file mode 100644 index 0000000000000..82a3a3c3a3199 --- /dev/null +++ b/cmake/script/GenerateHeaderFromRaw.cmake @@ -0,0 +1,22 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +file(READ ${RAW_SOURCE_PATH} hex_content HEX) +string(REGEX MATCHALL "([A-Za-z0-9][A-Za-z0-9])" bytes "${hex_content}") + +get_filename_component(raw_source_basename ${RAW_SOURCE_PATH} NAME_WE) +file(WRITE ${HEADER_PATH} "static unsigned const char ${raw_source_basename}_raw[] = {\n") + +set(i 0) +foreach(byte ${bytes}) + math(EXPR i "${i} + 1") + math(EXPR remainder "${i} % 8") + if(remainder EQUAL 0) + file(APPEND ${HEADER_PATH} "0x${byte},\n") + else() + file(APPEND ${HEADER_PATH} "0x${byte}, ") + endif() +endforeach() + +file(APPEND ${HEADER_PATH} "\n};") diff --git a/cmake/secp256k1.cmake b/cmake/secp256k1.cmake new file mode 100644 index 0000000000000..5b932cc4c6bc1 --- /dev/null +++ b/cmake/secp256k1.cmake @@ -0,0 +1,60 @@ +# Copyright (c) 2023-present The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://opensource.org/license/mit/. + +# This file is part of the transition from Autotools to CMake. Once CMake +# support has been merged we should switch to using the upstream CMake +# buildsystem. + +enable_language(C) +set(CMAKE_C_STANDARD 90) +set(CMAKE_C_EXTENSIONS OFF) + +if(ASM) + include(CheckCSourceCompiles) + check_c_source_compiles(" + #include + + int main() + { + uint64_t a = 11, tmp; + __asm__ __volatile__(\"movq $0x100000000,%1; mulq %%rsi\" : \"+a\"(a) : \"S\"(tmp) : \"cc\", \"%rdx\"); + } + " HAVE_64BIT_ASM + ) +endif() + +add_library(secp256k1 STATIC EXCLUDE_FROM_ALL + ${PROJECT_SOURCE_DIR}/src/secp256k1/src/secp256k1.c + ${PROJECT_SOURCE_DIR}/src/secp256k1/src/precomputed_ecmult.c + ${PROJECT_SOURCE_DIR}/src/secp256k1/src/precomputed_ecmult_gen.c +) + +target_compile_definitions(secp256k1 + PRIVATE + ECMULT_GEN_PREC_BITS=4 + ECMULT_WINDOW_SIZE=15 + ENABLE_MODULE_RECOVERY + ENABLE_MODULE_SCHNORRSIG + ENABLE_MODULE_EXTRAKEYS + ENABLE_MODULE_ELLSWIFT + $<$:USE_ASM_X86_64=1> + INTERFACE + $<$:SECP256K1_STATIC> +) + +target_include_directories(secp256k1 + PUBLIC + $ +) + +if(MSVC) + target_compile_options(secp256k1 + PRIVATE + /wd4146 + /wd4244 + /wd4267 + ) +endif() + +target_link_libraries(secp256k1 PRIVATE core_interface) diff --git a/cmake/tests.cmake b/cmake/tests.cmake new file mode 100644 index 0000000000000..ba73e7d32b4b8 --- /dev/null +++ b/cmake/tests.cmake @@ -0,0 +1,57 @@ +# Copyright (c) 2023-present The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://opensource.org/license/mit/. + +include(CTest) + +if(TARGET bitcoin-util AND TARGET bitcoin-tx AND PYTHON_COMMAND) + add_test(NAME util_test_runner + COMMAND ${CMAKE_COMMAND} -E env BITCOINUTIL=$ BITCOINTX=$ ${PYTHON_COMMAND} ${CMAKE_BINARY_DIR}/test/util/test_runner.py + ) +endif() + +if(PYTHON_COMMAND) + add_test(NAME util_rpcauth_test + COMMAND ${PYTHON_COMMAND} ${CMAKE_BINARY_DIR}/test/util/rpcauth-test.py + ) +endif() + +if(TARGET bench_bitcoin) + add_test(NAME bench_sanity_check_high_priority + COMMAND bench_bitcoin -sanity-check -priority-level=high + ) +endif() + +if(TARGET test_bitcoin) + function(add_boost_test source_dir source_file) + set(source_file_path ${source_dir}/${source_file}) + if(NOT EXISTS ${source_file_path}) + return() + endif() + + file(READ "${source_file_path}" source_file_content) + string(REGEX + MATCH "(BOOST_FIXTURE_TEST_SUITE|BOOST_AUTO_TEST_SUITE)\\(([A-Za-z0-9_]+)" + test_suite_macro "${source_file_content}" + ) + string(REGEX + REPLACE "(BOOST_FIXTURE_TEST_SUITE|BOOST_AUTO_TEST_SUITE)\\(" "" + test_suite_name "${test_suite_macro}" + ) + if(test_suite_name) + add_test(NAME ${test_suite_name}:${source_file} + COMMAND test_bitcoin --run_test=${test_suite_name} --catch_system_error=no + ) + endif() + endfunction() + + function(add_all_test_targets) + get_target_property(test_source_dir test_bitcoin SOURCE_DIR) + get_target_property(test_sources test_bitcoin SOURCES) + foreach(test_source ${test_sources}) + add_boost_test(${test_source_dir} ${test_source}) + endforeach() + endfunction() + + add_all_test_targets() +endif() diff --git a/contrib/guix/guix-build b/contrib/guix/guix-build index 298e7bfbd689f..5010b63a6012b 100755 --- a/contrib/guix/guix-build +++ b/contrib/guix/guix-build @@ -74,9 +74,11 @@ mkdir -p "$VERSION_BASE" ################ # Default to building for all supported HOSTs (overridable by environment) -export HOSTS="${HOSTS:-x86_64-linux-gnu arm-linux-gnueabihf aarch64-linux-gnu riscv64-linux-gnu powerpc64-linux-gnu powerpc64le-linux-gnu - x86_64-w64-mingw32 - x86_64-apple-darwin arm64-apple-darwin}" +# TODO: Re-enable Windows and macOS hosts. +# export HOSTS="${HOSTS:-x86_64-linux-gnu arm-linux-gnueabihf aarch64-linux-gnu riscv64-linux-gnu powerpc64-linux-gnu powerpc64le-linux-gnu +# x86_64-w64-mingw32 +# x86_64-apple-darwin arm64-apple-darwin}" +export HOSTS="${HOSTS:-x86_64-linux-gnu arm-linux-gnueabihf aarch64-linux-gnu riscv64-linux-gnu powerpc64-linux-gnu powerpc64le-linux-gnu}" # Usage: distsrc_for_host HOST # diff --git a/contrib/guix/libexec/build.sh b/contrib/guix/libexec/build.sh index b301369ad92eb..2be4bb93e79f5 100755 --- a/contrib/guix/libexec/build.sh +++ b/contrib/guix/libexec/build.sh @@ -182,7 +182,9 @@ esac #################### # Build the depends tree, overriding variables that assume multilib gcc +# TODO: Drop NO_QT=1 make -C depends --jobs="$JOBS" HOST="$HOST" \ + NO_QT=1 \ ${V:+V=1} \ ${SOURCES_PATH+SOURCES_PATH="$SOURCES_PATH"} \ ${BASE_CACHE+BASE_CACHE="$BASE_CACHE"} \ @@ -215,7 +217,8 @@ mkdir -p "$OUTDIR" ########################### # CONFIGFLAGS -CONFIGFLAGS="--enable-reduce-exports --disable-bench --disable-gui-tests --disable-fuzz-binary" +# TODO: Re-add CMake's analogue of --disable-gui-tests. +CONFIGFLAGS="-DREDUCE_EXPORTS=ON -DBUILD_BENCH=OFF -DBUILD_FUZZ_BINARY=OFF" # CFLAGS HOST_CFLAGS="-O2 -g" @@ -248,31 +251,23 @@ mkdir -p "$DISTSRC" # Extract the source tarball tar --strip-components=1 -xf "${GIT_ARCHIVE}" - ./autogen.sh - # Configure this DISTSRC for $HOST # shellcheck disable=SC2086 - env CONFIG_SITE="${BASEPREFIX}/${HOST}/share/config.site" \ - ./configure --prefix=/ \ - --disable-ccache \ - --disable-maintainer-mode \ - --disable-dependency-tracking \ - ${CONFIGFLAGS} \ - ${HOST_CFLAGS:+CFLAGS="${HOST_CFLAGS}"} \ - ${HOST_CXXFLAGS:+CXXFLAGS="${HOST_CXXFLAGS}"} \ - ${HOST_LDFLAGS:+LDFLAGS="${HOST_LDFLAGS}"} - - sed -i.old 's/-lstdc++ //g' config.status libtool + env CFLAGS="${HOST_CFLAGS}" CXXFLAGS="${HOST_CXXFLAGS}" LDFLAGS="${HOST_LDFLAGS}" \ + cmake -S . -B build \ + --toolchain "${BASEPREFIX}/${HOST}/share/toolchain.cmake" \ + -DCCACHE=OFF \ + ${CONFIGFLAGS} # Build Bitcoin Core - make --jobs="$JOBS" ${V:+V=1} + cmake --build build -j "$JOBS" ${V:+--verbose} # Check that symbol/security checks tools are sane. - make test-security-check ${V:+V=1} + cmake --build build --target test-security-check ${V:+--verbose} # Perform basic security checks on a series of executables. - make -C src --jobs=1 check-security ${V:+V=1} + cmake --build build -j 1 --target check-security ${V:+--verbose} # Check that executables only contain allowed version symbols. - make -C src --jobs=1 check-symbols ${V:+V=1} + cmake --build build -j 1 --target check-symbols ${V:+--verbose} mkdir -p "$OUTDIR" @@ -294,7 +289,7 @@ mkdir -p "$DISTSRC" make install-strip DESTDIR="${INSTALLPATH}" ${V:+V=1} ;; *) - make install DESTDIR="${INSTALLPATH}" ${V:+V=1} + cmake --install build --prefix "${INSTALLPATH}" ${V:+--verbose} ;; esac @@ -327,21 +322,15 @@ mkdir -p "$DISTSRC" ;; esac - # Prune libtool and object archives - find . -name "lib*.la" -delete - find . -name "lib*.a" -delete - - # Prune pkg-config files - rm -rf "${DISTNAME}/lib/pkgconfig" - case "$HOST" in *darwin*) ;; *) # Split binaries and libraries from their debug symbols + # TODO: Re-enable code for libbitcoinkernel. { find "${DISTNAME}/bin" -type f -executable -print0 - find "${DISTNAME}/lib" -type f -print0 - } | xargs -0 -P"$JOBS" -I{} "${DISTSRC}/contrib/devtools/split-debug.sh" {} {} {}.dbg + # find "${DISTNAME}/lib" -type f -print0 + } | xargs -0 -P"$JOBS" -I{} "${DISTSRC}/build/split-debug.sh" {} {} {}.dbg ;; esac diff --git a/contrib/guix/manifest.scm b/contrib/guix/manifest.scm index 7335596107e62..0a638379cba45 100644 --- a/contrib/guix/manifest.scm +++ b/contrib/guix/manifest.scm @@ -499,6 +499,7 @@ inspecting signatures in Mach-O binaries.") gzip xz ;; Build tools + cmake-minimal gnu-make libtool autoconf-2.71 @@ -525,5 +526,5 @@ inspecting signatures in Mach-O binaries.") ((string-contains target "-linux-") (list (make-bitcoin-cross-toolchain target))) ((string-contains target "darwin") - (list clang-toolchain-17 binutils cmake-minimal python-signapple zip)) + (list clang-toolchain-17 binutils python-signapple zip)) (else '()))))) diff --git a/depends/Makefile b/depends/Makefile index 88aae7ad81495..216a8e6ecb82c 100644 --- a/depends/Makefile +++ b/depends/Makefile @@ -191,6 +191,7 @@ $(host_arch)_$(host_os)_native_toolchain?=$($(host_os)_native_toolchain) include funcs.mk final_build_id_long+=$(shell $(build_SHA256SUM) config.site.in) +final_build_id_long+=$(shell $(build_SHA256SUM) toolchain.cmake.in) final_build_id+=$(shell echo -n "$(final_build_id_long)" | $(build_SHA256SUM) | cut -c-$(HASH_LENGTH)) $(host_prefix)/.stamp_$(final_build_id): $(native_packages) $(packages) rm -rf $(@D) @@ -258,6 +259,34 @@ $(host_prefix)/share/config.site : config.site.in $(host_prefix)/.stamp_$(final_ $< > $@ touch $@ +$(host_prefix)/share/toolchain.cmake : toolchain.cmake.in $(host_prefix)/.stamp_$(final_build_id) + @mkdir -p $(@D) + sed -e 's|@host_system@|$($(host_os)_cmake_system)|' \ + -e 's|@host_arch@|$(host_arch)|' \ + -e 's|@CC@|$(host_CC)|' \ + -e 's|@CXX@|$(host_CXX)|' \ + -e 's|@OSX_SDK@|$(OSX_SDK)|' \ + -e 's|@AR@|$(host_AR)|' \ + -e 's|@RANLIB@|$(host_RANLIB)|' \ + -e 's|@STRIP@|$(host_STRIP)|' \ + -e 's|@OBJCOPY@|$(host_OBJCOPY)|' \ + -e 's|@INSTALL_NAME_TOOL@|$(host_INSTALL_NAME_TOOL)|' \ + -e 's|@OTOOL@|$(host_OTOOL)|' \ + -e 's|@depends_prefix@|$(host_prefix)|' \ + -e 's|@CFLAGS@|$(strip $(host_CFLAGS) $(host_$(release_type)_CFLAGS))|' \ + -e 's|@CXXFLAGS@|$(strip $(host_CXXFLAGS) $(host_$(release_type)_CXXFLAGS))|' \ + -e 's|@CPPFLAGS@|$(strip $(host_CPPFLAGS) $(host_$(release_type)_CPPFLAGS))|' \ + -e 's|@no_qt@|$(NO_QT)|' \ + -e 's|@no_qr@|$(NO_QR)|' \ + -e 's|@no_zmq@|$(NO_ZMQ)|' \ + -e 's|@no_wallet@|$(NO_WALLET)|' \ + -e 's|@no_bdb@|$(NO_BDB)|' \ + -e 's|@no_sqlite@|$(NO_SQLITE)|' \ + -e 's|@no_upnp@|$(NO_UPNP)|' \ + -e 's|@no_natpmp@|$(NO_NATPMP)|' \ + -e 's|@no_usdt@|$(NO_USDT)|' \ + $< > $@ + touch $@ define check_or_remove_cached mkdir -p $(BASE_CACHE)/$(host)/$(package) && cd $(BASE_CACHE)/$(host)/$(package); \ @@ -279,6 +308,7 @@ check-sources: @$(foreach package,$(all_packages),$(call check_or_remove_sources,$(package));) $(host_prefix)/share/config.site: check-packages +$(host_prefix)/share/toolchain.cmake: check-packages check-packages: check-sources @@ -288,7 +318,7 @@ clean-all: clean clean: @rm -rf $(WORK_PATH) $(BASE_CACHE) $(BUILD) *.log -install: check-packages $(host_prefix)/share/config.site +install: check-packages $(host_prefix)/share/config.site $(host_prefix)/share/toolchain.cmake download-one: check-sources $(all_sources) diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk index 5608e5f07387d..ffa2e66a84607 100644 --- a/depends/packages/qt.mk +++ b/depends/packages/qt.mk @@ -280,13 +280,14 @@ define $(package)_build_cmds $(MAKE) endef +# TODO: Investigate whether specific targets can be used here to minimize the amount of files/components installed. define $(package)_stage_cmds - $(MAKE) -C qtbase/src INSTALL_ROOT=$($(package)_staging_dir) $(addsuffix -install_subtargets,$(addprefix sub-,$($(package)_qt_libs))) && \ - $(MAKE) -C qttools/src/linguist INSTALL_ROOT=$($(package)_staging_dir) $(addsuffix -install_subtargets,$(addprefix sub-,$($(package)_linguist_tools))) && \ + $(MAKE) -C qtbase INSTALL_ROOT=$($(package)_staging_dir) install && \ + $(MAKE) -C qttools INSTALL_ROOT=$($(package)_staging_dir) install && \ $(MAKE) -C qttranslations INSTALL_ROOT=$($(package)_staging_dir) install_subtargets endef define $(package)_postprocess_cmds - rm -rf native/mkspecs/ native/lib/ lib/cmake/ && \ + rm -rf doc/ native/lib/ && \ rm -f lib/lib*.la endef diff --git a/depends/patches/qt/qt.pro b/depends/patches/qt/qt.pro index 8f2e900a840fb..6d8b7fdb6a2ca 100644 --- a/depends/patches/qt/qt.pro +++ b/depends/patches/qt/qt.pro @@ -3,10 +3,6 @@ cache(, super) !QTDIR_build: cache(CONFIG, add, $$list(QTDIR_build)) -prl = no_install_prl -CONFIG += $$prl -cache(CONFIG, add stash, prl) - TEMPLATE = subdirs SUBDIRS = qtbase qttools qttranslations diff --git a/depends/toolchain.cmake.in b/depends/toolchain.cmake.in new file mode 100644 index 0000000000000..7193c172868a1 --- /dev/null +++ b/depends/toolchain.cmake.in @@ -0,0 +1,136 @@ +# This file is expected to be highly volatile and may still change substantially. + +set(CMAKE_SYSTEM_NAME @host_system@) +set(CMAKE_SYSTEM_PROCESSOR @host_arch@) + +function(split_compiler_launcher env_compiler launcher compiler) + set(${launcher}) + list(GET ${env_compiler} 0 start_token) + if(start_token STREQUAL "env") + set(${compiler}) + set(env_arg_parsing TRUE) + foreach(token IN LISTS ${env_compiler}) + if(env_arg_parsing) + list(APPEND ${launcher} ${token}) + set(env_arg_parsing FALSE) + continue() + elseif(token STREQUAL "-u") + list(APPEND ${launcher} ${token}) + set(env_arg_parsing TRUE) + continue() + endif() + list(APPEND ${compiler} ${token}) + endforeach() + else() + set(${compiler} ${${env_compiler}}) + endif() + set(${launcher} ${${launcher}} PARENT_SCOPE) + set(${compiler} ${${compiler}} PARENT_SCOPE) +endfunction() + +if(NOT CMAKE_C_COMPILER) + set(DEPENDS_C_COMPILER_WITH_LAUNCHER @CC@) + split_compiler_launcher(DEPENDS_C_COMPILER_WITH_LAUNCHER CMAKE_C_COMPILER_LAUNCHER CMAKE_C_COMPILER) + if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.21) + set(CMAKE_C_LINKER_LAUNCHER ${CMAKE_C_COMPILER_LAUNCHER}) + endif() + if(CMAKE_VERSION VERSION_LESS 3.19) + # Being provided with CC="compiler -arg1 -arg2", the old CMake cannot + # store the compiler arguments in the CMAKE_C_COMPILER variable. + # Therefore, we have to store them separately. + set(mandatory_c_compiler_flags ${CMAKE_C_COMPILER}) + list(POP_FRONT mandatory_c_compiler_flags CMAKE_C_COMPILER) + list(JOIN mandatory_c_compiler_flags " " mandatory_c_compiler_flags) + string(PREPEND CMAKE_C_FLAGS_INIT "${mandatory_c_compiler_flags} ") + unset(mandatory_c_compiler_flags) + endif() + set(DEPENDS_C_COMPILER_FLAGS @CFLAGS@) +endif() + +if(NOT CMAKE_CXX_COMPILER) + set(DEPENDS_CXX_COMPILER_WITH_LAUNCHER @CXX@) + split_compiler_launcher(DEPENDS_CXX_COMPILER_WITH_LAUNCHER CMAKE_CXX_COMPILER_LAUNCHER CMAKE_CXX_COMPILER) + if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.21) + set(CMAKE_CXX_LINKER_LAUNCHER ${CMAKE_CXX_COMPILER_LAUNCHER}) + endif() + if(CMAKE_VERSION VERSION_LESS 3.19) + # Being provided with CXX="compiler -arg1 -arg2", the old CMake cannot + # store the compiler arguments in the CMAKE_CXX_COMPILER variable. + # Therefore, we have to store them separately. + set(mandatory_cxx_compiler_flags ${CMAKE_CXX_COMPILER}) + list(POP_FRONT mandatory_cxx_compiler_flags CMAKE_CXX_COMPILER) + list(JOIN mandatory_cxx_compiler_flags " " mandatory_cxx_compiler_flags) + string(PREPEND CMAKE_CXX_FLAGS_INIT "${mandatory_cxx_compiler_flags} ") + string(PREPEND CMAKE_OBJCXX_FLAGS_INIT "${mandatory_cxx_compiler_flags} ") + string(PREPEND CMAKE_EXE_LINKER_FLAGS_INIT "${mandatory_cxx_compiler_flags} ") + string(PREPEND CMAKE_SHARED_LINKER_FLAGS_INIT "${mandatory_cxx_compiler_flags} ") + unset(mandatory_cxx_compiler_flags) + endif() + set(DEPENDS_CXX_COMPILER_FLAGS @CXXFLAGS@) + + set(CMAKE_OBJCXX_COMPILER ${CMAKE_CXX_COMPILER}) + set(CMAKE_OBJCXX_COMPILER_LAUNCHER ${CMAKE_CXX_COMPILER_LAUNCHER}) + set(CMAKE_OBJCXX_LINKER_LAUNCHER ${CMAKE_CXX_LINKER_LAUNCHER}) +endif() + +set(DEPENDS_COMPILE_DEFINITIONS @CPPFLAGS@) + +set(CMAKE_AR "@AR@") +set(CMAKE_RANLIB "@RANLIB@") +set(CMAKE_STRIP "@STRIP@") +set(CMAKE_OBJCOPY "@OBJCOPY@") +set(CMAKE_INSTALL_NAME_TOOL "@INSTALL_NAME_TOOL@") +set(OTOOL "@OTOOL@") + +set(CMAKE_FIND_ROOT_PATH "@depends_prefix@") +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) +set(PKG_CONFIG_PATH "@depends_prefix@/lib/pkgconfig") +set(PKG_CONFIG_LIBDIR "${PKG_CONFIG_PATH}") +set(QT_TRANSLATIONS_DIR "@depends_prefix@/translations") + +if(CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND NOT CMAKE_HOST_APPLE) + # The find_package(Qt ...) function internally uses find_library() + # calls for all dependencies to ensure their availability. + # In turn, the find_library() inspects the well-known locations + # on the file system; therefore, a hint is required. + set(CMAKE_FRAMEWORK_PATH "@OSX_SDK@/System/Library/Frameworks") +endif() + +if(NOT WITH_GUI AND "@no_qt@" STREQUAL "1") + set(WITH_GUI OFF CACHE STRING "") +endif() + +if(NOT WITH_QRENCODE AND "@no_qr@" STREQUAL "1") + set(WITH_QRENCODE OFF CACHE STRING "") +endif() + +if(NOT WITH_ZMQ AND "@no_zmq@" STREQUAL "1") + set(WITH_ZMQ OFF CACHE STRING "") +endif() + +if(NOT ENABLE_WALLET AND "@no_wallet@" STREQUAL "1") + set(ENABLE_WALLET OFF CACHE BOOL "") +endif() + +if(NOT WITH_BDB AND "@no_bdb@" STREQUAL "1") + set(WITH_BDB OFF CACHE STRING "") +endif() + +if(NOT WITH_SQLITE AND "@no_sqlite@" STREQUAL "1") + set(WITH_SQLITE OFF CACHE STRING "") +endif() + +if(NOT WITH_MINIUPNPC AND "@no_upnp@" STREQUAL "1") + set(WITH_MINIUPNPC OFF CACHE STRING "") +endif() + +if(NOT WITH_NATPMP AND "@no_natpmp@" STREQUAL "1") + set(WITH_NATPMP OFF CACHE STRING "") +endif() + +if(NOT WITH_USDT AND "@no_usdt@" STREQUAL "1") + set(WITH_USDT OFF CACHE STRING "") +endif() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000000000..a30d6b27e0d3c --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,360 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +include(GNUInstallDirs) + +configure_file(${CMAKE_SOURCE_DIR}/cmake/bitcoin-config.h.in config/bitcoin-config.h @ONLY) +add_compile_definitions(HAVE_CONFIG_H) +include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) + +# After the transition from Autotools to CMake, the obj/ subdirectory +# could be dropped as its only purpose was to separate a generated header +# from source files. +add_custom_target(generate_build_info + BYPRODUCTS ${PROJECT_BINARY_DIR}/src/obj/build.h + COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/src/obj + COMMAND ${CMAKE_COMMAND} -DBUILD_INFO_HEADER_PATH=${PROJECT_BINARY_DIR}/src/obj/build.h -DSOURCE_DIR=${PROJECT_SOURCE_DIR} -P ${CMAKE_SOURCE_DIR}/cmake/script/GenerateBuildInfo.cmake + COMMENT "Generating obj/build.h" + VERBATIM +) +add_library(bitcoin_clientversion OBJECT EXCLUDE_FROM_ALL + clientversion.cpp +) +target_compile_definitions(bitcoin_clientversion + PRIVATE + HAVE_BUILD_INFO +) +target_link_libraries(bitcoin_clientversion + PRIVATE + core_interface +) +add_dependencies(bitcoin_clientversion generate_build_info) + +add_subdirectory(crypto) +add_subdirectory(univalue) +add_subdirectory(util) + + +add_library(bitcoin_consensus_sources INTERFACE) +target_sources(bitcoin_consensus_sources INTERFACE + arith_uint256.cpp + consensus/merkle.cpp + consensus/tx_check.cpp + hash.cpp + primitives/block.cpp + primitives/transaction.cpp + pubkey.cpp + script/interpreter.cpp + script/script.cpp + script/script_error.cpp + uint256.cpp + util/strencodings.cpp +) + +# Stable, backwards-compatible consensus functionality +# also exposed as a shared library or a static one. +add_library(bitcoin_consensus STATIC EXCLUDE_FROM_ALL) +target_link_libraries(bitcoin_consensus + PRIVATE + core_interface + bitcoin_consensus_sources + bitcoin_crypto + secp256k1 +) + +if(WITH_ZMQ) + add_subdirectory(zmq EXCLUDE_FROM_ALL) +endif() + +# Home for common functionality shared by different executables and libraries. +# Similar to `bitcoin_util` library, but higher-level. +add_library(bitcoin_common STATIC EXCLUDE_FROM_ALL + addresstype.cpp + base58.cpp + bech32.cpp + chainparams.cpp + coins.cpp + common/args.cpp + common/bloom.cpp + common/config.cpp + common/init.cpp + common/interfaces.cpp + common/run_command.cpp + common/settings.cpp + common/system.cpp + $<$:common/url.cpp> + compressor.cpp + core_read.cpp + core_write.cpp + deploymentinfo.cpp + external_signer.cpp + init/common.cpp + kernel/chainparams.cpp + key.cpp + key_io.cpp + merkleblock.cpp + net_types.cpp + netaddress.cpp + netbase.cpp + net_permissions.cpp + outputtype.cpp + policy/feerate.cpp + policy/policy.cpp + protocol.cpp + psbt.cpp + rpc/rawtransaction_util.cpp + rpc/request.cpp + rpc/external_signer.cpp + rpc/util.cpp + scheduler.cpp + script/descriptor.cpp + script/miniscript.cpp + script/sign.cpp + script/signingprovider.cpp + script/solver.cpp + warnings.cpp +) +target_compile_definitions(bitcoin_common + PRIVATE + ${THREAD_LOCAL_IF_AVAILABLE} +) +target_link_libraries(bitcoin_common + PRIVATE + core_interface + bitcoin_consensus + bitcoin_util + univalue + secp256k1 + Boost::headers + $ +) + + +set(installable_targets) +if(ENABLE_WALLET) + add_subdirectory(wallet) + + if(BUILD_WALLET_TOOL) + add_executable(bitcoin-wallet + bitcoin-wallet.cpp + init/bitcoin-wallet.cpp + wallet/wallettool.cpp + ) + target_link_libraries(bitcoin-wallet + core_interface + bitcoin_wallet + bitcoin_common + bitcoin_util + Boost::headers + ) + list(APPEND installable_targets bitcoin-wallet) + endif() +endif() + + +# P2P and RPC server functionality used by `bitcoind` and `bitcoin-qt` executables. +add_library(bitcoin_node STATIC EXCLUDE_FROM_ALL + addrdb.cpp + addrman.cpp + banman.cpp + bip324.cpp + blockencodings.cpp + blockfilter.cpp + chain.cpp + consensus/tx_verify.cpp + dbwrapper.cpp + deploymentstatus.cpp + flatfile.cpp + headerssync.cpp + httprpc.cpp + httpserver.cpp + i2p.cpp + index/base.cpp + index/blockfilterindex.cpp + index/coinstatsindex.cpp + index/txindex.cpp + init.cpp + kernel/chain.cpp + kernel/checks.cpp + kernel/coinstats.cpp + kernel/context.cpp + kernel/cs_main.cpp + kernel/disconnected_transactions.cpp + kernel/mempool_persist.cpp + kernel/mempool_removal_reason.cpp + mapport.cpp + net.cpp + net_processing.cpp + netgroup.cpp + node/abort.cpp + node/blockmanager_args.cpp + node/blockstorage.cpp + node/caches.cpp + node/chainstate.cpp + node/chainstatemanager_args.cpp + node/coin.cpp + node/coins_view_args.cpp + node/connection_types.cpp + node/context.cpp + node/database_args.cpp + node/eviction.cpp + node/interface_ui.cpp + node/interfaces.cpp + node/kernel_notifications.cpp + node/mempool_args.cpp + node/mempool_persist_args.cpp + node/miner.cpp + node/mini_miner.cpp + node/minisketchwrapper.cpp + node/peerman_args.cpp + node/psbt.cpp + node/transaction.cpp + node/txreconciliation.cpp + node/utxo_snapshot.cpp + node/validation_cache_args.cpp + noui.cpp + policy/fees.cpp + policy/fees_args.cpp + policy/packages.cpp + policy/rbf.cpp + policy/settings.cpp + pow.cpp + rest.cpp + rpc/blockchain.cpp + rpc/fees.cpp + rpc/mempool.cpp + rpc/mining.cpp + rpc/net.cpp + rpc/node.cpp + rpc/output_script.cpp + rpc/rawtransaction.cpp + rpc/server.cpp + rpc/server_util.cpp + rpc/signmessage.cpp + rpc/txoutproof.cpp + script/sigcache.cpp + signet.cpp + timedata.cpp + torcontrol.cpp + txdb.cpp + txmempool.cpp + txorphanage.cpp + txrequest.cpp + validation.cpp + validationinterface.cpp + versionbits.cpp + $<$:wallet/init.cpp> + $<$>:dummywallet.cpp> +) +target_link_libraries(bitcoin_node + PRIVATE + core_interface + bitcoin_common + bitcoin_util + leveldb + minisketch + univalue + Boost::headers + libevent::libevent + $ + $ + $ + $ +) + + +# Bitcoin Core bitcoind. +if(BUILD_DAEMON) + add_executable(bitcoind + bitcoind.cpp + init/bitcoind.cpp + ) + target_link_libraries(bitcoind + core_interface + bitcoin_node + $ + ) + list(APPEND installable_targets bitcoind) +endif() + + +add_library(bitcoin_cli STATIC EXCLUDE_FROM_ALL + compat/stdin.cpp + rpc/client.cpp +) +target_link_libraries(bitcoin_cli + PUBLIC + core_interface + univalue +) + + +# Bitcoin Core RPC client +if(BUILD_CLI) + add_executable(bitcoin-cli bitcoin-cli.cpp) + target_link_libraries(bitcoin-cli + core_interface + bitcoin_cli + bitcoin_common + bitcoin_util + libevent::libevent + ) + list(APPEND installable_targets bitcoin-cli) +endif() + + +if(BUILD_TX) + add_executable(bitcoin-tx bitcoin-tx.cpp) + target_link_libraries(bitcoin-tx + core_interface + bitcoin_common + bitcoin_util + univalue + ) + list(APPEND installable_targets bitcoin-tx) +endif() + + +if(BUILD_UTIL) + add_executable(bitcoin-util bitcoin-util.cpp) + target_link_libraries(bitcoin-util + core_interface + bitcoin_common + bitcoin_util + ) + list(APPEND installable_targets bitcoin-util) +endif() + + +if(WITH_GUI) + add_subdirectory(qt) +endif() + + +add_subdirectory(test/util) +if(BUILD_BENCH) + add_subdirectory(bench) +endif() + +if(BUILD_TESTS) + add_subdirectory(test) +endif() + +if(BUILD_FUZZ_BINARY) + add_subdirectory(test/fuzz) +endif() + + +install(TARGETS ${installable_targets} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) +unset(installable_targets) + +if(INSTALL_MAN) + # TODO: these stubs are no longer needed. man pages should be generated at install time. + install(DIRECTORY ../doc/man/ + DESTINATION ${CMAKE_INSTALL_MANDIR}/man1 + FILES_MATCHING PATTERN *.1 + ) +endif() diff --git a/src/bench/CMakeLists.txt b/src/bench/CMakeLists.txt new file mode 100644 index 0000000000000..d4e6299fcd192 --- /dev/null +++ b/src/bench/CMakeLists.txt @@ -0,0 +1,74 @@ +# Copyright (c) 2023-present The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://opensource.org/license/mit/. + +include(GenerateHeaders) +generate_header_from_raw(data/block413567.raw) + +add_executable(bench_bitcoin + bench_bitcoin.cpp + bench.cpp + data.cpp + nanobench.cpp + ${CMAKE_CURRENT_BINARY_DIR}/data/block413567.raw.h +# Benchmarks: + addrman.cpp + base58.cpp + bech32.cpp + bip324_ecdh.cpp + block_assemble.cpp + ccoins_caching.cpp + chacha20.cpp + checkblock.cpp + checkqueue.cpp + crypto_hash.cpp + descriptors.cpp + disconnected_transactions.cpp + duplicate_inputs.cpp + ellswift.cpp + examples.cpp + gcs_filter.cpp + hashpadding.cpp + load_external.cpp + lockedpool.cpp + logging.cpp + mempool_eviction.cpp + mempool_stress.cpp + merkle_root.cpp + peer_eviction.cpp + poly1305.cpp + pool.cpp + prevector.cpp + readblock.cpp + rollingbloom.cpp + rpc_blockchain.cpp + rpc_mempool.cpp + streams_findbyte.cpp + strencodings.cpp + util_time.cpp + verify_script.cpp + xor.cpp +) + +target_link_libraries(bench_bitcoin + core_interface + test_util + bitcoin_node + Boost::headers +) + +if(ENABLE_WALLET) + target_sources(bench_bitcoin + PRIVATE + coin_selection.cpp + wallet_balance.cpp + wallet_create.cpp + wallet_create_tx.cpp + wallet_loading.cpp + ) + target_link_libraries(bench_bitcoin bitcoin_wallet) +endif() + +install(TARGETS bench_bitcoin + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) diff --git a/src/crypto/CMakeLists.txt b/src/crypto/CMakeLists.txt new file mode 100644 index 0000000000000..1014d052374fe --- /dev/null +++ b/src/crypto/CMakeLists.txt @@ -0,0 +1,142 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +if(ASM AND NOT MSVC) + include(CheckSourceCompilesAndLinks) + + # Check for SSE4.1 intrinsics. + set(SSE41_CXXFLAGS -msse4.1) + check_cxx_source_compiles_with_flags("${SSE41_CXXFLAGS}" " + #include + + int main() + { + __m128i l = _mm_set1_epi32(0); + return _mm_extract_epi32(l, 3); + } + " HAVE_SSE41 + ) + + # Check for AVX2 intrinsics. + set(AVX2_CXXFLAGS -mavx -mavx2) + check_cxx_source_compiles_with_flags("${AVX2_CXXFLAGS}" " + #include + + int main() + { + __m256i l = _mm256_set1_epi32(0); + return _mm256_extract_epi32(l, 7); + } + " HAVE_AVX2 + ) + + # Check for x86 SHA-NI intrinsics. + set(X86_SHANI_CXXFLAGS -msse4 -msha) + check_cxx_source_compiles_with_flags("${X86_SHANI_CXXFLAGS}" " + #include + + int main() + { + __m128i i = _mm_set1_epi32(0); + __m128i j = _mm_set1_epi32(1); + __m128i k = _mm_set1_epi32(2); + return _mm_extract_epi32(_mm_sha256rnds2_epu32(i, j, k), 0); + } + " HAVE_X86_SHANI + ) + + # Check for ARMv8 SHA-NI intrinsics. + set(ARM_SHANI_CXXFLAGS -march=armv8-a+crypto) + check_cxx_source_compiles_with_flags("${ARM_SHANI_CXXFLAGS}" " + #include + + int main() + { + uint32x4_t a, b, c; + vsha256h2q_u32(a, b, c); + vsha256hq_u32(a, b, c); + vsha256su0q_u32(a, b); + vsha256su1q_u32(a, b, c); + } + " HAVE_ARM_SHANI + ) +endif() + +include(CheckCXXSymbolExists) +check_cxx_symbol_exists(timingsafe_bcmp "string.h" HAVE_TIMINGSAFE_BCMP) + +add_library(bitcoin_crypto_sources INTERFACE) +target_sources(bitcoin_crypto_sources INTERFACE + aes.cpp + chacha20.cpp + chacha20poly1305.cpp + hkdf_sha256_32.cpp + hmac_sha256.cpp + hmac_sha512.cpp + poly1305.cpp + muhash.cpp + ripemd160.cpp + sha1.cpp + sha256.cpp + $<$:${CMAKE_CURRENT_SOURCE_DIR}/sha256_sse4.cpp> + sha3.cpp + sha512.cpp + siphash.cpp +) + +add_library(bitcoin_crypto STATIC EXCLUDE_FROM_ALL) +target_compile_definitions(bitcoin_crypto + PRIVATE + $<$:USE_ASM> + $<$:HAVE_TIMINGSAFE_BCMP> +) +target_link_libraries(bitcoin_crypto + PRIVATE + core_interface + bitcoin_crypto_sources +) + +if(HAVE_SSE41) + target_sources(bitcoin_crypto PRIVATE sha256_sse41.cpp) + set_property(SOURCE sha256_sse41.cpp + APPEND PROPERTY COMPILE_OPTIONS ${SSE41_CXXFLAGS} + ) + target_compile_definitions(bitcoin_crypto + PRIVATE + ENABLE_SSE41 + ) +endif() + +if(HAVE_AVX2) + target_sources(bitcoin_crypto PRIVATE sha256_avx2.cpp) + set_property(SOURCE sha256_avx2.cpp + APPEND PROPERTY COMPILE_OPTIONS ${AVX2_CXXFLAGS} + ) + target_compile_definitions(bitcoin_crypto + PRIVATE + ENABLE_AVX2 + ) +endif() + +if(HAVE_X86_SHANI) + target_sources(bitcoin_crypto PRIVATE sha256_x86_shani.cpp) + set_property(SOURCE sha256_x86_shani.cpp + APPEND PROPERTY COMPILE_OPTIONS ${X86_SHANI_CXXFLAGS} + ) + target_compile_definitions(bitcoin_crypto + PRIVATE + ENABLE_X86_SHANI + ) +endif() + +if(HAVE_ARM_SHANI) + target_sources(bitcoin_crypto PRIVATE sha256_arm_shani.cpp) + set_property(SOURCE sha256_arm_shani.cpp + APPEND PROPERTY COMPILE_OPTIONS ${ARM_SHANI_CXXFLAGS} + ) + target_compile_definitions(bitcoin_crypto + PRIVATE + ENABLE_ARM_SHANI + ) +endif() diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt new file mode 100644 index 0000000000000..8af0a65ccc158 --- /dev/null +++ b/src/qt/CMakeLists.txt @@ -0,0 +1,172 @@ +# Copyright (c) 2023-present The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://opensource.org/license/mit/. + +# See: +# - https://cmake.org/cmake/help/latest/manual/cmake-qt.7.html +# - https://doc.qt.io/qt-5/cmake-manual.html + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) +set(CMAKE_AUTOUIC_SEARCH_PATHS forms) + +set(qt_minimum_required_version 5.11.3) + +set(qt_components Core Gui Widgets Network LinguistTools) + +if(CMAKE_CROSSCOMPILING) + # The find_package(Qt ...) function internally uses find_library() + # calls for all dependencies to ensure their availability. + # In turn, the find_library() inspects the well-known locations + # on the file system; therefore, it must be able to find + # platform-specific system libraries, for example: + # /usr/x86_64-w64-mingw32/lib/libm.a or /usr/arm-linux-gnueabihf/lib/libm.a. + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH) +endif() + +find_package(Qt5 ${qt_minimum_required_version} REQUIRED + COMPONENTS ${qt_components} + HINTS ${qt5_brew_prefix} + PATH_SUFFIXES Qt5 # Required on OpenBSD systems. +) +unset(qt_components) +message(STATUS "Found Qt: ${Qt5_DIR} (found suitable version \"${Qt5_VERSION}\", minimum required is \"${qt_minimum_required_version}\")") +unset(qt_minimum_required_version) + +# TODO: The file(GLOB ...) command should be replaced with an explicit +# file list. Such a change must be synced with the corresponding change +# to https://github.com/bitcoin-core/bitcoin-maintainer-tools/blob/main/update-translations.py +file(GLOB ts_files RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} locale/*.ts) +set_source_files_properties(${ts_files} PROPERTIES OUTPUT_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/locale) +qt5_add_translation(qm_files ${ts_files}) + +configure_file(bitcoin_locale.qrc bitcoin_locale.qrc COPYONLY) + +add_library(bitcoinqt STATIC EXCLUDE_FROM_ALL + bantablemodel.cpp + bitcoin.cpp + bitcoinaddressvalidator.cpp + bitcoinamountfield.cpp + bitcoingui.cpp + bitcoinunits.cpp + clientmodel.cpp + csvmodelwriter.cpp + guiutil.cpp + initexecutor.cpp + intro.cpp + modaloverlay.cpp + networkstyle.cpp + notificator.cpp + optionsdialog.cpp + optionsmodel.cpp + peertablemodel.cpp + peertablesortproxy.cpp + platformstyle.cpp + qvalidatedlineedit.cpp + qvaluecombobox.cpp + rpcconsole.cpp + splashscreen.cpp + trafficgraphwidget.cpp + utilitydialog.cpp + $<$:winshutdownmonitor.cpp> + $<$:macdockiconhandler.mm> + $<$:macnotificationhandler.mm> + $<$:macos_appnap.mm> + bitcoin.qrc + ${CMAKE_CURRENT_BINARY_DIR}/bitcoin_locale.qrc +) +target_compile_definitions(bitcoinqt + PUBLIC + QT_NO_KEYWORDS + QT_USE_QSTRINGBUILDER +) +target_include_directories(bitcoinqt + PUBLIC + $ +) +target_link_libraries(bitcoinqt + PUBLIC + Qt5::Widgets + PRIVATE + core_interface + bitcoin_cli + leveldb + Boost::headers + $ + $ + $<$:-framework\ AppKit> + $<$:shlwapi> +) + +if(ENABLE_WALLET) + target_sources(bitcoinqt + PRIVATE + addressbookpage.cpp + addresstablemodel.cpp + askpassphrasedialog.cpp + coincontroldialog.cpp + coincontroltreewidget.cpp + createwalletdialog.cpp + editaddressdialog.cpp + openuridialog.cpp + overviewpage.cpp + paymentserver.cpp + psbtoperationsdialog.cpp + qrimagewidget.cpp + receivecoinsdialog.cpp + receiverequestdialog.cpp + recentrequeststablemodel.cpp + sendcoinsdialog.cpp + sendcoinsentry.cpp + signverifymessagedialog.cpp + transactiondesc.cpp + transactiondescdialog.cpp + transactionfilterproxy.cpp + transactionoverviewwidget.cpp + transactionrecord.cpp + transactiontablemodel.cpp + transactionview.cpp + walletcontroller.cpp + walletframe.cpp + walletmodel.cpp + walletmodeltransaction.cpp + walletview.cpp + ) + target_link_libraries(bitcoinqt + PRIVATE + bitcoin_wallet + Qt5::Network + ) +endif() + +if(CMAKE_CROSSCOMPILING) + target_compile_definitions(bitcoinqt PRIVATE QT_STATICPLUGIN) + if(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND TARGET Qt5::QXcbIntegrationPlugin) + target_compile_definitions(bitcoinqt PRIVATE QT_QPA_PLATFORM_XCB) + elseif(WIN32 AND TARGET Qt5::QWindowsIntegrationPlugin AND TARGET Qt5::QWindowsVistaStylePlugin) + target_compile_definitions(bitcoinqt PRIVATE QT_QPA_PLATFORM_WINDOWS) + elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND TARGET Qt5::QCocoaIntegrationPlugin AND TARGET Qt5::QMacStylePlugin) + target_compile_definitions(bitcoinqt PRIVATE QT_QPA_PLATFORM_COCOA) + endif() +endif() + +add_executable(bitcoin-qt + main.cpp + ../init/bitcoin-qt.cpp +) + +target_link_libraries(bitcoin-qt + core_interface + bitcoinqt + bitcoin_node +) + +if(WIN32) + set_target_properties(bitcoin-qt PROPERTIES WIN32_EXECUTABLE TRUE) +endif() + +install(TARGETS bitcoin-qt + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + COMPONENT GUI +) diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt new file mode 100644 index 0000000000000..eb8af00e6c4c9 --- /dev/null +++ b/src/test/CMakeLists.txt @@ -0,0 +1,178 @@ +# Copyright (c) 2023-present The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://opensource.org/license/mit/. + +include(GenerateHeaders) +generate_header_from_json(data/base58_encode_decode.json) +generate_header_from_json(data/bip341_wallet_vectors.json) +generate_header_from_json(data/blockfilters.json) +generate_header_from_json(data/key_io_invalid.json) +generate_header_from_json(data/key_io_valid.json) +generate_header_from_json(data/script_tests.json) +generate_header_from_json(data/sighash.json) +generate_header_from_json(data/tx_invalid.json) +generate_header_from_json(data/tx_valid.json) +generate_header_from_raw(data/asmap.raw) + +add_executable(test_bitcoin + main.cpp + $ + ${CMAKE_CURRENT_BINARY_DIR}/data/asmap.raw.h + ${CMAKE_CURRENT_BINARY_DIR}/data/base58_encode_decode.json.h + ${CMAKE_CURRENT_BINARY_DIR}/data/bip341_wallet_vectors.json.h + ${CMAKE_CURRENT_BINARY_DIR}/data/blockfilters.json.h + ${CMAKE_CURRENT_BINARY_DIR}/data/key_io_invalid.json.h + ${CMAKE_CURRENT_BINARY_DIR}/data/key_io_valid.json.h + ${CMAKE_CURRENT_BINARY_DIR}/data/script_tests.json.h + ${CMAKE_CURRENT_BINARY_DIR}/data/sighash.json.h + ${CMAKE_CURRENT_BINARY_DIR}/data/tx_invalid.json.h + ${CMAKE_CURRENT_BINARY_DIR}/data/tx_valid.json.h +# Tests: + addrman_tests.cpp + allocator_tests.cpp + amount_tests.cpp + argsman_tests.cpp + arith_uint256_tests.cpp + banman_tests.cpp + base32_tests.cpp + base58_tests.cpp + base64_tests.cpp + bech32_tests.cpp + bip32_tests.cpp + bip324_tests.cpp + blockchain_tests.cpp + blockencodings_tests.cpp + blockfilter_index_tests.cpp + blockfilter_tests.cpp + blockmanager_tests.cpp + bloom_tests.cpp + bswap_tests.cpp + checkqueue_tests.cpp + coins_tests.cpp + coinstatsindex_tests.cpp + compilerbug_tests.cpp + compress_tests.cpp + crypto_tests.cpp + cuckoocache_tests.cpp + dbwrapper_tests.cpp + denialofservice_tests.cpp + descriptor_tests.cpp + disconnected_transactions.cpp + flatfile_tests.cpp + fs_tests.cpp + getarg_tests.cpp + hash_tests.cpp + headers_sync_chainwork_tests.cpp + httpserver_tests.cpp + i2p_tests.cpp + interfaces_tests.cpp + key_io_tests.cpp + key_tests.cpp + logging_tests.cpp + mempool_tests.cpp + merkle_tests.cpp + merkleblock_tests.cpp + miner_tests.cpp + miniminer_tests.cpp + miniscript_tests.cpp + minisketch_tests.cpp + multisig_tests.cpp + net_peer_connection_tests.cpp + net_peer_eviction_tests.cpp + net_tests.cpp + netbase_tests.cpp + orphanage_tests.cpp + pmt_tests.cpp + policy_fee_tests.cpp + policyestimator_tests.cpp + pool_tests.cpp + pow_tests.cpp + prevector_tests.cpp + raii_event_tests.cpp + random_tests.cpp + rbf_tests.cpp + rest_tests.cpp + result_tests.cpp + reverselock_tests.cpp + rpc_tests.cpp + sanity_tests.cpp + scheduler_tests.cpp + script_p2sh_tests.cpp + script_parse_tests.cpp + script_segwit_tests.cpp + script_standard_tests.cpp + script_tests.cpp + scriptnum_tests.cpp + serfloat_tests.cpp + serialize_tests.cpp + settings_tests.cpp + sighash_tests.cpp + sigopcount_tests.cpp + skiplist_tests.cpp + sock_tests.cpp + span_tests.cpp + streams_tests.cpp + sync_tests.cpp + system_tests.cpp + timedata_tests.cpp + torcontrol_tests.cpp + transaction_tests.cpp + translation_tests.cpp + txindex_tests.cpp + txpackage_tests.cpp + txreconciliation_tests.cpp + txrequest_tests.cpp + txvalidation_tests.cpp + txvalidationcache_tests.cpp + uint256_tests.cpp + util_tests.cpp + util_threadnames_tests.cpp + validation_block_tests.cpp + validation_chainstate_tests.cpp + validation_chainstatemanager_tests.cpp + validation_flush_tests.cpp + validation_tests.cpp + validationinterface_tests.cpp + versionbits_tests.cpp + xoroshiro128plusplus_tests.cpp +) + +target_link_libraries(test_bitcoin + core_interface + test_util + bitcoin_cli + bitcoin_node + minisketch + Boost::headers +) + +if(ENABLE_WALLET) + target_sources(test_bitcoin + PRIVATE + ../wallet/test/init_test_fixture.cpp + ../wallet/test/wallet_test_fixture.cpp + + ../wallet/test/coinselector_tests.cpp + ../wallet/test/feebumper_tests.cpp + ../wallet/test/group_outputs_tests.cpp + ../wallet/test/init_tests.cpp + ../wallet/test/ismine_tests.cpp + ../wallet/test/psbt_wallet_tests.cpp + ../wallet/test/rpc_util_tests.cpp + ../wallet/test/scriptpubkeyman_tests.cpp + ../wallet/test/spend_tests.cpp + ../wallet/test/wallet_crypto_tests.cpp + ../wallet/test/wallet_tests.cpp + ../wallet/test/wallet_transaction_tests.cpp + ../wallet/test/walletdb_tests.cpp + ../wallet/test/walletload_tests.cpp + ) + target_link_libraries(test_bitcoin bitcoin_wallet) + if(USE_BDB) + target_sources(test_bitcoin PRIVATE ../wallet/test/db_tests.cpp) + endif() +endif() + +install(TARGETS test_bitcoin + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) diff --git a/src/test/compilerbug_tests.cpp b/src/test/compilerbug_tests.cpp index ef558c1e32269..4492a9686c766 100644 --- a/src/test/compilerbug_tests.cpp +++ b/src/test/compilerbug_tests.cpp @@ -6,6 +6,13 @@ BOOST_AUTO_TEST_SUITE(compilerbug_tests) +// At least one test case is required to avoid the "Test setup error: no test +// cases matching filter or all test cases were disabled" errror. +BOOST_AUTO_TEST_CASE(dummy) +{ + BOOST_CHECK(true); +} + #if defined(__GNUC__) // This block will also be built under clang, which is fine (as it supports noinline) void __attribute__ ((noinline)) set_one(unsigned char* ptr) diff --git a/src/test/fuzz/CMakeLists.txt b/src/test/fuzz/CMakeLists.txt new file mode 100644 index 0000000000000..b4acc4134ff26 --- /dev/null +++ b/src/test/fuzz/CMakeLists.txt @@ -0,0 +1,144 @@ +# Copyright (c) 2023-present The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://opensource.org/license/mit/. + +add_subdirectory(util) + +add_executable(fuzz + addition_overflow.cpp + addrman.cpp + asmap.cpp + asmap_direct.cpp + autofile.cpp + banman.cpp + base_encode_decode.cpp + bech32.cpp + bip324.cpp + bitdeque.cpp + block.cpp + block_header.cpp + blockfilter.cpp + bloom_filter.cpp + buffered_file.cpp + chain.cpp + checkqueue.cpp + coins_view.cpp + coinscache_sim.cpp + connman.cpp + crypto.cpp + crypto_aes256.cpp + crypto_aes256cbc.cpp + crypto_chacha20.cpp + crypto_common.cpp + crypto_diff_fuzz_chacha20.cpp + crypto_hkdf_hmac_sha256_l32.cpp + crypto_poly1305.cpp + cuckoocache.cpp + decode_tx.cpp + descriptor_parse.cpp + deserialize.cpp + eval_script.cpp + fee_rate.cpp + fees.cpp + flatfile.cpp + float.cpp + golomb_rice.cpp + headerssync.cpp + hex.cpp + http_request.cpp + integer.cpp + key.cpp + key_io.cpp + kitchen_sink.cpp + load_external_block_file.cpp + locale.cpp + merkleblock.cpp + message.cpp + miniscript.cpp + minisketch.cpp + mini_miner.cpp + muhash.cpp + multiplication_overflow.cpp + net.cpp + net_permissions.cpp + netaddress.cpp + netbase_dns_lookup.cpp + node_eviction.cpp + p2p_transport_serialization.cpp + package_eval.cpp + parse_hd_keypath.cpp + parse_numbers.cpp + parse_script.cpp + parse_univalue.cpp + partially_downloaded_block.cpp + policy_estimator.cpp + policy_estimator_io.cpp + poolresource.cpp + pow.cpp + prevector.cpp + primitives_transaction.cpp + process_message.cpp + process_messages.cpp + protocol.cpp + psbt.cpp + random.cpp + rbf.cpp + rolling_bloom_filter.cpp + rpc.cpp + script.cpp + script_assets_test_minimizer.cpp + script_descriptor_cache.cpp + script_flags.cpp + script_format.cpp + script_interpreter.cpp + script_ops.cpp + script_sigcache.cpp + script_sign.cpp + scriptnum_ops.cpp + secp256k1_ec_seckey_import_export_der.cpp + secp256k1_ecdsa_signature_parse_der_lax.cpp + signature_checker.cpp + signet.cpp + socks5.cpp + span.cpp + spanparsing.cpp + string.cpp + strprintf.cpp + system.cpp + timedata.cpp + torcontrol.cpp + transaction.cpp + tx_in.cpp + tx_out.cpp + tx_pool.cpp + txorphan.cpp + txrequest.cpp + utxo_snapshot.cpp + utxo_total_supply.cpp + validation_load_mempool.cpp + versionbits.cpp +) +target_link_libraries(fuzz + core_interface + test_fuzz + bitcoin_cli + bitcoin_common + minisketch + leveldb + univalue + secp256k1 + Boost::headers + libevent::libevent +) + +if(ENABLE_WALLET) + target_sources(fuzz + PRIVATE + ${CMAKE_SOURCE_DIR}/src/wallet/test/fuzz/coincontrol.cpp + ${CMAKE_SOURCE_DIR}/src/wallet/test/fuzz/coinselection.cpp + ${CMAKE_SOURCE_DIR}/src/wallet/test/fuzz/fees.cpp + ${CMAKE_SOURCE_DIR}/src/wallet/test/fuzz/parse_iso8601.cpp + $<$:${CMAKE_SOURCE_DIR}/src/wallet/test/fuzz/notifications.cpp> + ) + target_link_libraries(fuzz bitcoin_wallet) +endif() diff --git a/src/test/fuzz/util/CMakeLists.txt b/src/test/fuzz/util/CMakeLists.txt new file mode 100644 index 0000000000000..a5e148d4a8e1f --- /dev/null +++ b/src/test/fuzz/util/CMakeLists.txt @@ -0,0 +1,31 @@ +# Copyright (c) 2023-present The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://opensource.org/license/mit/. + +add_library(test_fuzz STATIC EXCLUDE_FROM_ALL + descriptor.cpp + mempool.cpp + net.cpp + ../fuzz.cpp + ../util.cpp +) + +target_link_libraries(test_fuzz + PRIVATE + core_interface + test_util + bitcoin_node + Boost::headers +) + +include(CheckSourceCompilesAndLinks) +check_cxx_source_links_with_flags("${SANITIZER_LDFLAGS}" " + #include + #include + extern \"C\" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { return 0; } + // No main() function. + " BINARY_LINKS_WITHOUT_MAIN_FUNCTION +) +if(NOT BINARY_LINKS_WITHOUT_MAIN_FUNCTION) + target_compile_definitions(test_fuzz PRIVATE PROVIDE_FUZZ_MAIN_FUNCTION) +endif() diff --git a/src/test/util/CMakeLists.txt b/src/test/util/CMakeLists.txt new file mode 100644 index 0000000000000..5d88d1da3ecf6 --- /dev/null +++ b/src/test/util/CMakeLists.txt @@ -0,0 +1,29 @@ +# Copyright (c) 2023-present The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://opensource.org/license/mit/. + +add_library(test_util STATIC EXCLUDE_FROM_ALL + blockfilter.cpp + coins.cpp + index.cpp + json.cpp + logging.cpp + mining.cpp + net.cpp + random.cpp + script.cpp + setup_common.cpp + str.cpp + transaction_utils.cpp + txmempool.cpp + validation.cpp + $<$:${PROJECT_SOURCE_DIR}/src/wallet/test/util.cpp> +) + +target_link_libraries(test_util + PRIVATE + core_interface + Boost::headers + PUBLIC + univalue +) diff --git a/src/univalue/CMakeLists.txt b/src/univalue/CMakeLists.txt new file mode 100644 index 0000000000000..796d3881b4cc8 --- /dev/null +++ b/src/univalue/CMakeLists.txt @@ -0,0 +1,17 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +add_library(univalue STATIC EXCLUDE_FROM_ALL + lib/univalue.cpp + lib/univalue_get.cpp + lib/univalue_read.cpp + lib/univalue_write.cpp +) + +target_include_directories(univalue + PUBLIC + $ +) + +target_link_libraries(univalue PRIVATE core_interface) diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt new file mode 100644 index 0000000000000..9834726094d0d --- /dev/null +++ b/src/util/CMakeLists.txt @@ -0,0 +1,57 @@ +# Copyright (c) 2023-present The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://opensource.org/license/mit/. + +add_library(bitcoin_util STATIC EXCLUDE_FROM_ALL + asmap.cpp + batchpriority.cpp + bip32.cpp + bytevectorhash.cpp + chaintype.cpp + check.cpp + error.cpp + exception.cpp + fees.cpp + fs.cpp + fs_helpers.cpp + hasher.cpp + message.cpp + moneystr.cpp + rbf.cpp + readwritefile.cpp + serfloat.cpp + signalinterrupt.cpp + sock.cpp + spanparsing.cpp + strencodings.cpp + string.cpp + syserror.cpp + thread.cpp + threadinterrupt.cpp + threadnames.cpp + time.cpp + tokenpipe.cpp + ../chainparamsbase.cpp + ../logging.cpp + ../random.cpp + ../randomenv.cpp + ../streams.cpp + ../support/cleanse.cpp + ../support/lockedpool.cpp + ../sync.cpp +) + +target_compile_definitions(bitcoin_util + PRIVATE + ${THREAD_LOCAL_IF_AVAILABLE} + $<$:_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING> +) + +target_link_libraries(bitcoin_util + PRIVATE + core_interface + bitcoin_clientversion + bitcoin_crypto + Threads::Threads + $<$:ws2_32> +) diff --git a/src/wallet/CMakeLists.txt b/src/wallet/CMakeLists.txt new file mode 100644 index 0000000000000..99c1f2c9bea25 --- /dev/null +++ b/src/wallet/CMakeLists.txt @@ -0,0 +1,57 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# Wallet functionality used by bitcoind and bitcoin-wallet executables. +add_library(bitcoin_wallet STATIC EXCLUDE_FROM_ALL + coincontrol.cpp + coinselection.cpp + context.cpp + crypter.cpp + db.cpp + dump.cpp + external_signer_scriptpubkeyman.cpp + feebumper.cpp + fees.cpp + interfaces.cpp + load.cpp + receive.cpp + rpc/addresses.cpp + rpc/backup.cpp + rpc/coins.cpp + rpc/encrypt.cpp + rpc/spend.cpp + rpc/signmessage.cpp + rpc/transactions.cpp + rpc/util.cpp + rpc/wallet.cpp + scriptpubkeyman.cpp + spend.cpp + transaction.cpp + wallet.cpp + walletdb.cpp + walletutil.cpp +) +target_link_libraries(bitcoin_wallet + PRIVATE + core_interface + bitcoin_common + univalue + Boost::headers +) + +if(NOT USE_SQLITE AND NOT USE_BDB) + message(FATAL_ERROR "Wallet functionality requested but no BDB or SQLite support available.") +endif() +if(USE_SQLITE) + target_sources(bitcoin_wallet PRIVATE sqlite.cpp) + target_link_libraries(bitcoin_wallet + PRIVATE + $ + $ + ) +endif() +if(USE_BDB) + target_sources(bitcoin_wallet PRIVATE bdb.cpp salvage.cpp) + target_link_libraries(bitcoin_wallet PUBLIC BerkeleyDB::BerkeleyDB) +endif() diff --git a/src/zmq/CMakeLists.txt b/src/zmq/CMakeLists.txt new file mode 100644 index 0000000000000..61fdaa819ff1e --- /dev/null +++ b/src/zmq/CMakeLists.txt @@ -0,0 +1,22 @@ +# Copyright (c) 2023-present The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://opensource.org/license/mit/. + +add_library(bitcoin_zmq STATIC + zmqabstractnotifier.cpp + zmqnotificationinterface.cpp + zmqpublishnotifier.cpp + zmqrpc.cpp + zmqutil.cpp +) +target_compile_definitions(bitcoin_zmq + INTERFACE + ENABLE_ZMQ=1 +) +target_link_libraries(bitcoin_zmq + PRIVATE + core_interface + univalue + $ + $ +) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000000000..3b7eeb93036c1 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,49 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +function(create_test_config) + set(abs_top_srcdir ${PROJECT_SOURCE_DIR}) + set(abs_top_builddir ${PROJECT_BINARY_DIR}) + set(EXEEXT ${CMAKE_EXECUTABLE_SUFFIX}) + + macro(set_configure_variable var conf_var) + if(${var}) + set(${conf_var}_TRUE "") + else() + set(${conf_var}_TRUE "#") + endif() + endmacro() + + set_configure_variable(ENABLE_WALLET ENABLE_WALLET) + set_configure_variable(WITH_SQLITE USE_SQLITE) + set_configure_variable(WITH_BDB USE_BDB) + set_configure_variable(BUILD_CLI BUILD_BITCOIN_CLI) + set_configure_variable(BUILD_UTIL BUILD_BITCOIN_UTIL) + set_configure_variable(BUILD_WALLET_TOOL BUILD_BITCOIN_WALLET) + set_configure_variable(BUILD_DAEMON BUILD_BITCOIND_TRUE) + set_configure_variable(FUZZ ENABLE_FUZZ) + set_configure_variable(WITH_ZMQ ENABLE_ZMQ) + set_configure_variable(ENABLE_EXTERNAL_SIGNER ENABLE_EXTERNAL_SIGNER) + set_configure_variable(ENABLE_TRACING ENABLE_USDT_TRACEPOINTS) + + configure_file(config.ini.in config.ini @ONLY) +endfunction() + +create_test_config() + +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/functional) +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/fuzz) +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/util) + +function(create_test_script script) + if(MSVC) + file(CREATE_LINK ${CMAKE_CURRENT_SOURCE_DIR}/${script} ${CMAKE_CURRENT_BINARY_DIR}/${script} COPY_ON_ERROR) + else() + file(CREATE_LINK ${CMAKE_CURRENT_SOURCE_DIR}/${script} ${CMAKE_CURRENT_BINARY_DIR}/${script} COPY_ON_ERROR SYMBOLIC) + endif() +endfunction() + +foreach(script functional/test_runner.py fuzz/test_runner.py util/rpcauth-test.py util/test_runner.py) + create_test_script(${script}) +endforeach() diff --git a/vcpkg.json b/vcpkg.json new file mode 100644 index 0000000000000..2917412320821 --- /dev/null +++ b/vcpkg.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json", + "builtin-baseline": "9edb1b8e590cc086563301d735cae4b6e732d2d2", + "dependencies": [ + "berkeleydb", + "boost-date-time", + "boost-multi-index", + "boost-process", + "boost-signals2", + "boost-test", + "libevent", + "miniupnpc", + "sqlite3", + "qt5-base", + "qt5-tools", + "zeromq" + ] +}