Merge pull request #1107 from gwillen/test-fix-1058

Bring Elements up to date with Bitcoin Core 22.0 (Updated)
This commit is contained in:
Glenn Willen 2022-06-28 16:27:30 -07:00 committed by GitHub
commit 87028135ad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
1341 changed files with 99665 additions and 38629 deletions

View file

@ -1,29 +1,30 @@
version: '{branch}.{build}'
skip_tags: true
image: Previous Visual Studio 2019
image: Visual Studio 2019
configuration: Release
platform: x64
clone_depth: 5
environment:
PATH: 'C:\Python37-x64;C:\Python37-x64\Scripts;%PATH%'
PYTHONUTF8: 1
QT_DOWNLOAD_URL: 'https://github.com/sipsorcery/qt_win_binary/releases/download/v1.6/Qt5.9.8_x64_static_vs2019.zip'
QT_DOWNLOAD_HASH: '9a8c6eb20967873785057fdcd329a657c7f922b0af08c5fde105cc597dd37e21'
QT_LOCAL_PATH: 'C:\Qt5.9.8_x64_static_vs2019'
VCPKG_INSTALL_PATH: 'C:\tools\vcpkg\installed'
VCPKG_COMMIT_ID: '40230b8e3f6368dcb398d649331be878ca1e9007'
QT_DOWNLOAD_URL: 'https://github.com/sipsorcery/qt_win_binary/releases/download/qt51211x64_static_vs2019_16101/Qt5.12.11_x64_static_vs2019_16101.zip'
QT_DOWNLOAD_HASH: 'cf1b58107fadbf0d9a957d14dab16cde6b6eb6936a1908472da1f967dda34a3a'
QT_LOCAL_PATH: 'C:\Qt5.12.11_x64_static_vs2019_16101'
VCPKG_TAG: '75522bb1f2e7d863078bcd06322348f053a9e33f'
install:
# Disable zmq test for now since python zmq library on Windows would cause Access violation sometimes.
# - cmd: pip install zmq
# Powershell block below is to install the c++ dependencies via vcpkg. The pseudo code is:
# The powershell block below is to set up vcpkg to install the c++ dependencies. The pseudo code is:
# a. Checkout the vcpkg source (including port files) for the specific checkout and build the vcpkg binary,
# b. Install the missing packages using the vcpkg manifest.
# b. Append a setting to the vcpkg cmake config file to only do release builds of dependencies (skipping deubg builds saves ~5 mins).
# Note originally this block also installed the dependencies using 'vcpkg install'. Dependencies are now installed
# as part of the msbuild command using vcpkg mainfests.
- ps: |
cd c:\tools\vcpkg
$env:GIT_REDIRECT_STDERR = '2>&1' # git is writing non-errors to STDERR when doing git pull. Send to STDOUT instead.
git pull origin master > $null
git -c advice.detachedHead=false checkout $env:VCPKG_COMMIT_ID
git -c advice.detachedHead=false checkout $env:VCPKG_TAG
.\bootstrap-vcpkg.bat > $null
Add-Content "C:\tools\vcpkg\triplets\$env:PLATFORM-windows-static.cmake" "set(VCPKG_BUILD_TYPE release)"
cd "$env:APPVEYOR_BUILD_FOLDER"
before_build:
# Powershell block below is to download and extract the Qt static libraries. The pseudo code is:

View file

@ -1,34 +1,26 @@
### Global defaults
timeout_in: 120m # https://cirrus-ci.org/faq/#instance-timed-out
container:
# https://cirrus-ci.org/faq/#are-there-any-limits
# Each project has 16 CPU in total, assign 2 to each container, so that 8 tasks run in parallel
cpu: 2
memory: 8G # Set to 8GB to avoid OOM. https://cirrus-ci.org/guide/linux/#linux-containers
kvm: true # Use kvm to avoid spurious CI failures in the default virtualization cluster, see https://github.com/bitcoin/bitcoin/issues/20093
env:
SECP256K1_TEST_ITERS: 16 # ELEMENTS: avoid test timeouts on arm
PACKAGE_MANAGER_INSTALL: "apt-get update && apt-get install -y"
MAKEJOBS: "-j3" # ELEMENTS: reduced from j4
DANGER_RUN_CI_ON_HOST: "1" # Containers will be discarded after the run, so there is no risk that the ci scripts modify the system
TEST_RUNNER_PORT_MIN: "14000" # Must be larger than 12321, which is used for the http cache. See https://cirrus-ci.org/guide/writing-tasks/#http-cache
CCACHE_SIZE: "200M"
CCACHE_DIR: "/tmp/ccache_dir"
CCACHE_NOHASHDIR: "1" # Debug info might contain a stale path if the build dir changes, but this is fine
### Global task template
cirrus_ephemeral_worker_template_env: &CIRRUS_EPHEMERAL_WORKER_TEMPLATE_ENV
DANGER_RUN_CI_ON_HOST: "1" # Containers will be discarded after the run, so there is no risk that the ci scripts modify the system
persistent_worker_template_env: &PERSISTENT_WORKER_TEMPLATE_ENV
RESTART_CI_DOCKER_BEFORE_RUN: "1"
persistent_worker_template: &PERSISTENT_WORKER_TEMPLATE
persistent_worker: {} # https://cirrus-ci.org/guide/persistent-workers/
# https://cirrus-ci.org/guide/tips-and-tricks/#sharing-configuration-between-tasks
global_task_template: &GLOBAL_TASK_TEMPLATE
base_template: &BASE_TEMPLATE
skip: $CIRRUS_REPO_FULL_NAME == "bitcoin-core/gui" && $CIRRUS_PR == "" # No need to run on the read-only mirror, unless it is a PR. https://cirrus-ci.org/guide/writing-tasks/#conditional-task-execution
ccache_cache:
folder: "/tmp/ccache_dir"
depends_built_cache:
folder: "/tmp/cirrus-ci-build/depends/built"
depends_sdk_cache:
folder: "/tmp/cirrus-ci-build/depends/sdk-sources"
depends_releases_cache:
folder: "/tmp/cirrus-ci-build/releases"
merge_base_script:
- if [ "$CIRRUS_PR" = "" ]; then exit 0; fi
- bash -c "$PACKAGE_MANAGER_INSTALL git"
@ -36,9 +28,32 @@ global_task_template: &GLOBAL_TASK_TEMPLATE
- git config --global user.email "ci@ci.ci"
- git config --global user.name "ci"
- git merge FETCH_HEAD # Merge base to detect silent merge conflicts
stateful: false # https://cirrus-ci.org/guide/writing-tasks/#stateful-tasks
global_task_template: &GLOBAL_TASK_TEMPLATE
<< : *BASE_TEMPLATE
timeout_in: 120m # https://cirrus-ci.org/faq/#instance-timed-out
container:
# https://cirrus-ci.org/faq/#are-there-any-limits
# Each project has 16 CPU in total, assign 2 to each container, so that 8 tasks run in parallel
cpu: 2
memory: 8G # Set to 8GB to avoid OOM. https://cirrus-ci.org/guide/linux/#linux-containers
ccache_cache:
folder: "/tmp/ccache_dir"
depends_built_cache:
folder: "depends/built"
ci_script:
- ./ci/test_run_all.sh
depends_sdk_cache_template: &DEPENDS_SDK_CACHE_TEMPLATE
depends_sdk_cache:
folder: "depends/sdk-sources"
compute_credits_template: &CREDITS_TEMPLATE
# https://cirrus-ci.org/pricing/#compute-credits
# Only use credits for pull requests to the main repo
use_compute_credits: $CIRRUS_REPO_FULL_NAME == 'ElementsProject/elements' && $CIRRUS_PR != ""
#task:
# name: "Windows"
# windows_container:
@ -55,38 +70,67 @@ global_task_template: &GLOBAL_TASK_TEMPLATE
# install_script:
# - choco install python --version=3.7.7 -y
task:
name: 'lint [bionic]'
<< : *BASE_TEMPLATE
container:
image: ubuntu:bionic # For python 3.6, oldest supported version according to doc/dependencies.md
cpu: 1
memory: 1G
# For faster CI feedback, immediately schedule the linters
<< : *CREDITS_TEMPLATE
lint_script:
- ./ci/lint_run_all.sh
env:
<< : *CIRRUS_EPHEMERAL_WORKER_TEMPLATE_ENV
task:
name: 'ARM [unit tests, no functional tests] [buster]'
<< : *GLOBAL_TASK_TEMPLATE
container:
image: debian:buster
env:
<< : *CIRRUS_EPHEMERAL_WORKER_TEMPLATE_ENV
FILE_ENV: "./ci/test/00_setup_env_arm.sh"
task:
name: 'Win64 [unit tests, no gui tests, no boost::process, no functional tests] [bionic]'
<< : *GLOBAL_TASK_TEMPLATE
container:
image: ubuntu:bionic
env:
FILE_ENV: "./ci/test/00_setup_env_win64.sh"
task:
name: '[previous releases, uses qt5 dev package and some depends packages] [unsigned char] [bionic]'
<< : *GLOBAL_TASK_TEMPLATE
container:
image: ubuntu:bionic
env:
FILE_ENV: "./ci/test/00_setup_env_native_qt5.sh"
task:
name: '[depends, sanitizers: thread (TSan), no gui] [focal]'
name: 'Win64 [unit tests, no gui tests, no boost::process, no functional tests] [focal]'
<< : *GLOBAL_TASK_TEMPLATE
container:
image: ubuntu:focal
cpu: 4 # Double CPU and Memory to avoid timeout
memory: 16G
env:
<< : *CIRRUS_EPHEMERAL_WORKER_TEMPLATE_ENV
FILE_ENV: "./ci/test/00_setup_env_win64.sh"
task:
name: '32-bit + dash [gui] [CentOS 8]'
<< : *GLOBAL_TASK_TEMPLATE
container:
image: quay.io/centos/centos:stream8
env:
<< : *CIRRUS_EPHEMERAL_WORKER_TEMPLATE_ENV
PACKAGE_MANAGER_INSTALL: "yum install -y"
FILE_ENV: "./ci/test/00_setup_env_i686_centos.sh"
task:
name: '[previous releases, uses qt5 dev package and some depends packages, DEBUG] [unsigned char] [bionic]'
previous_releases_cache:
folder: "releases"
<< : *GLOBAL_TASK_TEMPLATE
<< : *PERSISTENT_WORKER_TEMPLATE
env:
<< : *PERSISTENT_WORKER_TEMPLATE_ENV
FILE_ENV: "./ci/test/00_setup_env_native_qt5.sh"
task:
name: '[depends, sanitizers: thread (TSan), no gui] [hirsute]'
<< : *GLOBAL_TASK_TEMPLATE
container:
image: ubuntu:hirsute
cpu: 6 # Increase CPU and Memory to avoid timeout
memory: 24G
env:
<< : *CIRRUS_EPHEMERAL_WORKER_TEMPLATE_ENV
MAKEJOBS: "-j6" # ELEMENTS: reduced from -j8
FILE_ENV: "./ci/test/00_setup_env_native_tsan.sh"
@ -96,34 +140,44 @@ task:
container:
image: ubuntu:focal
env:
<< : *CIRRUS_EPHEMERAL_WORKER_TEMPLATE_ENV
FILE_ENV: "./ci/test/00_setup_env_native_msan.sh"
task:
name: '[no depends, only system libs, sanitizers: address/leak (ASan + LSan) + undefined (UBSan) + integer] [focal]'
name: '[no depends, sanitizers: address/leak (ASan + LSan) + undefined (UBSan) + integer] [hirsute]'
<< : *GLOBAL_TASK_TEMPLATE
container:
image: ubuntu:focal
image: ubuntu:hirsute
memory: 16G # ELEMENTS: need more memory
cpu: 4 # ELEMENTS: cirrus wants more CPUs if you want more memory
env:
<< : *CIRRUS_EPHEMERAL_WORKER_TEMPLATE_ENV
FILE_ENV: "./ci/test/00_setup_env_native_asan.sh"
task:
name: '[no depends, only system libs, sanitizers: fuzzer,address,undefined] [focal]'
name: '[no depends, sanitizers: fuzzer,address,undefined,integer] [focal]'
<< : *GLOBAL_TASK_TEMPLATE
container:
image: ubuntu:focal
memory: 16G # ELEMENTS: need more memory
cpu: 4 # ELEMENTS: cirrus wants more CPUs if you want more memory
cpu: 4 # Increase CPU and memory to avoid timeout
memory: 16G
env:
<< : *CIRRUS_EPHEMERAL_WORKER_TEMPLATE_ENV
MAKEJOBS: "-j8"
FILE_ENV: "./ci/test/00_setup_env_native_fuzz.sh"
task:
name: '[multiprocess] [focal]'
name: '[multiprocess, DEBUG] [focal]'
# Disable for Elements for now; Multiprocess build is not supported or tested and fails CI.
only_if: false
<< : *GLOBAL_TASK_TEMPLATE
container:
image: ubuntu:focal
cpu: 4
memory: 16G # The default memory is sometimes just a bit too small, so double everything
env:
<< : *CIRRUS_EPHEMERAL_WORKER_TEMPLATE_ENV
MAKEJOBS: "-j8"
FILE_ENV: "./ci/test/00_setup_env_native_multiprocess.sh"
task:
@ -132,26 +186,43 @@ task:
container:
image: ubuntu:bionic
env:
<< : *CIRRUS_EPHEMERAL_WORKER_TEMPLATE_ENV
FILE_ENV: "./ci/test/00_setup_env_native_nowallet.sh"
task:
name: 'macOS 10.14 [gui, no tests] [bionic]'
name: 'macOS 10.14 [gui, no tests] [focal]'
<< : *DEPENDS_SDK_CACHE_TEMPLATE
<< : *GLOBAL_TASK_TEMPLATE
container:
image: ubuntu:bionic
image: ubuntu:focal
env:
<< : *CIRRUS_EPHEMERAL_WORKER_TEMPLATE_ENV
FILE_ENV: "./ci/test/00_setup_env_mac.sh"
task:
name: 'macOS 11 native [gui] [no depends]'
brew_install_script:
- brew install boost libevent berkeley-db4 qt@5 miniupnpc ccache zeromq qrencode sqlite libtool automake pkg-config gnu-getopt
- brew install boost libevent berkeley-db4 qt@5 miniupnpc libnatpmp ccache zeromq qrencode sqlite libtool automake pkg-config gnu-getopt
<< : *GLOBAL_TASK_TEMPLATE
osx_instance:
# Use latest image, but hardcode version to avoid silent upgrades (and breaks)
image: big-sur-xcode-12.5 # https://cirrus-ci.org/guide/macOS
env:
DANGER_RUN_CI_ON_HOST: "true"
<< : *CIRRUS_EPHEMERAL_WORKER_TEMPLATE_ENV
CI_USE_APT_INSTALL: "no"
PACKAGE_MANAGER_INSTALL: "echo" # Nothing to do
FILE_ENV: "./ci/test/00_setup_env_mac_host.sh"
task:
name: 'ARM64 Android APK [focal]'
# Disable for Elements; Android build is broken and unsupported.
only_if: false
<< : *DEPENDS_SDK_CACHE_TEMPLATE
depends_sources_cache:
folder: "depends/sources"
<< : *GLOBAL_TASK_TEMPLATE
container:
image: ubuntu:focal
env:
<< : *CIRRUS_EPHEMERAL_WORKER_TEMPLATE_ENV
FILE_ENV: "./ci/test/00_setup_env_android.sh"

26
.editorconfig Normal file
View file

@ -0,0 +1,26 @@
# This is the top-most EditorConfig file.
root = true
# For all files.
[*]
charset = utf-8
end_of_line = lf
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
# Source code files
[*.{h,cpp,py,sh}]
indent_size = 4
# .cirrus.yml, .appveyor.yml, .fuzzbuzz.yml, etc.
[*.yml]
indent_size = 2
# Makefiles
[{*.am,Makefile.*.include}]
indent_style = tab
# Autoconf scripts
[configure.ac]
indent_size = 2

View file

@ -1,16 +0,0 @@
base: ubuntu:16.04
language: c++
engine: libFuzzer
environment:
- CXXFLAGS=-fcoverage-mapping -fno-omit-frame-pointer -fprofile-instr-generate -gline-tables-only -O1
setup:
- sudo apt-get update
- sudo apt-get install -y autoconf bsdmainutils clang git libboost-all-dev libboost-program-options-dev libc++1 libc++abi1 libc++abi-dev libc++-dev libclang1 libclang-dev libdb5.3++ libevent-dev libllvm-ocaml-dev libomp5 libomp-dev libprotobuf-dev libqt5core5a libqt5dbus5 libqt5gui5 libssl-dev libtool llvm llvm-dev llvm-runtime pkg-config protobuf-compiler qttools5-dev qttools5-dev-tools software-properties-common
- ./autogen.sh
- CC=clang CXX=clang++ ./configure --enable-fuzz --with-sanitizers=address,fuzzer,undefined
- make
- git clone https://github.com/bitcoin-core/qa-assets
auto_targets:
find_targets_command: find src/test/fuzz/ -executable -type f ! -name "*.cpp" ! -name "*.h"
base_corpus_dir: qa-assets/fuzz_seed_corpus/
memory_limit: none

9
.gitignore vendored
View file

@ -8,9 +8,9 @@ src/elements-cli
src/elements-gui
src/elements-node
src/elements-tx
src/elements-util
src/elements-wallet
src/test/fuzz/*
!src/test/fuzz/*.*
src/test/fuzz/fuzz
src/test/test_bitcoin
src/qt/test/test_elements-qt
@ -61,7 +61,7 @@ src/qt/bitcoin-qt.includes
.dirstamp
.libs
.*.swp
*.*~*
*~
*.bak
*.rej
*.orig
@ -76,6 +76,7 @@ src/qt/bitcoin-qt.includes
*.log
*.trs
*.dmg
*.iso
*.json.h
*.raw.h
@ -148,3 +149,5 @@ db4/
osx_volname
dist/
*.background.tiff
/guix-build-*

View file

@ -1 +1 @@
3.5.6
3.6.12

View file

@ -1,71 +0,0 @@
# Travis caches can be manually removed if necessary. This is one of the very
# few manual operations that is possible with Travis, and it can be done by a
# Bitcoin Core GitHub member via the Travis web interface [0].
#
# Travis CI uploads the cache after the script phase of the build [1].
# However, the build is terminated without saving the cache if it takes over
# 50 minutes [2]. Thus, if we spent too much time in early build stages, fail
# with an error and save the cache.
#
# [0] https://travis-ci.org/bitcoin/bitcoin/caches
# [1] https://docs.travis-ci.com/user/caching/#build-phases
# [2] https://docs.travis-ci.com/user/customizing-the-build#build-timeouts
version: ~> 1.0
dist: bionic
os: linux
language: minimal
arch: amd64
cache:
directories:
- $TRAVIS_BUILD_DIR/depends/built
- $TRAVIS_BUILD_DIR/depends/sdk-sources
- $TRAVIS_BUILD_DIR/ci/scratch/.ccache
- $TRAVIS_BUILD_DIR/releases/$HOST
stages:
- lint
- test
env:
global:
- CI_RETRY_EXE="travis_retry"
- CACHE_ERR_MSG="Error! Initial build successful, but not enough time remains to run later build stages and tests. See https://docs.travis-ci.com/user/customizing-the-build#build-timeouts . Please manually re-run this job by using the travis restart button. The next run should not time out because the build cache has been saved."
before_install:
- set -o errexit; source ./ci/test/00_setup_env.sh
- set -o errexit; source ./ci/test/03_before_install.sh
install:
- set -o errexit; source ./ci/test/04_install.sh
before_script:
# Temporary workaround for https://github.com/bitcoin/bitcoin/issues/16368
- for i in {1..4}; do echo "$(sleep 500)" ; done &
- set -o errexit; source ./ci/test/05_before_script.sh &> "/dev/null"
script:
- export CONTINUE=1
- if [ $SECONDS -gt 1200 ]; then export CONTINUE=0; fi # Likely the depends build took very long
- if [ $TRAVIS_REPO_SLUG = "bitcoin/bitcoin" ]; then export CONTINUE=1; fi # continue on repos with extended build time (90 minutes)
- if [ $CONTINUE = "1" ]; then set -o errexit; source ./ci/test/06_script_a.sh; else set +o errexit; echo "$CACHE_ERR_MSG"; false; fi
- if [[ $SECONDS -gt 50*60-$EXPECTED_TESTS_DURATION_IN_SECONDS ]]; then export CONTINUE=0; fi
- if [ $TRAVIS_REPO_SLUG = "bitcoin/bitcoin" ]; then export CONTINUE=1; fi # continue on repos with extended build time (90 minutes)
- if [ $CONTINUE = "1" ]; then set -o errexit; source ./ci/test/06_script_b.sh; else set +o errexit; echo "$CACHE_ERR_MSG"; false; fi
after_script:
- echo $TRAVIS_COMMIT_RANGE
jobs:
include:
- stage: lint
name: 'lint'
env:
cache: pip
language: python
python: '3.5' # Oldest supported version according to doc/dependencies.md
install:
- set -o errexit; source ./ci/lint/04_install.sh
before_script:
- set -o errexit; source ./ci/lint/05_before_script.sh
script:
- set -o errexit; source ./ci/lint/06_script.sh
- stage: test
name: '32-bit + dash [GOAL: install] [CentOS 8] [gui]'
env: >-
FILE_ENV="./ci/test/00_setup_env_i686_centos.sh"

View file

@ -1,7 +1,7 @@
[main]
host = https://www.transifex.com
[bitcoin.qt-translation-021x]
file_filter = src/qt/locale/bitcoin_<lang>.ts
source_file = src/qt/locale/bitcoin_en.ts
[bitcoin.qt-translation-022x]
file_filter = src/qt/locale/bitcoin_<lang>.xlf
source_file = src/qt/locale/bitcoin_en.xlf
source_lang = en

View file

@ -57,8 +57,8 @@ Communication Channels
----------------------
Most communication about Bitcoin Core development happens on IRC, in the
`#bitcoin-core-dev` channel on Freenode. The easiest way to participate on IRC is
with the web client, [webchat.freenode.net](https://webchat.freenode.net/). Chat
`#bitcoin-core-dev` channel on Libera Chat. The easiest way to participate on IRC is
with the web client, [web.libera.chat](https://web.libera.chat/#bitcoin-core-dev). Chat
history logs can be found
on [http://www.erisian.com.au/bitcoin-core-dev/](http://www.erisian.com.au/bitcoin-core-dev/)
and [http://gnusha.org/bitcoin-core-dev/](http://gnusha.org/bitcoin-core-dev/).
@ -197,7 +197,7 @@ Note: Code review is a burdensome but important part of the development process,
If your pull request contains fixup commits (commits that change the same line of code repeatedly) or too fine-grained
commits, you may be asked to [squash](https://git-scm.com/docs/git-rebase#_interactive_mode) your commits
before it will be merged. The basic squashing workflow is shown below.
before it will be reviewed. The basic squashing workflow is shown below.
git checkout your_branch_name
git rebase -i HEAD~n

View file

@ -1,7 +1,7 @@
The MIT License (MIT)
Copyright (c) 2009-2020 The Bitcoin Core developers
Copyright (c) 2009-2020 Bitcoin Developers
Copyright (c) 2009-2021 The Bitcoin Core developers
Copyright (c) 2009-2021 Bitcoin Developers
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View file

@ -3,8 +3,8 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
# Pattern rule to print variables, e.g. make print-top_srcdir
print-%:
@echo $* = $($*)
print-%: FORCE
@echo '$*'='$($*)'
ACLOCAL_AMFLAGS = -I build-aux/m4
SUBDIRS = src
@ -12,6 +12,7 @@ if ENABLE_MAN
SUBDIRS += doc/man
endif
.PHONY: deploy FORCE
.INTERMEDIATE: $(OSX_TEMP_ISO) $(COVERAGE_INFO)
export PYTHONPATH
@ -24,26 +25,30 @@ BITCOIND_BIN=$(top_builddir)/src/$(BITCOIN_DAEMON_NAME)$(EXEEXT)
BITCOIN_QT_BIN=$(top_builddir)/src/qt/$(BITCOIN_GUI_NAME)$(EXEEXT)
BITCOIN_CLI_BIN=$(top_builddir)/src/$(BITCOIN_CLI_NAME)$(EXEEXT)
BITCOIN_TX_BIN=$(top_builddir)/src/$(BITCOIN_TX_NAME)$(EXEEXT)
BITCOIN_UTIL_BIN=$(top_builddir)/src/$(BITCOIN_UTIL_NAME)$(EXEEXT)
BITCOIN_WALLET_BIN=$(top_builddir)/src/$(BITCOIN_WALLET_TOOL_NAME)$(EXEEXT)
BITCOIN_NODE_BIN=$(top_builddir)/src/$(BITCOIN_MP_NODE_NAME)$(EXEEXT)
BITCOIN_GUI_BIN=$(top_builddir)/src/$(BITCOIN_MP_GUI_NAME)$(EXEEXT)
BITCOIN_WIN_INSTALLER=$(PACKAGE)-$(PACKAGE_VERSION)-win64-setup$(EXEEXT)
empty :=
space := $(empty) $(empty)
OSX_APP=Bitcoin-Qt.app
OSX_APP=Elements-Qt.app
OSX_VOLNAME = $(subst $(space),-,$(PACKAGE_NAME))
OSX_DMG = $(OSX_VOLNAME).dmg
OSX_TEMP_ISO = $(OSX_DMG:.dmg=).temp.iso
OSX_BACKGROUND_SVG=background.svg
OSX_BACKGROUND_IMAGE=background.tiff
OSX_BACKGROUND_IMAGE_DPIS=36 72
OSX_DSSTORE_GEN=$(top_srcdir)/contrib/macdeploy/custom_dsstore.py
OSX_DEPLOY_SCRIPT=$(top_srcdir)/contrib/macdeploy/macdeployqtplus
OSX_FANCY_PLIST=$(top_srcdir)/contrib/macdeploy/fancy.plist
OSX_INSTALLER_ICONS=$(top_srcdir)/src/qt/res/icons/bitcoin.icns
OSX_PLIST=$(top_builddir)/share/qt/Info.plist #not installed
OSX_QT_TRANSLATIONS = ar,bg,ca,cs,da,de,es,fa,fi,fr,gd,gl,he,hu,it,ja,ko,lt,lv,pl,pt,ru,sk,sl,sv,uk,zh_CN,zh_TW
DIST_CONTRIB = \
$(top_srcdir)/test/sanitizer_suppressions/lsan \
$(top_srcdir)/test/sanitizer_suppressions/tsan \
$(top_srcdir)/test/sanitizer_suppressions/ubsan \
$(top_srcdir)/contrib/linearize/linearize-data.py \
$(top_srcdir)/contrib/linearize/linearize-hashes.py
@ -52,16 +57,17 @@ DIST_SHARE = \
$(top_srcdir)/share/rpcauth
BIN_CHECKS=$(top_srcdir)/contrib/devtools/symbol-check.py \
$(top_srcdir)/contrib/devtools/security-check.py
$(top_srcdir)/contrib/devtools/security-check.py \
$(top_srcdir)/contrib/devtools/utils.py \
$(top_srcdir)/contrib/devtools/pixie.py
WINDOWS_PACKAGING = $(top_srcdir)/share/pixmaps/bitcoin.ico \
$(top_srcdir)/share/pixmaps/nsis-header.bmp \
$(top_srcdir)/share/pixmaps/nsis-wizard.bmp \
$(top_srcdir)/doc/README_windows.txt
OSX_PACKAGING = $(OSX_DEPLOY_SCRIPT) $(OSX_FANCY_PLIST) $(OSX_INSTALLER_ICONS) \
OSX_PACKAGING = $(OSX_DEPLOY_SCRIPT) $(OSX_INSTALLER_ICONS) \
$(top_srcdir)/contrib/macdeploy/$(OSX_BACKGROUND_SVG) \
$(OSX_DSSTORE_GEN) \
$(top_srcdir)/contrib/macdeploy/detached-sig-apply.sh \
$(top_srcdir)/contrib/macdeploy/detached-sig-create.sh
@ -73,6 +79,7 @@ COVERAGE_INFO = $(COV_TOOL_WRAPPER) baseline.info \
dist-hook:
-$(GIT) archive --format=tar HEAD -- src/clientversion.cpp | $(AMTAR) -C $(top_distdir) -xf -
if TARGET_WINDOWS
$(BITCOIN_WIN_INSTALLER): all-recursive
$(MKDIR_P) $(top_builddir)/release
STRIPPROG="$(STRIP)" $(INSTALL_STRIP_PROGRAM) $(BITCOIND_BIN) $(top_builddir)/release
@ -80,10 +87,15 @@ $(BITCOIN_WIN_INSTALLER): all-recursive
STRIPPROG="$(STRIP)" $(INSTALL_STRIP_PROGRAM) $(BITCOIN_CLI_BIN) $(top_builddir)/release
STRIPPROG="$(STRIP)" $(INSTALL_STRIP_PROGRAM) $(BITCOIN_TX_BIN) $(top_builddir)/release
STRIPPROG="$(STRIP)" $(INSTALL_STRIP_PROGRAM) $(BITCOIN_WALLET_BIN) $(top_builddir)/release
STRIPPROG="$(STRIP)" $(INSTALL_STRIP_PROGRAM) $(BITCOIN_UTIL_BIN) $(top_builddir)/release
@test -f $(MAKENSIS) && echo 'OutFile "$@"' | cat $(top_builddir)/share/setup.nsi - | $(MAKENSIS) -V2 - || \
echo error: could not build $@
@echo built $@
deploy: $(BITCOIN_WIN_INSTALLER)
endif
if TARGET_DARWIN
$(OSX_APP)/Contents/PkgInfo:
$(MKDIR_P) $(@D)
@echo "APPL????" > $@
@ -117,7 +129,7 @@ osx_volname:
if BUILD_DARWIN
$(OSX_DMG): $(OSX_APP_BUILT) $(OSX_PACKAGING) $(OSX_BACKGROUND_IMAGE)
$(PYTHON) $(OSX_DEPLOY_SCRIPT) $(OSX_APP) -add-qt-tr $(OSX_QT_TRANSLATIONS) -translations-dir=$(QT_TRANSLATION_DIR) -dmg -fancy $(OSX_FANCY_PLIST) -verbose 2 -volname $(OSX_VOLNAME)
$(PYTHON) $(OSX_DEPLOY_SCRIPT) $(OSX_APP) $(OSX_VOLNAME) -translations-dir=$(QT_TRANSLATION_DIR) -dmg
$(OSX_BACKGROUND_IMAGE).png: contrib/macdeploy/$(OSX_BACKGROUND_SVG)
sed 's/PACKAGE_NAME/$(PACKAGE_NAME)/' < "$<" | $(RSVG_CONVERT) -f png -d 36 -p 36 -o $@
@ -127,7 +139,7 @@ $(OSX_BACKGROUND_IMAGE): $(OSX_BACKGROUND_IMAGE).png $(OSX_BACKGROUND_IMAGE)@2x.
tiffutil -cathidpicheck $^ -out $@
deploydir: $(OSX_DMG)
else
else !BUILD_DARWIN
APP_DIST_DIR=$(top_builddir)/dist
APP_DIST_EXTRAS=$(APP_DIST_DIR)/.background/$(OSX_BACKGROUND_IMAGE) $(APP_DIST_DIR)/.DS_Store $(APP_DIST_DIR)/Applications
@ -137,8 +149,11 @@ $(APP_DIST_DIR)/Applications:
$(APP_DIST_EXTRAS): $(APP_DIST_DIR)/$(OSX_APP)/Contents/MacOS/Elements-Qt
$(OSX_DMG): $(APP_DIST_EXTRAS)
$(GENISOIMAGE) -no-cache-inodes -D -l -probe -V "$(OSX_VOLNAME)" -no-pad -r -dir-mode 0755 -apple -o $@ dist
$(OSX_TEMP_ISO): $(APP_DIST_EXTRAS)
$(XORRISOFS) -D -l -V "$(OSX_VOLNAME)" -no-pad -r -dir-mode 0755 -o $@ $(APP_DIST_DIR) -- $(if $(SOURCE_DATE_EPOCH),-volume_date all_file_dates =$(SOURCE_DATE_EPOCH))
$(OSX_DMG): $(OSX_TEMP_ISO)
$(DMG) dmg "$<" "$@"
dpi%.$(OSX_BACKGROUND_IMAGE): contrib/macdeploy/$(OSX_BACKGROUND_SVG)
sed 's/PACKAGE_NAME/$(PACKAGE_NAME)/' < "$<" | $(RSVG_CONVERT) -f png -d $* -p $* | $(IMAGEMAGICK_CONVERT) - $@
@ -147,22 +162,15 @@ $(APP_DIST_DIR)/.background/$(OSX_BACKGROUND_IMAGE): $(OSX_BACKGROUND_IMAGE_DPIF
$(MKDIR_P) $(@D)
$(TIFFCP) -c none $(OSX_BACKGROUND_IMAGE_DPIFILES) $@
$(APP_DIST_DIR)/.DS_Store: $(OSX_DSSTORE_GEN)
$(PYTHON) $< "$@" "$(OSX_VOLNAME)"
$(APP_DIST_DIR)/$(OSX_APP)/Contents/MacOS/Elements-Qt: $(OSX_APP_BUILT) $(OSX_PACKAGING)
INSTALLNAMETOOL=$(INSTALLNAMETOOL) OTOOL=$(OTOOL) STRIP=$(STRIP) $(PYTHON) $(OSX_DEPLOY_SCRIPT) $(OSX_APP) -translations-dir=$(QT_TRANSLATION_DIR) -add-qt-tr $(OSX_QT_TRANSLATIONS) -verbose 2
INSTALLNAMETOOL=$(INSTALLNAMETOOL) OTOOL=$(OTOOL) STRIP=$(STRIP) $(PYTHON) $(OSX_DEPLOY_SCRIPT) $(OSX_APP) $(OSX_VOLNAME) -translations-dir=$(QT_TRANSLATION_DIR)
deploydir: $(APP_DIST_EXTRAS)
endif
endif !BUILD_DARWIN
if TARGET_DARWIN
appbundle: $(OSX_APP_BUILT)
deploy: $(OSX_DMG)
endif
if TARGET_WINDOWS
deploy: $(BITCOIN_WIN_INSTALLER)
endif
$(BITCOIN_QT_BIN): FORCE
$(MAKE) -C src qt/$(@F)
@ -176,9 +184,18 @@ $(BITCOIN_CLI_BIN): FORCE
$(BITCOIN_TX_BIN): FORCE
$(MAKE) -C src $(@F)
$(BITCOIN_UTIL_BIN): FORCE
$(MAKE) -C src $(@F)
$(BITCOIN_WALLET_BIN): FORCE
$(MAKE) -C src $(@F)
$(BITCOIN_NODE_BIN): FORCE
$(MAKE) -C src $(@F)
$(BITCOIN_GUI_BIN): FORCE
$(MAKE) -C src $(@F)
if USE_LCOV
LCOV_FILTER_PATTERN = \
-p "/usr/local/" \
@ -324,8 +341,6 @@ EXTRA_DIST += \
CLEANFILES = $(OSX_DMG) $(BITCOIN_WIN_INSTALLER)
.INTERMEDIATE: $(COVERAGE_INFO)
DISTCHECK_CONFIGURE_FLAGS = --enable-man
doc/doxygen/.stamp: doc/Doxyfile FORCE
@ -350,11 +365,14 @@ clean-local: clean-docs
test-security-check:
if TARGET_DARWIN
$(AM_V_at) $(PYTHON) $(top_srcdir)/contrib/devtools/test-security-check.py TestSecurityChecks.test_MACHO
$(AM_V_at) CC='$(CC)' $(PYTHON) $(top_srcdir)/contrib/devtools/test-security-check.py TestSecurityChecks.test_MACHO
$(AM_V_at) CC='$(CC)' $(PYTHON) $(top_srcdir)/contrib/devtools/test-symbol-check.py TestSymbolChecks.test_MACHO
endif
if TARGET_WINDOWS
$(AM_V_at) $(PYTHON) $(top_srcdir)/contrib/devtools/test-security-check.py TestSecurityChecks.test_PE
$(AM_V_at) CC='$(CC)' $(PYTHON) $(top_srcdir)/contrib/devtools/test-security-check.py TestSecurityChecks.test_PE
$(AM_V_at) CC='$(CC)' $(PYTHON) $(top_srcdir)/contrib/devtools/test-symbol-check.py TestSymbolChecks.test_PE
endif
if TARGET_LINUX
$(AM_V_at) $(PYTHON) $(top_srcdir)/contrib/devtools/test-security-check.py TestSecurityChecks.test_ELF
$(AM_V_at) CC='$(CC)' $(PYTHON) $(top_srcdir)/contrib/devtools/test-security-check.py TestSecurityChecks.test_ELF
$(AM_V_at) CC='$(CC)' CPPFILT='$(CPPFILT)' $(PYTHON) $(top_srcdir)/contrib/devtools/test-symbol-check.py TestSymbolChecks.test_ELF
endif

View file

@ -53,6 +53,9 @@ Elements deferred for additional research and standardization:
Additional RPC commands and parameters:
* [RPC Docs](https://elementsproject.org/en/doc/)
The CI (Continuous Integration) systems make sure that every pull request is built for Windows, Linux, and macOS,
and that unit/sanity tests are run automatically.
License
-------
Elements is released under the terms of the MIT license. See [COPYING](COPYING) for more

View file

@ -1,20 +1,15 @@
# ==============================================================================
# Bitcoin Core CODEOWNERS
# Bitcoin Core REVIEWERS
# ==============================================================================
# Configuration of code ownership and review approvals for the bitcoin/bitcoin
# repo.
# Configuration of automated review requests for the bitcoin/bitcoin repo
# via DrahtBot.
# Order is important; the last matching pattern takes the most precedence.
# More info on how this file works can be found at:
# https://help.github.com/articles/about-codeowners/
# Order is not important; if a modified file or directory matches a fnmatch,
# the reviewer will be mentioned in a PR comment requesting a review.
# This file is called CODEOWNERS because it is a magic file for GitHub to
# automatically suggest reviewers. In this project's case, the names below
# should be thought of as code reviewers rather than owners. Regular
# contributors are free to add their names to specific directories or files
# provided that they are willing to provide a review when automatically
# assigned.
# Regular contributors are free to add their names to specific directories or
# files provided that they are willing to provide a review.
# Absence from this list should not be interpreted as a discouragement to
# review a pull request. Peer review is always welcome and is a critical
@ -23,12 +18,13 @@
# Maintainers
# @laanwj
# @sipa
# @fanquake
# @hebasto
# @jonasschnelli
# @laanwj
# @marcofalke
# @meshcollider
# @sipa
# Docs
/doc/*[a-zA-Z-].md @harding
@ -61,14 +57,17 @@
/src/util/settings.* @ryanofsky
# Fuzzing
/src/test/fuzz/ @practicalswift
/doc/fuzzing.md @practicalswift
# Test framework
# Tests
/src/test/net_peer_eviction_tests.cpp @jonatack
/test/functional/mempool_updatefromblock.py @hebasto
/test/functional/feature_asmap.py @jonatack
/test/functional/interface_bitcoin_cli.py @jonatack
/test/functional/tool_wallet.py @jonatack
# Backwards compatibility tests
*_compatibility.py @sjors
/test/functional/wallet_upgradewallet.py @sjors @achow101
/test/get_previous_releases.py @sjors
# Translations
/src/util/translation.h @hebasto
@ -103,6 +102,11 @@
# Descriptors
*descriptor* @achow101 @sipa
# External signer
*external_signer* @sjors
/doc/external-signer.md @sjors
*signer.py @sjors
# Interfaces
/src/interfaces/ @ryanofsky
@ -110,9 +114,7 @@
/src/txdb.* @jamesob
/src/dbwrapper.* @jamesob
# Scripts/Linter
*.sh @practicalswift
/test/lint/ @practicalswift
# Linter
/test/lint/lint-shell.sh @hebasto
# Bech32

View file

@ -11,7 +11,7 @@
# Test for the Boost C++ libraries of a particular version (or newer)
#
# If no path to the installed boost library is given the macro searchs
# under /usr, /usr/local, /opt and /opt/local and evaluates the
# under /usr, /usr/local, /opt, /opt/local and /opt/homebrew and evaluates the
# $BOOST_ROOT environment variable. Further documentation is available at
# <http://randspringer.de/boost/index.html>.
#
@ -151,7 +151,7 @@ AC_DEFUN([_AX_BOOST_BASE_RUNDETECT],[
else
search_libsubdirs="$multiarch_libsubdir $libsubdirs"
fi
for _AX_BOOST_BASE_boost_path_tmp in /usr /usr/local /opt /opt/local ; do
for _AX_BOOST_BASE_boost_path_tmp in /usr /usr/local /opt /opt/local /opt/homebrew/; do
if test -d "$_AX_BOOST_BASE_boost_path_tmp/include/boost" && test -r "$_AX_BOOST_BASE_boost_path_tmp/include/boost" ; then
for libsubdir in $search_libsubdirs ; do
if ls "$_AX_BOOST_BASE_boost_path_tmp/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi
@ -227,7 +227,7 @@ AC_DEFUN([_AX_BOOST_BASE_RUNDETECT],[
fi
else
if test "x$cross_compiling" != "xyes" ; then
for _AX_BOOST_BASE_boost_path in /usr /usr/local /opt /opt/local ; do
for _AX_BOOST_BASE_boost_path in /usr /usr/local /opt /opt/local /opt/homebrew ; do
if test -d "$_AX_BOOST_BASE_boost_path" && test -r "$_AX_BOOST_BASE_boost_path" ; then
for i in `ls -d $_AX_BOOST_BASE_boost_path/include/boost-* 2>/dev/null`; do
_version_tmp=`echo $i | sed "s#$_AX_BOOST_BASE_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'`

View file

@ -1,121 +0,0 @@
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_boost_process.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_BOOST_PROCESS
#
# DESCRIPTION
#
# Test for Process library from the Boost C++ libraries. The macro
# requires a preceding call to AX_BOOST_BASE. Further documentation is
# available at <http://randspringer.de/boost/index.html>.
#
# This macro calls:
#
# AC_SUBST(BOOST_PROCESS_LIB)
#
# And sets:
#
# HAVE_BOOST_PROCESS
#
# LICENSE
#
# Copyright (c) 2008 Thomas Porschberg <thomas@randspringer.de>
# Copyright (c) 2008 Michael Tindal
# Copyright (c) 2008 Daniel Casimiro <dan.casimiro@gmail.com>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 2
AC_DEFUN([AX_BOOST_PROCESS],
[
AC_ARG_WITH([boost-process],
AS_HELP_STRING([--with-boost-process@<:@=special-lib@:>@],
[use the Process library from boost - it is possible to specify a certain library for the linker
e.g. --with-boost-process=boost_process-gcc-mt ]),
[
if test "$withval" = "no"; then
want_boost_process="no"
elif test "$withval" = "yes"; then
want_boost_process="yes"
ax_boost_user_process_lib=""
else
want_boost_process="yes"
ax_boost_user_process_lib="$withval"
fi
],
[want_boost_process="yes"]
)
if test "x$want_boost_process" = "xyes"; then
AC_REQUIRE([AC_PROG_CC])
AC_REQUIRE([AC_CANONICAL_BUILD])
CPPFLAGS_SAVED="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
export CPPFLAGS
LDFLAGS_SAVED="$LDFLAGS"
LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
export LDFLAGS
AC_CACHE_CHECK(whether the Boost::Process library is available,
ax_cv_boost_process,
[AC_LANG_PUSH([C++])
CXXFLAGS_SAVE=$CXXFLAGS
CXXFLAGS=
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <boost/process.hpp>]],
[[boost::process::child* child = new boost::process::child; delete child;]])],
ax_cv_boost_process=yes, ax_cv_boost_process=no)
CXXFLAGS=$CXXFLAGS_SAVE
AC_LANG_POP([C++])
])
if test "x$ax_cv_boost_process" = "xyes"; then
AC_SUBST(BOOST_CPPFLAGS)
AC_DEFINE(HAVE_BOOST_PROCESS,,[define if the Boost::Process library is available])
BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'`
LDFLAGS_SAVE=$LDFLAGS
if test "x$ax_boost_user_process_lib" = "x"; then
for libextension in `ls -r $BOOSTLIBDIR/libboost_process* 2>/dev/null | sed 's,.*/lib,,' | sed 's,\..*,,'` ; do
ax_lib=${libextension}
AC_CHECK_LIB($ax_lib, exit,
[BOOST_PROCESS_LIB="-l$ax_lib"; AC_SUBST(BOOST_PROCESS_LIB) link_process="yes"; break],
[link_process="no"])
done
if test "x$link_process" != "xyes"; then
for libextension in `ls -r $BOOSTLIBDIR/boost_process* 2>/dev/null | sed 's,.*/,,' | sed -e 's,\..*,,'` ; do
ax_lib=${libextension}
AC_CHECK_LIB($ax_lib, exit,
[BOOST_PROCESS_LIB="-l$ax_lib"; AC_SUBST(BOOST_PROCESS_LIB) link_process="yes"; break],
[link_process="no"])
done
fi
else
for ax_lib in $ax_boost_user_process_lib boost_process-$ax_boost_user_process_lib; do
AC_CHECK_LIB($ax_lib, exit,
[BOOST_PROCESS_LIB="-l$ax_lib"; AC_SUBST(BOOST_PROCESS_LIB) link_process="yes"; break],
[link_process="no"])
done
fi
if test "x$ax_lib" = "x"; then
AC_MSG_ERROR(Could not find a version of the Boost::Process library!)
fi
if test "x$link_process" = "xno"; then
AC_MSG_ERROR(Could not link against $ax_lib !)
fi
fi
CPPFLAGS="$CPPFLAGS_SAVED"
LDFLAGS="$LDFLAGS_SAVED"
fi
])

View file

@ -1,187 +0,0 @@
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_boost_thread.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_BOOST_THREAD
#
# DESCRIPTION
#
# Test for Thread library from the Boost C++ libraries. The macro requires
# a preceding call to AX_BOOST_BASE. Further documentation is available at
# <http://randspringer.de/boost/index.html>.
#
# This macro calls:
#
# AC_SUBST(BOOST_THREAD_LIB)
#
# And sets:
#
# HAVE_BOOST_THREAD
#
# LICENSE
#
# Copyright (c) 2009 Thomas Porschberg <thomas@randspringer.de>
# Copyright (c) 2009 Michael Tindal
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 33
AC_DEFUN([AX_BOOST_THREAD],
[
AC_ARG_WITH([boost-thread],
AS_HELP_STRING([--with-boost-thread@<:@=special-lib@:>@],
[use the Thread library from boost -
it is possible to specify a certain library for the linker
e.g. --with-boost-thread=boost_thread-gcc-mt ]),
[
if test "$withval" = "yes"; then
want_boost="yes"
ax_boost_user_thread_lib=""
else
want_boost="yes"
ax_boost_user_thread_lib="$withval"
fi
],
[want_boost="yes"]
)
if test "x$want_boost" = "xyes"; then
AC_REQUIRE([AC_PROG_CC])
AC_REQUIRE([AC_CANONICAL_BUILD])
CPPFLAGS_SAVED="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
export CPPFLAGS
LDFLAGS_SAVED="$LDFLAGS"
LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
export LDFLAGS
AC_CACHE_CHECK(whether the Boost::Thread library is available,
ax_cv_boost_thread,
[AC_LANG_PUSH([C++])
CXXFLAGS_SAVE=$CXXFLAGS
case "x$host_os" in
xsolaris )
CXXFLAGS="-pthreads $CXXFLAGS"
break;
;;
xmingw32 )
CXXFLAGS="-mthreads $CXXFLAGS"
break;
;;
*android* )
break;
;;
* )
CXXFLAGS="-pthread $CXXFLAGS"
break;
;;
esac
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM(
[[@%:@include <boost/thread/thread.hpp>]],
[[boost::thread_group thrds;
return 0;]])],
ax_cv_boost_thread=yes, ax_cv_boost_thread=no)
CXXFLAGS=$CXXFLAGS_SAVE
AC_LANG_POP([C++])
])
if test "x$ax_cv_boost_thread" = "xyes"; then
case "x$host_os" in
xsolaris )
BOOST_CPPFLAGS="-pthreads $BOOST_CPPFLAGS"
break;
;;
xmingw32 )
BOOST_CPPFLAGS="-mthreads $BOOST_CPPFLAGS"
break;
;;
*android* )
break;
;;
* )
BOOST_CPPFLAGS="-pthread $BOOST_CPPFLAGS"
break;
;;
esac
AC_SUBST(BOOST_CPPFLAGS)
AC_DEFINE(HAVE_BOOST_THREAD,,
[define if the Boost::Thread library is available])
BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'`
LDFLAGS_SAVE=$LDFLAGS
case "x$host_os" in
*bsd* )
LDFLAGS="-pthread $LDFLAGS"
break;
;;
esac
if test "x$ax_boost_user_thread_lib" = "x"; then
for libextension in `ls -r $BOOSTLIBDIR/libboost_thread* 2>/dev/null | sed 's,.*/lib,,' | sed 's,\..*,,'`; do
ax_lib=${libextension}
AC_CHECK_LIB($ax_lib, exit,
[link_thread="yes"; break],
[link_thread="no"])
done
if test "x$link_thread" != "xyes"; then
for libextension in `ls -r $BOOSTLIBDIR/boost_thread* 2>/dev/null | sed 's,.*/,,' | sed 's,\..*,,'`; do
ax_lib=${libextension}
AC_CHECK_LIB($ax_lib, exit,
[link_thread="yes"; break],
[link_thread="no"])
done
fi
else
for ax_lib in $ax_boost_user_thread_lib boost_thread-$ax_boost_user_thread_lib; do
AC_CHECK_LIB($ax_lib, exit,
[link_thread="yes"; break],
[link_thread="no"])
done
fi
if test "x$ax_lib" = "x"; then
AC_MSG_ERROR(Could not find a version of the Boost::Thread library!)
fi
if test "x$link_thread" = "xno"; then
AC_MSG_ERROR(Could not link against $ax_lib !)
else
BOOST_THREAD_LIB="-l$ax_lib"
case "x$host_os" in
*bsd* )
BOOST_LDFLAGS="-pthread $BOOST_LDFLAGS"
break;
;;
xsolaris )
BOOST_THREAD_LIB="$BOOST_THREAD_LIB -lpthread"
break;
;;
xmingw32 )
break;
;;
*android* )
break;
;;
* )
BOOST_THREAD_LIB="$BOOST_THREAD_LIB -lpthread"
break;
;;
esac
AC_SUBST(BOOST_THREAD_LIB)
fi
fi
CPPFLAGS="$CPPFLAGS_SAVED"
LDFLAGS="$LDFLAGS_SAVED"
fi
])

View file

@ -1,223 +0,0 @@
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_gcc_func_attribute.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_GCC_FUNC_ATTRIBUTE(ATTRIBUTE)
#
# DESCRIPTION
#
# This macro checks if the compiler supports one of GCC's function
# attributes; many other compilers also provide function attributes with
# the same syntax. Compiler warnings are used to detect supported
# attributes as unsupported ones are ignored by default so quieting
# warnings when using this macro will yield false positives.
#
# The ATTRIBUTE parameter holds the name of the attribute to be checked.
#
# If ATTRIBUTE is supported define HAVE_FUNC_ATTRIBUTE_<ATTRIBUTE>.
#
# The macro caches its result in the ax_cv_have_func_attribute_<attribute>
# variable.
#
# The macro currently supports the following function attributes:
#
# alias
# aligned
# alloc_size
# always_inline
# artificial
# cold
# const
# constructor
# constructor_priority for constructor attribute with priority
# deprecated
# destructor
# dllexport
# dllimport
# error
# externally_visible
# flatten
# format
# format_arg
# gnu_inline
# hot
# ifunc
# leaf
# malloc
# noclone
# noinline
# nonnull
# noreturn
# nothrow
# optimize
# pure
# unused
# used
# visibility
# warning
# warn_unused_result
# weak
# weakref
#
# Unsuppored function attributes will be tested with a prototype returning
# an int and not accepting any arguments and the result of the check might
# be wrong or meaningless so use with care.
#
# LICENSE
#
# Copyright (c) 2013 Gabriele Svelto <gabriele.svelto@gmail.com>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 3
AC_DEFUN([AX_GCC_FUNC_ATTRIBUTE], [
AS_VAR_PUSHDEF([ac_var], [ax_cv_have_func_attribute_$1])
AC_CACHE_CHECK([for __attribute__(($1))], [ac_var], [
AC_LINK_IFELSE([AC_LANG_PROGRAM([
m4_case([$1],
[alias], [
int foo( void ) { return 0; }
int bar( void ) __attribute__(($1("foo")));
],
[aligned], [
int foo( void ) __attribute__(($1(32)));
],
[alloc_size], [
void *foo(int a) __attribute__(($1(1)));
],
[always_inline], [
inline __attribute__(($1)) int foo( void ) { return 0; }
],
[artificial], [
inline __attribute__(($1)) int foo( void ) { return 0; }
],
[cold], [
int foo( void ) __attribute__(($1));
],
[const], [
int foo( void ) __attribute__(($1));
],
[constructor_priority], [
int foo( void ) __attribute__((__constructor__(65535/2)));
],
[constructor], [
int foo( void ) __attribute__(($1));
],
[deprecated], [
int foo( void ) __attribute__(($1("")));
],
[destructor], [
int foo( void ) __attribute__(($1));
],
[dllexport], [
__attribute__(($1)) int foo( void ) { return 0; }
],
[dllimport], [
int foo( void ) __attribute__(($1));
],
[error], [
int foo( void ) __attribute__(($1("")));
],
[externally_visible], [
int foo( void ) __attribute__(($1));
],
[flatten], [
int foo( void ) __attribute__(($1));
],
[format], [
int foo(const char *p, ...) __attribute__(($1(printf, 1, 2)));
],
[format_arg], [
char *foo(const char *p) __attribute__(($1(1)));
],
[gnu_inline], [
inline __attribute__(($1)) int foo( void ) { return 0; }
],
[hot], [
int foo( void ) __attribute__(($1));
],
[ifunc], [
int my_foo( void ) { return 0; }
static int (*resolve_foo(void))(void) { return my_foo; }
int foo( void ) __attribute__(($1("resolve_foo")));
],
[leaf], [
__attribute__(($1)) int foo( void ) { return 0; }
],
[malloc], [
void *foo( void ) __attribute__(($1));
],
[noclone], [
int foo( void ) __attribute__(($1));
],
[noinline], [
__attribute__(($1)) int foo( void ) { return 0; }
],
[nonnull], [
int foo(char *p) __attribute__(($1(1)));
],
[noreturn], [
void foo( void ) __attribute__(($1));
],
[nothrow], [
int foo( void ) __attribute__(($1));
],
[optimize], [
__attribute__(($1(3))) int foo( void ) { return 0; }
],
[pure], [
int foo( void ) __attribute__(($1));
],
[unused], [
int foo( void ) __attribute__(($1));
],
[used], [
int foo( void ) __attribute__(($1));
],
[visibility], [
int foo_def( void ) __attribute__(($1("default")));
int foo_hid( void ) __attribute__(($1("hidden")));
int foo_int( void ) __attribute__(($1("internal")));
int foo_pro( void ) __attribute__(($1("protected")));
],
[warning], [
int foo( void ) __attribute__(($1("")));
],
[warn_unused_result], [
int foo( void ) __attribute__(($1));
],
[weak], [
int foo( void ) __attribute__(($1));
],
[weakref], [
static int foo( void ) { return 0; }
static int bar( void ) __attribute__(($1("foo")));
],
[
m4_warn([syntax], [Unsupported attribute $1, the test may fail])
int foo( void ) __attribute__(($1));
]
)], [])
],
dnl GCC doesn't exit with an error if an unknown attribute is
dnl provided but only outputs a warning, so accept the attribute
dnl only if no warning were issued.
[AS_IF([test -s conftest.err],
[AS_VAR_SET([ac_var], [no])],
[AS_VAR_SET([ac_var], [yes])])],
[AS_VAR_SET([ac_var], [no])])
])
AS_IF([test yes = AS_VAR_GET([ac_var])],
[AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_FUNC_ATTRIBUTE_$1), 1,
[Define to 1 if the system has the `$1' function attribute])], [])
AS_VAR_POPDEF([ac_var])
])

View file

@ -6,7 +6,9 @@ AC_DEFUN([BITCOIN_FIND_BDB48],[
AC_ARG_VAR(BDB_CFLAGS, [C compiler flags for BerkeleyDB, bypasses autodetection])
AC_ARG_VAR(BDB_LIBS, [Linker flags for BerkeleyDB, bypasses autodetection])
if test "x$BDB_CFLAGS" = "x"; then
if test "x$use_bdb" = "xno"; then
use_bdb=no
elif test "x$BDB_CFLAGS" = "x"; then
AC_MSG_CHECKING([for Berkeley DB C++ headers])
BDB_CPPFLAGS=
bdbpath=X
@ -44,25 +46,30 @@ AC_DEFUN([BITCOIN_FIND_BDB48],[
],[])
done
if test "x$bdbpath" = "xX"; then
use_bdb=no
AC_MSG_RESULT([no])
AC_MSG_ERROR([libdb_cxx headers missing, ]AC_PACKAGE_NAME[ requires this library for wallet functionality (--disable-wallet to disable wallet functionality)])
AC_MSG_ERROR([libdb_cxx headers missing, ]AC_PACKAGE_NAME[ requires this library for BDB wallet support (--without-bdb to disable BDB wallet support)])
elif test "x$bdb48path" = "xX"; then
BITCOIN_SUBDIR_TO_INCLUDE(BDB_CPPFLAGS,[${bdbpath}],db_cxx)
AC_ARG_WITH([incompatible-bdb],[AS_HELP_STRING([--with-incompatible-bdb], [allow using a bdb version other than 4.8])],[
AC_MSG_WARN([Found Berkeley DB other than 4.8; wallets opened by this build will not be portable!])
AC_MSG_WARN([Found Berkeley DB other than 4.8; BDB wallets opened by this build will not be portable!])
],[
AC_MSG_ERROR([Found Berkeley DB other than 4.8, required for portable wallets (--with-incompatible-bdb to ignore or --disable-wallet to disable wallet functionality)])
AC_MSG_ERROR([Found Berkeley DB other than 4.8, required for portable BDB wallets (--with-incompatible-bdb to ignore or --without-bdb to disable BDB wallet support)])
])
use_bdb=yes
else
BITCOIN_SUBDIR_TO_INCLUDE(BDB_CPPFLAGS,[${bdb48path}],db_cxx)
bdbpath="${bdb48path}"
use_bdb=yes
fi
else
BDB_CPPFLAGS=${BDB_CFLAGS}
fi
AC_SUBST(BDB_CPPFLAGS)
if test "x$BDB_LIBS" = "x"; then
if test "x$use_bdb" = "xno"; then
use_bdb=no
elif test "x$BDB_LIBS" = "x"; then
# TODO: Ideally this could find the library version and make sure it matches the headers being used
for searchlib in db_cxx-4.8 db_cxx db4_cxx; do
AC_CHECK_LIB([$searchlib],[main],[
@ -71,8 +78,12 @@ AC_DEFUN([BITCOIN_FIND_BDB48],[
])
done
if test "x$BDB_LIBS" = "x"; then
AC_MSG_ERROR([libdb_cxx missing, ]AC_PACKAGE_NAME[ requires this library for wallet functionality (--disable-wallet to disable wallet functionality)])
AC_MSG_ERROR([libdb_cxx missing, ]AC_PACKAGE_NAME[ requires this library for BDB wallet support (--without-bdb to disable BDB wallet support)])
fi
fi
AC_SUBST(BDB_LIBS)
if test "x$use_bdb" != "xno"; then
AC_SUBST(BDB_LIBS)
AC_DEFINE([USE_BDB], [1], [Define if BDB support should be compiled in])
use_bdb=yes
fi
])

View file

@ -64,6 +64,13 @@ AC_DEFUN([BITCOIN_QT_INIT],[
],
[bitcoin_qt_want_version=auto])
AS_IF([test "x$with_gui" = xqt5_debug],
[AS_CASE([$host],
[*darwin*], [qt_lib_suffix=_debug],
[*mingw*], [qt_lib_suffix=d],
[qt_lib_suffix= ]); bitcoin_qt_want_version=qt5],
[qt_lib_suffix= ])
AC_ARG_WITH([qt-incdir],[AS_HELP_STRING([--with-qt-incdir=INC_DIR],[specify qt include path (overridden by pkgconfig)])], [qt_include_path=$withval], [])
AC_ARG_WITH([qt-libdir],[AS_HELP_STRING([--with-qt-libdir=LIB_DIR],[specify qt lib path (overridden by pkgconfig)])], [qt_lib_path=$withval], [])
AC_ARG_WITH([qt-plugindir],[AS_HELP_STRING([--with-qt-plugindir=PLUGIN_DIR],[specify qt plugin path (overridden by pkgconfig)])], [qt_plugin_path=$withval], [])
@ -101,13 +108,10 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[
BITCOIN_QT_CHECK([_BITCOIN_QT_FIND_LIBS])
dnl This is ugly and complicated. Yuck. Works as follows:
dnl For Qt5, we can check a header to find out whether Qt is build
dnl statically. When Qt is built statically, some plugins must be linked into
dnl the final binary as well.
dnl With Qt5, languages moved into core and the WindowsIntegration plugin was
dnl added.
dnl _BITCOIN_QT_CHECK_STATIC_PLUGINS does a quick link-check and appends the
dnl results to QT_LIBS.
dnl We check a header to find out whether Qt is built statically.
dnl When Qt is built statically, some plugins must be linked into
dnl the final binary as well. _BITCOIN_QT_CHECK_STATIC_PLUGIN does
dnl a quick link-check and appends the results to QT_LIBS.
BITCOIN_QT_CHECK([
TEMP_CPPFLAGS=$CPPFLAGS
TEMP_CXXFLAGS=$CXXFLAGS
@ -115,24 +119,50 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[
CXXFLAGS="$PIC_FLAGS $CXXFLAGS"
_BITCOIN_QT_IS_STATIC
if test "x$bitcoin_cv_static_qt" = xyes; then
_BITCOIN_QT_FIND_STATIC_PLUGINS
_BITCOIN_QT_CHECK_STATIC_LIBS
if test "x$qt_plugin_path" != x; then
if test -d "$qt_plugin_path/platforms"; then
QT_LIBS="$QT_LIBS -L$qt_plugin_path/platforms"
fi
if test -d "$qt_plugin_path/styles"; then
QT_LIBS="$QT_LIBS -L$qt_plugin_path/styles"
fi
if test -d "$qt_plugin_path/accessible"; then
QT_LIBS="$QT_LIBS -L$qt_plugin_path/accessible"
fi
if test -d "$qt_plugin_path/platforms/android"; then
QT_LIBS="$QT_LIBS -L$qt_plugin_path/platforms/android -lqtfreetype -lEGL"
fi
fi
AC_DEFINE(QT_STATICPLUGIN, 1, [Define this symbol if qt plugins are static])
if test "x$TARGET_OS" != xandroid; then
_BITCOIN_QT_CHECK_STATIC_PLUGINS([Q_IMPORT_PLUGIN(QMinimalIntegrationPlugin)],[-lqminimal])
_BITCOIN_QT_CHECK_STATIC_PLUGIN([QMinimalIntegrationPlugin], [-lqminimal])
AC_DEFINE(QT_QPA_PLATFORM_MINIMAL, 1, [Define this symbol if the minimal qt platform exists])
fi
if test "x$TARGET_OS" = xwindows; then
_BITCOIN_QT_CHECK_STATIC_PLUGINS([Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin)],[-lqwindows])
dnl Linking against wtsapi32 is required. See #17749 and
dnl https://bugreports.qt.io/browse/QTBUG-27097.
AX_CHECK_LINK_FLAG([-lwtsapi32], [QT_LIBS="$QT_LIBS -lwtsapi32"], [AC_MSG_ERROR([could not link against -lwtsapi32])])
_BITCOIN_QT_CHECK_STATIC_PLUGIN([QWindowsIntegrationPlugin], [-lqwindows])
_BITCOIN_QT_CHECK_STATIC_PLUGIN([QWindowsVistaStylePlugin], [-lqwindowsvistastyle])
AC_DEFINE(QT_QPA_PLATFORM_WINDOWS, 1, [Define this symbol if the qt platform is windows])
elif test "x$TARGET_OS" = xlinux; then
_BITCOIN_QT_CHECK_STATIC_PLUGINS([Q_IMPORT_PLUGIN(QXcbIntegrationPlugin)],[-lqxcb -lxcb-static])
dnl workaround for https://bugreports.qt.io/browse/QTBUG-74874
AX_CHECK_LINK_FLAG([-lxcb-shm], [QT_LIBS="$QT_LIBS -lxcb-shm"], [AC_MSG_ERROR([could not link against -lxcb-shm])])
_BITCOIN_QT_CHECK_STATIC_PLUGIN([QXcbIntegrationPlugin], [-lqxcb])
AC_DEFINE(QT_QPA_PLATFORM_XCB, 1, [Define this symbol if the qt platform is xcb])
elif test "x$TARGET_OS" = xdarwin; then
AX_CHECK_LINK_FLAG([[-framework IOKit]],[QT_LIBS="$QT_LIBS -framework IOKit"],[AC_MSG_ERROR(could not iokit framework)])
_BITCOIN_QT_CHECK_STATIC_PLUGINS([Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin)],[-lqcocoa])
AX_CHECK_LINK_FLAG([[-framework Carbon]],[QT_LIBS="$QT_LIBS -framework Carbon"],[AC_MSG_ERROR(could not link against Carbon framework)])
AX_CHECK_LINK_FLAG([[-framework IOSurface]],[QT_LIBS="$QT_LIBS -framework IOSurface"],[AC_MSG_ERROR(could not link against IOSurface framework)])
AX_CHECK_LINK_FLAG([[-framework Metal]],[QT_LIBS="$QT_LIBS -framework Metal"],[AC_MSG_ERROR(could not link against Metal framework)])
AX_CHECK_LINK_FLAG([[-framework QuartzCore]],[QT_LIBS="$QT_LIBS -framework QuartzCore"],[AC_MSG_ERROR(could not link against QuartzCore framework)])
_BITCOIN_QT_CHECK_STATIC_PLUGIN([QCocoaIntegrationPlugin], [-lqcocoa])
_BITCOIN_QT_CHECK_STATIC_PLUGIN([QMacStylePlugin], [-lqmacstyle])
AC_DEFINE(QT_QPA_PLATFORM_COCOA, 1, [Define this symbol if the qt platform is cocoa])
elif test "x$TARGET_OS" = xandroid; then
QT_LIBS="-Wl,--export-dynamic,--undefined=JNI_OnLoad -lqtforandroid -ljnigraphics -landroid -lqtfreetype -lQt5EglSupport $QT_LIBS"
QT_LIBS="-Wl,--export-dynamic,--undefined=JNI_OnLoad -lqtforandroid -ljnigraphics -landroid -lqtfreetype $QT_LIBS"
AC_DEFINE(QT_QPA_PLATFORM_ANDROID, 1, [Define this symbol if the qt platform is android])
fi
fi
@ -141,7 +171,7 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[
])
if test "x$qt_bin_path" = x; then
qt_bin_path="`$PKG_CONFIG --variable=host_bins Qt5Core 2>/dev/null`"
qt_bin_path="`$PKG_CONFIG --variable=host_bins ${qt_lib_prefix}Core 2>/dev/null`"
fi
if test "x$use_hardening" != xno; then
@ -196,13 +226,14 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[
BITCOIN_QT_PATH_PROGS([RCC], [rcc-qt5 rcc5 rcc], $qt_bin_path)
BITCOIN_QT_PATH_PROGS([LRELEASE], [lrelease-qt5 lrelease5 lrelease], $qt_bin_path)
BITCOIN_QT_PATH_PROGS([LUPDATE], [lupdate-qt5 lupdate5 lupdate],$qt_bin_path, yes)
BITCOIN_QT_PATH_PROGS([LCONVERT], [lconvert-qt5 lconvert5 lconvert], $qt_bin_path, yes)
MOC_DEFS='-DHAVE_CONFIG_H -I$(srcdir)'
case $host in
*darwin*)
BITCOIN_QT_CHECK([
MOC_DEFS="${MOC_DEFS} -DQ_OS_MAC"
base_frameworks="-framework Foundation -framework ApplicationServices -framework AppKit"
base_frameworks="-framework Foundation -framework AppKit"
AX_CHECK_LINK_FLAG([[$base_frameworks]],[QT_LIBS="$QT_LIBS $base_frameworks"],[AC_MSG_ERROR(could not find base frameworks)])
])
;;
@ -229,7 +260,10 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[
AC_MSG_ERROR([libQtDBus not found. Install libQtDBus or remove --with-qtdbus.])
fi
if test "x$LUPDATE" = x; then
AC_MSG_WARN([lupdate is required to update qt translations])
AC_MSG_WARN([lupdate tool is required to update Qt translations.])
fi
if test "x$LCONVERT" = x; then
AC_MSG_WARN([lconvert tool is required to update Qt translations.])
fi
],[
bitcoin_enable_qt=no
@ -252,12 +286,13 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[
AC_SUBST(MOC_DEFS)
])
dnl All macros below are internal and should _not_ be used from the main
dnl configure.ac.
dnl ----
dnl All macros below are internal and should _not_ be used from configure.ac.
dnl Internal. Check if the linked version of Qt was built as static libs.
dnl Requires: Qt5.
dnl Internal. Check if the linked version of Qt was built statically.
dnl
dnl _BITCOIN_QT_IS_STATIC
dnl ---------------------
dnl
dnl Requires: INCLUDES and LIBS must be populated as necessary.
dnl Output: bitcoin_cv_static_qt=yes|no
AC_DEFUN([_BITCOIN_QT_IS_STATIC],[
@ -278,78 +313,84 @@ AC_DEFUN([_BITCOIN_QT_IS_STATIC],[
])
])
dnl Internal. Check if the link-requirements for static plugins are met.
dnl Internal. Check if the link-requirements for a static plugin are met.
dnl
dnl _BITCOIN_QT_CHECK_STATIC_PLUGIN(PLUGIN, LIBRARIES)
dnl --------------------------------------------------
dnl
dnl Requires: INCLUDES and LIBS must be populated as necessary.
dnl Inputs: $1: A series of Q_IMPORT_PLUGIN().
dnl Inputs: $1: A static plugin name.
dnl Inputs: $2: The libraries that resolve $1.
dnl Output: QT_LIBS is prepended or configure exits.
AC_DEFUN([_BITCOIN_QT_CHECK_STATIC_PLUGINS],[
AC_MSG_CHECKING(for static Qt plugins: $2)
AC_DEFUN([_BITCOIN_QT_CHECK_STATIC_PLUGIN], [
AC_MSG_CHECKING([for $1 ($2)])
CHECK_STATIC_PLUGINS_TEMP_LIBS="$LIBS"
LIBS="$2 $QT_LIBS $LIBS"
LIBS="$2${qt_lib_suffix} $QT_LIBS $LIBS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#define QT_STATICPLUGIN
#include <QtPlugin>
$1]],
[[return 0;]])],
[AC_MSG_RESULT(yes); QT_LIBS="$2 $QT_LIBS"],
[AC_MSG_RESULT(no); BITCOIN_QT_FAIL(Could not resolve: $2)])
#include <QtPlugin>
Q_IMPORT_PLUGIN($1)
]])],
[AC_MSG_RESULT([yes]); QT_LIBS="$2${qt_lib_suffix} $QT_LIBS"],
[AC_MSG_RESULT([no]); BITCOIN_QT_FAIL([$1 not found.])])
LIBS="$CHECK_STATIC_PLUGINS_TEMP_LIBS"
])
dnl Internal. Find paths necessary for linking qt static plugins
dnl Inputs: qt_plugin_path. optional.
dnl Outputs: QT_LIBS is appended
AC_DEFUN([_BITCOIN_QT_FIND_STATIC_PLUGINS],[
if test "x$qt_plugin_path" != x; then
QT_LIBS="$QT_LIBS -L$qt_plugin_path/platforms"
if test -d "$qt_plugin_path/accessible"; then
QT_LIBS="$QT_LIBS -L$qt_plugin_path/accessible"
fi
if test -d "$qt_plugin_path/platforms/android"; then
QT_LIBS="$QT_LIBS -L$qt_plugin_path/platforms/android -lqtfreetype -lEGL"
fi
PKG_CHECK_MODULES([QTFONTDATABASE], [Qt5FontDatabaseSupport], [QT_LIBS="-lQt5FontDatabaseSupport $QT_LIBS"])
PKG_CHECK_MODULES([QTEVENTDISPATCHER], [Qt5EventDispatcherSupport], [QT_LIBS="-lQt5EventDispatcherSupport $QT_LIBS"])
PKG_CHECK_MODULES([QTTHEME], [Qt5ThemeSupport], [QT_LIBS="-lQt5ThemeSupport $QT_LIBS"])
PKG_CHECK_MODULES([QTDEVICEDISCOVERY], [Qt5DeviceDiscoverySupport], [QT_LIBS="-lQt5DeviceDiscoverySupport $QT_LIBS"])
PKG_CHECK_MODULES([QTACCESSIBILITY], [Qt5AccessibilitySupport], [QT_LIBS="-lQt5AccessibilitySupport $QT_LIBS"])
PKG_CHECK_MODULES([QTFB], [Qt5FbSupport], [QT_LIBS="-lQt5FbSupport $QT_LIBS"])
if test "x$TARGET_OS" = xlinux; then
PKG_CHECK_MODULES([QTXCBQPA], [Qt5XcbQpa], [QT_LIBS="$QTXCBQPA_LIBS $QT_LIBS"])
elif test "x$TARGET_OS" = xdarwin; then
PKG_CHECK_MODULES([QTCLIPBOARD], [Qt5ClipboardSupport], [QT_LIBS="-lQt5ClipboardSupport $QT_LIBS"])
PKG_CHECK_MODULES([QTGRAPHICS], [Qt5GraphicsSupport], [QT_LIBS="-lQt5GraphicsSupport $QT_LIBS"])
PKG_CHECK_MODULES([QTCGL], [Qt5CglSupport], [QT_LIBS="-lQt5CglSupport $QT_LIBS"])
fi
fi
dnl Internal. Check Qt static libs with PKG_CHECK_MODULES.
dnl
dnl _BITCOIN_QT_CHECK_STATIC_LIBS
dnl -----------------------------
dnl
dnl Outputs: QT_LIBS is prepended.
AC_DEFUN([_BITCOIN_QT_CHECK_STATIC_LIBS], [
PKG_CHECK_MODULES([QT_ACCESSIBILITY], [${qt_lib_prefix}AccessibilitySupport${qt_lib_suffix}], [QT_LIBS="$QT_ACCESSIBILITY_LIBS $QT_LIBS"])
PKG_CHECK_MODULES([QT_DEVICEDISCOVERY], [${qt_lib_prefix}DeviceDiscoverySupport${qt_lib_suffix}], [QT_LIBS="$QT_DEVICEDISCOVERY_LIBS $QT_LIBS"])
PKG_CHECK_MODULES([QT_EDID], [${qt_lib_prefix}EdidSupport${qt_lib_suffix}], [QT_LIBS="$QT_EDID_LIBS $QT_LIBS"])
PKG_CHECK_MODULES([QT_EVENTDISPATCHER], [${qt_lib_prefix}EventDispatcherSupport${qt_lib_suffix}], [QT_LIBS="$QT_EVENTDISPATCHER_LIBS $QT_LIBS"])
PKG_CHECK_MODULES([QT_FB], [${qt_lib_prefix}FbSupport${qt_lib_suffix}], [QT_LIBS="$QT_FB_LIBS $QT_LIBS"])
PKG_CHECK_MODULES([QT_FONTDATABASE], [${qt_lib_prefix}FontDatabaseSupport${qt_lib_suffix}], [QT_LIBS="$QT_FONTDATABASE_LIBS $QT_LIBS"])
PKG_CHECK_MODULES([QT_THEME], [${qt_lib_prefix}ThemeSupport${qt_lib_suffix}], [QT_LIBS="$QT_THEME_LIBS $QT_LIBS"])
if test "x$TARGET_OS" = xlinux; then
PKG_CHECK_MODULES([QT_INPUT], [${qt_lib_prefix}XcbQpa], [QT_LIBS="$QT_INPUT_LIBS $QT_LIBS"])
PKG_CHECK_MODULES([QT_SERVICE], [${qt_lib_prefix}ServiceSupport], [QT_LIBS="$QT_SERVICE_LIBS $QT_LIBS"])
PKG_CHECK_MODULES([QT_XCBQPA], [${qt_lib_prefix}XcbQpa], [QT_LIBS="$QT_XCBQPA_LIBS $QT_LIBS"])
elif test "x$TARGET_OS" = xdarwin; then
PKG_CHECK_MODULES([QT_CLIPBOARD], [${qt_lib_prefix}ClipboardSupport${qt_lib_suffix}], [QT_LIBS="$QT_CLIPBOARD_LIBS $QT_LIBS"])
PKG_CHECK_MODULES([QT_GRAPHICS], [${qt_lib_prefix}GraphicsSupport${qt_lib_suffix}], [QT_LIBS="$QT_GRAPHICS_LIBS $QT_LIBS"])
PKG_CHECK_MODULES([QT_SERVICE], [${qt_lib_prefix}ServiceSupport${qt_lib_suffix}], [QT_LIBS="$QT_SERVICE_LIBS $QT_LIBS"])
elif test "x$TARGET_OS" = xwindows; then
PKG_CHECK_MODULES([QT_WINDOWSUIAUTOMATION], [${qt_lib_prefix}WindowsUIAutomationSupport${qt_lib_suffix}], [QT_LIBS="$QT_WINDOWSUIAUTOMATION_LIBS $QT_LIBS"])
elif test "x$TARGET_OS" = xandroid; then
PKG_CHECK_MODULES([QT_EGL], [${qt_lib_prefix}EglSupport], [QT_LIBS="$QT_EGL_LIBS $QT_LIBS"])
fi
])
dnl Internal. Find Qt libraries using pkg-config.
dnl
dnl _BITCOIN_QT_FIND_LIBS
dnl ---------------------
dnl
dnl Outputs: All necessary QT_* variables are set.
dnl Outputs: have_qt_test and have_qt_dbus are set (if applicable) to yes|no.
AC_DEFUN([_BITCOIN_QT_FIND_LIBS],[
BITCOIN_QT_CHECK([
PKG_CHECK_MODULES([QT_CORE], [${qt_lib_prefix}Core $qt_version], [],
[BITCOIN_QT_FAIL([${qt_lib_prefix}Core $qt_version not found])])
PKG_CHECK_MODULES([QT_CORE], [${qt_lib_prefix}Core${qt_lib_suffix} $qt_version], [QT_INCLUDES="$QT_CORE_CFLAGS $QT_INCLUDES" QT_LIBS="$QT_CORE_LIBS $QT_LIBS"],
[BITCOIN_QT_FAIL([${qt_lib_prefix}Core${qt_lib_suffix} $qt_version not found])])
])
BITCOIN_QT_CHECK([
PKG_CHECK_MODULES([QT_GUI], [${qt_lib_prefix}Gui $qt_version], [],
[BITCOIN_QT_FAIL([${qt_lib_prefix}Gui $qt_version not found])])
PKG_CHECK_MODULES([QT_GUI], [${qt_lib_prefix}Gui${qt_lib_suffix} $qt_version], [QT_INCLUDES="$QT_GUI_CFLAGS $QT_INCLUDES" QT_LIBS="$QT_GUI_LIBS $QT_LIBS"],
[BITCOIN_QT_FAIL([${qt_lib_prefix}Gui${qt_lib_suffix} $qt_version not found])])
])
BITCOIN_QT_CHECK([
PKG_CHECK_MODULES([QT_WIDGETS], [${qt_lib_prefix}Widgets $qt_version], [],
[BITCOIN_QT_FAIL([${qt_lib_prefix}Widgets $qt_version not found])])
PKG_CHECK_MODULES([QT_WIDGETS], [${qt_lib_prefix}Widgets${qt_lib_suffix} $qt_version], [QT_INCLUDES="$QT_WIDGETS_CFLAGS $QT_INCLUDES" QT_LIBS="$QT_WIDGETS_LIBS $QT_LIBS"],
[BITCOIN_QT_FAIL([${qt_lib_prefix}Widgets${qt_lib_suffix} $qt_version not found])])
])
BITCOIN_QT_CHECK([
PKG_CHECK_MODULES([QT_NETWORK], [${qt_lib_prefix}Network $qt_version], [],
[BITCOIN_QT_FAIL([${qt_lib_prefix}Network $qt_version not found])])
PKG_CHECK_MODULES([QT_NETWORK], [${qt_lib_prefix}Network${qt_lib_suffix} $qt_version], [QT_INCLUDES="$QT_NETWORK_CFLAGS $QT_INCLUDES" QT_LIBS="$QT_NETWORK_LIBS $QT_LIBS"],
[BITCOIN_QT_FAIL([${qt_lib_prefix}Network${qt_lib_suffix} $qt_version not found])])
])
QT_INCLUDES="$QT_CORE_CFLAGS $QT_GUI_CFLAGS $QT_WIDGETS_CFLAGS $QT_NETWORK_CFLAGS"
QT_LIBS="$QT_CORE_LIBS $QT_GUI_LIBS $QT_WIDGETS_LIBS $QT_NETWORK_LIBS"
BITCOIN_QT_CHECK([
PKG_CHECK_MODULES([QT_TEST], [${qt_lib_prefix}Test $qt_version], [QT_TEST_INCLUDES="$QT_TEST_CFLAGS"; have_qt_test=yes], [have_qt_test=no])
PKG_CHECK_MODULES([QT_TEST], [${qt_lib_prefix}Test${qt_lib_suffix} $qt_version], [QT_TEST_INCLUDES="$QT_TEST_CFLAGS"; have_qt_test=yes], [have_qt_test=no])
if test "x$use_dbus" != xno; then
PKG_CHECK_MODULES([QT_DBUS], [${qt_lib_prefix}DBus $qt_version], [QT_DBUS_INCLUDES="$QT_DBUS_CFLAGS"; have_qt_dbus=yes], [have_qt_dbus=no])
fi

View file

@ -12,8 +12,17 @@ dnl warranty.
m4_define([_CHECK_ATOMIC_testbody], [[
#include <atomic>
#include <cstdint>
#include <chrono>
using namespace std::chrono_literals;
int main() {
std::atomic<bool> lock{true};
std::atomic_exchange(&lock, false);
std::atomic<std::chrono::seconds> t{0s};
t.store(2s);
std::atomic<int64_t> a{};
int64_t v = 5;

36
build-aux/m4/l_socket.m4 Normal file
View file

@ -0,0 +1,36 @@
# Illumos/SmartOS requires linking with -lsocket if
# using getifaddrs & freeifaddrs
m4_define([_CHECK_SOCKET_testbody], [[
#include <sys/types.h>
#include <ifaddrs.h>
int main() {
struct ifaddrs *ifaddr;
getifaddrs(&ifaddr);
freeifaddrs(ifaddr);
}
]])
AC_DEFUN([CHECK_SOCKET], [
AC_LANG_PUSH(C++)
AC_MSG_CHECKING([whether ifaddrs funcs can be used without link library])
AC_LINK_IFELSE([AC_LANG_SOURCE([_CHECK_SOCKET_testbody])],[
AC_MSG_RESULT([yes])
],[
AC_MSG_RESULT([no])
LIBS="$LIBS -lsocket"
AC_MSG_CHECKING([whether getifaddrs needs -lsocket])
AC_LINK_IFELSE([AC_LANG_SOURCE([_CHECK_SOCKET_testbody])],[
AC_MSG_RESULT([yes])
],[
AC_MSG_RESULT([no])
AC_MSG_FAILURE([cannot figure out how to use getifaddrs])
])
])
AC_LANG_POP
])

View file

@ -3,7 +3,7 @@ Building Bitcoin Core with Visual Studio
Introduction
---------------------
Solution and project files to build the Bitcoin Core applications `msbuild` or Visual Studio can be found in the `build_msvc` directory. The build has been tested with Visual Studio 2017 and 2019.
Solution and project files to build the Bitcoin Core applications `msbuild` or Visual Studio can be found in the `build_msvc` directory. The build has been tested with Visual Studio 2019 (building with earlier versions of Visual Studio should not be expected to work).
Building with Visual Studio is an alternative to the Linux based [cross-compiler build](https://github.com/bitcoin/bitcoin/blob/master/doc/build-windows.md).
@ -27,11 +27,15 @@ Options for installing the dependencies in a Visual Studio compatible manner are
- Download the source code, build each dependency, add the required include paths, link libraries and binary tools to the Visual Studio project files.
- Use [nuget](https://www.nuget.org/) packages with the understanding that any binary files have been compiled by an untrusted third party.
The [external dependencies](https://github.com/bitcoin/bitcoin/blob/master/doc/dependencies.md) required for building are listed in the `build_msvc/vcpkg.json` file. The `msbuild` project files are configured to automatically install the `vcpkg` dependencies.
The [external dependencies](https://github.com/bitcoin/bitcoin/blob/master/doc/dependencies.md) required for building are listed in the `build_msvc/vcpkg.json` file. To ensure `msbuild` project files automatically install the `vcpkg` dependencies use:
```
vcpkg integrate install
```
Qt
---------------------
In order to build the Bitcoin Core a static build of Qt is required. The runtime library version (e.g. v141, v142) and platform type (x86 or x64) must also match.
In order to build Bitcoin Core a static build of Qt is required. The runtime library version (e.g. v142) and platform type (x86 or x64) must also match.
Some prebuilt x64 versions of Qt can be downloaded from [here](https://github.com/sipsorcery/qt_win_binary/releases). Please be aware these downloads are NOT officially sanctioned by Bitcoin Core and are provided for developer convenience only. They should NOT be used for builds that will be used in a production environment or with real funds.
@ -53,19 +57,13 @@ PS >py -3 msvc-autogen.py
- An optional step is to adjust the settings in the `build_msvc` directory and the `common.init.vcxproj` file. This project file contains settings that are common to all projects such as the runtime library version and target Windows SDK version. The Qt directories can also be set.
- To build from the command line with the Visual Studio 2017 toolchain use:
```
msbuild /m bitcoin.sln /p:Platform=x64 /p:Configuration=Release /p:PlatformToolset=v141 /t:build
```
- To build from the command line with the Visual Studio 2019 toolchain use:
```
msbuild /m bitcoin.sln /p:Platform=x64 /p:Configuration=Release /t:build
```
- Alternatively open the `build_msvc/bitcoin.sln` file in Visual Studio.
- Alternatively, open the `build_msvc/bitcoin.sln` file in Visual Studio 2019.
AppVeyor
---------------------
@ -77,3 +75,25 @@ For safety reasons the Bitcoin Core .appveyor.yml file has the artifact options
#- 7z a bitcoin-%APPVEYOR_BUILD_VERSION%.zip %APPVEYOR_BUILD_FOLDER%\build_msvc\%platform%\%configuration%\*.exe
#- path: bitcoin-%APPVEYOR_BUILD_VERSION%.zip
```
Security
---------------------
[Base address randomization](https://docs.microsoft.com/en-us/cpp/build/reference/dynamicbase-use-address-space-layout-randomization?view=msvc-160) is used to make Bitcoin Core more secure. When building Bitcoin using the `build_msvc` process base address randomization can be disabled by editing `common.init.vcproj` to change `RandomizedBaseAddress` from `true` to `false` and then rebuilding the project.
To check if `bitcoind` has `RandomizedBaseAddress` enabled or disabled run
```
.\dumpbin.exe /headers src/bitcoind.exe
```
If is it enabled then in the output `Dynamic base` will be listed in the `DLL characteristics` under `OPTIONAL HEADER VALUES` as shown below
```
8160 DLL characteristics
High Entropy Virtual Addresses
Dynamic base
NX compatible
Terminal Server Aware
```
This may not disable all stack randomization as versions of windows employ additional stack randomization protections. These protections must be turned off in the OS configuration.

View file

@ -55,8 +55,9 @@
<AdditionalIncludeDirectories>$(QtIncludes);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<AdditionalDependencies>$(QtReleaseLibraries);%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalOptions>/ignore:4206</AdditionalOptions>
<AdditionalOptions>/ignore:4206 /LTCG:OFF</AdditionalOptions>
</Link>
<ResourceCompile>
<AdditionalIncludeDirectories>..\..\src;</AdditionalIncludeDirectories>

View file

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\common.init.vcxproj" />
<PropertyGroup Label="Globals">
<ProjectGuid>{D3022AF6-AD33-4CE3-B358-87CB6A1B29CF}</ProjectGuid>
</PropertyGroup>
<PropertyGroup Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
</PropertyGroup>
<ItemGroup>
<ClCompile Include="..\..\src\bitcoin-util.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\libbitcoinconsensus\libbitcoinconsensus.vcxproj">
<Project>{2b384fa8-9ee1-4544-93cb-0d733c25e8ce}</Project>
</ProjectReference>
<ProjectReference Include="..\libbitcoin_common\libbitcoin_common.vcxproj">
<Project>{7c87e378-df58-482e-aa2f-1bc129bc19ce}</Project>
</ProjectReference>
<ProjectReference Include="..\libbitcoin_crypto\libbitcoin_crypto.vcxproj">
<Project>{6190199c-6cf4-4dad-bfbd-93fa72a760c1}</Project>
</ProjectReference>
<ProjectReference Include="..\libbitcoin_util\libbitcoin_util.vcxproj">
<Project>{b53a5535-ee9d-4c6f-9a26-f79ee3bc3754}</Project>
</ProjectReference>
<ProjectReference Include="..\libunivalue\libunivalue.vcxproj">
<Project>{5724ba7d-a09a-4ba8-800b-c4c1561b3d69}</Project>
</ProjectReference>
<ProjectReference Include="..\libsecp256k1\libsecp256k1.vcxproj">
<Project>{bb493552-3b8c-4a8c-bf69-a6e7a51d2ea6}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<Import Project="..\common.vcxproj" />
</Project>

View file

@ -32,6 +32,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bench_bitcoin", "bench_bitc
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bitcoin-tx", "bitcoin-tx\bitcoin-tx.vcxproj", "{D3022AF6-AD33-4CE3-B358-87CB6A1B29CF}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bitcoin-util", "bitcoin-util\bitcoin-util.vcxproj", "{D3022AF6-AD33-4CE3-B358-87CB6A1B29CF}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bitcoin-wallet", "bitcoin-wallet\bitcoin-wallet.vcxproj", "{84DE8790-EDE3-4483-81AC-C32F15E861F4}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libbitcoin_wallet_tool", "libbitcoin_wallet_tool\libbitcoin_wallet_tool.vcxproj", "{F91AC55E-6F5E-4C58-9AC5-B40DB7DEEF93}"

View file

@ -15,13 +15,10 @@
#define CLIENT_VERSION_IS_RELEASE false
/* Major version */
#define CLIENT_VERSION_MAJOR 0
#define CLIENT_VERSION_MAJOR 21
/* Minor version */
#define CLIENT_VERSION_MINOR 20
/* Build revision */
#define CLIENT_VERSION_REVISION 99
#define CLIENT_VERSION_MINOR 99
/* Copyright holder(s) before %s replacement */
#define COPYRIGHT_HOLDERS "The %s developers"
@ -38,6 +35,12 @@
/* Define to 1 to enable wallet functions */
#define ENABLE_WALLET 1
/* Define to 1 to enable BDB wallet */
#define USE_BDB 1
/* Define to 1 to enable SQLite wallet */
#define USE_SQLITE 1
/* Define to 1 to enable ZMQ functions */
#define ENABLE_ZMQ 1
@ -47,15 +50,12 @@
/* define if the Boost::Filesystem library is available */
#define HAVE_BOOST_FILESYSTEM /**/
/* define if the Boost::Process library is available */
#define HAVE_BOOST_PROCESS /**/
/* define if external signer support is enabled (requires Boost::Process) */
#define ENABLE_EXTERNAL_SIGNER /**/
/* define if the Boost::System library is available */
#define HAVE_BOOST_SYSTEM /**/
/* define if the Boost::Thread library is available */
#define HAVE_BOOST_THREAD /**/
/* define if the Boost::Unit_Test_Framework library is available */
#define HAVE_BOOST_UNIT_TEST_FRAMEWORK /**/
@ -92,9 +92,9 @@
don't. */
#define HAVE_DECL_BSWAP_64 0
/* Define to 1 if you have the declaration of `daemon', and to 0 if you don't.
/* Define to 1 if you have the declaration of `fork', and to 0 if you don't.
*/
#define HAVE_DECL_DAEMON 0
#define HAVE_DECL_FORK 0
/* Define to 1 if you have the declaration of `htobe16', and to 0 if you
don't. */
@ -132,6 +132,10 @@
don't. */
#define HAVE_DECL_LE64TOH 0
/* Define to 1 if you have the declaration of `setsid', and to 0 if you don't.
*/
#define HAVE_DECL_SETSID 0
/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you
don't. */
#define HAVE_DECL_STRERROR_R 0
@ -177,9 +181,6 @@
/* Define to 1 if you have the <miniupnpc/miniupnpc.h> header file. */
#define HAVE_MINIUPNPC_MINIUPNPC_H 1
/* Define to 1 if you have the <miniupnpc/miniwget.h> header file. */
#define HAVE_MINIUPNPC_MINIWGET_H 1
/* Define to 1 if you have the <miniupnpc/upnpcommands.h> header file. */
#define HAVE_MINIUPNPC_UPNPCOMMANDS_H 1
@ -253,7 +254,7 @@
#define PACKAGE_NAME "Bitcoin Core"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "Bitcoin Core 0.19.99"
#define PACKAGE_STRING "Bitcoin Core 21.99.0"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "bitcoin"
@ -262,7 +263,7 @@
#define PACKAGE_URL "https://bitcoincore.org/"
/* Define to the version of this package. */
#define PACKAGE_VERSION "0.19.99"
#define PACKAGE_VERSION "21.99.0"
/* Define to necessary symbol if this constant uses a non-standard name on
your system. */

View file

@ -10,6 +10,9 @@
</PropertyGroup>
<ItemGroup>
<ClCompile Include="..\..\src\bitcoind.cpp" />
<ClCompile Include="..\..\src\init\bitcoind.cpp">
<ObjectFileName>$(IntDir)init_bitcoind.obj</ObjectFileName>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\libbitcoinconsensus\libbitcoinconsensus.vcxproj">
@ -62,6 +65,10 @@
Replace="@EXEEXT@" By=".exe"></ReplaceInFile>
<ReplaceInFile FilePath="$(ConfigIniOut)"
Replace="@ENABLE_WALLET_TRUE@" By=""></ReplaceInFile>
<ReplaceInFile FilePath="$(ConfigIniOut)"
Replace="@USE_BDB_TRUE@" By=""></ReplaceInFile>
<ReplaceInFile FilePath="$(ConfigIniOut)"
Replace="@USE_SQLITE_TRUE@" By=""></ReplaceInFile>
<ReplaceInFile FilePath="$(ConfigIniOut)"
Replace="@BUILD_BITCOIN_CLI_TRUE@" By=""></ReplaceInFile>
<ReplaceInFile FilePath="$(ConfigIniOut)"

View file

@ -4,8 +4,6 @@
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<VcpkgTriplet Condition="'$(Platform)'=='Win32'">x86-windows-static</VcpkgTriplet>
<VcpkgTriplet Condition="'$(Platform)'=='x64'">x64-windows-static</VcpkgTriplet>
<UseNativeEnvironment>true</UseNativeEnvironment>
</PropertyGroup>
@ -16,6 +14,8 @@
<VcpkgUseStatic>true</VcpkgUseStatic>
<VcpkgAutoLink>true</VcpkgAutoLink>
<VcpkgConfiguration>$(Configuration)</VcpkgConfiguration>
<VcpkgTriplet Condition="'$(Platform)'=='Win32'">x86-windows-static</VcpkgTriplet>
<VcpkgTriplet Condition="'$(Platform)'=='x64'">x64-windows-static</VcpkgTriplet>
</PropertyGroup>
<PropertyGroup Condition="'$(WindowsTargetPlatformVersion)'=='' and !Exists('$(WindowsSdkDir)\DesignTime\CommonConfiguration\Neutral\Windows.props')">
@ -45,66 +45,46 @@
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
<LinkIncremental>false</LinkIncremental>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<GenerateManifest>No</GenerateManifest>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</OutDir>
<IntDir>$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
<LinkIncremental>true</LinkIncremental>
<WholeProgramOptimization>false</WholeProgramOptimization>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</OutDir>
<IntDir>$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
<LinkIncremental>false</LinkIncremental>
<WholeProgramOptimization>true</WholeProgramOptimization>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</OutDir>
<IntDir>$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<Optimization>Disabled</Optimization>
<WholeProgramOptimization>false</WholeProgramOptimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<DebugInformationFormat>None</DebugInformationFormat>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>false</EnableCOMDATFolding>
<OptimizeReferences>false</OptimizeReferences>
<AdditionalOptions>/LTCG:OFF</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
<ClCompile>
<Optimization>Disabled</Optimization>
<WholeProgramOptimization>false</WholeProgramOptimization>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
@ -116,16 +96,16 @@
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<AdditionalOptions>/utf-8 /std:c++17 %(AdditionalOptions)</AdditionalOptions>
<DisableSpecificWarnings>4018;4221;4244;4267;4334;4715;4805;4834</DisableSpecificWarnings>
<AdditionalOptions>/utf-8 /Zc:__cplusplus /std:c++17 %(AdditionalOptions)</AdditionalOptions>
<DisableSpecificWarnings>4018;4244;4267;4334;4715;4805;4834</DisableSpecificWarnings>
<TreatWarningAsError>true</TreatWarningAsError>
<PreprocessorDefinitions>_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;_SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING;ZMQ_STATIC;NOMINMAX;WIN32;HAVE_CONFIG_H;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_CONSOLE;_WIN32_WINNT=0x0601;_WIN32_IE=0x0501;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\..\src;..\..\src\univalue\include;..\..\src\secp256k1\include;..\..\src\leveldb\include;..\..\src\leveldb\helpers\memenv;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>Iphlpapi.lib;ws2_32.lib;Shlwapi.lib;kernel32.lib;user32.lib;gdi32.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<RandomizedBaseAddress>true</RandomizedBaseAddress>
</Link>
<Lib>
<AdditionalOptions>/ignore:4221</AdditionalOptions>

View file

@ -2,15 +2,15 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="QtGlobals">
<QtBaseDir>C:\Qt5.9.8_x64_static_vs2019</QtBaseDir>
<QtBaseDir>C:\Qt5.12.11_x64_static_vs2019_16101</QtBaseDir>
<QtPluginsLibraryDir>$(QtBaseDir)\plugins</QtPluginsLibraryDir>
<QtLibraryDir>$(QtBaseDir)\lib</QtLibraryDir>
<QtIncludeDir>$(QtBaseDir)\include</QtIncludeDir>
<QtIncludes>$(QtIncludeDir);$(QtIncludeDir)\QtNetwork;$(QtIncludeDir)\QtCore;$(QtIncludeDir)\QtWidgets;$(QtIncludeDir)\QtGui;</QtIncludes>
<GeneratedFilesOutDir>.\QtGeneratedFiles\qt</GeneratedFilesOutDir>
<QtToolsDir>$(QtBaseDir)\bin</QtToolsDir>
<QtReleaseLibraries>$(QtPluginsLibraryDir)\platforms\qminimal.lib;$(QtPluginsLibraryDir)\platforms\qwindows.lib;$(QtLibraryDir)\qtfreetype.lib;$(QtLibraryDir)\qtharfbuzz.lib;$(QtLibraryDir)\qtlibpng.lib;$(QtLibraryDir)\qtpcre2.lib;$(QtLibraryDir)\Qt5AccessibilitySupport.lib;$(QtLibraryDir)\Qt5Core.lib;$(QtLibraryDir)\Qt5Concurrent.lib;$(QtLibraryDir)\Qt5EventDispatcherSupport.lib;$(QtLibraryDir)\Qt5FontDatabaseSupport.lib;$(QtLibraryDir)\Qt5Gui.lib;$(QtLibraryDir)\Qt5Network.lib;$(QtLibraryDir)\Qt5PlatformCompositorSupport.lib;$(QtLibraryDir)\Qt5ThemeSupport.lib;$(QtLibraryDir)\Qt5Widgets.lib;$(QtLibraryDir)\Qt5WinExtras.lib;$(QtLibraryDir)\qtmain.lib;userenv.lib;netapi32.lib;imm32.lib;Dwmapi.lib;version.lib;winmm.lib;UxTheme.lib</QtReleaseLibraries>
<QtDebugLibraries>$(QtPluginsLibraryDir)\platforms\qwindowsd.lib;$(QtPluginsLibraryDir)\platforms\qminimald.lib;$(QtLibraryDir)\*d.lib;crypt32.lib;userenv.lib;netapi32.lib;imm32.lib;Dwmapi.lib;version.lib;winmm.lib;UxTheme.lib</QtDebugLibraries>
<QtReleaseLibraries>$(QtPluginsLibraryDir)\platforms\qminimal.lib;$(QtPluginsLibraryDir)\platforms\qwindows.lib;$(QtPluginsLibraryDir)\styles\qwindowsvistastyle.lib;$(QtLibraryDir)\Qt5WindowsUIAutomationSupport.lib;$(QtLibraryDir)\qtfreetype.lib;$(QtLibraryDir)\qtharfbuzz.lib;$(QtLibraryDir)\qtlibpng.lib;$(QtLibraryDir)\qtpcre2.lib;$(QtLibraryDir)\Qt5AccessibilitySupport.lib;$(QtLibraryDir)\Qt5Core.lib;$(QtLibraryDir)\Qt5Concurrent.lib;$(QtLibraryDir)\Qt5EventDispatcherSupport.lib;$(QtLibraryDir)\Qt5FontDatabaseSupport.lib;$(QtLibraryDir)\Qt5Gui.lib;$(QtLibraryDir)\Qt5Network.lib;$(QtLibraryDir)\Qt5PlatformCompositorSupport.lib;$(QtLibraryDir)\Qt5ThemeSupport.lib;$(QtLibraryDir)\Qt5Widgets.lib;$(QtLibraryDir)\Qt5WinExtras.lib;$(QtLibraryDir)\qtmain.lib;Wtsapi32.lib;userenv.lib;netapi32.lib;imm32.lib;Dwmapi.lib;version.lib;winmm.lib;UxTheme.lib</QtReleaseLibraries>
<QtDebugLibraries>$(QtPluginsLibraryDir)\platforms\qwindowsd.lib;$(QtPluginsLibraryDir)\platforms\qminimald.lib;$(QtPluginsLibraryDir)\styles\qwindowsvistastyled.lib;$(QtLibraryDir)\*d.lib;Wtsapi32.lib;crypt32.lib;userenv.lib;netapi32.lib;imm32.lib;Dwmapi.lib;version.lib;winmm.lib;UxTheme.lib</QtDebugLibraries>
</PropertyGroup>
</Project>

View file

@ -4,7 +4,7 @@
<Target Name="CopyBuildArtifacts" Condition="'$(ConfigurationType)' != 'StaticLibrary'">
<ItemGroup>
<BuildArtifacts Include="$(OutDir)$(TargetName)$(TargetExt)"></BuildArtifacts>
<BuildArtifacts Include="$(OutDir)$(TargetName).pdb"></BuildArtifacts>
<BuildArtifacts Include="$(OutDir)$(TargetName).pdb" Condition="Exists('$(OutDir)$(TargetName).pdb')"></BuildArtifacts>
</ItemGroup>
<Copy SourceFiles="@(BuildArtifacts)" SkipUnchangedFiles="true" DestinationFolder="..\..\src\" Condition="'$(OutDir)' != ''"></Copy>
</Target>

View file

@ -34,6 +34,7 @@
<ClCompile Include="..\..\src\qt\overviewpage.cpp" />
<ClCompile Include="..\..\src\qt\paymentserver.cpp" />
<ClCompile Include="..\..\src\qt\peertablemodel.cpp" />
<ClCompile Include="..\..\src\qt\peertablesortproxy.cpp" />
<ClCompile Include="..\..\src\qt\platformstyle.cpp" />
<ClCompile Include="..\..\src\qt\psbtoperationsdialog.cpp" />
<ClCompile Include="..\..\src\qt\qrimagewidget.cpp" />
@ -87,6 +88,7 @@
<ClCompile Include="$(GeneratedFilesOutDir)\moc\moc_overviewpage.cpp" />
<ClCompile Include="$(GeneratedFilesOutDir)\moc\moc_paymentserver.cpp" />
<ClCompile Include="$(GeneratedFilesOutDir)\moc\moc_peertablemodel.cpp" />
<ClCompile Include="$(GeneratedFilesOutDir)\moc\moc_peertablesortproxy.cpp" />
<ClCompile Include="$(GeneratedFilesOutDir)\moc\moc_platformstyle.cpp" />
<ClCompile Include="$(GeneratedFilesOutDir)\moc\moc_psbtoperationsdialog.cpp" />
<ClCompile Include="$(GeneratedFilesOutDir)\moc\moc_qrimagewidget.cpp" />
@ -104,6 +106,7 @@
<ClCompile Include="$(GeneratedFilesOutDir)\moc\moc_transactiondesc.cpp" />
<ClCompile Include="$(GeneratedFilesOutDir)\moc\moc_transactiondescdialog.cpp" />
<ClCompile Include="$(GeneratedFilesOutDir)\moc\moc_transactionfilterproxy.cpp" />
<ClCompile Include="$(GeneratedFilesOutDir)\moc\moc_transactionoverviewwidget.cpp" />
<ClCompile Include="$(GeneratedFilesOutDir)\moc\moc_transactionrecord.cpp" />
<ClCompile Include="$(GeneratedFilesOutDir)\moc\moc_transactiontablemodel.cpp" />
<ClCompile Include="$(GeneratedFilesOutDir)\moc\moc_transactionview.cpp" />

View file

@ -8,6 +8,9 @@
<ConfigurationType>StaticLibrary</ConfigurationType>
</PropertyGroup>
<ItemGroup>
<ClCompile Include="..\..\src\wallet\bdb.cpp" />
<ClCompile Include="..\..\src\wallet\salvage.cpp" />
<ClCompile Include="..\..\src\wallet\sqlite.cpp" />
@SOURCE_FILES@
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

View file

@ -51,7 +51,7 @@
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>HAVE_CRC32C=0;HAVE_SNAPPY=0;__STDC_LIMIT_MACROS;LEVELDB_IS_BIG_ENDIAN=0;_UNICODE;UNICODE;_CRT_NONSTDC_NO_DEPRECATE;LEVELDB_PLATFORM_WINDOWS;LEVELDB_ATOMIC_PRESENT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<DisableSpecificWarnings>4244;4267;4312;4722;</DisableSpecificWarnings>
<DisableSpecificWarnings>4244;4267</DisableSpecificWarnings>
<AdditionalIncludeDirectories>..\..\src\leveldb;..\..\src\leveldb\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>

0
build_msvc/msvc-autogen.py Normal file → Executable file
View file

View file

@ -11,7 +11,6 @@
<ClCompile Include="..\..\src\test\util\setup_common.cpp" />
<ClCompile Include="..\..\src\qt\test\addressbooktests.cpp" />
<ClCompile Include="..\..\src\qt\test\apptests.cpp" />
<ClCompile Include="..\..\src\qt\test\compattests.cpp" />
<ClCompile Include="..\..\src\qt\test\rpcnestedtests.cpp" />
<ClCompile Include="..\..\src\qt\test\test_main.cpp" />
<ClCompile Include="..\..\src\qt\test\uritests.cpp" />
@ -20,7 +19,6 @@
<ClCompile Include="..\..\src\wallet\test\wallet_test_fixture.cpp" />
<ClCompile Include="$(GeneratedFilesOutDir)\moc\moc_addressbooktests.cpp" />
<ClCompile Include="$(GeneratedFilesOutDir)\moc\moc_apptests.cpp" />
<ClCompile Include="$(GeneratedFilesOutDir)\moc\moc_compattests.cpp" />
<ClCompile Include="$(GeneratedFilesOutDir)\moc\moc_rpcnestedtests.cpp" />
<ClCompile Include="$(GeneratedFilesOutDir)\moc\moc_uritests.cpp" />
<ClCompile Include="$(GeneratedFilesOutDir)\moc\moc_wallettests.cpp" />
@ -73,7 +71,7 @@
</ClCompile>
<Link>
<AdditionalDependencies>$(QtLibraryDir)\Qt5Test.lib;$(QtReleaseLibraries);%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalOptions>/ignore:4206</AdditionalOptions>
<AdditionalOptions>/ignore:4206 /LTCG:OFF</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
@ -83,13 +81,12 @@
</ClCompile>
<Link>
<AdditionalDependencies>$(QtDebugLibraries);%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalOptions>/ignore:4206</AdditionalOptions>
<AdditionalOptions>/ignore:4206</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<MocTestFiles Include="..\..\src\qt\test\addressbooktests.h" />
<MocTestFiles Include="..\..\src\qt\test\apptests.h" />
<MocTestFiles Include="..\..\src\qt\test\compattests.h" />
<MocTestFiles Include="..\..\src\qt\test\rpcnestedtests.h" />
<MocTestFiles Include="..\..\src\qt\test\uritests.h" />
<MocTestFiles Include="..\..\src\qt\test\wallettests.h" />

View file

@ -1,4 +1,4 @@
// Copyright (c) 2018-2019 The Bitcoin Core developers
// Copyright (c) 2018-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@ -45,7 +45,7 @@ int main()
stream << vanillaSpendTx;
bitcoinconsensus_error err;
auto op0Result = bitcoinconsensus_verify_script_with_amount(pubKeyScript.data(), pubKeyScript.size(), amount, (const unsigned char*)&stream[0], stream.size(), 0, bitcoinconsensus_SCRIPT_FLAGS_VERIFY_ALL, &err);
auto op0Result = bitcoinconsensus_verify_script_with_amount(pubKeyScript.data(), pubKeyScript.size(), amount, stream.data(), stream.size(), 0, bitcoinconsensus_SCRIPT_FLAGS_VERIFY_ALL, &err);
std::cout << "Op0 result: " << op0Result << ", error code " << err << std::endl;
getchar();

View file

@ -8,7 +8,6 @@
"boost-process",
"boost-signals2",
"boost-test",
"boost-thread",
"sqlite3",
"double-conversion",
{

View file

@ -1,20 +1,22 @@
#!/usr/bin/env bash
#
# Copyright (c) 2018-2019 The Bitcoin Core developers
# Copyright (c) 2018-2020 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
export LC_ALL=C
travis_retry sudo apt update && sudo apt install -y clang-format-9
sudo update-alternatives --install /usr/bin/clang-format clang-format $(which clang-format-9 ) 100
sudo update-alternatives --install /usr/bin/clang-format-diff clang-format-diff $(which clang-format-diff-9) 100
${CI_RETRY_EXE} apt-get update
${CI_RETRY_EXE} apt-get install -y clang-format-9 python3-pip curl git gawk jq
update-alternatives --install /usr/bin/clang-format clang-format $(which clang-format-9 ) 100
update-alternatives --install /usr/bin/clang-format-diff clang-format-diff $(which clang-format-diff-9) 100
travis_retry pip3 install codespell==1.17.1
travis_retry pip3 install flake8==3.8.3
travis_retry pip3 install yq
travis_retry pip3 install mypy==0.781
${CI_RETRY_EXE} pip3 install codespell==2.0.0
${CI_RETRY_EXE} pip3 install flake8==3.8.3
${CI_RETRY_EXE} pip3 install yq
${CI_RETRY_EXE} pip3 install mypy==0.781
${CI_RETRY_EXE} pip3 install vulture==2.3
SHELLCHECK_VERSION=v0.7.1
SHELLCHECK_VERSION=v0.7.2
curl -sL "https://github.com/koalaman/shellcheck/releases/download/${SHELLCHECK_VERSION}/shellcheck-${SHELLCHECK_VERSION}.linux.x86_64.tar.xz" | tar --xz -xf - --directory /tmp/
export PATH="/tmp/shellcheck-${SHELLCHECK_VERSION}:${PATH}"

View file

@ -1,9 +0,0 @@
#!/usr/bin/env bash
#
# Copyright (c) 2018-2019 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
export LC_ALL=C
git fetch --unshallow

View file

@ -1,30 +1,33 @@
#!/usr/bin/env bash
#
# Copyright (c) 2018-2019 The Bitcoin Core developers
# Copyright (c) 2018-2020 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
export LC_ALL=C
if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then
# TRAVIS_BRANCH will be present in a Travis environment. For builds triggered
# by a pull request this is the name of the branch targeted by the pull request.
# https://docs.travis-ci.com/user/environment-variables/
COMMIT_RANGE="$TRAVIS_BRANCH..HEAD"
GIT_HEAD=$(git rev-parse HEAD)
if [ -n "$CIRRUS_PR" ]; then
COMMIT_RANGE="$CIRRUS_BASE_SHA..$GIT_HEAD"
test/lint/commit-script-check.sh $COMMIT_RANGE
fi
export COMMIT_RANGE
# This only checks that the trees are pure subtrees, it is not doing a full
# check with -r to not have to fetch all the remotes.
test/lint/git-subtree-check.sh src/crypto/ctaes
test/lint/git-subtree-check.sh src/secp256k1
test/lint/git-subtree-check.sh src/univalue
test/lint/git-subtree-check.sh src/leveldb
test/lint/git-subtree-check.sh src/crc32c
test/lint/check-doc.py
test/lint/check-rpc-mappings.py .
test/lint/lint-all.sh
if [ "$TRAVIS_REPO_SLUG" = "bitcoin/bitcoin" ] && [ "$TRAVIS_EVENT_TYPE" = "cron" ]; then
if [ "$CIRRUS_REPO_FULL_NAME" = "bitcoin/bitcoin" ] && [ -n "$CIRRUS_CRON" ]; then
git log --merges --before="2 days ago" -1 --format='%H' > ./contrib/verify-commits/trusted-sha512-root-commit
travis_retry gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys $(<contrib/verify-commits/trusted-keys) &&
${CI_RETRY_EXE} gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys $(<contrib/verify-commits/trusted-keys) &&
./contrib/verify-commits/verify-commits.py --clean-merge=2;
fi
echo
git log --no-merges --oneline $COMMIT_RANGE

11
ci/lint_run_all.sh Executable file
View file

@ -0,0 +1,11 @@
#!/usr/bin/env bash
#
# Copyright (c) 2019-2020 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
export LC_ALL=C.UTF-8
set -o errexit; source ./ci/test/00_setup_env.sh
set -o errexit; source ./ci/lint/04_install.sh
set -o errexit; source ./ci/lint/06_script.sh

View file

@ -11,6 +11,12 @@ export LC_ALL=C.UTF-8
# This is where the depends build is done.
BASE_ROOT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )"/../../ >/dev/null 2>&1 && pwd )
export BASE_ROOT_DIR
# The depends dir.
# This folder exists on the ci host and ci guest. Changes are propagated back and forth.
export DEPENDS_DIR=${DEPENDS_DIR:-$BASE_ROOT_DIR/depends}
# A folder for the ci system to put temporary files (ccache, datadirs for tests, ...)
# This folder only exists on the ci host.
export BASE_SCRATCH_DIR=${BASE_SCRATCH_DIR:-$BASE_ROOT_DIR/ci/scratch}
echo "Setting specific values in env"
if [ -n "${FILE_ENV}" ]; then
@ -22,9 +28,6 @@ fi
echo "Fallback to default values in env (if not yet set)"
# The number of parallel jobs to pass down to make and test_runner.py
export MAKEJOBS=${MAKEJOBS:--j4}
# A folder for the ci system to put temporary files (ccache, datadirs for tests, ...)
# This folder only exists on the ci host.
export BASE_SCRATCH_DIR=${BASE_SCRATCH_DIR:-$BASE_ROOT_DIR/ci/scratch}
# What host to compile for. See also ./depends/README.md
# Tests that need cross-compilation export the appropriate HOST.
# Tests that run natively guess the host
@ -44,7 +47,7 @@ export RUN_FUZZ_TESTS=${RUN_FUZZ_TESTS:-false}
export EXPECTED_TESTS_DURATION_IN_SECONDS=${EXPECTED_TESTS_DURATION_IN_SECONDS:-1000}
export CONTAINER_NAME=${CONTAINER_NAME:-ci_unnamed}
export DOCKER_NAME_TAG=${DOCKER_NAME_TAG:-ubuntu:18.04}
export DOCKER_NAME_TAG=${DOCKER_NAME_TAG:-ubuntu:20.04}
# Randomize test order.
# See https://www.boost.org/doc/libs/1_71_0/libs/test/doc/html/boost_test/utf_reference/rt_param_reference/random.html
export BOOST_TEST_RANDOM=${BOOST_TEST_RANDOM:-1}
@ -56,16 +59,13 @@ export CCACHE_COMPRESS=${CCACHE_COMPRESS:-1}
# The cache dir.
# This folder exists on the ci host and ci guest. Changes are propagated back and forth.
export CCACHE_DIR=${CCACHE_DIR:-$BASE_SCRATCH_DIR/.ccache}
# The depends dir.
# This folder exists on the ci host and ci guest. Changes are propagated back and forth.
export DEPENDS_DIR=${DEPENDS_DIR:-$BASE_ROOT_DIR/depends}
# Folder where the build result is put (bin and lib).
export BASE_OUTDIR=${BASE_OUTDIR:-$BASE_SCRATCH_DIR/out/$HOST}
# Folder where the build is done (dist and out-of-tree build).
export BASE_BUILD_DIR=${BASE_BUILD_DIR:-$BASE_SCRATCH_DIR/build}
export PREVIOUS_RELEASES_DIR=${PREVIOUS_RELEASES_DIR:-$BASE_ROOT_DIR/releases/$HOST}
export SDK_URL=${SDK_URL:-https://bitcoincore.org/depends-sources/sdks}
export DOCKER_PACKAGES=${DOCKER_PACKAGES:-build-essential libtool autotools-dev automake pkg-config bsdmainutils curl ca-certificates ccache python3 rsync git procps}
export DOCKER_PACKAGES=${DOCKER_PACKAGES:-build-essential libtool autotools-dev automake pkg-config bsdmainutils curl ca-certificates ccache python3 rsync git procps bison}
export GOAL=${GOAL:-install}
export DIR_QA_ASSETS=${DIR_QA_ASSETS:-${BASE_SCRATCH_DIR}/qa-assets}
export PATH=${BASE_ROOT_DIR}/ci/retry:$PATH

25
ci/test/00_setup_env_android.sh Executable file
View file

@ -0,0 +1,25 @@
#!/usr/bin/env bash
#
# Copyright (c) 2019-2020 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
export LC_ALL=C.UTF-8
export HOST=aarch64-linux-android
export PACKAGES="clang llvm unzip openjdk-8-jdk gradle"
export CONTAINER_NAME=ci_android
export DOCKER_NAME_TAG="ubuntu:focal"
export RUN_UNIT_TESTS=false
export RUN_FUNCTIONAL_TESTS=false
export ANDROID_API_LEVEL=28
export ANDROID_BUILD_TOOLS_VERSION=28.0.3
export ANDROID_NDK_VERSION=21.1.6352462
export ANDROID_TOOLS_URL=https://dl.google.com/android/repository/commandlinetools-linux-6609375_latest.zip
export ANDROID_HOME="${DEPENDS_DIR}/SDKs/android"
export ANDROID_NDK_HOME="${ANDROID_HOME}/ndk/${ANDROID_NDK_VERSION}"
export DEP_OPTS="ANDROID_SDK=${ANDROID_HOME} ANDROID_NDK=${ANDROID_NDK_HOME} ANDROID_API_LEVEL=${ANDROID_API_LEVEL} ANDROID_TOOLCHAIN_BIN=${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin/"
export BITCOIN_CONFIG="--disable-ccache"

2
ci/test/00_setup_env_arm.sh Normal file → Executable file
View file

@ -25,4 +25,4 @@ export RUN_FUNCTIONAL_TESTS=false
export GOAL="install"
# -Wno-psabi is to disable ABI warnings: "note: parameter passing for argument of type ... changed in GCC 7.1"
# This could be removed once the ABI change warning does not show up by default
export BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports CXXFLAGS=-Wno-psabi --enable-werror --with-boost-process"
export BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports CXXFLAGS=-Wno-psabi"

9
ci/test/00_setup_env_i686_centos.sh Normal file → Executable file
View file

@ -7,9 +7,10 @@
export LC_ALL=C.UTF-8
export HOST=i686-pc-linux-gnu
export CONTAINER_NAME=ci_i686_centos_7
export DOCKER_NAME_TAG=centos:7
export DOCKER_PACKAGES="gcc-c++ glibc-devel.x86_64 libstdc++-devel.x86_64 glibc-devel.i686 libstdc++-devel.i686 ccache libtool make git python3 python36-zmq which patch lbzip2 dash"
export CONTAINER_NAME=ci_i686_centos
export DOCKER_NAME_TAG=quay.io/centos/centos:stream8
export DOCKER_PACKAGES="gcc-c++ glibc-devel.x86_64 libstdc++-devel.x86_64 glibc-devel.i686 libstdc++-devel.i686 ccache libtool make git python3 python3-zmq which patch lbzip2 xz procps-ng dash rsync coreutils bison"
export GOAL="install"
export BITCOIN_CONFIG="--enable-zmq --with-gui=qt5 --enable-reduce-exports --with-boost-process"
export BITCOIN_CONFIG="--enable-zmq --with-gui=qt5 --enable-reduce-exports"
export CONFIG_SHELL="/bin/dash"
export TEST_RUNNER_ENV="LC_ALL=en_US.UTF-8"

10
ci/test/00_setup_env_mac.sh Normal file → Executable file
View file

@ -7,12 +7,12 @@
export LC_ALL=C.UTF-8
export CONTAINER_NAME=ci_macos_cross
export DOCKER_NAME_TAG=ubuntu:18.04 # Check that bionic can cross-compile to macos (bionic is used in the gitian build as well)
export DOCKER_NAME_TAG=ubuntu:20.04 # Check that Focal can cross-compile to macos (Focal is used in the gitian build as well)
export HOST=x86_64-apple-darwin18
export PACKAGES="cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python3-dev python3-setuptools"
export XCODE_VERSION=11.3.1
export XCODE_BUILD_ID=11C505
export PACKAGES="cmake imagemagick librsvg2-bin libz-dev libtiff-tools libtinfo5 python3-setuptools xorriso"
export XCODE_VERSION=12.1
export XCODE_BUILD_ID=12A7403
export RUN_UNIT_TESTS=false
export RUN_FUNCTIONAL_TESTS=false
export GOAL="deploy"
export BITCOIN_CONFIG="--with-gui --enable-reduce-exports --enable-werror --with-boost-process"
export BITCOIN_CONFIG="--with-gui --enable-reduce-exports"

6
ci/test/00_setup_env_mac_host.sh Normal file → Executable file
View file

@ -7,14 +7,12 @@
export LC_ALL=C.UTF-8
export HOST=x86_64-apple-darwin18
export PIP_PACKAGES="zmq"
export PIP_PACKAGES="zmq lief"
export GOAL="install"
# ELEMENTS: add -fno-stack-check to work around clang bug on macos
# ELEMENTS: remove --enable-werror because it triggers on Boost Thread includes (FIXME remove this after 22.0 rebase when boost-thread is removed)
export BITCOIN_CONFIG="--with-gui --enable-reduce-exports --with-boost-process CXXFLAGS=-fno-stack-check"
export BITCOIN_CONFIG="--with-gui --enable-reduce-exports CXXFLAGS=-fno-stack-check"
export CI_OS_NAME="macos"
export NO_DEPENDS=1
export OSX_SDK=""
export CCACHE_SIZE=300M
export RUN_SECURITY_TESTS="true"

6
ci/test/00_setup_env_native_asan.sh Normal file → Executable file
View file

@ -7,8 +7,8 @@
export LC_ALL=C.UTF-8
export CONTAINER_NAME=ci_native_asan
export PACKAGES="clang llvm python3-zmq qtbase5-dev qttools5-dev-tools libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-test-dev libboost-thread-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev libqrencode-dev libsqlite3-dev"
export DOCKER_NAME_TAG=ubuntu:20.04
export PACKAGES="clang llvm python3-zmq qtbase5-dev qttools5-dev-tools libevent-dev bsdmainutils libboost-dev libboost-system-dev libboost-filesystem-dev libboost-test-dev libdb5.3++-dev libminiupnpc-dev libnatpmp-dev libzmq3-dev libqrencode-dev libsqlite3-dev"
export DOCKER_NAME_TAG=ubuntu:hirsute
export NO_DEPENDS=1
export GOAL="install"
export BITCOIN_CONFIG="--enable-zmq --with-incompatible-bdb --with-gui=qt5 CPPFLAGS='-DARENA_DEBUG -DDEBUG_LOCKORDER' --with-sanitizers=address,integer,undefined CC=clang CXX=clang++ --with-boost-process"
export BITCOIN_CONFIG="--enable-zmq --with-incompatible-bdb --with-gui=qt5 CPPFLAGS='-DARENA_DEBUG -DDEBUG_LOCKORDER' --with-sanitizers=address,integer,undefined CC=clang CXX=clang++"

5
ci/test/00_setup_env_native_fuzz.sh Normal file → Executable file
View file

@ -8,11 +8,12 @@ export LC_ALL=C.UTF-8
export DOCKER_NAME_TAG="ubuntu:20.04"
export CONTAINER_NAME=ci_native_fuzz
export PACKAGES="clang llvm python3 libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-test-dev libboost-thread-dev"
export PACKAGES="clang llvm python3 libevent-dev bsdmainutils libboost-dev libboost-system-dev libboost-filesystem-dev libboost-test-dev"
export NO_DEPENDS=1
export RUN_UNIT_TESTS=false
export RUN_FUNCTIONAL_TESTS=false
export RUN_FUZZ_TESTS=true
export FUZZ_TESTS_CONFIG="--exclude=coins_view" # work around https://github.com/bitcoin/bitcoin/issues/22233
export GOAL="install"
export BITCOIN_CONFIG="--enable-fuzz --with-sanitizers=fuzzer,address,undefined CC=clang CXX=clang++ --with-boost-process"
export BITCOIN_CONFIG="--enable-fuzz --with-sanitizers=fuzzer,address,undefined,integer CC=clang CXX=clang++"
export CCACHE_SIZE=200M

View file

@ -0,0 +1,24 @@
#!/usr/bin/env bash
#
# Copyright (c) 2020 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
export LC_ALL=C.UTF-8
export DOCKER_NAME_TAG="ubuntu:20.04"
LIBCXX_DIR="${BASE_SCRATCH_DIR}/msan/build/"
export MSAN_FLAGS="-fsanitize=memory -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer -g -O1 -fno-optimize-sibling-calls"
LIBCXX_FLAGS="-nostdinc++ -stdlib=libc++ -L${LIBCXX_DIR}lib -lc++abi -I${LIBCXX_DIR}include -I${LIBCXX_DIR}include/c++/v1 -lpthread -Wl,-rpath,${LIBCXX_DIR}lib -Wno-unused-command-line-argument"
export MSAN_AND_LIBCXX_FLAGS="${MSAN_FLAGS} ${LIBCXX_FLAGS}"
export CONTAINER_NAME="ci_native_msan"
export PACKAGES="clang-9 llvm-9 cmake"
export DEP_OPTS="NO_BDB=1 NO_QT=1 CC='clang' CXX='clang++' CFLAGS='${MSAN_FLAGS}' CXXFLAGS='${MSAN_AND_LIBCXX_FLAGS}' boost_cxxflags='-std=c++17 -fvisibility=hidden -fPIC ${MSAN_AND_LIBCXX_FLAGS}' libevent_cflags='${MSAN_FLAGS}' zeromq_cxxflags='-std=c++17 ${MSAN_AND_LIBCXX_FLAGS}'"
export GOAL="install"
export BITCOIN_CONFIG="--enable-fuzz --with-sanitizers=fuzzer,memory --with-asm=no --prefix=${DEPENDS_DIR}/x86_64-pc-linux-gnu/ CC=clang CXX=clang++ CFLAGS='${MSAN_FLAGS}' CXXFLAGS='${MSAN_AND_LIBCXX_FLAGS}'"
export USE_MEMORY_SANITIZER="true"
export RUN_UNIT_TESTS="false"
export RUN_FUNCTIONAL_TESTS="false"
export RUN_FUZZ_TESTS=true
export CCACHE_SIZE=250M

2
ci/test/00_setup_env_native_fuzz_with_valgrind.sh Normal file → Executable file
View file

@ -8,7 +8,7 @@ export LC_ALL=C.UTF-8
export DOCKER_NAME_TAG="ubuntu:20.04"
export CONTAINER_NAME=ci_native_fuzz_valgrind
export PACKAGES="clang llvm python3 libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-test-dev libboost-thread-dev valgrind"
export PACKAGES="clang llvm python3 libevent-dev bsdmainutils libboost-dev libboost-system-dev libboost-filesystem-dev libboost-test-dev valgrind"
export NO_DEPENDS=1
export RUN_UNIT_TESTS=false
export RUN_FUNCTIONAL_TESTS=false

6
ci/test/00_setup_env_native_msan.sh Normal file → Executable file
View file

@ -7,7 +7,7 @@
export LC_ALL=C.UTF-8
export DOCKER_NAME_TAG="ubuntu:20.04"
LIBCXX_DIR="${BASE_ROOT_DIR}/ci/scratch/msan/build/"
LIBCXX_DIR="${BASE_SCRATCH_DIR}/msan/build/"
export MSAN_FLAGS="-fsanitize=memory -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer -g -O1 -fno-optimize-sibling-calls"
LIBCXX_FLAGS="-nostdinc++ -stdlib=libc++ -L${LIBCXX_DIR}lib -lc++abi -I${LIBCXX_DIR}include -I${LIBCXX_DIR}include/c++/v1 -lpthread -Wl,-rpath,${LIBCXX_DIR}lib -Wno-unused-command-line-argument"
export MSAN_AND_LIBCXX_FLAGS="${MSAN_FLAGS} ${LIBCXX_FLAGS}"
@ -15,9 +15,9 @@ export BDB_PREFIX="${BASE_ROOT_DIR}/db4"
export CONTAINER_NAME="ci_native_msan"
export PACKAGES="clang-9 llvm-9 cmake"
export DEP_OPTS="NO_BDB=1 NO_QT=1 CC='clang' CXX='clang++' CFLAGS='${MSAN_FLAGS}' CXXFLAGS='${MSAN_AND_LIBCXX_FLAGS}' boost_cxxflags='-std=c++11 -fvisibility=hidden -fPIC ${MSAN_AND_LIBCXX_FLAGS}' zeromq_cxxflags='-std=c++11 ${MSAN_AND_LIBCXX_FLAGS}'"
export DEP_OPTS="NO_BDB=1 NO_QT=1 CC='clang' CXX='clang++' CFLAGS='${MSAN_FLAGS}' CXXFLAGS='${MSAN_AND_LIBCXX_FLAGS}' boost_cxxflags='-std=c++17 -fvisibility=hidden -fPIC ${MSAN_AND_LIBCXX_FLAGS}' libevent_cflags='${MSAN_FLAGS}' sqlite_cflags='${MSAN_FLAGS}' zeromq_cxxflags='-std=c++17 ${MSAN_AND_LIBCXX_FLAGS}'"
export GOAL="install"
export BITCOIN_CONFIG="--enable-wallet --with-sanitizers=memory --with-asm=no --prefix=${BASE_ROOT_DIR}/depends/x86_64-pc-linux-gnu/ CC=clang CXX=clang++ CFLAGS='${MSAN_FLAGS}' CXXFLAGS='${MSAN_AND_LIBCXX_FLAGS}' BDB_LIBS='-L${BDB_PREFIX}/lib -ldb_cxx-4.8' BDB_CFLAGS='-I${BDB_PREFIX}/include'"
export BITCOIN_CONFIG="--enable-wallet --with-sanitizers=memory --with-asm=no --prefix=${DEPENDS_DIR}/x86_64-pc-linux-gnu/ CC=clang CXX=clang++ CFLAGS='${MSAN_FLAGS}' CXXFLAGS='${MSAN_AND_LIBCXX_FLAGS}' BDB_LIBS='-L${BDB_PREFIX}/lib -ldb_cxx-4.8' BDB_CFLAGS='-I${BDB_PREFIX}/include'"
export USE_MEMORY_SANITIZER="true"
export RUN_FUNCTIONAL_TESTS="false"
export CCACHE_SIZE=250M

7
ci/test/00_setup_env_native_multiprocess.sh Normal file → Executable file
View file

@ -8,8 +8,9 @@ export LC_ALL=C.UTF-8
export CONTAINER_NAME=ci_native_multiprocess
export DOCKER_NAME_TAG=ubuntu:20.04
export PACKAGES="cmake python3"
export DEP_OPTS="MULTIPROCESS=1"
export PACKAGES="cmake python3 python3-pip llvm clang"
export DEP_OPTS="DEBUG=1 MULTIPROCESS=1"
export GOAL="install"
export BITCOIN_CONFIG="--with-boost-process"
export BITCOIN_CONFIG="--enable-debug CC=clang CXX=clang++" # Use clang to avoid OOM
export TEST_RUNNER_ENV="BITCOIND=elements-node"
export PIP_PACKAGES="lief"

2
ci/test/00_setup_env_native_nowallet.sh Normal file → Executable file
View file

@ -11,4 +11,4 @@ export DOCKER_NAME_TAG=ubuntu:18.04 # Use bionic to have one config run the tes
export PACKAGES="python3-zmq clang-5.0 llvm-5.0" # Use clang-5 to test C++17 compatibility, see doc/dependencies.md
export DEP_OPTS="NO_WALLET=1"
export GOAL="install"
export BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports CC=clang-5.0 CXX=clang++-5.0 --with-boost-process"
export BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports CC=clang-5.0 CXX=clang++-5.0"

10
ci/test/00_setup_env_native_qt5.sh Normal file → Executable file
View file

@ -7,13 +7,13 @@
export LC_ALL=C.UTF-8
export CONTAINER_NAME=ci_native_qt5
export DOCKER_NAME_TAG=ubuntu:18.04 # Check that bionic can compile our c++17 and run our functional tests in python3
export DOCKER_NAME_TAG=ubuntu:18.04 # Check that bionic gcc-7 can compile our c++17 and run our functional tests in python3, see doc/dependencies.md
export PACKAGES="python3-zmq qtbase5-dev qttools5-dev-tools libdbus-1-dev libharfbuzz-dev"
export DEP_OPTS="NO_QT=1 NO_UPNP=1 DEBUG=1 ALLOW_HOST_PACKAGES=1"
export DEP_OPTS="NO_QT=1 NO_UPNP=1 NO_NATPMP=1 DEBUG=1 ALLOW_HOST_PACKAGES=1"
export TEST_RUNNER_EXTRA="--previous-releases --coverage --extended --exclude feature_dbcrash" # Run extended tests so that coverage does not fail, but exclude the very slow dbcrash
export RUN_SECURITY_TESTS="true"
export RUN_UNIT_TESTS_SEQUENTIAL="true"
export RUN_UNIT_TESTS="false"
export GOAL="install"
export PREVIOUS_RELEASES_TO_DOWNLOAD="v0.15.2 v0.16.3 v0.17.2 v0.18.1 v0.19.1"
export BITCOIN_CONFIG="--enable-zmq --with-libs=no --with-gui=qt5 --enable-glibc-back-compat --enable-reduce-exports --enable-c++17 --enable-debug CFLAGS=\"-g0 -O2 -funsigned-char\" CXXFLAGS=\"-g0 -O2 -funsigned-char\" --with-boost-process"
export PREVIOUS_RELEASES_TO_DOWNLOAD="v0.15.2 v0.16.3 v0.17.2 v0.18.1 v0.19.1 v0.20.1"
export BITCOIN_CONFIG="--enable-zmq --with-libs=no --with-gui=qt5 --enable-glibc-back-compat --enable-reduce-exports
--enable-debug --disable-fuzz-binary CFLAGS=\"-g0 -O2 -funsigned-char\" CXXFLAGS=\"-g0 -O2 -funsigned-char\""

5
ci/test/00_setup_env_native_tsan.sh Normal file → Executable file
View file

@ -7,9 +7,8 @@
export LC_ALL=C.UTF-8
export CONTAINER_NAME=ci_native_tsan
export DOCKER_NAME_TAG=ubuntu:20.04
export DOCKER_NAME_TAG=ubuntu:hirsute
export PACKAGES="clang llvm libc++abi-dev libc++-dev python3-zmq"
export DEP_OPTS="CC=clang CXX='clang++ -stdlib=libc++'"
export TEST_RUNNER_EXTRA="--exclude feature_block" # Low memory on Travis machines, exclude feature_block.
export GOAL="install"
export BITCOIN_CONFIG="--enable-zmq --with-gui=no CPPFLAGS='-DARENA_DEBUG -DDEBUG_LOCKORDER' CXXFLAGS='-g' --with-sanitizers=thread CC=clang CXX='clang++ -stdlib=libc++' --with-boost-process"
export BITCOIN_CONFIG="--enable-zmq --with-gui=no CPPFLAGS='-DARENA_DEBUG -DDEBUG_LOCKORDER' CXXFLAGS='-g' --with-sanitizers=thread CC=clang CXX='clang++ -stdlib=libc++'"

2
ci/test/00_setup_env_native_valgrind.sh Normal file → Executable file
View file

@ -7,7 +7,7 @@
export LC_ALL=C.UTF-8
export CONTAINER_NAME=ci_native_valgrind
export PACKAGES="valgrind clang llvm python3-zmq libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-test-dev libboost-thread-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev libsqlite3-dev"
export PACKAGES="valgrind clang llvm python3-zmq libevent-dev bsdmainutils libboost-dev libboost-system-dev libboost-filesystem-dev libboost-test-dev libdb5.3++-dev libminiupnpc-dev libnatpmp-dev libzmq3-dev libsqlite3-dev"
export USE_VALGRIND=1
export NO_DEPENDS=1
export TEST_RUNNER_EXTRA="--exclude rpc_bind" # Excluded for now, see https://github.com/bitcoin/bitcoin/issues/17765#issuecomment-602068547

2
ci/test/00_setup_env_s390x.sh Normal file → Executable file
View file

@ -23,4 +23,4 @@ export RUN_UNIT_TESTS=true
export TEST_RUNNER_ENV="LC_ALL=C"
export RUN_FUNCTIONAL_TESTS=true
export GOAL="install"
export BITCOIN_CONFIG="--enable-reduce-exports --with-incompatible-bdb --with-boost-process"
export BITCOIN_CONFIG="--enable-reduce-exports --with-incompatible-bdb"

12
ci/test/00_setup_env_win64.sh Normal file → Executable file
View file

@ -7,10 +7,14 @@
export LC_ALL=C.UTF-8
export CONTAINER_NAME=ci_win64
export DOCKER_NAME_TAG=ubuntu:18.04 # Check that bionic can cross-compile to win64 (bionic is used in the gitian build as well)
export DOCKER_NAME_TAG=ubuntu:20.04 # Check that Focal can cross-compile to win64 (Focal is used in the gitian build as well)
export HOST=x86_64-w64-mingw32
export PACKAGES="python3 nsis g++-mingw-w64-x86-64 wine-binfmt wine64 file"
export DPKG_ADD_ARCH="i386"
export PACKAGES="python3 nsis g++-mingw-w64-x86-64 wine-binfmt wine64 wine32 file"
export RUN_FUNCTIONAL_TESTS=false
export RUN_SECURITY_TESTS="true"
export GOAL="deploy"
export BITCOIN_CONFIG="--enable-reduce-exports --disable-gui-tests --without-boost-process"
export BITCOIN_CONFIG="--enable-reduce-exports --disable-gui-tests --disable-external-signer"
# Compiler for MinGW-w64 causes false -Wreturn-type warning.
# See https://sourceforge.net/p/mingw-w64/bugs/306/
export NO_WERROR=1

View file

@ -1,22 +0,0 @@
#!/usr/bin/env bash
#
# Copyright (c) 2018-2019 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
export LC_ALL=C.UTF-8
BEGIN_FOLD () {
echo ""
CURRENT_FOLD_NAME=$1
echo "travis_fold:start:${CURRENT_FOLD_NAME}"
}
END_FOLD () {
RET=$?
echo "travis_fold:end:${CURRENT_FOLD_NAME}"
if [ $RET != 0 ]; then
echo "${CURRENT_FOLD_NAME} failed with status code ${RET}"
fi
}

View file

@ -6,14 +6,12 @@
export LC_ALL=C.UTF-8
if [[ $DOCKER_NAME_TAG == centos* ]]; then
export LC_ALL=en_US.utf8
fi
if [[ $QEMU_USER_CMD == qemu-s390* ]]; then
export LC_ALL=C
fi
if [ "$CI_OS_NAME" == "macos" ]; then
sudo -H pip3 install --upgrade pip
IN_GETOPT_BIN="/usr/local/opt/gnu-getopt/bin/getopt" ${CI_RETRY_EXE} pip3 install --user $PIP_PACKAGES
fi
@ -36,7 +34,12 @@ if [ -z "$DANGER_RUN_CI_ON_HOST" ]; then
echo "Creating $DOCKER_NAME_TAG container to run in"
${CI_RETRY_EXE} docker pull "$DOCKER_NAME_TAG"
DOCKER_ID=$(docker run $DOCKER_ADMIN -idt \
if [ -n "${RESTART_CI_DOCKER_BEFORE_RUN}" ] ; then
echo "Restart docker before run to stop and clear all containers started with --rm"
systemctl restart docker
fi
DOCKER_ID=$(docker run $DOCKER_ADMIN --rm --interactive --detach --tty \
--mount type=bind,src=$BASE_ROOT_DIR,dst=/ro_base,readonly \
--mount type=bind,src=$CCACHE_DIR,dst=$CCACHE_DIR \
--mount type=bind,src=$DEPENDS_DIR,dst=$DEPENDS_DIR \
@ -59,12 +62,15 @@ if [ -n "$DPKG_ADD_ARCH" ]; then
DOCKER_EXEC dpkg --add-architecture "$DPKG_ADD_ARCH"
fi
if [[ $DOCKER_NAME_TAG == centos* ]]; then
${CI_RETRY_EXE} DOCKER_EXEC yum -y install epel-release
${CI_RETRY_EXE} DOCKER_EXEC yum -y install $DOCKER_PACKAGES $PACKAGES
if [[ $DOCKER_NAME_TAG == *centos* ]]; then
${CI_RETRY_EXE} DOCKER_EXEC dnf -y install epel-release
${CI_RETRY_EXE} DOCKER_EXEC dnf -y --allowerasing install $DOCKER_PACKAGES $PACKAGES
elif [ "$CI_USE_APT_INSTALL" != "no" ]; then
${CI_RETRY_EXE} DOCKER_EXEC apt-get update
${CI_RETRY_EXE} DOCKER_EXEC apt-get install --no-install-recommends --no-upgrade -y $PACKAGES $DOCKER_PACKAGES
if [ -n "$PIP_PACKAGES" ]; then
${CI_RETRY_EXE} pip3 install --user $PIP_PACKAGES
fi
fi
if [ "$CI_OS_NAME" == "macos" ]; then
@ -78,11 +84,14 @@ fi
DOCKER_EXEC echo "Free disk space:"
DOCKER_EXEC df -h
if [ ! -d ${DIR_QA_ASSETS} ]; then
DOCKER_EXEC git clone --depth=1 https://github.com/bitcoin-core/qa-assets ${DIR_QA_ASSETS}
if [ "$RUN_FUZZ_TESTS" = "true" ] || [ "$RUN_UNIT_TESTS" = "true" ] || [ "$RUN_UNIT_TESTS_SEQUENTIAL" = "true" ]; then
if [ ! -d ${DIR_QA_ASSETS} ]; then
DOCKER_EXEC git clone --depth=1 https://github.com/bitcoin-core/qa-assets ${DIR_QA_ASSETS}
fi
export DIR_FUZZ_IN=${DIR_QA_ASSETS}/fuzz_seed_corpus/
export DIR_UNIT_TEST_DATA=${DIR_QA_ASSETS}/unit_test_data/
fi
export DIR_FUZZ_IN=${DIR_QA_ASSETS}/fuzz_seed_corpus/
export DIR_UNIT_TEST_DATA=${DIR_QA_ASSETS}/unit_test_data/
DOCKER_EXEC mkdir -p "${BASE_SCRATCH_DIR}/sanitizer-output/"
@ -90,7 +99,7 @@ if [[ ${USE_MEMORY_SANITIZER} == "true" ]]; then
DOCKER_EXEC "update-alternatives --install /usr/bin/clang++ clang++ \$(which clang++-9) 100"
DOCKER_EXEC "update-alternatives --install /usr/bin/clang clang \$(which clang-9) 100"
DOCKER_EXEC "mkdir -p ${BASE_SCRATCH_DIR}/msan/build/"
DOCKER_EXEC "git clone --depth=1 https://github.com/llvm/llvm-project -b llvmorg-10.0.0 ${BASE_SCRATCH_DIR}/msan/llvm-project"
DOCKER_EXEC "git clone --depth=1 https://github.com/llvm/llvm-project -b llvmorg-12.0.0 ${BASE_SCRATCH_DIR}/msan/llvm-project"
DOCKER_EXEC "cd ${BASE_SCRATCH_DIR}/msan/build/ && cmake -DLLVM_ENABLE_PROJECTS='libcxx;libcxxabi' -DCMAKE_BUILD_TYPE=Release -DLLVM_USE_SANITIZER=Memory -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DLLVM_TARGETS_TO_BUILD=X86 ../llvm-project/llvm/"
DOCKER_EXEC "cd ${BASE_SCRATCH_DIR}/msan/build/ && make $MAKEJOBS cxx"
fi

View file

@ -19,7 +19,16 @@ OSX_SDK_BASENAME="Xcode-${XCODE_VERSION}-${XCODE_BUILD_ID}-extracted-SDK-with-li
OSX_SDK_PATH="${DEPENDS_DIR}/sdk-sources/${OSX_SDK_BASENAME}"
if [ -n "$XCODE_VERSION" ] && [ ! -f "$OSX_SDK_PATH" ]; then
curl --location --fail "${SDK_URL}/${OSX_SDK_BASENAME}" -o "$OSX_SDK_PATH"
DOCKER_EXEC curl --location --fail "${SDK_URL}/${OSX_SDK_BASENAME}" -o "$OSX_SDK_PATH"
fi
if [ -n "$ANDROID_TOOLS_URL" ]; then
ANDROID_TOOLS_PATH=$DEPENDS_DIR/sdk-sources/android-tools.zip
DOCKER_EXEC curl --location --fail "${ANDROID_TOOLS_URL}" -o "$ANDROID_TOOLS_PATH"
DOCKER_EXEC mkdir -p "${ANDROID_HOME}/cmdline-tools"
DOCKER_EXEC unzip -o "$ANDROID_TOOLS_PATH" -d "${ANDROID_HOME}/cmdline-tools"
DOCKER_EXEC "yes | ${ANDROID_HOME}/cmdline-tools/tools/bin/sdkmanager --install \"build-tools;${ANDROID_BUILD_TOOLS_VERSION}\" \"platform-tools\" \"platforms;android-${ANDROID_API_LEVEL}\" \"ndk;${ANDROID_NDK_VERSION}\""
fi
if [[ ${USE_MEMORY_SANITIZER} == "true" ]]; then
@ -36,18 +45,16 @@ if [[ $HOST = *-mingw32 ]]; then
DOCKER_EXEC update-alternatives --set $HOST-g++ \$\(which $HOST-g++-posix\)
fi
if [ -z "$NO_DEPENDS" ]; then
if [[ $DOCKER_NAME_TAG == centos* ]]; then
if [[ $DOCKER_NAME_TAG == *centos* ]]; then
# CentOS has problems building the depends if the config shell is not explicitly set
# (i.e. for libevent a Makefile with an empty SHELL variable is generated, leading to
# an error as the first command is executed)
SHELL_OPTS="CONFIG_SHELL=/bin/bash"
SHELL_OPTS="LC_ALL=en_US.UTF-8 CONFIG_SHELL=/bin/bash"
else
SHELL_OPTS="CONFIG_SHELL="
fi
DOCKER_EXEC $SHELL_OPTS make $MAKEJOBS -C depends HOST=$HOST $DEP_OPTS
fi
if [ -n "$PREVIOUS_RELEASES_TO_DOWNLOAD" ]; then
BEGIN_FOLD previous-versions
DOCKER_EXEC test/get_previous_releases.py -b -t "$PREVIOUS_RELEASES_DIR" "${PREVIOUS_RELEASES_TO_DOWNLOAD}"
END_FOLD
fi

View file

@ -6,33 +6,36 @@
export LC_ALL=C.UTF-8
BITCOIN_CONFIG_ALL="--disable-dependency-tracking --prefix=$DEPENDS_DIR/$HOST --bindir=$BASE_OUTDIR/bin --libdir=$BASE_OUTDIR/lib"
if [ -n "$ANDROID_TOOLS_URL" ]; then
DOCKER_EXEC make distclean || true
DOCKER_EXEC ./autogen.sh
DOCKER_EXEC ./configure $BITCOIN_CONFIG --prefix=$DEPENDS_DIR/aarch64-linux-android || ( (DOCKER_EXEC cat config.log) && false)
DOCKER_EXEC "cd src/qt && make $MAKEJOBS && ANDROID_HOME=${ANDROID_HOME} ANDROID_NDK_HOME=${ANDROID_NDK_HOME} make apk"
exit 0
fi
BITCOIN_CONFIG_ALL="--enable-suppress-external-warnings --disable-dependency-tracking --prefix=$DEPENDS_DIR/$HOST --bindir=$BASE_OUTDIR/bin --libdir=$BASE_OUTDIR/lib"
if [ -z "$NO_WERROR" ]; then
BITCOIN_CONFIG_ALL="${BITCOIN_CONFIG_ALL} --enable-werror"
fi
DOCKER_EXEC "ccache --zero-stats --max-size=$CCACHE_SIZE"
BEGIN_FOLD autogen
if [ -n "$CONFIG_SHELL" ]; then
DOCKER_EXEC "$CONFIG_SHELL" -c "./autogen.sh"
else
DOCKER_EXEC ./autogen.sh
fi
END_FOLD
DOCKER_EXEC mkdir -p "${BASE_BUILD_DIR}"
export P_CI_DIR="${BASE_BUILD_DIR}"
BEGIN_FOLD configure
DOCKER_EXEC "${BASE_ROOT_DIR}/configure" --cache-file=config.cache $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( (DOCKER_EXEC cat config.log) && false)
END_FOLD
BEGIN_FOLD distdir
DOCKER_EXEC make distdir VERSION=$HOST
END_FOLD
export P_CI_DIR="${BASE_BUILD_DIR}/elements-$HOST"
BEGIN_FOLD configure
DOCKER_EXEC ./configure --cache-file=../config.cache $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( (DOCKER_EXEC cat config.log) && false)
END_FOLD
set -o errtrace
trap 'DOCKER_EXEC "cat ${BASE_SCRATCH_DIR}/sanitizer-output/* 2> /dev/null"' ERR
@ -45,12 +48,8 @@ if [[ ${USE_MEMORY_SANITIZER} == "true" ]]; then
DOCKER_EXEC 'grep -v HAVE_SYS_GETRANDOM src/config/bitcoin-config.h > src/config/bitcoin-config.h.tmp && mv src/config/bitcoin-config.h.tmp src/config/bitcoin-config.h'
fi
BEGIN_FOLD build
DOCKER_EXEC make $MAKEJOBS $GOAL || ( echo "Build failure. Verbose build follows." && DOCKER_EXEC make $GOAL V=1 ; false )
END_FOLD
BEGIN_FOLD cache_stats
DOCKER_EXEC "ccache --version | head -n 1 && ccache --show-stats"
DOCKER_EXEC du -sh "${DEPENDS_DIR}"/*/
DOCKER_EXEC du -sh "${PREVIOUS_RELEASES_DIR}"
END_FOLD

View file

@ -7,55 +7,39 @@
export LC_ALL=C.UTF-8
if [[ $HOST = *-mingw32 ]]; then
BEGIN_FOLD wrap-wine
# Generate all binaries, so that they can be wrapped
DOCKER_EXEC make $MAKEJOBS -C src/secp256k1 VERBOSE=1
DOCKER_EXEC make $MAKEJOBS -C src/univalue VERBOSE=1
DOCKER_EXEC "${BASE_ROOT_DIR}/ci/test/wrap-wine.sh"
END_FOLD
fi
if [ -n "$QEMU_USER_CMD" ]; then
BEGIN_FOLD wrap-qemu
# Generate all binaries, so that they can be wrapped
DOCKER_EXEC make $MAKEJOBS -C src/secp256k1 VERBOSE=1
DOCKER_EXEC make $MAKEJOBS -C src/univalue VERBOSE=1
DOCKER_EXEC "${BASE_ROOT_DIR}/ci/test/wrap-qemu.sh"
END_FOLD
fi
if [ -n "$USE_VALGRIND" ]; then
BEGIN_FOLD wrap-valgrind
DOCKER_EXEC "${BASE_ROOT_DIR}/ci/test/wrap-valgrind.sh"
END_FOLD
fi
if [ "$RUN_UNIT_TESTS" = "true" ]; then
BEGIN_FOLD unit-tests
DOCKER_EXEC ${TEST_RUNNER_ENV} DIR_UNIT_TEST_DATA=${DIR_UNIT_TEST_DATA} LD_LIBRARY_PATH=$DEPENDS_DIR/$HOST/lib make $MAKEJOBS check VERBOSE=1
END_FOLD
fi
if [ "$RUN_UNIT_TESTS_SEQUENTIAL" = "true" ]; then
BEGIN_FOLD unit-tests-seq
DOCKER_EXEC ${TEST_RUNNER_ENV} DIR_UNIT_TEST_DATA=${DIR_UNIT_TEST_DATA} LD_LIBRARY_PATH=$DEPENDS_DIR/$HOST/lib "${BASE_BUILD_DIR}/elements-*/src/test/test_bitcoin*" --catch_system_errors=no -l test_suite
END_FOLD
fi
if [ "$RUN_FUNCTIONAL_TESTS" = "true" ]; then
BEGIN_FOLD functional-tests
DOCKER_EXEC LD_LIBRARY_PATH=$DEPENDS_DIR/$HOST/lib ${TEST_RUNNER_ENV} test/functional/test_runner.py --ci $MAKEJOBS --tmpdirprefix "${BASE_SCRATCH_DIR}/test_runner/" --ansi --combinedlogslen=4000 --timeout-factor=${TEST_RUNNER_TIMEOUT_FACTOR} ${TEST_RUNNER_EXTRA} --quiet --failfast
END_FOLD
fi
if [ "$RUN_SECURITY_TESTS" = "true" ]; then
BEGIN_FOLD security-tests
DOCKER_EXEC make test-security-check
END_FOLD
fi
if [ "$RUN_FUZZ_TESTS" = "true" ]; then
BEGIN_FOLD fuzz-tests
DOCKER_EXEC LD_LIBRARY_PATH=$DEPENDS_DIR/$HOST/lib test/fuzz/test_runner.py ${FUZZ_TESTS_CONFIG} $MAKEJOBS -l DEBUG ${DIR_FUZZ_IN}
END_FOLD
fi

View file

@ -1,6 +1,6 @@
#!/usr/bin/env bash
#
# Copyright (c) 2018-2019 The Bitcoin Core developers
# Copyright (c) 2018-2020 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.

View file

@ -13,7 +13,7 @@ for b_name in {"${BASE_OUTDIR}/bin"/*,src/secp256k1/*tests,src/univalue/{no_nul,
echo "Wrap $b ..."
mv "$b" "${b}_orig"
echo '#!/usr/bin/env bash' > "$b"
echo "wine64 \"${b}_orig\" \"\$@\"" >> "$b"
echo "( wine \"${b}_orig\" \"\$@\" ) || ( sleep 1 && wine \"${b}_orig\" \"\$@\" )" >> "$b"
chmod +x "$b"
fi
done

View file

@ -1,13 +1,12 @@
#!/usr/bin/env bash
#
# Copyright (c) 2019 The Bitcoin Core developers
# Copyright (c) 2019-2020 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
export LC_ALL=C.UTF-8
set -o errexit; source ./ci/test/00_setup_env.sh
set -o errexit; source ./ci/test/03_before_install.sh
set -o errexit; source ./ci/test/04_install.sh
set -o errexit; source ./ci/test/05_before_script.sh
set -o errexit; source ./ci/test/06_script_a.sh

View file

@ -1,14 +1,13 @@
AC_PREREQ([2.69])
define(_CLIENT_VERSION_MAJOR, 0)
define(_CLIENT_VERSION_MINOR, 20)
define(_CLIENT_VERSION_REVISION, 99)
define(_CLIENT_VERSION_MAJOR, 21)
define(_CLIENT_VERSION_MINOR, 99)
define(_CLIENT_VERSION_BUILD, 0)
define(_CLIENT_VERSION_RC, 0)
define(_CLIENT_VERSION_IS_RELEASE, false)
define(_COPYRIGHT_YEAR, 2021)
define(_COPYRIGHT_HOLDERS,[The %s developers])
define(_COPYRIGHT_HOLDERS_SUBSTITUTION,[[Elements Project]])
AC_INIT([Elements Core],m4_join([.], _CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MINOR, _CLIENT_VERSION_REVISION, m4_if(_CLIENT_VERSION_BUILD, [0], [], _CLIENT_VERSION_BUILD))m4_if(_CLIENT_VERSION_RC, [0], [], [rc]_CLIENT_VERSION_RC),[https://github.com/ElementsProject/elements/issues],[elements],[https://elementsproject.org/])
AC_INIT([Elements Core],m4_join([.], _CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MINOR, _CLIENT_VERSION_BUILD)m4_if(_CLIENT_VERSION_RC, [0], [], [rc]_CLIENT_VERSION_RC),[https://github.com/ElementsProject/elements/issues],[elements],[https://elementsproject.org/])
AC_CONFIG_SRCDIR([src/validation.cpp])
AC_CONFIG_HEADERS([src/config/bitcoin-config.h])
AC_CONFIG_AUX_DIR([build-aux])
@ -24,7 +23,11 @@ BITCOIN_DAEMON_NAME=elementsd
BITCOIN_GUI_NAME=elements-qt
BITCOIN_CLI_NAME=elements-cli
BITCOIN_TX_NAME=elements-tx
BITCOIN_UTIL_NAME=elements-util
BITCOIN_WALLET_TOOL_NAME=elements-wallet
dnl Multi Process
BITCOIN_MP_NODE_NAME=elements-node
BITCOIN_MP_GUI_NAME=elements-gui
dnl Unless the user specified ARFLAGS, force it to be cr
AC_ARG_VAR(ARFLAGS, [Flags for the archiver, defaults to <cr> if not set])
@ -68,18 +71,8 @@ case $host in
;;
esac
AC_ARG_ENABLE([c++17],
[AS_HELP_STRING([--enable-c++17],
[enable compilation in c++17 mode (disabled by default)])],
[use_cxx17=$enableval],
[use_cxx17=no])
dnl Require C++11 or C++17 compiler (no GNU extensions)
if test "x$use_cxx17" = xyes -o "x$enable_fuzz" = xyes ; then
AX_CXX_COMPILE_STDCXX([17], [noext], [mandatory])
else
AX_CXX_COMPILE_STDCXX([11], [noext], [mandatory])
fi
dnl Require C++17 compiler (no GNU extensions)
AX_CXX_COMPILE_STDCXX([17], [noext], [mandatory])
dnl Check if -latomic is required for <std::atomic>
CHECK_ATOMIC
@ -107,14 +100,13 @@ AC_PATH_TOOL(STRIP, strip)
AC_PATH_TOOL(GCOV, gcov)
AC_PATH_TOOL(LLVM_COV, llvm-cov)
AC_PATH_PROG(LCOV, lcov)
dnl Python 3.5 is specified in .python-version and should be used if available, see doc/dependencies.md
AC_PATH_PROGS([PYTHON], [python3.5 python3.6 python3.7 python3.8 python3 python])
dnl Python 3.6 is specified in .python-version and should be used if available, see doc/dependencies.md
AC_PATH_PROGS([PYTHON], [python3.6 python3.7 python3.8 python3.9 python3 python])
AC_PATH_PROG(GENHTML, genhtml)
AC_PATH_PROG([GIT], [git])
AC_PATH_PROG(CCACHE,ccache)
AC_PATH_PROG(XGETTEXT,xgettext)
AC_PATH_PROG(HEXDUMP,hexdump)
AC_PATH_TOOL(READELF, readelf)
AC_PATH_TOOL(CPPFILT, c++filt)
AC_PATH_TOOL(OBJCOPY, objcopy)
AC_PATH_PROG(DOXYGEN, doxygen)
@ -126,7 +118,7 @@ AC_ARG_ENABLE([wallet],
[AS_HELP_STRING([--disable-wallet],
[disable wallet (enabled by default)])],
[enable_wallet=$enableval],
[enable_wallet=yes])
[enable_wallet=auto])
AC_ARG_WITH([sqlite],
[AS_HELP_STRING([--with-sqlite=yes|no|auto],
@ -134,6 +126,18 @@ AC_ARG_WITH([sqlite],
[use_sqlite=$withval],
[use_sqlite=auto])
AC_ARG_WITH([bdb],
[AS_HELP_STRING([--without-bdb],
[disable bdb wallet support (default is enabled if wallet is enabled)])],
[use_bdb=$withval],
[use_bdb=auto])
AC_ARG_ENABLE([ebpf],
[AS_HELP_STRING([--enable-ebpf],
[enable eBPF tracing (default is yes if sys/sdt.h is found)])],
[use_ebpf=$enableval],
[use_ebpf=yes])
AC_ARG_WITH([miniupnpc],
[AS_HELP_STRING([--with-miniupnpc],
[enable UPNP (default is yes if libminiupnpc is found)])],
@ -146,6 +150,18 @@ AC_ARG_ENABLE([upnp-default],
[use_upnp_default=$enableval],
[use_upnp_default=no])
AC_ARG_WITH([natpmp],
[AS_HELP_STRING([--with-natpmp],
[enable NAT-PMP (default is yes if libnatpmp is found)])],
[use_natpmp=$withval],
[use_natpmp=auto])
AC_ARG_ENABLE([natpmp-default],
[AS_HELP_STRING([--enable-natpmp-default],
[if NAT-PMP is enabled, turn it on at startup (default is no)])],
[use_natpmp_default=$enableval],
[use_natpmp_default=no])
AC_ARG_ENABLE(tests,
AS_HELP_STRING([--disable-tests],[do not compile tests (default is to compile)]),
[use_tests=$enableval],
@ -168,10 +184,16 @@ AC_ARG_ENABLE([extended-functional-tests],
AC_ARG_ENABLE([fuzz],
AS_HELP_STRING([--enable-fuzz],
[enable building of fuzz targets (default no). enabling this will disable all other targets]),
[build for fuzzing (default no). enabling this will disable all other targets and override --{enable,disable}-fuzz-binary]),
[enable_fuzz=$enableval],
[enable_fuzz=no])
AC_ARG_ENABLE([fuzz-binary],
AS_HELP_STRING([--enable-fuzz-binary],
[enable building of fuzz binary (default yes).]),
[enable_fuzz_binary=$enableval],
[enable_fuzz_binary=yes])
AC_ARG_WITH([qrencode],
[AS_HELP_STRING([--with-qrencode],
[enable QR code support (default is yes if qt is enabled and libqrencode is found)])],
@ -306,13 +328,6 @@ AC_ARG_ENABLE([gprof],
[enable_gprof=$enableval],
[enable_gprof=no])
dnl Pass compiler & linker flags that make builds deterministic
AC_ARG_ENABLE([determinism],
[AS_HELP_STRING([--enable-determinism],
[Enable compilation flags that make builds deterministic (default is no)])],
[enable_determinism=$enableval],
[enable_determinism=no])
dnl Turn warnings into errors
AC_ARG_ENABLE([werror],
[AS_HELP_STRING([--enable-werror],
@ -320,6 +335,11 @@ AC_ARG_ENABLE([werror],
[enable_werror=$enableval],
[enable_werror=no])
AC_ARG_ENABLE([external-signer],
[AS_HELP_STRING([--enable-external-signer],[compile external signer support (default is yes, requires Boost::Process)])],
[use_external_signer=$enableval],
[use_external_signer=yes])
AC_LANG_PUSH([C++])
dnl Check for a flag to turn compiler warnings into errors. This is helpful for checks which may
@ -363,6 +383,7 @@ if test "x$enable_debug" = xyes; then
AX_CHECK_PREPROC_FLAG([-DDEBUG],[[DEBUG_CPPFLAGS="$DEBUG_CPPFLAGS -DDEBUG"]],,[[$CXXFLAG_WERROR]])
AX_CHECK_PREPROC_FLAG([-DDEBUG_LOCKORDER],[[DEBUG_CPPFLAGS="$DEBUG_CPPFLAGS -DDEBUG_LOCKORDER"]],,[[$CXXFLAG_WERROR]])
AX_CHECK_PREPROC_FLAG([-DABORT_ON_FAILED_ASSUME],[[DEBUG_CPPFLAGS="$DEBUG_CPPFLAGS -DABORT_ON_FAILED_ASSUME"]],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-ftrapv],[DEBUG_CXXFLAGS="$DEBUG_CXXFLAGS -ftrapv"],,[[$CXXFLAG_WERROR]])
fi
@ -414,6 +435,12 @@ if test "x$enable_werror" = "xyes"; then
AX_CHECK_COMPILE_FLAG([-Werror=suggest-override],[ERROR_CXXFLAGS="$ERROR_CXXFLAGS -Werror=suggest-override"],,[[$CXXFLAG_WERROR]],
[AC_LANG_SOURCE([[struct A { virtual void f(); }; struct B : A { void f() final; };]])])
AX_CHECK_COMPILE_FLAG([-Werror=unreachable-code-loop-increment],[ERROR_CXXFLAGS="$ERROR_CXXFLAGS -Werror=unreachable-code-loop-increment"],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-Werror=mismatched-tags], [ERROR_CXXFLAGS="$ERROR_CXXFLAGS -Werror=mismatched-tags"], [], [$CXXFLAG_WERROR])
AX_CHECK_COMPILE_FLAG([-Werror=implicit-fallthrough], [ERROR_CXXFLAGS="$ERROR_CXXFLAGS -Werror=implicit-fallthrough"], [], [$CXXFLAG_WERROR])
if test x$suppress_external_warnings != xno ; then
AX_CHECK_COMPILE_FLAG([-Werror=documentation],[ERROR_CXXFLAGS="$ERROR_CXXFLAGS -Werror=documentation"],,[[$CXXFLAG_WERROR]])
fi
fi
if test "x$CXXFLAGS_overridden" = "xno"; then
@ -429,6 +456,7 @@ if test "x$CXXFLAGS_overridden" = "xno"; then
AX_CHECK_COMPILE_FLAG([-Wrange-loop-analysis],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wrange-loop-analysis"],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-Wredundant-decls],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wredundant-decls"],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-Wunused-variable],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wunused-variable"],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-Wunused-member-function],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wunused-member-function"],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-Wdate-time],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wdate-time"],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-Wconditional-uninitialized],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wconditional-uninitialized"],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-Wsign-compare],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wsign-compare"],,[[$CXXFLAG_WERROR]])
@ -439,6 +467,11 @@ if test "x$CXXFLAGS_overridden" = "xno"; then
AX_CHECK_COMPILE_FLAG([-Wsuggest-override],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wsuggest-override"],,[[$CXXFLAG_WERROR]],
[AC_LANG_SOURCE([[struct A { virtual void f(); }; struct B : A { void f() final; };]])])
AX_CHECK_COMPILE_FLAG([-Wunreachable-code-loop-increment],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wunreachable-code-loop-increment"],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-Wimplicit-fallthrough], [WARN_CXXFLAGS="$WARN_CXXFLAGS -Wimplicit-fallthrough"], [], [$CXXFLAG_WERROR])
if test x$suppress_external_warnings != xno ; then
AX_CHECK_COMPILE_FLAG([-Wdocumentation],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wdocumentation"],,[[$CXXFLAG_WERROR]])
fi
dnl Some compilers (gcc) ignore unknown -Wno-* options, but warn about all
dnl unknown options if any other warning is produced. Test the -Wfoo case, and
@ -446,9 +479,9 @@ if test "x$CXXFLAGS_overridden" = "xno"; then
AX_CHECK_COMPILE_FLAG([-Wunused-parameter],[NOWARN_CXXFLAGS="$NOWARN_CXXFLAGS -Wno-unused-parameter"],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-Wself-assign],[NOWARN_CXXFLAGS="$NOWARN_CXXFLAGS -Wno-self-assign"],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-Wunused-local-typedef],[NOWARN_CXXFLAGS="$NOWARN_CXXFLAGS -Wno-unused-local-typedef"],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-Wdeprecated-register],[NOWARN_CXXFLAGS="$NOWARN_CXXFLAGS -Wno-deprecated-register"],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-Wimplicit-fallthrough],[NOWARN_CXXFLAGS="$NOWARN_CXXFLAGS -Wno-implicit-fallthrough"],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-Wdeprecated-copy],[NOWARN_CXXFLAGS="$NOWARN_CXXFLAGS -Wno-deprecated-copy"],,[[$CXXFLAG_WERROR]])
if test x$suppress_external_warnings != xyes ; then
AX_CHECK_COMPILE_FLAG([-Wdeprecated-copy],[NOWARN_CXXFLAGS="$NOWARN_CXXFLAGS -Wno-deprecated-copy"],,[[$CXXFLAG_WERROR]])
fi
fi
dnl Don't allow extended (non-ASCII) symbols in identifiers. This is easier for code review.
@ -564,7 +597,7 @@ CPPFLAGS="$CPPFLAGS -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS"
AC_ARG_WITH([utils],
[AS_HELP_STRING([--with-utils],
[build bitcoin-cli bitcoin-tx bitcoin-wallet (default=yes)])],
[build bitcoin-cli bitcoin-tx bitcoin-util bitcoin-wallet (default=yes)])],
[build_bitcoin_utils=$withval],
[build_bitcoin_utils=yes])
@ -586,6 +619,12 @@ AC_ARG_ENABLE([util-wallet],
[build_bitcoin_wallet=$enableval],
[build_bitcoin_wallet=$build_bitcoin_utils])
AC_ARG_ENABLE([util-util],
[AS_HELP_STRING([--enable-util-util],
[build bitcoin-util])],
[build_bitcoin_util=$enableval],
[build_bitcoin_util=$build_bitcoin_utils])
AC_ARG_WITH([libs],
[AS_HELP_STRING([--with-libs],
[build libraries (default=yes)])],
@ -630,7 +669,7 @@ case $host in
AC_MSG_ERROR("windres not found")
fi
CPPFLAGS="$CPPFLAGS -D_MT -DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB -D_WIN32_WINNT=0x0601 -D_WIN32_IE=0x0501 -DWIN32_LEAN_AND_MEAN"
CPPFLAGS="$CPPFLAGS -D_MT -DWIN32 -D_WINDOWS -D_WIN32_WINNT=0x0601 -D_WIN32_IE=0x0501 -DWIN32_LEAN_AND_MEAN"
dnl libtool insists upon adding -nostdlib and a list of objects/libs to link against.
dnl That breaks our ability to build dll's with static libgcc/libstdc++/libssp. Override
@ -656,16 +695,19 @@ case $host in
dnl It's safe to add these paths even if the functionality is disabled by
dnl the user (--without-wallet or --without-gui for example).
bdb_prefix=$($BREW --prefix berkeley-db4 2>/dev/null)
qt5_prefix=$($BREW --prefix qt5 2>/dev/null)
if test x$bdb_prefix != x && test "x$BDB_CFLAGS" = "x" && test "x$BDB_LIBS" = "x"; then
if test "x$use_bdb" != xno && $BREW list --versions berkeley-db4 >/dev/null && test "x$BDB_CFLAGS" = "x" && test "x$BDB_LIBS" = "x"; then
bdb_prefix=$($BREW --prefix berkeley-db4 2>/dev/null)
dnl This must precede the call to BITCOIN_FIND_BDB48 below.
BDB_CFLAGS="-I$bdb_prefix/include"
BDB_LIBS="-L$bdb_prefix/lib -ldb_cxx-4.8"
fi
if test x$qt5_prefix != x; then
PKG_CONFIG_PATH="$qt5_prefix/lib/pkgconfig:$PKG_CONFIG_PATH"
export PKG_CONFIG_PATH
if test "x$use_sqlite" != xno && $BREW list --versions sqlite3 >/dev/null; then
export PKG_CONFIG_PATH="$($BREW --prefix sqlite3 2>/dev/null)/lib/pkgconfig:$PKG_CONFIG_PATH"
fi
if $BREW list --versions qt5 >/dev/null; then
export PKG_CONFIG_PATH="$($BREW --prefix qt5 2>/dev/null)/lib/pkgconfig:$PKG_CONFIG_PATH"
fi
dnl On some versions of osx stack check is turned on by default and is broken
AX_CHECK_COMPILE_FLAG([-fno-stack-check],[HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -fno-stack-check"])
@ -679,7 +721,8 @@ case $host in
AC_PATH_TOOL([DSYMUTIL], [dsymutil], dsymutil)
AC_PATH_TOOL([INSTALLNAMETOOL], [install_name_tool], install_name_tool)
AC_PATH_TOOL([OTOOL], [otool], otool)
AC_PATH_PROGS([GENISOIMAGE], [genisoimage mkisofs],genisoimage)
AC_PATH_PROGS([XORRISOFS], [xorrisofs], xorrisofs)
AC_PATH_PROGS([DMG], [dmg], dmg)
AC_PATH_PROGS([RSVG_CONVERT], [rsvg-convert rsvg],rsvg-convert)
AC_PATH_PROGS([IMAGEMAGICK_CONVERT], [convert],convert)
AC_PATH_PROGS([TIFFCP], [tiffcp],tiffcp)
@ -700,6 +743,21 @@ case $host in
*android*)
dnl make sure android stays above linux for hosts like *linux-android*
TARGET_OS=android
case $host in
*x86_64*)
ANDROID_ARCH=x86_64
;;
*aarch64*)
ANDROID_ARCH=arm64-v8a
;;
*armv7a*)
ANDROID_ARCH=armeabi-v7a
;;
*i686*)
ANDROID_ARCH=i686
;;
*) AC_MSG_ERROR("Could not determine Android arch") ;;
esac
;;
*linux*)
TARGET_OS=linux
@ -756,6 +814,9 @@ if test x$use_lcov_branch != xno; then
AC_SUBST(LCOV_OPTS, "$LCOV_OPTS --rc lcov_branch_coverage=1")
fi
dnl Check for __int128
AC_CHECK_TYPES([__int128])
dnl Check for endianness
AC_C_BIGENDIAN
@ -781,13 +842,14 @@ if test x$ac_cv_sys_large_files != x &&
CPPFLAGS="$CPPFLAGS -D_LARGE_FILES=$ac_cv_sys_large_files"
fi
AX_GCC_FUNC_ATTRIBUTE([visibility])
AX_GCC_FUNC_ATTRIBUTE([dllexport])
AX_GCC_FUNC_ATTRIBUTE([dllimport])
if test x$use_glibc_compat != xno; then
AX_CHECK_LINK_FLAG([[-Wl,--wrap=__divmoddi4]], [COMPAT_LDFLAGS="$COMPAT_LDFLAGS -Wl,--wrap=__divmoddi4"])
AX_CHECK_LINK_FLAG([[-Wl,--wrap=log2f]], [COMPAT_LDFLAGS="$COMPAT_LDFLAGS -Wl,--wrap=log2f"])
case $host in
powerpc64* | ppc64*)
AX_CHECK_LINK_FLAG([[-Wl,--no-tls-get-addr-optimize]], [COMPAT_LDFLAGS="$COMPAT_LDFLAGS -Wl,--no-tls-get-addr-optimize"])
;;
esac
else
AC_SEARCH_LIBS([clock_gettime],[rt])
fi
@ -823,13 +885,21 @@ if test x$use_hardening != xno; then
AX_CHECK_COMPILE_FLAG([-Wstack-protector],[HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -Wstack-protector"])
AX_CHECK_COMPILE_FLAG([-fstack-protector-all],[HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -fstack-protector-all"])
AX_CHECK_COMPILE_FLAG([-fcf-protection=full],[HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -fcf-protection=full"])
dnl -fcf-protection used with Clang 7 causes ld to emit warnings:
dnl ld: error: ... <corrupt x86 feature size: 0x8>
dnl Use CHECK_LINK_FLAG & --fatal-warnings to ensure we won't use the flag in this case.
AX_CHECK_LINK_FLAG([-fcf-protection=full],[HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -fcf-protection=full"],, [[$LDFLAG_WERROR]])
case $host in
*mingw*)
dnl stack-clash-protection doesn't currently work, and likely should just be skipped for Windows.
dnl See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90458 for more details.
;;
*)
AX_CHECK_COMPILE_FLAG([-fstack-clash-protection], [HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -fstack-clash-protection"], [], [$CXXFLAG_WERROR])
;;
esac
dnl stack-clash-protection does not work properly when building for Windows.
dnl We use the test case from https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90458
dnl to determine if it can be enabled.
AX_CHECK_COMPILE_FLAG([-fstack-clash-protection],[HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -fstack-clash-protection"],[],["-O0"],
[AC_LANG_SOURCE([[class D {public: unsigned char buf[32768];}; int main() {D d; return 0;}]])])
dnl When enable_debug is yes, all optimizations are disabled.
dnl However, FORTIFY_SOURCE requires that there is some level of optimization, otherwise it does nothing and just creates a compiler warning.
@ -843,6 +913,7 @@ if test x$use_hardening != xno; then
])
fi
AX_CHECK_LINK_FLAG([[-Wl,--enable-reloc-section]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,--enable-reloc-section"],, [[$LDFLAG_WERROR]])
AX_CHECK_LINK_FLAG([[-Wl,--dynamicbase]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,--dynamicbase"],, [[$LDFLAG_WERROR]])
AX_CHECK_LINK_FLAG([[-Wl,--nxcompat]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,--nxcompat"],, [[$LDFLAG_WERROR]])
AX_CHECK_LINK_FLAG([[-Wl,--high-entropy-va]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,--high-entropy-va"],, [[$LDFLAG_WERROR]])
@ -867,22 +938,19 @@ if test x$TARGET_OS = xdarwin; then
AX_CHECK_LINK_FLAG([[-Wl,-bind_at_load]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,-bind_at_load"],, [[$LDFLAG_WERROR]])
fi
if test x$enable_determinism = xyes; then
if test x$TARGET_OS = xwindows; then
AX_CHECK_LINK_FLAG([[-Wl,--no-insert-timestamp]], [LDFLAGS="$LDFLAGS -Wl,--no-insert-timestamp"],, [[$LDFLAG_WERROR]])
fi
fi
AC_CHECK_HEADERS([endian.h sys/endian.h byteswap.h stdio.h stdlib.h unistd.h strings.h sys/types.h sys/stat.h sys/select.h sys/prctl.h sys/sysctl.h vm/vm_param.h sys/vmmeter.h sys/resources.h])
AC_CHECK_DECLS([getifaddrs, freeifaddrs],,,
AC_CHECK_DECLS([getifaddrs, freeifaddrs],[CHECK_SOCKET],,
[#include <sys/types.h>
#include <ifaddrs.h>]
)
AC_CHECK_DECLS([strnlen])
dnl Check for daemon(3), unrelated to --with-daemon (although used by it)
AC_CHECK_DECLS([daemon])
dnl These are used for daemonization in bitcoind
AC_CHECK_DECLS([fork])
AC_CHECK_DECLS([setsid])
AC_CHECK_DECLS([pipe2])
AC_CHECK_DECLS([le16toh, le32toh, le64toh, htole16, htole32, htole64, be16toh, be32toh, be64toh, htobe16, htobe32, htobe64],,,
[#if HAVE_ENDIAN_H
@ -944,13 +1012,13 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
[ AC_MSG_RESULT(no)]
)
AC_MSG_CHECKING([for visibility attribute])
AC_LINK_IFELSE([AC_LANG_SOURCE([
int foo_def( void ) __attribute__((visibility("default")));
AC_MSG_CHECKING([for default visibility attribute])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
int foo(void) __attribute__((visibility("default")));
int main(){}
])],
[
AC_DEFINE(HAVE_VISIBILITY_ATTRIBUTE,1,[Define if the visibility attribute is supported.])
AC_DEFINE(HAVE_DEFAULT_VISIBILITY_ATTRIBUTE,1,[Define if the visibility attribute is supported.])
AC_MSG_RESULT(yes)
],
[
@ -961,6 +1029,18 @@ AC_LINK_IFELSE([AC_LANG_SOURCE([
]
)
AC_MSG_CHECKING([for dllexport attribute])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
__declspec(dllexport) int foo(void);
int main(){}
])],
[
AC_DEFINE(HAVE_DLLEXPORT_ATTRIBUTE,1,[Define if the dllexport attribute is supported.])
AC_MSG_RESULT(yes)
],
[AC_MSG_RESULT(no)]
)
dnl thread_local is currently disabled when building with glibc back compat.
dnl Our minimum supported glibc is 2.17, however support for thread_local
dnl did not arrive in glibc until 2.18.
@ -1096,6 +1176,7 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <fcntl.h>]],
[ AC_MSG_RESULT(yes); HAVE_O_CLOEXEC=1 ],
[ AC_MSG_RESULT(no); HAVE_O_CLOEXEC=0 ]
)
AC_DEFINE_UNQUOTED([HAVE_O_CLOEXEC], [$HAVE_O_CLOEXEC], [Define to 1 if O_CLOEXEC flag is available.])
dnl crc32c platform checks
AC_MSG_CHECKING(for __builtin_prefetch)
@ -1126,27 +1207,23 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
]], [[
getauxval(AT_HWCAP);
]])],
[ AC_MSG_RESULT(yes); HAVE_STRONG_GETAUXVAL=1 ],
[ AC_MSG_RESULT(yes); HAVE_STRONG_GETAUXVAL=1; AC_DEFINE(HAVE_STRONG_GETAUXVAL, 1, [Define this symbol to build code that uses getauxval)]) ],
[ AC_MSG_RESULT(no); HAVE_STRONG_GETAUXVAL=0 ]
)
AC_MSG_CHECKING(for weak getauxval support in the compiler)
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#ifdef __linux__
unsigned long getauxval(unsigned long type) __attribute__((weak));
#define AT_HWCAP 16
#endif
]], [[
getauxval(AT_HWCAP);
]])],
[ AC_MSG_RESULT(yes); HAVE_WEAK_GETAUXVAL=1 ],
[ AC_MSG_RESULT(yes); HAVE_WEAK_GETAUXVAL=1; AC_DEFINE(HAVE_WEAK_GETAUXVAL, 1, [Define this symbol to build code that uses getauxval (weak linking)]) ],
[ AC_MSG_RESULT(no); HAVE_WEAK_GETAUXVAL=0 ]
)
dnl Check for reduced exports
if test x$use_reduce_exports = xyes; then
AX_CHECK_COMPILE_FLAG([-fvisibility=hidden],[RE_CXXFLAGS="-fvisibility=hidden"],
[AC_MSG_ERROR([Cannot set default symbol visibility. Use --disable-reduce-exports.])])
fi
AC_MSG_CHECKING([for std::system])
AC_LINK_IFELSE(
[ AC_LANG_PROGRAM(
@ -1191,10 +1268,11 @@ AC_DEFUN([SUPPRESS_WARNINGS],
dnl enable-fuzz should disable all other targets
if test "x$enable_fuzz" = "xyes"; then
AC_MSG_WARN(enable-fuzz will disable all other targets)
AC_MSG_WARN(enable-fuzz will disable all other targets and force --enable-fuzz-binary=yes)
build_bitcoin_utils=no
build_bitcoin_cli=no
build_bitcoin_tx=no
build_bitcoin_util=no
build_bitcoin_wallet=no
build_bitcoind=no
build_bitcoin_libs=no
@ -1203,27 +1281,34 @@ if test "x$enable_fuzz" = "xyes"; then
bitcoin_enable_qt_dbus=no
enable_wallet=no
use_bench=no
use_external_signer=no
use_upnp=no
use_natpmp=no
use_zmq=no
enable_fuzz_binary=yes
AC_MSG_CHECKING([whether main function is needed])
AX_CHECK_PREPROC_FLAG([-DABORT_ON_FAILED_ASSUME],[[DEBUG_CPPFLAGS="$DEBUG_CPPFLAGS -DABORT_ON_FAILED_ASSUME"]],,[[$CXXFLAG_WERROR]])
AC_MSG_CHECKING([whether main function is needed for fuzz binary])
AX_CHECK_LINK_FLAG(
[[-fsanitize=$use_sanitizers]],
[AC_MSG_RESULT([no])],
[AC_MSG_RESULT([yes])
CPPFLAGS="$CPPFLAGS -DPROVIDE_MAIN_FUNCTION"],
CPPFLAGS="$CPPFLAGS -DPROVIDE_FUZZ_MAIN_FUNCTION"],
[],
[AC_LANG_PROGRAM([[
#include <cstdint>
#include <cstddef>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { return 0; }
/* unterminated comment to remove the main function ...
]],[[]])])
/* comment to remove the main function ...
]],[[
*/ int not_main() {
]])])
else
BITCOIN_QT_INIT
dnl sets $bitcoin_enable_qt, $bitcoin_enable_qt_test, $bitcoin_enable_qt_dbus
BITCOIN_QT_CONFIGURE([5.5.1])
BITCOIN_QT_CONFIGURE([5.9.5])
dnl Keep a copy of the original $QT_INCLUDES and use it when invoking qt's moc
QT_INCLUDES_UNSUPPRESSED=$QT_INCLUDES
@ -1232,13 +1317,17 @@ else
QT_DBUS_INCLUDES=SUPPRESS_WARNINGS($QT_DBUS_INCLUDES)
QT_TEST_INCLUDES=SUPPRESS_WARNINGS($QT_TEST_INCLUDES)
fi
CPPFLAGS="$CPPFLAGS -DPROVIDE_FUZZ_MAIN_FUNCTION"
fi
if test x$enable_wallet != xno; then
dnl Check for libdb_cxx only if wallet enabled
BITCOIN_FIND_BDB48
if test x$suppress_external_warnings != xno ; then
if test "x$use_bdb" != "xno"; then
BITCOIN_FIND_BDB48
if test x$suppress_external_warnings != xno ; then
BDB_CPPFLAGS=SUPPRESS_WARNINGS($BDB_CPPFLAGS)
fi
fi
dnl Check for sqlite3
@ -1260,12 +1349,32 @@ if test x$enable_wallet != xno; then
fi
fi
AC_MSG_RESULT([$use_sqlite])
dnl Disable wallet if both --without-bdb and --without-sqlite
if test "x$use_bdb$use_sqlite" = "xnono"; then
if test "x$enable_wallet" = "xyes"; then
AC_MSG_ERROR([wallet functionality requested but no BDB or SQLite support available.])
fi
enable_wallet=no
fi
fi
if test x$use_ebpf != xno; then
AC_MSG_CHECKING([whether eBPF tracepoints are supported])
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM(
[#include <sys/sdt.h>],
[DTRACE_PROBE("context", "event");]
)],
[AC_MSG_RESULT(yes); have_sdt=yes; AC_DEFINE([ENABLE_TRACING], [1], [Define to 1 to enable eBPF user static defined tracepoints])],
[AC_MSG_RESULT(no); have_sdt=no;]
)
fi
dnl Check for libminiupnpc (optional)
if test x$use_upnp != xno; then
AC_CHECK_HEADERS(
[miniupnpc/miniwget.h miniupnpc/miniupnpc.h miniupnpc/upnpcommands.h miniupnpc/upnperrors.h],
[miniupnpc/miniupnpc.h miniupnpc/upnpcommands.h miniupnpc/upnperrors.h],
[AC_CHECK_LIB([miniupnpc], [upnpDiscover], [MINIUPNPC_LIBS=-lminiupnpc], [have_miniupnpc=no])],
[have_miniupnpc=no]
)
@ -1291,44 +1400,46 @@ if test x$have_miniupnpc != xno; then
fi
fi
dnl Check for libnatpmp (optional).
if test "x$use_natpmp" != xno; then
AC_CHECK_HEADERS([natpmp.h],
[AC_CHECK_LIB([natpmp], [initnatpmp], [NATPMP_LIBS=-lnatpmp], [have_natpmp=no])],
[have_natpmp=no])
fi
if test x$build_bitcoin_wallet$build_bitcoin_cli$build_bitcoin_tx$build_bitcoind$bitcoin_enable_qt$use_tests$use_bench = xnonononononono; then
use_boost=no
use_boost=no
else
use_boost=yes
use_boost=yes
fi
if test x$use_boost = xyes; then
dnl Minimum required Boost version
define(MINIMUM_REQUIRED_BOOST, 1.58.0)
dnl Check for Boost libs
AX_BOOST_BASE([MINIMUM_REQUIRED_BOOST])
if test x$want_boost = xno; then
dnl Check for Boost headers
AX_BOOST_BASE([1.64.0],[],[AC_MSG_ERROR([Boost is not available!])])
if test x$want_boost = xno; then
AC_MSG_ERROR([[only libbitcoinconsensus can be built without boost]])
fi
AX_BOOST_SYSTEM
AX_BOOST_FILESYSTEM
AX_BOOST_THREAD
fi
AX_BOOST_SYSTEM
AX_BOOST_FILESYSTEM
dnl Opt-in to boost-process
AS_IF([ test x$with_boost_process != x ], [ AX_BOOST_PROCESS ], [ ax_cv_boost_process=no ] )
if test x$suppress_external_warnings != xno; then
if test x$suppress_external_warnings != xno; then
BOOST_CPPFLAGS=SUPPRESS_WARNINGS($BOOST_CPPFLAGS)
fi
BOOST_LIBS="$BOOST_LDFLAGS $BOOST_SYSTEM_LIB $BOOST_FILESYSTEM_LIB"
fi
dnl Boost 1.56 through 1.62 allow using std::atomic instead of its own atomic
dnl counter implementations. In 1.63 and later the std::atomic approach is default.
m4_pattern_allow(DBOOST_AC_USE_STD_ATOMIC) dnl otherwise it's treated like a macro
BOOST_CPPFLAGS="-DBOOST_SP_USE_STD_ATOMIC -DBOOST_AC_USE_STD_ATOMIC $BOOST_CPPFLAGS"
BOOST_LIBS="$BOOST_LDFLAGS $BOOST_SYSTEM_LIB $BOOST_FILESYSTEM_LIB $BOOST_THREAD_LIB"
if test "x$use_external_signer" != xno; then
AC_DEFINE([ENABLE_EXTERNAL_SIGNER],,[define if external signer support is enabled])
fi
AM_CONDITIONAL([ENABLE_EXTERNAL_SIGNER], [test "x$use_external_signer" = "xyes"])
dnl Check for reduced exports
if test x$use_reduce_exports = xyes; then
CXXFLAGS="$CXXFLAGS $RE_CXXFLAGS"
AX_CHECK_LINK_FLAG([[-Wl,--exclude-libs,ALL]], [RELDFLAGS="-Wl,--exclude-libs,ALL"],, [[$LDFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-fvisibility=hidden],[CXXFLAGS="$CXXFLAGS -fvisibility=hidden"],
[AC_MSG_ERROR([Cannot set hidden symbol visibility. Use --disable-reduce-exports.])],[[$CXXFLAG_WERROR]])
AX_CHECK_LINK_FLAG([[-Wl,--exclude-libs,ALL]],[RELDFLAGS="-Wl,--exclude-libs,ALL"],,[[$LDFLAG_WERROR]])
fi
if test x$use_tests = xyes; then
@ -1339,25 +1450,25 @@ if test x$use_tests = xyes; then
if test x$use_boost = xyes; then
AX_BOOST_UNIT_TEST_FRAMEWORK
AX_BOOST_UNIT_TEST_FRAMEWORK
dnl Determine if -DBOOST_TEST_DYN_LINK is needed
AC_MSG_CHECKING([for dynamic linked boost test])
TEMP_LIBS="$LIBS"
LIBS="$LIBS $BOOST_LDFLAGS $BOOST_UNIT_TEST_FRAMEWORK_LIB"
TEMP_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
AC_LINK_IFELSE([AC_LANG_SOURCE([
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>
dnl Determine if -DBOOST_TEST_DYN_LINK is needed
AC_MSG_CHECKING([for dynamic linked boost test])
TEMP_LIBS="$LIBS"
LIBS="$LIBS $BOOST_LDFLAGS $BOOST_UNIT_TEST_FRAMEWORK_LIB"
TEMP_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
AC_LINK_IFELSE([AC_LANG_SOURCE([
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>
])],
[AC_MSG_RESULT(yes)]
[TESTDEFS="$TESTDEFS -DBOOST_TEST_DYN_LINK"],
[AC_MSG_RESULT(no)])
LIBS="$TEMP_LIBS"
CPPFLAGS="$TEMP_CPPFLAGS"
])],
[AC_MSG_RESULT(yes)]
[TESTDEFS="$TESTDEFS -DBOOST_TEST_DYN_LINK"],
[AC_MSG_RESULT(no)])
LIBS="$TEMP_LIBS"
CPPFLAGS="$TEMP_CPPFLAGS"
fi
fi
@ -1369,6 +1480,10 @@ if test x$build_bitcoin_cli$build_bitcoind$bitcoin_enable_qt$use_tests$use_bench
if test x$TARGET_OS != xwindows; then
PKG_CHECK_MODULES([EVENT_PTHREADS], [libevent_pthreads >= 2.0.21],, [AC_MSG_ERROR([libevent_pthreads version 2.0.21 or greater not found.])])
fi
if test x$suppress_external_warnings != xno; then
EVENT_CFLAGS=SUPPRESS_WARNINGS($EVENT_CFLAGS)
fi
fi
dnl QR Code encoding library check
@ -1401,7 +1516,7 @@ fi
dnl univalue check
need_bundled_univalue=yes
if test x$build_bitcoin_wallet$build_bitcoin_cli$build_bitcoin_tx$build_bitcoind$bitcoin_enable_qt$use_tests$use_bench = xnonononononono; then
if test x$build_bitcoin_wallet$build_bitcoin_cli$build_bitcoin_tx$build_bitcoin_util$build_bitcoind$bitcoin_enable_qt$use_tests$use_bench = xnononononononono; then
need_bundled_univalue=no
else
if test x$system_univalue != xno; then
@ -1484,6 +1599,10 @@ AC_MSG_CHECKING([whether to build bitcoin-wallet])
AM_CONDITIONAL([BUILD_BITCOIN_WALLET], [test x$build_bitcoin_wallet = xyes])
AC_MSG_RESULT($build_bitcoin_wallet)
AC_MSG_CHECKING([whether to build bitcoin-util])
AM_CONDITIONAL([BUILD_BITCOIN_UTIL], [test x$build_bitcoin_util = xyes])
AC_MSG_RESULT($build_bitcoin_util)
AC_MSG_CHECKING([whether to build libraries])
AM_CONDITIONAL([BUILD_BITCOIN_LIBS], [test x$build_bitcoin_libs = xyes])
if test x$build_bitcoin_libs = xyes; then
@ -1508,6 +1627,10 @@ if test "x$use_ccache" != "xno"; then
CXX="$ac_cv_path_CCACHE $CXX"
fi
AC_MSG_RESULT($use_ccache)
if test "x$use_ccache" = "xyes"; then
AX_CHECK_COMPILE_FLAG([-fdebug-prefix-map=A=B],[DEBUG_CXXFLAGS="$DEBUG_CXXFLAGS -fdebug-prefix-map=\$(abs_srcdir)=."],,[[$CXXFLAG_WERROR]])
AX_CHECK_PREPROC_FLAG([-fmacro-prefix-map=A=B],[DEBUG_CPPFLAGS="$DEBUG_CPPFLAGS -fmacro-prefix-map=\$(abs_srcdir)=."],,[[$CXXFLAG_WERROR]])
fi
fi
dnl enable wallet
@ -1515,6 +1638,7 @@ AC_MSG_CHECKING([if wallet should be enabled])
if test x$enable_wallet != xno; then
AC_MSG_RESULT(yes)
AC_DEFINE_UNQUOTED([ENABLE_WALLET],[1],[Define to 1 to enable wallet functions])
enable_wallet=yes
else
AC_MSG_RESULT(no)
@ -1548,6 +1672,34 @@ else
fi
fi
dnl Enable NAT-PMP support.
AC_MSG_CHECKING([whether to build with support for NAT-PMP])
if test "x$have_natpmp" = xno; then
if test "x$use_natpmp" = xyes; then
AC_MSG_ERROR([NAT-PMP requested but cannot be built. Use --without-natpmp])
fi
AC_MSG_RESULT([no])
use_natpmp=no
else
if test "x$use_natpmp" != xno; then
AC_MSG_RESULT([yes])
AC_MSG_CHECKING([whether to build with NAT-PMP enabled by default])
use_natpmp=yes
natpmp_setting=0
if test "x$use_natpmp_default" != xno; then
use_natpmp_default=yes
natpmp_setting=1
fi
AC_MSG_RESULT($use_natpmp_default)
AC_DEFINE_UNQUOTED([USE_NATPMP], [$natpmp_setting], [NAT-PMP support not compiled if undefined, otherwise value (0 or 1) determines default state])
if test x$TARGET_OS = xwindows; then
NATPMP_CPPFLAGS="-DSTATICLIB -DNATPMP_STATICLIB"
fi
else
AC_MSG_RESULT([no])
fi
fi
dnl these are only used when qt is enabled
BUILD_TEST_QT=""
if test x$bitcoin_enable_qt != xno; then
@ -1590,7 +1742,11 @@ AM_CONDITIONAL([ENABLE_ZMQ], [test "x$use_zmq" = "xyes"])
AC_MSG_CHECKING([whether to build test_bitcoin])
if test x$use_tests = xyes; then
AC_MSG_RESULT([yes])
if test "x$enable_fuzz" = "xyes"; then
AC_MSG_RESULT([no, because fuzzing is enabled])
else
AC_MSG_RESULT([yes])
fi
BUILD_TEST="yes"
else
AC_MSG_RESULT([no])
@ -1614,8 +1770,11 @@ AM_CONDITIONAL([TARGET_LINUX], [test x$TARGET_OS = xlinux])
AM_CONDITIONAL([TARGET_WINDOWS], [test x$TARGET_OS = xwindows])
AM_CONDITIONAL([ENABLE_WALLET],[test x$enable_wallet = xyes])
AM_CONDITIONAL([USE_SQLITE], [test "x$use_sqlite" = "xyes"])
AM_CONDITIONAL([USE_BDB], [test "x$use_bdb" = "xyes"])
AM_CONDITIONAL([ENABLE_TRACING],[test x$have_sdt = xyes])
AM_CONDITIONAL([ENABLE_TESTS],[test x$BUILD_TEST = xyes])
AM_CONDITIONAL([ENABLE_FUZZ],[test x$enable_fuzz = xyes])
AM_CONDITIONAL([ENABLE_FUZZ_BINARY],[test x$enable_fuzz_binary = xyes])
AM_CONDITIONAL([ENABLE_QT],[test x$bitcoin_enable_qt = xyes])
AM_CONDITIONAL([ENABLE_QT_TESTS],[test x$BUILD_TEST_QT = xyes])
AM_CONDITIONAL([ENABLE_BENCH],[test x$use_bench = xyes])
@ -1631,11 +1790,12 @@ AM_CONDITIONAL([ENABLE_SHANI],[test x$enable_shani = xyes])
AM_CONDITIONAL([ENABLE_ARM_CRC],[test x$enable_arm_crc = xyes])
AM_CONDITIONAL([USE_ASM],[test x$use_asm = xyes])
AM_CONDITIONAL([WORDS_BIGENDIAN],[test x$ac_cv_c_bigendian = xyes])
AM_CONDITIONAL([USE_NATPMP],[test x$use_natpmp = xyes])
AM_CONDITIONAL([USE_UPNP],[test x$use_upnp = xyes])
AM_CONDITIONAL([LIQUID],[test x$liquid_build = xyes])
AC_DEFINE(CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MAJOR, [Major version])
AC_DEFINE(CLIENT_VERSION_MINOR, _CLIENT_VERSION_MINOR, [Minor version])
AC_DEFINE(CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION, [Build revision])
AC_DEFINE(CLIENT_VERSION_BUILD, _CLIENT_VERSION_BUILD, [Version Build])
AC_DEFINE(CLIENT_VERSION_IS_RELEASE, _CLIENT_VERSION_IS_RELEASE, [Version is release])
AC_DEFINE(COPYRIGHT_YEAR, _COPYRIGHT_YEAR, [Copyright year])
@ -1645,7 +1805,6 @@ define(_COPYRIGHT_HOLDERS_FINAL, [patsubst(_COPYRIGHT_HOLDERS, [%s], [_COPYRIGHT
AC_DEFINE(COPYRIGHT_HOLDERS_FINAL, "_COPYRIGHT_HOLDERS_FINAL", [Copyright holder(s)])
AC_SUBST(CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MAJOR)
AC_SUBST(CLIENT_VERSION_MINOR, _CLIENT_VERSION_MINOR)
AC_SUBST(CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION)
AC_SUBST(CLIENT_VERSION_BUILD, _CLIENT_VERSION_BUILD)
AC_SUBST(CLIENT_VERSION_IS_RELEASE, _CLIENT_VERSION_IS_RELEASE)
AC_SUBST(COPYRIGHT_YEAR, _COPYRIGHT_YEAR)
@ -1656,7 +1815,10 @@ AC_SUBST(BITCOIN_DAEMON_NAME)
AC_SUBST(BITCOIN_GUI_NAME)
AC_SUBST(BITCOIN_CLI_NAME)
AC_SUBST(BITCOIN_TX_NAME)
AC_SUBST(BITCOIN_UTIL_NAME)
AC_SUBST(BITCOIN_WALLET_TOOL_NAME)
AC_SUBST(BITCOIN_MP_NODE_NAME)
AC_SUBST(BITCOIN_MP_GUI_NAME)
AC_SUBST(RELDFLAGS)
AC_SUBST(DEBUG_CPPFLAGS)
@ -1681,6 +1843,8 @@ AC_SUBST(SHANI_CXXFLAGS)
AC_SUBST(ARM_CRC_CXXFLAGS)
AC_SUBST(LIBTOOL_APP_LDFLAGS)
AC_SUBST(USE_SQLITE)
AC_SUBST(USE_BDB)
AC_SUBST(ENABLE_EXTERNAL_SIGNER)
AC_SUBST(USE_UPNP)
AC_SUBST(USE_QRCODE)
AC_SUBST(BOOST_LIBS)
@ -1688,6 +1852,8 @@ AC_SUBST(SQLITE_LIBS)
AC_SUBST(TESTDEFS)
AC_SUBST(MINIUPNPC_CPPFLAGS)
AC_SUBST(MINIUPNPC_LIBS)
AC_SUBST(NATPMP_CPPFLAGS)
AC_SUBST(NATPMP_LIBS)
AC_SUBST(EVENT_LIBS)
AC_SUBST(EVENT_PTHREADS_LIBS)
AC_SUBST(ZMQ_LIBS)
@ -1700,11 +1866,14 @@ AC_SUBST(HAVE_BUILTIN_PREFETCH)
AC_SUBST(HAVE_MM_PREFETCH)
AC_SUBST(HAVE_STRONG_GETAUXVAL)
AC_SUBST(HAVE_WEAK_GETAUXVAL)
AC_SUBST(ANDROID_ARCH)
AC_CONFIG_FILES([Makefile src/Makefile doc/man/Makefile share/setup.nsi share/qt/Info.plist test/config.ini])
AC_CONFIG_FILES([contrib/devtools/split-debug.sh],[chmod +x contrib/devtools/split-debug.sh])
AM_COND_IF([HAVE_DOXYGEN], [AC_CONFIG_FILES([doc/Doxyfile])])
AC_CONFIG_LINKS([contrib/devtools/security-check.py:contrib/devtools/security-check.py])
AC_CONFIG_LINKS([contrib/devtools/symbol-check.py:contrib/devtools/symbol-check.py])
AC_CONFIG_LINKS([contrib/devtools/test-security-check.py:contrib/devtools/test-security-check.py])
AC_CONFIG_LINKS([contrib/devtools/test-symbol-check.py:contrib/devtools/test-symbol-check.py])
AC_CONFIG_LINKS([contrib/filter-lcov.py:contrib/filter-lcov.py])
AC_CONFIG_LINKS([test/functional/test_runner.py:test/functional/test_runner.py])
AC_CONFIG_LINKS([test/bitcoin_functional/functional/test_runner.py:test/bitcoin_functional/functional/test_runner.py])
@ -1754,38 +1923,44 @@ esac
echo
echo "Options used to compile and link:"
echo " boost process = $ax_cv_boost_process"
echo " multiprocess = $build_multiprocess"
echo " with wallet = $enable_wallet"
echo " external signer = $use_external_signer"
echo " multiprocess = $build_multiprocess"
echo " with libs = $build_bitcoin_libs"
echo " with wallet = $enable_wallet"
if test "x$enable_wallet" != "xno"; then
echo " with sqlite = $use_sqlite"
echo " with sqlite = $use_sqlite"
echo " with bdb = $use_bdb"
fi
echo " with gui / qt = $bitcoin_enable_qt"
echo " with gui / qt = $bitcoin_enable_qt"
if test x$bitcoin_enable_qt != xno; then
echo " with qr = $use_qr"
echo " with qr = $use_qr"
fi
echo " with zmq = $use_zmq"
echo " with test = $use_tests"
if test x$use_tests != xno; then
echo " with fuzz = $enable_fuzz"
echo " with zmq = $use_zmq"
if test x$enable_fuzz == xno; then
echo " with test = $use_tests"
else
echo " with test = not building test_bitcoin because fuzzing is enabled"
echo " with fuzz = $enable_fuzz"
fi
echo " with bench = $use_bench"
echo " with upnp = $use_upnp"
echo " use asm = $use_asm"
echo " liquid_build = $liquid_build"
echo " sanitizers = $use_sanitizers"
echo " debug enabled = $enable_debug"
echo " gprof enabled = $enable_gprof"
echo " werror = $enable_werror"
echo " with bench = $use_bench"
echo " with upnp = $use_upnp"
echo " with natpmp = $use_natpmp"
echo " use asm = $use_asm"
echo " ebpf tracing = $have_sdt"
echo " liquid_build = $liquid_build"
echo " sanitizers = $use_sanitizers"
echo " debug enabled = $enable_debug"
echo " gprof enabled = $enable_gprof"
echo " werror = $enable_werror"
echo
echo " target os = $TARGET_OS"
echo " build os = $build_os"
echo " target os = $TARGET_OS"
echo " build os = $build_os"
echo
echo " CC = $CC"
echo " CFLAGS = $PTHREAD_CFLAGS $CFLAGS"
echo " CPPFLAGS = $DEBUG_CPPFLAGS $HARDENED_CPPFLAGS $CPPFLAGS"
echo " CXX = $CXX"
echo " CXXFLAGS = $DEBUG_CXXFLAGS $HARDENED_CXXFLAGS $WARN_CXXFLAGS $NOWARN_CXXFLAGS $ERROR_CXXFLAGS $GPROF_CXXFLAGS $CXXFLAGS"
echo " LDFLAGS = $PTHREAD_LIBS $HARDENED_LDFLAGS $GPROF_LDFLAGS $LDFLAGS"
echo " ARFLAGS = $ARFLAGS"
echo " CC = $CC"
echo " CFLAGS = $PTHREAD_CFLAGS $CFLAGS"
echo " CPPFLAGS = $DEBUG_CPPFLAGS $HARDENED_CPPFLAGS $CPPFLAGS"
echo " CXX = $CXX"
echo " CXXFLAGS = $DEBUG_CXXFLAGS $HARDENED_CXXFLAGS $WARN_CXXFLAGS $NOWARN_CXXFLAGS $ERROR_CXXFLAGS $GPROF_CXXFLAGS $CXXFLAGS"
echo " LDFLAGS = $PTHREAD_LIBS $HARDENED_LDFLAGS $GPROF_LDFLAGS $LDFLAGS"
echo " ARFLAGS = $ARFLAGS"
echo

View file

@ -29,8 +29,8 @@ All other packaging related files can be found in the [bitcoin-core/packaging](h
### [Gitian-descriptors](/contrib/gitian-descriptors) ###
Files used during the gitian build process. For more information about gitian, see the [the Bitcoin Core documentation repository](https://github.com/bitcoin-core/docs).
### [Gitian-keys](/contrib/gitian-keys)
PGP keys used for signing Bitcoin Core [Gitian release](/doc/release-process.md) results.
### [Builder keys](/contrib/builder-keys)
PGP keys used for signing Bitcoin Core [release](/doc/release-process.md) results.
### [MacDeploy](/contrib/macdeploy) ###
Scripts and notes for Mac builds.

View file

@ -6,7 +6,7 @@ import argparse
import sys
from decimal import Decimal
## 0. Boilerplate to make the tutorial executable as a script
# 0. Boilerplate to make the tutorial executable as a script
#
# Skip ahead to step 1 if you are reading
#
@ -44,7 +44,7 @@ e2 = Daemon(
not args.no_cleanup,
)
## 1. Start nodes
# 1. Start nodes
print ("1. Start nodes")
#
# 1a. Confirm that we not start an elements node if validatepegin is set and there
@ -85,7 +85,7 @@ e2.connect_to(e1)
# already exist.
print ("1c. Creating wallets on all daemons")
# We have configured this regtest chain to start with 21M bitcoins, which are initally
# We have configured this regtest chain to start with 21M bitcoins, which are initially
# in a single OP_TRUE output. All Elements wallets recognize OP_TRUE outputs as their
# own (this differs from Bitcoin), so the 21M bitcoins are immediately available for
# use. This can be disabled by setting `anyonecanspend_aremine=0` in the daemon config.
@ -132,7 +132,7 @@ sync_all([e1, e2])
assert e1.getblockcount() == 10
assert e1.getbestblockhash() == e2.getbestblockhash()
## 2. Basic wallet usage
# 2. Basic wallet usage
print ("")
print ("2. Basic wallet usage")
@ -225,7 +225,7 @@ except JSONRPCException:
else:
raise Exception("Transaction 3 should not be in wallet 1")
## 3. Confidential assets and keys
# 3. Confidential assets and keys
print ("")
print ("3. Confidential Keys")
current_e1_balance = e1.getbalance()
@ -264,7 +264,7 @@ e1.sendtoaddress(e2.getnewaddress(), e1.getbalance()['bitcoin'] / 2, "", "", Tru
e1.generatetoaddress(1, e1.getnewaddress())
sync_all([e1, e2])
## 4. 2-of-2 multisig
# 4. 2-of-2 multisig
#
# Let's build a blinded 2-of-2 multisig p2sh address
print ("")
@ -303,7 +303,7 @@ e2.importblindingkey(blinded_addr, blindingkey)
assert e1.gettransaction(txid, True)['details'] != []
assert e2.gettransaction(txid, True)['details'] != []
## 5. Multi-asset support
# 5. Multi-asset support
#
# Many of the RPC calls have added asset type or label arguments, and reveal
# alternative asset information. With no argument all are listed. For example,
@ -338,7 +338,6 @@ assert len(new_issuances) == 1
assert new_issuances[0]['assetamount'] == 1
assert new_issuances[0]['tokenamount'] == 1
assert len(e2.listissuances()) == 1 ## ANDREW
print ("5b. Reissue the asset using the reissuance token.")
# If you gave `issueasset` a reissuance token argument greater than 0
# you can also reissue the base asset. This will appear as a second issuance
@ -449,7 +448,7 @@ sync_all([e1, e2])
e1.generatetoaddress(1, e1.getnewaddress())
sync_all([e1, e2])
## 6. Blocksigning
# 6. Blocksigning
#
# Up to now, we have been generating blocks to the default OP_TRUE script. Let's
# make this script more interesting. We'll use a 2-of-2 multisig made from keys
@ -561,7 +560,7 @@ sync_all([e1, e2])
assert e1.getblockcount() == 1
assert e2.getblockcount() == 1
## The peg
# The peg
#
# Everything peg-related can be done inside the Elements daemon directly,
# except for processing pegouts. This is because processing pegouts involves
@ -665,7 +664,7 @@ print ("7e. Request pegout")
e1.sendtomainchain(bitcoin.getnewaddress(), 5)
## Exercise(s)
# Exercise(s)
#
# 1. Implement really dumb/unsafe watchmen to allow pegouts for learning purposes.
# To custody the coins that users peg in, you need to extract the tweak from

View file

@ -3,22 +3,20 @@
from test_framework.authproxy import JSONRPCException
from test_framework.daemon import Daemon, sync_all
import argparse
import sys
from decimal import Decimal
## PSET Swap Tutorial
# PSET Swap Tutorial
#
# This script demonstrates how to implement an atomic swap, using a single
# Elements transaction, between two parties, Alice and Carol. Alice has
# ten thousand BTC and Carol has 1000 of a new asset. After the swap, Alice
# will have the new asset and Carol will have the BTC.
#
# This script can be executed in a Python intepreter. The user is encouraged
# This script can be executed in a Python interpreter. The user is encouraged
# to add tracing or debugging code throughout to better understand what is
# going on.
#
## 0. Boilerplate to make the tutorial executable as a script
# 0. Boilerplate to make the tutorial executable as a script
#
# Skip ahead to step 1 if you are reading
#
@ -47,7 +45,7 @@ carol = Daemon(
not args.no_cleanup,
)
## 1. Start nodes
# 1. Start nodes
print ("1. Start nodes and setup scenario")
# 1a. Turn on both nodes. Disable -validatepegin as we will just swap the
@ -92,7 +90,7 @@ asset_BTC = alice.dumpassetlabels()["bitcoin"]
assert len(alice.listunspent()) > 0
assert len(carol.listunspent()) > 0
## 2. Construct a swap transaction in PSET format
# 2. Construct a swap transaction in PSET format
#
# At this point node `alice` has 10.5MM "bitcoin" and node `carol` has 1000 of
# a new asset. We want to do an atomic swap: 2500 BTC for 1000 of
@ -119,7 +117,7 @@ carol_addr = carol.getnewaddress()
print (" Alice: ", alice_addr)
print (" Carol: ", carol_addr)
# Then they each create and fund (but don't sign!) partial transactions
# Then they each create and fund (but don't sign!) partial transactions
# which simply send the assets to each other.
print ("2b. Exchange partial transaction data")
raw_tx_a = alice.createrawtransaction(outputs=[{carol_addr: 2500}])
@ -148,12 +146,12 @@ for output in decoded_a["vout"]:
assert feerate > 0.1 # should probably compare against your own feerate
assert found_my_output
##
## Check that none of the inputs in the counterparty's transaction actually
## belong to us. This is the second-most important check (after making sure
## that your outputs are present :)) and by far the easiest to forget. Do
## not forget this!!!
##
#
# Check that none of the inputs in the counterparty's transaction actually
# belong to us. This is the second-most important check (after making sure
# that your outputs are present :)) and by far the easiest to forget. Do
# not forget this!!!
#
# The way we do this check in Python is by making a set of each
# output the wallet can spend...
@ -235,7 +233,7 @@ assert not any([x["has_utxo"] for x in analysis["inputs"]])
assert not any([x["is_final"] for x in analysis["inputs"]])
assert all([x["next"] == "updater" for x in analysis["inputs"]])
## 3. Update the PSET
# 3. Update the PSET
#
# Before blinding can take place, both parties need to provide UTXO data
# for their inputs. They can share this data by either updating the PSET
@ -258,7 +256,7 @@ assert all([x["has_utxo"] for x in analysis["inputs"]])
assert not any([x["is_final"] for x in analysis["inputs"]])
assert all([x["next"] == "signer" for x in analysis["inputs"]])
## 4. Blind the PSET
# 4. Blind the PSET
#
# Both parties now blind the PSET. Importantly, the final person to blind must
# have a combined PSET that has everyone else's blinding data included, so that
@ -314,7 +312,7 @@ assert all([x["has_utxo"] for x in analysis["inputs"]])
assert not any([x["is_final"] for x in analysis["inputs"]])
assert all([x["next"] == "signer" for x in analysis["inputs"]])
## 5. Sign the PSET
# 5. Sign the PSET
#
# When signing, there are a couple options for workflows. Each party can sign
# in turn, like we did when blinding, or they can each sign independently and

View file

@ -1,7 +1,6 @@
from test_framework.authproxy import AuthServiceProxy
import pathlib
import tempfile
import time
import shutil
@ -41,7 +40,7 @@ class Daemon():
if self.proc is not None:
print ("Shutting down %s" % self.name)
self.proc.terminate()
## FIXME determine why we need 30+ seconds to shut down with a tiny regtest chain
# FIXME determine why we need 30+ seconds to shut down with a tiny regtest chain
self.proc.wait(120)
self.proc = None
@ -92,8 +91,6 @@ class Daemon():
return self.config[key]
def sync_all(nodes, timeout_sec = 10):
totalWait = timeout_sec
stop_time = time.time() + timeout_sec
while time.time() <= stop_time:
best_hash = [x.getbestblockhash() for x in nodes]

View file

@ -1,22 +0,0 @@
FORMS += \
../src/qt/forms/aboutdialog.ui \
../src/qt/forms/addressbookpage.ui \
../src/qt/forms/askpassphrasedialog.ui \
../src/qt/forms/coincontroldialog.ui \
../src/qt/forms/editaddressdialog.ui \
../src/qt/forms/helpmessagedialog.ui \
../src/qt/forms/intro.ui \
../src/qt/forms/openuridialog.ui \
../src/qt/forms/optionsdialog.ui \
../src/qt/forms/overviewpage.ui \
../src/qt/forms/receivecoinsdialog.ui \
../src/qt/forms/receiverequestdialog.ui \
../src/qt/forms/debugwindow.ui \
../src/qt/forms/sendcoinsdialog.ui \
../src/qt/forms/sendcoinsentry.ui \
../src/qt/forms/signverifymessagedialog.ui \
../src/qt/forms/transactiondescdialog.ui \
../src/qt/forms/createwalletdialog.ui
RESOURCES += \
../src/qt/bitcoin.qrc

View file

@ -1,10 +1,10 @@
## PGP keys of Gitian builders and Developers
## PGP keys of builders and Developers
The file `keys.txt` contains fingerprints of the public keys of Gitian builders
and active developers.
The file `keys.txt` contains fingerprints of the public keys of builders and
active developers.
The associated keys are mainly used to sign git commits or the build results
of Gitian builds.
of Guix builds.
The most recent version of each pgp key can be found on most pgp key servers.
@ -16,12 +16,12 @@ To fetch the latest version of all pgp keys in your gpg homedir,
gpg --refresh-keys
```
To fetch keys of Gitian builders and active developers, feed the list of
fingerprints of the primary keys into gpg:
To fetch keys of builders and active developers, feed the list of fingerprints
of the primary keys into gpg:
```sh
while read fingerprint keyholder_name; do gpg --keyserver hkp://subset.pool.sks-keyservers.net --recv-keys ${fingerprint}; done < ./keys.txt
```
Add your key to the list if you provided Gitian signatures for two major or
Add your key to the list if you provided Guix attestations for two major or
minor releases of Bitcoin Core.

View file

@ -0,0 +1,51 @@
9D3CC86A72F8494342EA5FD10A41BDC3F4FAFF1C Aaron Clauson (sipsorcery)
617C90010B3BD370B0AC7D424BB42E31C79111B8 Akira Takizawa (akx20000)
E944AE667CF960B1004BC32FCA662BE18B877A60 Andreas Schildbach (aschildbach)
152812300785C96444D3334D17565732E08E5E41 Andrew Chow (achow101)
590B7292695AFFA5B672CBB2E13FC145CD3F4304 Antoine Poinsot (darosior)
0AD83877C1F0CD1EE9BD660AD7CC770B81FD22A8 Ben Carman (benthecarman)
912FD3228387123DC97E0E57D5566241A0295FA9 BtcDrak (btcdrak)
C519EBCF3B926298946783EFF6430754120EC2F4 Christian Decker (cdecker)
18AE2F798E0D239755DA4FD24B79F986CBDF8736 Chun Kuan Le (ken2812221)
101598DC823C1B5F9A6624ABA5E0907A0380E6C3 CoinForensics (CoinForensics)
F20F56EF6A067F70E8A5C99FFF95FAA971697405 centaur (centaur)
C060A6635913D98A3587D7DB1C2491FFEB0EF770 Cory Fields (cfields)
BF6273FAEF7CC0BA1F562E50989F6B3048A116B5 Dev Random (devrandom)
6D3170C1DC2C6FD0AEEBCA6743811D1A26623924 Douglas Roark (droark)
1C6621605EC50319C463D56C7F81D87985D61612 Emanuele Cisbani (cisba)
9A1689B60D1B3CCE9262307A2F40A9BF167FBA47 Erik Mossberg (erkmos)
D35176BE9264832E4ACA8986BF0792FBE95DC863 fivepiece (fivepiece)
6F993B250557E7B016ADE5713BDCDA2D87A881D9 Fuzzbawls (Fuzzbawls)
01CDF4627A3B88AAE4A571C87588242FBE38D3A8 Gavin Andresen (gavinandresen)
D1DBF2C4B96F2DEBF4C16654410108112E7EA81F Hennadii Stepanov (hebasto)
A2FD494D0021AA9B4FA58F759102B7AE654A4A5A Ilyas Ridhuan (IlyasRidhuan)
D3F22A3A4C366C2DCB66D3722DA9C5A7FA81EA35 Jarol Rodriguez (jarolrod)
7480909378D544EA6B6DCEB7535B12980BB8A4D3 Jeffri H Frontz (jhfrontz)
D3CC177286005BB8FF673294C5242A1AB3936517 jl2012 (jl2012)
82921A4B88FD454B7EB8CE3C796C4109063D4EAF Jon Atack (jonatack)
32EE5C4C3FA15CCADB46ABE529D4BCB6416F53EC Jonas Schnelli (jonasschnelli)
4B4E840451149DD7FB0D633477DFAB5C3108B9A8 Jorge Timon (jtimon)
C42AFF7C61B3E44A1454CD3557AF762DB3353322 Karl-Johan Alm (kallewoof)
30DE693AE0DE9E37B3E7EB6BBFF0F67810C1EED1 Lisa Neigut (niftynei)
E463A93F5F3117EEDE6C7316BD02942421F4889F Luke Dashjr (luke-jr)
B8B3F1C0E58C15DB6A81D30C3648A882F4316B9B Marco Falke (marco)
07DF3E57A548CCFB7530709189BBB8663E2E65CE Matt Corallo (BlueMatt)
CA03882CB1FC067B5D3ACFE4D300116E1C875A3D MeshCollider (meshcollider)
E777299FC265DD04793070EB944D35F9AC3DB76A Michael Ford (fanquake)
AD5764F4ADCE1B99BDFD179E12335A271D4D62EC Michael Tidwell (miketwenty1)
9692B91BBF0E8D34DFD33B1882C5C009628ECF0C Michagogo (michagogo)
C57E4B42223FDE851D4F69DD28DF2724F241D8EE midnightmagic (midnightmagic)
F4FC70F07310028424EFC20A8E4256593F177720 Oliver Gugger (guggero, Oliver Gugger)
D62A803E27E7F43486035ADBBCD04D8E9CCCAC2A Paul Rabahy (prab)
37EC7D7B0A217CDB4B4E007E7FAB114267E4FA04 Peter Todd (petertodd)
D762373D24904A3E42F33B08B9A408E71DAAC974 Pieter Wuille [Location: Leuven, Belgium] (sipa)
133EAC179436F14A5CF1B794860FEB804E669320 Pieter Wuille (sipa)
6A8F9C266528E25AEB1D7731C2371D91CB716EA7 Sebastian Falbesoner (theStack)
A8FC55F3B04BA3146F3492E79303B33A305224CB Sebastian Kung (TheCharlatan)
ED9BDF7AD6A55E232E84524257FF9BDBCC301009 Sjors Provoost (sjors)
867345026B6763E8B07EE73AB6737117397F5C4F Stephan Oeste (Emzy)
9EDAFF80E080659604F4A76B2EBB056FD847F8A7 Stephan Oeste (Emzy)
6DEEF79B050C4072509B743F8C275BC595448867 Tomas Kanocz (KanoczTomas)
AEC1884398647C47413C1C3FB1179EB7347DC10D Warren Togami (wtogami)
79D00BAC68B56D422F945A8F8E3A8F3247DBCBBF Willy Ko (willyko)
71A3B16735405025D447E8F274810B012346C9A6 Wladimir J. van der Laan (laanwj)

View file

@ -1,11 +1,11 @@
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: Bitcoin
Upstream-Contact: Satoshi Nakamoto <satoshin@gmx.com>
irc://#bitcoin@freenode.net
irc://#bitcoin-core-dev@libera.chat
Source: https://github.com/bitcoin/bitcoin
Files: *
Copyright: 2009-2020, Bitcoin Core Developers
Copyright: 2009-2021, Bitcoin Core Developers
License: Expat
Comment: The Bitcoin Core Developers encompasses the current developers listed on bitcoin.org,
as well as the numerous contributors to the project.
@ -87,6 +87,10 @@ Files: src/qt/res/icons/proxy.png
Copyright: Cristian Mircea Messel
License: public-domain
Files: src/qt/res/fonts/RobotoMono-Bold.ttf
License: Apache-2.0
Comment: Site: https://fonts.google.com/specimen/Roboto+Mono
License: Expat
Permission is hereby granted, free of charge, to any person obtaining a
@ -144,3 +148,14 @@ Comment:
License: public-domain
This work is in the public domain.
License: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View file

@ -7,7 +7,8 @@ clang-format-diff.py
A script to format unified git diffs according to [.clang-format](../../src/.clang-format).
Requires `clang-format`, installed e.g. via `brew install clang-format` on macOS.
Requires `clang-format`, installed e.g. via `brew install clang-format` on macOS,
or `sudo apt install clang-format` on Debian/Ubuntu.
For instance, to format the last commit with 0 lines of context,
the script should be called from the git root folder as follows.

View file

@ -1,10 +1,11 @@
#!/usr/bin/env python3
# Copyright (c) 2018-2019 The Bitcoin Core developers
# Copyright (c) 2018-2020 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
import sys
import re
from typing import Dict, List, Set
MAPPING = {
'core_read.cpp': 'core_io.cpp',
@ -32,7 +33,7 @@ def module_name(path):
return None
files = dict()
deps = dict()
deps: Dict[str, Set[str]] = dict()
RE = re.compile("^#include <(.*)>")
@ -59,12 +60,12 @@ for arg in sorted(files.keys()):
deps[module].add(included_module)
# Loop to find the shortest (remaining) circular dependency
have_cycle = False
have_cycle: bool = False
while True:
shortest_cycle = None
for module in sorted(deps.keys()):
# Build the transitive closure of dependencies of module
closure = dict()
closure: Dict[str, List[str]] = dict()
for dep in deps[module]:
closure[dep] = []
while True:

View file

@ -1,5 +1,5 @@
#!/usr/bin/env bash
# Copyright (c) 2016-2019 The Bitcoin Core developers
# Copyright (c) 2016-2020 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
@ -14,10 +14,27 @@ BITCOIND=${BITCOIND:-$BINDIR/elementsd}
BITCOINCLI=${BITCOINCLI:-$BINDIR/elements-cli}
BITCOINTX=${BITCOINTX:-$BINDIR/elements-tx}
WALLET_TOOL=${WALLET_TOOL:-$BINDIR/elements-wallet}
BITCOINUTIL=${BITCOINQT:-$BINDIR/elements-util}
BITCOINQT=${BITCOINQT:-$BINDIR/qt/elements-qt}
[ ! -x $BITCOIND ] && echo "$BITCOIND not found or not executable." && exit 1
# Don't allow man pages to be generated for binaries built from a dirty tree
DIRTY=""
for cmd in $BITCOIND $BITCOINCLI $BITCOINTX $WALLET_TOOL $BITCOINUTIL $BITCOINQT; do
VERSION_OUTPUT=$($cmd --version)
if [[ $VERSION_OUTPUT == *"dirty"* ]]; then
DIRTY="${DIRTY}${cmd}\n"
fi
done
if [ -n "$DIRTY" ]
then
echo -e "WARNING: the following binaries were built from a dirty tree:\n"
echo -e $DIRTY
echo "man pages generated from dirty binaries should NOT be committed."
echo "To properly generate man pages, please commit your changes to the above binaries, rebuild them, then run this script again."
fi
# The autodetected version git tag can screw up manpage output a little bit
read -r -a BTCVER <<< "$($BITCOINCLI --version | head -n1 | awk -F'[ -]' '{ print $6, $7 }')"
@ -27,7 +44,7 @@ read -r -a BTCVER <<< "$($BITCOINCLI --version | head -n1 | awk -F'[ -]' '{ prin
echo "[COPYRIGHT]" > footer.h2m
$BITCOIND --version | sed -n '1!p' >> footer.h2m
for cmd in $BITCOIND $BITCOINCLI $BITCOINTX $WALLET_TOOL $BITCOINQT; do
for cmd in $BITCOIND $BITCOINCLI $BITCOINTX $WALLET_TOOL $BITCOINUTIL $BITCOINQT; do
cmdname="${cmd##*/}"
help2man -N --version-string=${BTCVER[0]} --include=footer.h2m -o ${MANDIR}/${cmdname}.1 ${cmd}
sed -i "s/\\\-${BTCVER[1]}//g" ${MANDIR}/${cmdname}.1

323
contrib/devtools/pixie.py Normal file
View file

@ -0,0 +1,323 @@
#!/usr/bin/env python3
# Copyright (c) 2020 Wladimir J. van der Laan
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
'''
Compact, self-contained ELF implementation for bitcoin-core security checks.
'''
import struct
import types
from typing import Dict, List, Optional, Union, Tuple
# you can find all these values in elf.h
EI_NIDENT = 16
# Byte indices in e_ident
EI_CLASS = 4 # ELFCLASSxx
EI_DATA = 5 # ELFDATAxxxx
ELFCLASS32 = 1 # 32-bit
ELFCLASS64 = 2 # 64-bit
ELFDATA2LSB = 1 # little endian
ELFDATA2MSB = 2 # big endian
# relevant values for e_machine
EM_386 = 3
EM_PPC64 = 21
EM_ARM = 40
EM_AARCH64 = 183
EM_X86_64 = 62
EM_RISCV = 243
# relevant values for e_type
ET_DYN = 3
# relevant values for sh_type
SHT_PROGBITS = 1
SHT_STRTAB = 3
SHT_DYNAMIC = 6
SHT_DYNSYM = 11
SHT_GNU_verneed = 0x6ffffffe
SHT_GNU_versym = 0x6fffffff
# relevant values for p_type
PT_LOAD = 1
PT_GNU_STACK = 0x6474e551
PT_GNU_RELRO = 0x6474e552
# relevant values for p_flags
PF_X = (1 << 0)
PF_W = (1 << 1)
PF_R = (1 << 2)
# relevant values for d_tag
DT_NEEDED = 1
DT_FLAGS = 30
# relevant values of `d_un.d_val' in the DT_FLAGS entry
DF_BIND_NOW = 0x00000008
# relevant d_tags with string payload
STRING_TAGS = {DT_NEEDED}
# rrlevant values for ST_BIND subfield of st_info (symbol binding)
STB_LOCAL = 0
class ELFRecord(types.SimpleNamespace):
'''Unified parsing for ELF records.'''
def __init__(self, data: bytes, offset: int, eh: 'ELFHeader', total_size: Optional[int]) -> None:
hdr_struct = self.STRUCT[eh.ei_class][0][eh.ei_data]
if total_size is not None and hdr_struct.size > total_size:
raise ValueError(f'{self.__class__.__name__} header size too small ({total_size} < {hdr_struct.size})')
for field, value in zip(self.STRUCT[eh.ei_class][1], hdr_struct.unpack(data[offset:offset + hdr_struct.size])):
setattr(self, field, value)
def BiStruct(chars: str) -> Dict[int, struct.Struct]:
'''Compile a struct parser for both endians.'''
return {
ELFDATA2LSB: struct.Struct('<' + chars),
ELFDATA2MSB: struct.Struct('>' + chars),
}
class ELFHeader(ELFRecord):
FIELDS = ['e_type', 'e_machine', 'e_version', 'e_entry', 'e_phoff', 'e_shoff', 'e_flags', 'e_ehsize', 'e_phentsize', 'e_phnum', 'e_shentsize', 'e_shnum', 'e_shstrndx']
STRUCT = {
ELFCLASS32: (BiStruct('HHIIIIIHHHHHH'), FIELDS),
ELFCLASS64: (BiStruct('HHIQQQIHHHHHH'), FIELDS),
}
def __init__(self, data: bytes, offset: int) -> None:
self.e_ident = data[offset:offset + EI_NIDENT]
if self.e_ident[0:4] != b'\x7fELF':
raise ValueError('invalid ELF magic')
self.ei_class = self.e_ident[EI_CLASS]
self.ei_data = self.e_ident[EI_DATA]
super().__init__(data, offset + EI_NIDENT, self, None)
def __repr__(self) -> str:
return f'Header(e_ident={self.e_ident!r}, e_type={self.e_type}, e_machine={self.e_machine}, e_version={self.e_version}, e_entry={self.e_entry}, e_phoff={self.e_phoff}, e_shoff={self.e_shoff}, e_flags={self.e_flags}, e_ehsize={self.e_ehsize}, e_phentsize={self.e_phentsize}, e_phnum={self.e_phnum}, e_shentsize={self.e_shentsize}, e_shnum={self.e_shnum}, e_shstrndx={self.e_shstrndx})'
class Section(ELFRecord):
name: Optional[bytes] = None
FIELDS = ['sh_name', 'sh_type', 'sh_flags', 'sh_addr', 'sh_offset', 'sh_size', 'sh_link', 'sh_info', 'sh_addralign', 'sh_entsize']
STRUCT = {
ELFCLASS32: (BiStruct('IIIIIIIIII'), FIELDS),
ELFCLASS64: (BiStruct('IIQQQQIIQQ'), FIELDS),
}
def __init__(self, data: bytes, offset: int, eh: ELFHeader) -> None:
super().__init__(data, offset, eh, eh.e_shentsize)
self._data = data
def __repr__(self) -> str:
return f'Section(sh_name={self.sh_name}({self.name!r}), sh_type=0x{self.sh_type:x}, sh_flags={self.sh_flags}, sh_addr=0x{self.sh_addr:x}, sh_offset=0x{self.sh_offset:x}, sh_size={self.sh_size}, sh_link={self.sh_link}, sh_info={self.sh_info}, sh_addralign={self.sh_addralign}, sh_entsize={self.sh_entsize})'
def contents(self) -> bytes:
'''Return section contents.'''
return self._data[self.sh_offset:self.sh_offset + self.sh_size]
class ProgramHeader(ELFRecord):
STRUCT = {
# different ELF classes have the same fields, but in a different order to optimize space versus alignment
ELFCLASS32: (BiStruct('IIIIIIII'), ['p_type', 'p_offset', 'p_vaddr', 'p_paddr', 'p_filesz', 'p_memsz', 'p_flags', 'p_align']),
ELFCLASS64: (BiStruct('IIQQQQQQ'), ['p_type', 'p_flags', 'p_offset', 'p_vaddr', 'p_paddr', 'p_filesz', 'p_memsz', 'p_align']),
}
def __init__(self, data: bytes, offset: int, eh: ELFHeader) -> None:
super().__init__(data, offset, eh, eh.e_phentsize)
def __repr__(self) -> str:
return f'ProgramHeader(p_type={self.p_type}, p_offset={self.p_offset}, p_vaddr={self.p_vaddr}, p_paddr={self.p_paddr}, p_filesz={self.p_filesz}, p_memsz={self.p_memsz}, p_flags={self.p_flags}, p_align={self.p_align})'
class Symbol(ELFRecord):
STRUCT = {
# different ELF classes have the same fields, but in a different order to optimize space versus alignment
ELFCLASS32: (BiStruct('IIIBBH'), ['st_name', 'st_value', 'st_size', 'st_info', 'st_other', 'st_shndx']),
ELFCLASS64: (BiStruct('IBBHQQ'), ['st_name', 'st_info', 'st_other', 'st_shndx', 'st_value', 'st_size']),
}
def __init__(self, data: bytes, offset: int, eh: ELFHeader, symtab: Section, strings: bytes, version: Optional[bytes]) -> None:
super().__init__(data, offset, eh, symtab.sh_entsize)
self.name = _lookup_string(strings, self.st_name)
self.version = version
def __repr__(self) -> str:
return f'Symbol(st_name={self.st_name}({self.name!r}), st_value={self.st_value}, st_size={self.st_size}, st_info={self.st_info}, st_other={self.st_other}, st_shndx={self.st_shndx}, version={self.version!r})'
@property
def is_import(self) -> bool:
'''Returns whether the symbol is an imported symbol.'''
return self.st_bind != STB_LOCAL and self.st_shndx == 0
@property
def is_export(self) -> bool:
'''Returns whether the symbol is an exported symbol.'''
return self.st_bind != STB_LOCAL and self.st_shndx != 0
@property
def st_bind(self) -> int:
'''Returns STB_*.'''
return self.st_info >> 4
class Verneed(ELFRecord):
DEF = (BiStruct('HHIII'), ['vn_version', 'vn_cnt', 'vn_file', 'vn_aux', 'vn_next'])
STRUCT = { ELFCLASS32: DEF, ELFCLASS64: DEF }
def __init__(self, data: bytes, offset: int, eh: ELFHeader) -> None:
super().__init__(data, offset, eh, None)
def __repr__(self) -> str:
return f'Verneed(vn_version={self.vn_version}, vn_cnt={self.vn_cnt}, vn_file={self.vn_file}, vn_aux={self.vn_aux}, vn_next={self.vn_next})'
class Vernaux(ELFRecord):
DEF = (BiStruct('IHHII'), ['vna_hash', 'vna_flags', 'vna_other', 'vna_name', 'vna_next'])
STRUCT = { ELFCLASS32: DEF, ELFCLASS64: DEF }
def __init__(self, data: bytes, offset: int, eh: ELFHeader, strings: bytes) -> None:
super().__init__(data, offset, eh, None)
self.name = _lookup_string(strings, self.vna_name)
def __repr__(self) -> str:
return f'Veraux(vna_hash={self.vna_hash}, vna_flags={self.vna_flags}, vna_other={self.vna_other}, vna_name={self.vna_name}({self.name!r}), vna_next={self.vna_next})'
class DynTag(ELFRecord):
STRUCT = {
ELFCLASS32: (BiStruct('II'), ['d_tag', 'd_val']),
ELFCLASS64: (BiStruct('QQ'), ['d_tag', 'd_val']),
}
def __init__(self, data: bytes, offset: int, eh: ELFHeader, section: Section) -> None:
super().__init__(data, offset, eh, section.sh_entsize)
def __repr__(self) -> str:
return f'DynTag(d_tag={self.d_tag}, d_val={self.d_val})'
def _lookup_string(data: bytes, index: int) -> bytes:
'''Look up string by offset in ELF string table.'''
endx = data.find(b'\x00', index)
assert endx != -1
return data[index:endx]
VERSYM_S = BiStruct('H') # .gnu_version section has a single 16-bit integer per symbol in the linked section
def _parse_symbol_table(section: Section, strings: bytes, eh: ELFHeader, versym: bytes, verneed: Dict[int, bytes]) -> List[Symbol]:
'''Parse symbol table, return a list of symbols.'''
data = section.contents()
symbols = []
versym_iter = (verneed.get(v[0]) for v in VERSYM_S[eh.ei_data].iter_unpack(versym))
for ofs, version in zip(range(0, len(data), section.sh_entsize), versym_iter):
symbols.append(Symbol(data, ofs, eh, section, strings, version))
return symbols
def _parse_verneed(section: Section, strings: bytes, eh: ELFHeader) -> Dict[int, bytes]:
'''Parse .gnu.version_r section, return a dictionary of {versym: 'GLIBC_...'}.'''
data = section.contents()
ofs = 0
result = {}
while True:
verneed = Verneed(data, ofs, eh)
aofs = ofs + verneed.vn_aux
while True:
vernaux = Vernaux(data, aofs, eh, strings)
result[vernaux.vna_other] = vernaux.name
if not vernaux.vna_next:
break
aofs += vernaux.vna_next
if not verneed.vn_next:
break
ofs += verneed.vn_next
return result
def _parse_dyn_tags(section: Section, strings: bytes, eh: ELFHeader) -> List[Tuple[int, Union[bytes, int]]]:
'''Parse dynamic tags. Return array of tuples.'''
data = section.contents()
ofs = 0
result = []
for ofs in range(0, len(data), section.sh_entsize):
tag = DynTag(data, ofs, eh, section)
val = _lookup_string(strings, tag.d_val) if tag.d_tag in STRING_TAGS else tag.d_val
result.append((tag.d_tag, val))
return result
class ELFFile:
sections: List[Section]
program_headers: List[ProgramHeader]
dyn_symbols: List[Symbol]
dyn_tags: List[Tuple[int, Union[bytes, int]]]
def __init__(self, data: bytes) -> None:
self.data = data
self.hdr = ELFHeader(self.data, 0)
self._load_sections()
self._load_program_headers()
self._load_dyn_symbols()
self._load_dyn_tags()
self._section_to_segment_mapping()
def _load_sections(self) -> None:
self.sections = []
for idx in range(self.hdr.e_shnum):
offset = self.hdr.e_shoff + idx * self.hdr.e_shentsize
self.sections.append(Section(self.data, offset, self.hdr))
shstr = self.sections[self.hdr.e_shstrndx].contents()
for section in self.sections:
section.name = _lookup_string(shstr, section.sh_name)
def _load_program_headers(self) -> None:
self.program_headers = []
for idx in range(self.hdr.e_phnum):
offset = self.hdr.e_phoff + idx * self.hdr.e_phentsize
self.program_headers.append(ProgramHeader(self.data, offset, self.hdr))
def _load_dyn_symbols(self) -> None:
# first, load 'verneed' section
verneed = None
for section in self.sections:
if section.sh_type == SHT_GNU_verneed:
strtab = self.sections[section.sh_link].contents() # associated string table
assert verneed is None # only one section of this kind please
verneed = _parse_verneed(section, strtab, self.hdr)
assert verneed is not None
# then, correlate GNU versym sections with dynamic symbol sections
versym = {}
for section in self.sections:
if section.sh_type == SHT_GNU_versym:
versym[section.sh_link] = section
# finally, load dynsym sections
self.dyn_symbols = []
for idx, section in enumerate(self.sections):
if section.sh_type == SHT_DYNSYM: # find dynamic symbol tables
strtab_data = self.sections[section.sh_link].contents() # associated string table
versym_data = versym[idx].contents() # associated symbol version table
self.dyn_symbols += _parse_symbol_table(section, strtab_data, self.hdr, versym_data, verneed)
def _load_dyn_tags(self) -> None:
self.dyn_tags = []
for idx, section in enumerate(self.sections):
if section.sh_type == SHT_DYNAMIC: # find dynamic tag tables
strtab = self.sections[section.sh_link].contents() # associated string table
self.dyn_tags += _parse_dyn_tags(section, strtab, self.hdr)
def _section_to_segment_mapping(self) -> None:
for ph in self.program_headers:
ph.sections = []
for section in self.sections:
if ph.p_vaddr <= section.sh_addr < (ph.p_vaddr + ph.p_memsz):
ph.sections.append(section)
def query_dyn_tags(self, tag_in: int) -> List[Union[int, bytes]]:
'''Return the values of all dyn tags with the specified tag.'''
return [val for (tag, val) in self.dyn_tags if tag == tag_in]
def load(filename: str) -> ELFFile:
with open(filename, 'rb') as f:
data = f.read()
return ELFFile(data)

View file

@ -6,95 +6,31 @@
Perform basic security checks on a series of executables.
Exit status will be 0 if successful, and the program will be silent.
Otherwise the exit status will be 1 and it will log which executables failed which checks.
Needs `readelf` (for ELF), `objdump` (for PE) and `otool` (for MACHO).
'''
import subprocess
import sys
import os
from typing import List, Optional
READELF_CMD = os.getenv('READELF', '/usr/bin/readelf')
OBJDUMP_CMD = os.getenv('OBJDUMP', '/usr/bin/objdump')
OTOOL_CMD = os.getenv('OTOOL', '/usr/bin/otool')
def run_command(command) -> str:
p = subprocess.run(command, stdout=subprocess.PIPE, check=True, universal_newlines=True)
return p.stdout
import lief
import pixie
def check_ELF_PIE(executable) -> bool:
'''
Check for position independent executable (PIE), allowing for address space randomization.
'''
stdout = run_command([READELF_CMD, '-h', '-W', executable])
ok = False
for line in stdout.splitlines():
tokens = line.split()
if len(line)>=2 and tokens[0] == 'Type:' and tokens[1] == 'DYN':
ok = True
return ok
def get_ELF_program_headers(executable):
'''Return type and flags for ELF program headers'''
stdout = run_command([READELF_CMD, '-l', '-W', executable])
in_headers = False
headers = []
for line in stdout.splitlines():
if line.startswith('Program Headers:'):
in_headers = True
count = 0
if line == '':
in_headers = False
if in_headers:
if count == 1: # header line
header = [x.strip() for x in line.split()]
ofs_typ = header.index('Type')
ofs_flags = header.index('Flg')
# assert readelf output is what we expect
if ofs_typ == -1 or ofs_flags == -1:
raise ValueError('Cannot parse elfread -lW output')
elif count > 1:
splitline = [x.strip() for x in line.split()]
typ = splitline[ofs_typ]
if not typ.startswith('[R'): # skip [Requesting ...]
splitline = [x.strip() for x in line.split()]
flags = splitline[ofs_flags]
# check for 'R', ' E'
if splitline[ofs_flags + 1] == 'E':
flags += ' E'
headers.append((typ, flags, []))
count += 1
if line.startswith(' Section to Segment mapping:'):
in_mapping = True
count = 0
if line == '':
in_mapping = False
if in_mapping:
if count == 1: # header line
ofs_segment = line.find('Segment')
ofs_sections = line.find('Sections...')
if ofs_segment == -1 or ofs_sections == -1:
raise ValueError('Cannot parse elfread -lW output')
elif count > 1:
segment = int(line[ofs_segment:ofs_sections].strip())
sections = line[ofs_sections:].strip().split()
headers[segment][2].extend(sections)
count += 1
return headers
elf = pixie.load(executable)
return elf.hdr.e_type == pixie.ET_DYN
def check_ELF_NX(executable) -> bool:
'''
Check that no sections are writable and executable (including the stack)
'''
elf = pixie.load(executable)
have_wx = False
have_gnu_stack = False
for (typ, flags, _) in get_ELF_program_headers(executable):
if typ == 'GNU_STACK':
for ph in elf.program_headers:
if ph.p_type == pixie.PT_GNU_STACK:
have_gnu_stack = True
if 'W' in flags and 'E' in flags: # section is both writable and executable
if (ph.p_flags & pixie.PF_W) != 0 and (ph.p_flags & pixie.PF_X) != 0: # section is both writable and executable
have_wx = True
return have_gnu_stack and not have_wx
@ -104,35 +40,34 @@ def check_ELF_RELRO(executable) -> bool:
GNU_RELRO program header must exist
Dynamic section must have BIND_NOW flag
'''
elf = pixie.load(executable)
have_gnu_relro = False
for (typ, flags, _) in get_ELF_program_headers(executable):
# Note: not checking flags == 'R': here as linkers set the permission differently
for ph in elf.program_headers:
# Note: not checking p_flags == PF_R: here as linkers set the permission differently
# This does not affect security: the permission flags of the GNU_RELRO program
# header are ignored, the PT_LOAD header determines the effective permissions.
# However, the dynamic linker need to write to this area so these are RW.
# Glibc itself takes care of mprotecting this area R after relocations are finished.
# See also https://marc.info/?l=binutils&m=1498883354122353
if typ == 'GNU_RELRO':
if ph.p_type == pixie.PT_GNU_RELRO:
have_gnu_relro = True
have_bindnow = False
stdout = run_command([READELF_CMD, '-d', '-W', executable])
for line in stdout.splitlines():
tokens = line.split()
if len(tokens)>1 and tokens[1] == '(BIND_NOW)' or (len(tokens)>2 and tokens[1] == '(FLAGS)' and 'BIND_NOW' in tokens[2:]):
for flags in elf.query_dyn_tags(pixie.DT_FLAGS):
assert isinstance(flags, int)
if flags & pixie.DF_BIND_NOW:
have_bindnow = True
return have_gnu_relro and have_bindnow
def check_ELF_Canary(executable) -> bool:
'''
Check for use of stack canary
'''
stdout = run_command([READELF_CMD, '--dyn-syms', '-W', executable])
elf = pixie.load(executable)
ok = False
for line in stdout.splitlines():
if '__stack_chk_fail' in line:
for symbol in elf.dyn_symbols:
if symbol.name == b'__stack_chk_fail':
ok = True
return ok
@ -142,48 +77,55 @@ def check_ELF_separate_code(executable):
based on their permissions. This checks for missing -Wl,-z,separate-code
and potentially other problems.
'''
elf = pixie.load(executable)
R = pixie.PF_R
W = pixie.PF_W
E = pixie.PF_X
EXPECTED_FLAGS = {
# Read + execute
'.init': 'R E',
'.plt': 'R E',
'.plt.got': 'R E',
'.plt.sec': 'R E',
'.text': 'R E',
'.fini': 'R E',
b'.init': R | E,
b'.plt': R | E,
b'.plt.got': R | E,
b'.plt.sec': R | E,
b'.text': R | E,
b'.fini': R | E,
# Read-only data
'.interp': 'R',
'.note.gnu.property': 'R',
'.note.gnu.build-id': 'R',
'.note.ABI-tag': 'R',
'.gnu.hash': 'R',
'.dynsym': 'R',
'.dynstr': 'R',
'.gnu.version': 'R',
'.gnu.version_r': 'R',
'.rela.dyn': 'R',
'.rela.plt': 'R',
'.rodata': 'R',
'.eh_frame_hdr': 'R',
'.eh_frame': 'R',
'.qtmetadata': 'R',
'.gcc_except_table': 'R',
'.stapsdt.base': 'R',
b'.interp': R,
b'.note.gnu.property': R,
b'.note.gnu.build-id': R,
b'.note.ABI-tag': R,
b'.gnu.hash': R,
b'.dynsym': R,
b'.dynstr': R,
b'.gnu.version': R,
b'.gnu.version_r': R,
b'.rela.dyn': R,
b'.rela.plt': R,
b'.rodata': R,
b'.eh_frame_hdr': R,
b'.eh_frame': R,
b'.qtmetadata': R,
b'.gcc_except_table': R,
b'.stapsdt.base': R,
# Writable data
'.init_array': 'RW',
'.fini_array': 'RW',
'.dynamic': 'RW',
'.got': 'RW',
'.data': 'RW',
'.bss': 'RW',
b'.init_array': R | W,
b'.fini_array': R | W,
b'.dynamic': R | W,
b'.got': R | W,
b'.data': R | W,
b'.bss': R | W,
}
if elf.hdr.e_machine == pixie.EM_PPC64:
# .plt is RW on ppc64 even with separate-code
EXPECTED_FLAGS[b'.plt'] = R | W
# For all LOAD program headers get mapping to the list of sections,
# and for each section, remember the flags of the associated program header.
flags_per_section = {}
for (typ, flags, sections) in get_ELF_program_headers(executable):
if typ == 'LOAD':
for section in sections:
assert(section not in flags_per_section)
flags_per_section[section] = flags
for ph in elf.program_headers:
if ph.p_type == pixie.PT_LOAD:
for section in ph.sections:
assert(section.name not in flags_per_section)
flags_per_section[section.name] = ph.p_flags
# Spot-check ELF LOAD program header flags per section
# If these sections exist, check them against the expected R/W/E flags
for (section, flags) in flags_per_section.items():
@ -192,112 +134,72 @@ def check_ELF_separate_code(executable):
return False
return True
def get_PE_dll_characteristics(executable) -> int:
'''Get PE DllCharacteristics bits'''
stdout = run_command([OBJDUMP_CMD, '-x', executable])
bits = 0
for line in stdout.splitlines():
tokens = line.split()
if len(tokens)>=2 and tokens[0] == 'DllCharacteristics':
bits = int(tokens[1],16)
return bits
IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA = 0x0020
IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE = 0x0040
IMAGE_DLL_CHARACTERISTICS_NX_COMPAT = 0x0100
def check_PE_DYNAMIC_BASE(executable) -> bool:
'''PIE: DllCharacteristics bit 0x40 signifies dynamicbase (ASLR)'''
bits = get_PE_dll_characteristics(executable)
return (bits & IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE) == IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE
binary = lief.parse(executable)
return lief.PE.DLL_CHARACTERISTICS.DYNAMIC_BASE in binary.optional_header.dll_characteristics_lists
# Must support high-entropy 64-bit address space layout randomization
# in addition to DYNAMIC_BASE to have secure ASLR.
def check_PE_HIGH_ENTROPY_VA(executable) -> bool:
'''PIE: DllCharacteristics bit 0x20 signifies high-entropy ASLR'''
bits = get_PE_dll_characteristics(executable)
return (bits & IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA) == IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA
binary = lief.parse(executable)
return lief.PE.DLL_CHARACTERISTICS.HIGH_ENTROPY_VA in binary.optional_header.dll_characteristics_lists
def check_PE_RELOC_SECTION(executable) -> bool:
'''Check for a reloc section. This is required for functional ASLR.'''
stdout = run_command([OBJDUMP_CMD, '-h', executable])
for line in stdout.splitlines():
if '.reloc' in line:
return True
return False
def check_PE_NX(executable) -> bool:
'''NX: DllCharacteristics bit 0x100 signifies nxcompat (DEP)'''
bits = get_PE_dll_characteristics(executable)
return (bits & IMAGE_DLL_CHARACTERISTICS_NX_COMPAT) == IMAGE_DLL_CHARACTERISTICS_NX_COMPAT
def get_MACHO_executable_flags(executable) -> List[str]:
stdout = run_command([OTOOL_CMD, '-vh', executable])
flags = []
for line in stdout.splitlines():
tokens = line.split()
# filter first two header lines
if 'magic' in tokens or 'Mach' in tokens:
continue
# filter ncmds and sizeofcmds values
flags += [t for t in tokens if not t.isdigit()]
return flags
def check_MACHO_PIE(executable) -> bool:
'''
Check for position independent executable (PIE), allowing for address space randomization.
'''
flags = get_MACHO_executable_flags(executable)
if 'PIE' in flags:
return True
return False
binary = lief.parse(executable)
return binary.has_relocations
def check_MACHO_NOUNDEFS(executable) -> bool:
'''
Check for no undefined references.
'''
flags = get_MACHO_executable_flags(executable)
if 'NOUNDEFS' in flags:
return True
return False
def check_MACHO_NX(executable) -> bool:
'''
Check for no stack execution
'''
flags = get_MACHO_executable_flags(executable)
if 'ALLOW_STACK_EXECUTION' in flags:
return False
return True
binary = lief.parse(executable)
return binary.header.has(lief.MachO.HEADER_FLAGS.NOUNDEFS)
def check_MACHO_LAZY_BINDINGS(executable) -> bool:
'''
Check for no lazy bindings.
We don't use or check for MH_BINDATLOAD. See #18295.
'''
stdout = run_command([OTOOL_CMD, '-l', executable])
for line in stdout.splitlines():
tokens = line.split()
if 'lazy_bind_off' in tokens or 'lazy_bind_size' in tokens:
if tokens[1] != '0':
return False
return True
binary = lief.parse(executable)
return binary.dyld_info.lazy_bind == (0,0)
def check_MACHO_Canary(executable) -> bool:
'''
Check for use of stack canary
'''
stdout = run_command([OTOOL_CMD, '-Iv', executable])
binary = lief.parse(executable)
return binary.has_symbol('___stack_chk_fail')
def check_PIE(executable) -> bool:
'''
Check for position independent executable (PIE),
allowing for address space randomization.
'''
binary = lief.parse(executable)
return binary.is_pie
def check_NX(executable) -> bool:
'''
Check for no stack execution
'''
binary = lief.parse(executable)
return binary.has_nx
def check_control_flow(executable) -> bool:
'''
Check for control flow instrumentation
'''
binary = lief.parse(executable)
content = binary.get_content_from_virtual_address(binary.entrypoint, 4, lief.Binary.VA_TYPES.AUTO)
if content == [243, 15, 30, 250]: # endbr64
return True
return False
ok = False
for line in stdout.splitlines():
if '___stack_chk_fail' in line:
ok = True
return ok
CHECKS = {
'ELF': [
@ -308,17 +210,19 @@ CHECKS = {
('separate_code', check_ELF_separate_code),
],
'PE': [
('PIE', check_PIE),
('DYNAMIC_BASE', check_PE_DYNAMIC_BASE),
('HIGH_ENTROPY_VA', check_PE_HIGH_ENTROPY_VA),
('NX', check_PE_NX),
('NX', check_NX),
('RELOC_SECTION', check_PE_RELOC_SECTION)
],
'MACHO': [
('PIE', check_MACHO_PIE),
('PIE', check_PIE),
('NOUNDEFS', check_MACHO_NOUNDEFS),
('NX', check_MACHO_NX),
('NX', check_NX),
('LAZY_BINDINGS', check_MACHO_LAZY_BINDINGS),
('Canary', check_MACHO_Canary)
('Canary', check_MACHO_Canary),
('CONTROL_FLOW', check_control_flow),
]
}
@ -334,24 +238,24 @@ def identify_executable(executable) -> Optional[str]:
return None
if __name__ == '__main__':
retval = 0
retval: int = 0
for filename in sys.argv[1:]:
try:
etype = identify_executable(filename)
if etype is None:
print('%s: unknown format' % filename)
print(f'{filename}: unknown format')
retval = 1
continue
failed = []
failed: List[str] = []
for (name, func) in CHECKS[etype]:
if not func(filename):
failed.append(name)
if failed:
print('%s: failed %s' % (filename, ' '.join(failed)))
print(f'{filename}: failed {" ".join(failed)}')
retval = 1
except IOError:
print('%s: cannot open' % filename)
print(f'{filename}: cannot open')
retval = 1
sys.exit(retval)

View file

@ -3,18 +3,21 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
'''
A script to check that the executables produced by gitian only contain
certain symbols and are only linked against allowed libraries.
A script to check that release executables only contain certain symbols
and are only linked against allowed libraries.
Example usage:
find ../gitian-builder/build -type f -executable | xargs python3 contrib/devtools/symbol-check.py
find ../path/to/binaries -type f -executable | xargs python3 contrib/devtools/symbol-check.py
'''
import subprocess
import re
import sys
import os
from typing import List, Optional, Tuple
from typing import List, Optional
import lief
import pixie
from utils import determine_wellknown_cmd
# Debian 8 (Jessie) EOL: 2020. https://wiki.debian.org/DebianReleases#Production_Releases
#
@ -39,8 +42,16 @@ from typing import List, Optional, Tuple
#
MAX_VERSIONS = {
'GCC': (4,8,0),
'GLIBC': (2,17),
'LIBATOMIC': (1,0)
'GLIBC': {
pixie.EM_386: (2,17),
pixie.EM_X86_64: (2,17),
pixie.EM_ARM: (2,17),
pixie.EM_AARCH64:(2,17),
pixie.EM_PPC64: (2,17),
pixie.EM_RISCV: (2,27),
},
'LIBATOMIC': (1,0),
'V': (0,5,0), # xkb (bitcoin-qt only)
}
# See here for a description of _IO_stdin_used:
# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=634261#109
@ -50,10 +61,6 @@ IGNORE_EXPORTS = {
'_edata', '_end', '__end__', '_init', '__bss_start', '__bss_start__', '_bss_end__', '__bss_end__', '_fini', '_IO_stdin_used', 'stdin', 'stdout', 'stderr',
'environ', '_environ', '__environ',
}
READELF_CMD = os.getenv('READELF', '/usr/bin/readelf')
CPPFILT_CMD = os.getenv('CPPFILT', '/usr/bin/c++filt')
OBJDUMP_CMD = os.getenv('OBJDUMP', '/usr/bin/objdump')
OTOOL_CMD = os.getenv('OTOOL', '/usr/bin/otool')
# Allowed NEEDED libraries
ELF_ALLOWED_LIBRARIES = {
@ -68,20 +75,17 @@ ELF_ALLOWED_LIBRARIES = {
'ld-linux.so.2', # 32-bit dynamic linker
'ld-linux-aarch64.so.1', # 64-bit ARM dynamic linker
'ld-linux-armhf.so.3', # 32-bit ARM dynamic linker
'ld64.so.1', # POWER64 ABIv1 dynamic linker
'ld64.so.2', # POWER64 ABIv2 dynamic linker
'ld-linux-riscv64-lp64d.so.1', # 64-bit RISC-V dynamic linker
# bitcoin-qt only
'libxcb.so.1', # part of X11
'libxkbcommon.so.0', # keyboard keymapping
'libxkbcommon-x11.so.0', # keyboard keymapping
'libfontconfig.so.1', # font support
'libfreetype.so.6', # font parsing
'libdl.so.2' # programming interface to dynamic linker
}
ARCH_MIN_GLIBC_VER = {
'80386': (2,1),
'X86-64': (2,2,5),
'ARM': (2,4),
'AArch64':(2,17),
'RISC-V': (2,27)
}
MACHO_ALLOWED_LIBRARIES = {
# bitcoind and bitcoin-qt
@ -95,10 +99,15 @@ MACHO_ALLOWED_LIBRARIES = {
'CoreGraphics', # 2D rendering
'CoreServices', # operating system services
'CoreText', # interface for laying out text and handling fonts.
'CoreVideo', # video processing
'Foundation', # base layer functionality for apps/frameworks
'ImageIO', # read and write image file formats.
'IOKit', # user-space access to hardware devices and drivers.
'IOSurface', # cross process image/drawing buffers
'libobjc.A.dylib', # Objective-C runtime library
'Metal', # 3D graphics
'Security', # access control and authentication
'QuartzCore', # animation
}
PE_ALLOWED_LIBRARIES = {
@ -113,12 +122,15 @@ PE_ALLOWED_LIBRARIES = {
'dwmapi.dll', # desktop window manager
'GDI32.dll', # graphics device interface
'IMM32.dll', # input method editor
'NETAPI32.dll',
'ole32.dll', # component object model
'OLEAUT32.dll', # OLE Automation API
'SHLWAPI.dll', # light weight shell API
'USERENV.dll',
'UxTheme.dll',
'VERSION.dll', # version checking
'WINMM.dll', # WinMM audio API
'WTSAPI32.dll',
}
class CPPFilt(object):
@ -128,7 +140,7 @@ class CPPFilt(object):
Use a pipe to the 'c++filt' command.
'''
def __init__(self):
self.proc = subprocess.Popen(CPPFILT_CMD, stdin=subprocess.PIPE, stdout=subprocess.PIPE, universal_newlines=True)
self.proc = subprocess.Popen(determine_wellknown_cmd('CPPFILT', 'c++filt'), stdin=subprocess.PIPE, stdout=subprocess.PIPE, universal_newlines=True)
def __call__(self, mangled):
self.proc.stdin.write(mangled + '\n')
@ -140,29 +152,6 @@ class CPPFilt(object):
self.proc.stdout.close()
self.proc.wait()
def read_symbols(executable, imports=True) -> List[Tuple[str, str, str]]:
'''
Parse an ELF executable and return a list of (symbol,version, arch) tuples
for dynamic, imported symbols.
'''
p = subprocess.Popen([READELF_CMD, '--dyn-syms', '-W', '-h', executable], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, universal_newlines=True)
(stdout, stderr) = p.communicate()
if p.returncode:
raise IOError('Could not read symbols for {}: {}'.format(executable, stderr.strip()))
syms = []
for line in stdout.splitlines():
line = line.split()
if 'Machine:' in line:
arch = line[-1]
if len(line)>7 and re.match('[0-9]+:$', line[0]):
(sym, _, version) = line[7].partition('@')
is_import = line[6] == 'UND'
if version.startswith('@'):
version = version[1:]
if is_import == imports:
syms.append((sym, version, arch))
return syms
def check_version(max_versions, version, arch) -> bool:
if '_' in version:
(lib, _, ver) = version.rpartition('_')
@ -172,92 +161,89 @@ def check_version(max_versions, version, arch) -> bool:
ver = tuple([int(x) for x in ver.split('.')])
if not lib in max_versions:
return False
return ver <= max_versions[lib] or lib == 'GLIBC' and ver <= ARCH_MIN_GLIBC_VER[arch]
def elf_read_libraries(filename) -> List[str]:
p = subprocess.Popen([READELF_CMD, '-d', '-W', filename], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, universal_newlines=True)
(stdout, stderr) = p.communicate()
if p.returncode:
raise IOError('Error opening file')
libraries = []
for line in stdout.splitlines():
tokens = line.split()
if len(tokens)>2 and tokens[1] == '(NEEDED)':
match = re.match(r'^Shared library: \[(.*)\]$', ' '.join(tokens[2:]))
if match:
libraries.append(match.group(1))
else:
raise ValueError('Unparseable (NEEDED) specification')
return libraries
if isinstance(max_versions[lib], tuple):
return ver <= max_versions[lib]
else:
return ver <= max_versions[lib][arch]
def check_imported_symbols(filename) -> bool:
elf = pixie.load(filename)
cppfilt = CPPFilt()
ok = True
for sym, version, arch in read_symbols(filename, True):
if version and not check_version(MAX_VERSIONS, version, arch):
ok: bool = True
for symbol in elf.dyn_symbols:
if not symbol.is_import:
continue
sym = symbol.name.decode()
version = symbol.version.decode() if symbol.version is not None else None
if version and not check_version(MAX_VERSIONS, version, elf.hdr.e_machine):
print('{}: symbol {} from unsupported version {}'.format(filename, cppfilt(sym), version))
ok = False
return ok
def check_exported_symbols(filename) -> bool:
elf = pixie.load(filename)
cppfilt = CPPFilt()
ok = True
for sym,version,arch in read_symbols(filename, False):
if arch == 'RISC-V' or sym in IGNORE_EXPORTS:
ok: bool = True
for symbol in elf.dyn_symbols:
if not symbol.is_export:
continue
sym = symbol.name.decode()
if elf.hdr.e_machine == pixie.EM_RISCV or sym in IGNORE_EXPORTS:
continue
print('{}: export of symbol {} not allowed'.format(filename, cppfilt(sym)))
ok = False
return ok
def check_ELF_libraries(filename) -> bool:
ok = True
for library_name in elf_read_libraries(filename):
if library_name not in ELF_ALLOWED_LIBRARIES:
print('{}: NEEDED library {} is not allowed'.format(filename, library_name))
ok: bool = True
elf = pixie.load(filename)
for library_name in elf.query_dyn_tags(pixie.DT_NEEDED):
assert(isinstance(library_name, bytes))
if library_name.decode() not in ELF_ALLOWED_LIBRARIES:
print('{}: NEEDED library {} is not allowed'.format(filename, library_name.decode()))
ok = False
return ok
def macho_read_libraries(filename) -> List[str]:
p = subprocess.Popen([OTOOL_CMD, '-L', filename], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, universal_newlines=True)
(stdout, stderr) = p.communicate()
if p.returncode:
raise IOError('Error opening file')
libraries = []
for line in stdout.splitlines():
tokens = line.split()
if len(tokens) == 1: # skip executable name
continue
libraries.append(tokens[0].split('/')[-1])
return libraries
def check_MACHO_libraries(filename) -> bool:
ok = True
for dylib in macho_read_libraries(filename):
if dylib not in MACHO_ALLOWED_LIBRARIES:
print('{} is not in ALLOWED_LIBRARIES!'.format(dylib))
ok: bool = True
binary = lief.parse(filename)
for dylib in binary.libraries:
split = dylib.name.split('/')
if split[-1] not in MACHO_ALLOWED_LIBRARIES:
print(f'{split[-1]} is not in ALLOWED_LIBRARIES!')
ok = False
return ok
def pe_read_libraries(filename) -> List[str]:
p = subprocess.Popen([OBJDUMP_CMD, '-x', filename], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, universal_newlines=True)
(stdout, stderr) = p.communicate()
if p.returncode:
raise IOError('Error opening file')
libraries = []
for line in stdout.splitlines():
if 'DLL Name:' in line:
tokens = line.split(': ')
libraries.append(tokens[1])
return libraries
def check_MACHO_min_os(filename) -> bool:
binary = lief.parse(filename)
if binary.build_version.minos == [10,14,0]:
return True
return False
def check_MACHO_sdk(filename) -> bool:
binary = lief.parse(filename)
if binary.build_version.sdk == [10, 15, 6]:
return True
return False
def check_PE_libraries(filename) -> bool:
ok = True
for dylib in pe_read_libraries(filename):
ok: bool = True
binary = lief.parse(filename)
for dylib in binary.libraries:
if dylib not in PE_ALLOWED_LIBRARIES:
print('{} is not in ALLOWED_LIBRARIES!'.format(dylib))
print(f'{dylib} is not in ALLOWED_LIBRARIES!')
ok = False
return ok
def check_PE_subsystem_version(filename) -> bool:
binary = lief.parse(filename)
major: int = binary.optional_header.major_subsystem_version
minor: int = binary.optional_header.minor_subsystem_version
if major == 6 and minor == 1:
return True
return False
CHECKS = {
'ELF': [
('IMPORTED_SYMBOLS', check_imported_symbols),
@ -265,10 +251,13 @@ CHECKS = {
('LIBRARY_DEPENDENCIES', check_ELF_libraries)
],
'MACHO': [
('DYNAMIC_LIBRARIES', check_MACHO_libraries)
('DYNAMIC_LIBRARIES', check_MACHO_libraries),
('MIN_OS', check_MACHO_min_os),
('SDK', check_MACHO_sdk),
],
'PE' : [
('DYNAMIC_LIBRARIES', check_PE_libraries)
('DYNAMIC_LIBRARIES', check_PE_libraries),
('SUBSYSTEM_VERSION', check_PE_subsystem_version),
]
}
@ -284,23 +273,23 @@ def identify_executable(executable) -> Optional[str]:
return None
if __name__ == '__main__':
retval = 0
retval: int = 0
for filename in sys.argv[1:]:
try:
etype = identify_executable(filename)
if etype is None:
print('{}: unknown format'.format(filename))
print(f'{filename}: unknown format')
retval = 1
continue
failed = []
failed: List[str] = []
for (name, func) in CHECKS[etype]:
if not func(filename):
failed.append(name)
if failed:
print('{}: failed {}'.format(filename, ' '.join(failed)))
print(f'{filename}: failed {" ".join(failed)}')
retval = 1
except IOError:
print('{}: cannot open'.format(filename))
print(f'{filename}: cannot open')
retval = 1
sys.exit(retval)

View file

@ -5,9 +5,12 @@
'''
Test script for security-check.py
'''
import os
import subprocess
import unittest
from utils import determine_wellknown_cmd
def write_testcode(filename):
with open(filename, 'w', encoding="utf8") as f:
f.write('''
@ -19,8 +22,12 @@ def write_testcode(filename):
}
''')
def clean_files(source, executable):
os.remove(source)
os.remove(executable)
def call_security_check(cc, source, executable, options):
subprocess.run([cc,source,'-o',executable] + options, check=True)
subprocess.run([*cc,source,'-o',executable] + options, check=True)
p = subprocess.run(['./contrib/devtools/security-check.py',executable], stdout=subprocess.PIPE, universal_newlines=True)
return (p.returncode, p.stdout.rstrip())
@ -28,7 +35,7 @@ class TestSecurityChecks(unittest.TestCase):
def test_ELF(self):
source = 'test1.c'
executable = 'test1'
cc = 'gcc'
cc = determine_wellknown_cmd('CC', 'gcc')
write_testcode(source)
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-zexecstack','-fno-stack-protector','-Wl,-znorelro','-no-pie','-fno-PIE', '-Wl,-z,separate-code']),
@ -44,42 +51,51 @@ class TestSecurityChecks(unittest.TestCase):
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fstack-protector-all','-Wl,-zrelro','-Wl,-z,now','-pie','-fPIE', '-Wl,-z,separate-code']),
(0, ''))
clean_files(source, executable)
def test_PE(self):
source = 'test1.c'
executable = 'test1.exe'
cc = 'x86_64-w64-mingw32-gcc'
cc = determine_wellknown_cmd('CC', 'x86_64-w64-mingw32-gcc')
write_testcode(source)
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--no-nxcompat','-Wl,--no-dynamicbase','-Wl,--no-high-entropy-va','-no-pie','-fno-PIE']),
(1, executable+': failed DYNAMIC_BASE HIGH_ENTROPY_VA NX RELOC_SECTION'))
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat','-Wl,--no-dynamicbase','-Wl,--no-high-entropy-va','-no-pie','-fno-PIE']),
(1, executable+': failed DYNAMIC_BASE HIGH_ENTROPY_VA RELOC_SECTION'))
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat','-Wl,--dynamicbase','-Wl,--no-high-entropy-va','-no-pie','-fno-PIE']),
(1, executable+': failed HIGH_ENTROPY_VA RELOC_SECTION'))
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat','-Wl,--dynamicbase','-Wl,--high-entropy-va','-no-pie','-fno-PIE']),
(1, executable+': failed RELOC_SECTION'))
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat','-Wl,--dynamicbase','-Wl,--high-entropy-va','-pie','-fPIE']),
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--no-nxcompat','-Wl,--disable-reloc-section','-Wl,--no-dynamicbase','-Wl,--no-high-entropy-va','-no-pie','-fno-PIE']),
(1, executable+': failed PIE DYNAMIC_BASE HIGH_ENTROPY_VA NX RELOC_SECTION'))
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat','-Wl,--disable-reloc-section','-Wl,--no-dynamicbase','-Wl,--no-high-entropy-va','-no-pie','-fno-PIE']),
(1, executable+': failed PIE DYNAMIC_BASE HIGH_ENTROPY_VA RELOC_SECTION'))
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat','-Wl,--enable-reloc-section','-Wl,--no-dynamicbase','-Wl,--no-high-entropy-va','-no-pie','-fno-PIE']),
(1, executable+': failed PIE DYNAMIC_BASE HIGH_ENTROPY_VA'))
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat','-Wl,--enable-reloc-section','-Wl,--no-dynamicbase','-Wl,--no-high-entropy-va','-pie','-fPIE']),
(1, executable+': failed PIE DYNAMIC_BASE HIGH_ENTROPY_VA')) # -pie -fPIE does nothing unless --dynamicbase is also supplied
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat','-Wl,--enable-reloc-section','-Wl,--dynamicbase','-Wl,--no-high-entropy-va','-pie','-fPIE']),
(1, executable+': failed HIGH_ENTROPY_VA'))
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat','-Wl,--enable-reloc-section','-Wl,--dynamicbase','-Wl,--high-entropy-va','-pie','-fPIE']),
(0, ''))
clean_files(source, executable)
def test_MACHO(self):
source = 'test1.c'
executable = 'test1'
cc = 'clang'
cc = determine_wellknown_cmd('CC', 'clang')
write_testcode(source)
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-no_pie','-Wl,-flat_namespace','-Wl,-allow_stack_execute','-fno-stack-protector']),
(1, executable+': failed PIE NOUNDEFS NX LAZY_BINDINGS Canary'))
(1, executable+': failed PIE NOUNDEFS NX LAZY_BINDINGS Canary CONTROL_FLOW'))
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-no_pie','-Wl,-flat_namespace','-Wl,-allow_stack_execute','-fstack-protector-all']),
(1, executable+': failed PIE NOUNDEFS NX LAZY_BINDINGS'))
(1, executable+': failed PIE NOUNDEFS NX LAZY_BINDINGS CONTROL_FLOW'))
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-no_pie','-Wl,-flat_namespace','-fstack-protector-all']),
(1, executable+': failed PIE NOUNDEFS LAZY_BINDINGS'))
(1, executable+': failed PIE NOUNDEFS LAZY_BINDINGS CONTROL_FLOW'))
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-no_pie','-fstack-protector-all']),
(1, executable+': failed PIE LAZY_BINDINGS'))
(1, executable+': failed PIE LAZY_BINDINGS CONTROL_FLOW'))
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-no_pie','-Wl,-bind_at_load','-fstack-protector-all']),
(1, executable+': failed PIE CONTROL_FLOW'))
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-no_pie','-Wl,-bind_at_load','-fstack-protector-all', '-fcf-protection=full']),
(1, executable+': failed PIE'))
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-pie','-Wl,-bind_at_load','-fstack-protector-all']),
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-pie','-Wl,-bind_at_load','-fstack-protector-all', '-fcf-protection=full']),
(0, ''))
clean_files(source, executable)
if __name__ == '__main__':
unittest.main()

View file

@ -0,0 +1,194 @@
#!/usr/bin/env python3
# Copyright (c) 2020 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
'''
Test script for symbol-check.py
'''
import os
import subprocess
from typing import List
import unittest
from utils import determine_wellknown_cmd
def call_symbol_check(cc: List[str], source, executable, options):
subprocess.run([*cc,source,'-o',executable] + options, check=True)
p = subprocess.run(['./contrib/devtools/symbol-check.py',executable], stdout=subprocess.PIPE, universal_newlines=True)
os.remove(source)
os.remove(executable)
return (p.returncode, p.stdout.rstrip())
def get_machine(cc: List[str]):
p = subprocess.run([*cc,'-dumpmachine'], stdout=subprocess.PIPE, universal_newlines=True)
return p.stdout.rstrip()
class TestSymbolChecks(unittest.TestCase):
def test_ELF(self):
source = 'test1.c'
executable = 'test1'
cc = determine_wellknown_cmd('CC', 'gcc')
# there's no way to do this test for RISC-V at the moment; we build for
# RISC-V in a glibc 2.27 envinonment and we allow all symbols from 2.27.
if 'riscv' in get_machine(cc):
self.skipTest("test not available for RISC-V")
# nextup was introduced in GLIBC 2.24, so is newer than our supported
# glibc (2.17), and available in our release build environment (2.24).
with open(source, 'w', encoding="utf8") as f:
f.write('''
#define _GNU_SOURCE
#include <math.h>
double nextup(double x);
int main()
{
nextup(3.14);
return 0;
}
''')
self.assertEqual(call_symbol_check(cc, source, executable, ['-lm']),
(1, executable + ': symbol nextup from unsupported version GLIBC_2.24\n' +
executable + ': failed IMPORTED_SYMBOLS'))
# -lutil is part of the libc6 package so a safe bet that it's installed
# it's also out of context enough that it's unlikely to ever become a real dependency
source = 'test2.c'
executable = 'test2'
with open(source, 'w', encoding="utf8") as f:
f.write('''
#include <utmp.h>
int main()
{
login(0);
return 0;
}
''')
self.assertEqual(call_symbol_check(cc, source, executable, ['-lutil']),
(1, executable + ': NEEDED library libutil.so.1 is not allowed\n' +
executable + ': failed LIBRARY_DEPENDENCIES'))
# finally, check a conforming file that simply uses a math function
source = 'test3.c'
executable = 'test3'
with open(source, 'w', encoding="utf8") as f:
f.write('''
#include <math.h>
int main()
{
return (int)pow(2.0, 4.0);
}
''')
self.assertEqual(call_symbol_check(cc, source, executable, ['-lm']),
(0, ''))
def test_MACHO(self):
source = 'test1.c'
executable = 'test1'
cc = determine_wellknown_cmd('CC', 'clang')
with open(source, 'w', encoding="utf8") as f:
f.write('''
#include <expat.h>
int main()
{
XML_ExpatVersion();
return 0;
}
''')
self.assertEqual(call_symbol_check(cc, source, executable, ['-lexpat', '-Wl,-platform_version','-Wl,macos', '-Wl,11.4', '-Wl,11.4']),
(1, 'libexpat.1.dylib is not in ALLOWED_LIBRARIES!\n' +
f'{executable}: failed DYNAMIC_LIBRARIES MIN_OS SDK'))
source = 'test2.c'
executable = 'test2'
with open(source, 'w', encoding="utf8") as f:
f.write('''
#include <CoreGraphics/CoreGraphics.h>
int main()
{
CGMainDisplayID();
return 0;
}
''')
self.assertEqual(call_symbol_check(cc, source, executable, ['-framework', 'CoreGraphics', '-Wl,-platform_version','-Wl,macos', '-Wl,11.4', '-Wl,11.4']),
(1, f'{executable}: failed MIN_OS SDK'))
source = 'test3.c'
executable = 'test3'
with open(source, 'w', encoding="utf8") as f:
f.write('''
int main()
{
return 0;
}
''')
self.assertEqual(call_symbol_check(cc, source, executable, ['-Wl,-platform_version','-Wl,macos', '-Wl,10.14', '-Wl,11.4']),
(1, f'{executable}: failed SDK'))
def test_PE(self):
source = 'test1.c'
executable = 'test1.exe'
cc = determine_wellknown_cmd('CC', 'x86_64-w64-mingw32-gcc')
with open(source, 'w', encoding="utf8") as f:
f.write('''
#include <pdh.h>
int main()
{
PdhConnectMachineA(NULL);
return 0;
}
''')
self.assertEqual(call_symbol_check(cc, source, executable, ['-lpdh', '-Wl,--major-subsystem-version', '-Wl,6', '-Wl,--minor-subsystem-version', '-Wl,1']),
(1, 'pdh.dll is not in ALLOWED_LIBRARIES!\n' +
executable + ': failed DYNAMIC_LIBRARIES'))
source = 'test2.c'
executable = 'test2.exe'
with open(source, 'w', encoding="utf8") as f:
f.write('''
int main()
{
return 0;
}
''')
self.assertEqual(call_symbol_check(cc, source, executable, ['-Wl,--major-subsystem-version', '-Wl,9', '-Wl,--minor-subsystem-version', '-Wl,9']),
(1, executable + ': failed SUBSYSTEM_VERSION'))
source = 'test3.c'
executable = 'test3.exe'
with open(source, 'w', encoding="utf8") as f:
f.write('''
#include <windows.h>
int main()
{
CoFreeUnusedLibrariesEx(0,0);
return 0;
}
''')
self.assertEqual(call_symbol_check(cc, source, executable, ['-lole32', '-Wl,--major-subsystem-version', '-Wl,6', '-Wl,--minor-subsystem-version', '-Wl,1']),
(0, ''))
if __name__ == '__main__':
unittest.main()

22
contrib/devtools/utils.py Executable file
View file

@ -0,0 +1,22 @@
#!/usr/bin/env python3
# Copyright (c) 2021 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
'''
Common utility functions
'''
import shutil
import sys
import os
from typing import List
def determine_wellknown_cmd(envvar, progname) -> List[str]:
maybe_env = os.getenv(envvar)
maybe_which = shutil.which(progname)
if maybe_env:
return maybe_env.split(' ') # Well-known vars are often meant to be word-split
elif maybe_which:
return [ maybe_which ]
else:
sys.exit(f"{progname} not found")

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# Copyright (c) 2017-2019 The Bitcoin Core developers
# Copyright (c) 2017-2020 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# Copyright (c) 2018-2019 The Bitcoin Core developers
# Copyright (c) 2018-2020 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
@ -13,15 +13,16 @@ def setup():
programs = ['ruby', 'git', 'make', 'wget', 'curl']
if args.kvm:
programs += ['apt-cacher-ng', 'python-vm-builder', 'qemu-kvm', 'qemu-utils']
elif args.docker and not os.path.isfile('/lib/systemd/system/docker.service'):
dockers = ['docker.io', 'docker-ce']
for i in dockers:
return_code = subprocess.call(['sudo', 'apt-get', 'install', '-qq', i])
if return_code == 0:
break
if return_code != 0:
print('Cannot find any way to install Docker.', file=sys.stderr)
sys.exit(1)
elif args.docker:
if not os.path.isfile('/lib/systemd/system/docker.service'):
dockers = ['docker.io', 'docker-ce']
for i in dockers:
return_code = subprocess.call(['sudo', 'apt-get', 'install', '-qq', i])
if return_code == 0:
break
if return_code != 0:
print('Cannot find any way to install Docker.', file=sys.stderr)
sys.exit(1)
else:
programs += ['apt-cacher-ng', 'lxc', 'debootstrap']
subprocess.check_call(['sudo', 'apt-get', 'install', '-qq'] + programs)
@ -34,14 +35,14 @@ def setup():
if not os.path.isdir('bitcoin'):
subprocess.check_call(['git', 'clone', 'https://github.com/bitcoin/bitcoin.git'])
os.chdir('gitian-builder')
make_image_prog = ['bin/make-base-vm', '--suite', 'bionic', '--arch', 'amd64']
make_image_prog = ['bin/make-base-vm', '--suite', 'focal', '--arch', 'amd64']
if args.docker:
make_image_prog += ['--docker']
elif not args.kvm:
make_image_prog += ['--lxc']
make_image_prog += ['--lxc', '--disksize', '13000']
subprocess.check_call(make_image_prog)
os.chdir(workdir)
if args.is_bionic and not args.kvm and not args.docker:
if args.is_focal and not args.kvm and not args.docker:
subprocess.check_call(['sudo', 'sed', '-i', 's/lxcbr0/br0/', '/etc/default/lxc-net'])
print('Reboot is required')
sys.exit(0)
@ -175,7 +176,7 @@ def main():
args = parser.parse_args()
workdir = os.getcwd()
args.is_bionic = b'bionic' in subprocess.check_output(['lsb_release', '-cs'])
args.is_focal = b'focal' in subprocess.check_output(['lsb_release', '-cs'])
if args.kvm and args.docker:
raise Exception('Error: cannot have both kvm and docker')
@ -209,7 +210,7 @@ def main():
args.macos = 'm' in args.os
# Disable for MacOS if no SDK found
if args.macos and not os.path.isfile('gitian-builder/inputs/Xcode-11.3.1-11C505-extracted-SDK-with-libcxx-headers.tar.gz'):
if args.macos and not os.path.isfile('gitian-builder/inputs/Xcode-12.1-12A7403-extracted-SDK-with-libcxx-headers.tar.gz'):
print('Cannot build for MacOS, SDK does not exist. Will build for other OSes')
args.macos = False

2
contrib/gitian-descriptors/assign_DISTNAME Executable file → Normal file
View file

@ -4,7 +4,7 @@
#
# A helper script to be sourced into the gitian descriptors
if RECENT_TAG="$(git describe --exact-match HEAD)"; then
if RECENT_TAG="$(git describe --exact-match HEAD 2> /dev/null)"; then
VERSION="${RECENT_TAG#v}"
else
VERSION="$(git rev-parse --short=12 HEAD)"

View file

@ -1,9 +1,9 @@
---
name: "elements-linux-0.21"
name: "elements-linux-22"
enable_cache: true
distro: "ubuntu"
suites:
- "bionic"
- "focal"
architectures:
- "amd64"
packages:
@ -11,15 +11,19 @@ packages:
- "autoconf"
- "automake"
- "binutils"
- "bison"
- "bsdmainutils"
- "ca-certificates"
- "curl"
- "faketime"
- "g++-8"
- "gcc-8"
- "git"
- "libtool"
- "patch"
- "pkg-config"
- "python3"
- "python3-pip"
# Cross compilation HOSTS:
# - arm-linux-gnueabihf
- "binutils-arm-linux-gnueabihf"
@ -27,6 +31,12 @@ packages:
# - aarch64-linux-gnu
- "binutils-aarch64-linux-gnu"
- "g++-8-aarch64-linux-gnu"
# - powerpc64-linux-gnu
- "binutils-powerpc64-linux-gnu"
- "g++-8-powerpc64-linux-gnu"
# - powerpc64le-linux-gnu
- "binutils-powerpc64le-linux-gnu"
- "g++-8-powerpc64le-linux-gnu"
# - riscv64-linux-gnu
- "binutils-riscv64-linux-gnu"
- "g++-8-riscv64-linux-gnu"
@ -43,16 +53,14 @@ script: |
set -e -o pipefail
WRAP_DIR=$HOME/wrapped
HOSTS="x86_64-linux-gnu arm-linux-gnueabihf aarch64-linux-gnu riscv64-linux-gnu"
CONFIGFLAGS="--enable-glibc-back-compat --enable-reduce-exports --disable-bench --disable-gui-tests"
HOSTS="x86_64-linux-gnu arm-linux-gnueabihf aarch64-linux-gnu powerpc64-linux-gnu powerpc64le-linux-gnu riscv64-linux-gnu"
CONFIGFLAGS="--enable-glibc-back-compat --enable-reduce-exports --disable-bench --disable-gui-tests --disable-fuzz-binary"
FAKETIME_HOST_PROGS="gcc g++"
FAKETIME_PROGS="date ar ranlib nm"
HOST_CFLAGS="-O2 -g"
HOST_CXXFLAGS="-O2 -g"
HOST_LDFLAGS_BASE="-static-libstdc++ -Wl,-O2"
export QT_RCC_TEST=1
export QT_RCC_SOURCE_DATE_OVERRIDE=1
export TZ="UTC"
export BUILD_DIR="$PWD"
mkdir -p ${WRAP_DIR}
@ -69,7 +77,7 @@ script: |
echo "REAL=\`which -a ${prog} | grep -v ${WRAP_DIR}/${prog} | head -1\`" >> ${WRAP_DIR}/${prog}
echo "export LD_PRELOAD='/usr/\$LIB/faketime/libfaketime.so.1'" >> ${WRAP_DIR}/${prog}
echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${prog}
echo "\$REAL \$@" >> $WRAP_DIR/${prog}
echo "exec \"\$REAL\" \"\$@\"" >> $WRAP_DIR/${prog}
chmod +x ${WRAP_DIR}/${prog}
done
}
@ -83,13 +91,21 @@ script: |
echo "REAL=\`which -a ${i}-${prog}-8 | grep -v ${WRAP_DIR}/${i}-${prog} | head -1\`" >> ${WRAP_DIR}/${i}-${prog}
echo "export LD_PRELOAD='/usr/\$LIB/faketime/libfaketime.so.1'" >> ${WRAP_DIR}/${i}-${prog}
echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${i}-${prog}
echo "\$REAL \"\$@\"" >> $WRAP_DIR/${i}-${prog}
if [ "${i:0:11}" = "powerpc64le" ]; then
echo "exec \"\$REAL\" -mcpu=power8 -mtune=power9 \"\$@\"" >> $WRAP_DIR/${i}-${prog}
elif [ "${i:0:9}" = "powerpc64" ]; then
echo "exec \"\$REAL\" -mcpu=970 -mtune=power9 \"\$@\"" >> $WRAP_DIR/${i}-${prog}
else
echo "exec \"\$REAL\" \"\$@\"" >> $WRAP_DIR/${i}-${prog}
fi
chmod +x ${WRAP_DIR}/${i}-${prog}
fi
done
done
}
pip3 install lief==0.11.5
# Faketime for depends so intermediate results are comparable
export PATH_orig=${PATH}
create_global_faketime_wrappers "2000-01-01 12:00:00"
@ -100,7 +116,7 @@ script: |
BASEPREFIX="${PWD}/depends"
# Build dependencies for each host
for i in $HOSTS; do
make ${MAKEOPTS} -C ${BASEPREFIX} HOST="${i}"
make ${MAKEOPTS} -C ${BASEPREFIX} HOST="${i}" CC=${i}-gcc-8 CXX=${i}-g++-8
done
# Faketime for binaries
@ -123,7 +139,7 @@ script: |
# Extract the git archive into a dir for each host and build
for i in ${HOSTS}; do
export PATH=${BASEPREFIX}/${i}/native/bin:${ORIGPATH}
if [ "${i}" = "riscv64-linux-gnu" ]; then
if [ "${i}" = "powerpc64-linux-gnu" ]; then
# Workaround for https://bugs.launchpad.net/ubuntu/+source/gcc-8-cross-ports/+bug/1853740
# TODO: remove this when no longer needed
HOST_LDFLAGS="${HOST_LDFLAGS_BASE} -Wl,-z,noexecstack"
@ -137,7 +153,7 @@ script: |
tar --strip-components=1 -xf "${GIT_ARCHIVE}"
./autogen.sh
CONFIG_SITE=${BASEPREFIX}/${i}/share/config.site ./configure --prefix=/ --disable-ccache --disable-maintainer-mode --disable-dependency-tracking ${CONFIGFLAGS} CFLAGS="${HOST_CFLAGS}" CXXFLAGS="${HOST_CXXFLAGS}" LDFLAGS="${HOST_LDFLAGS}"
CONFIG_SITE=${BASEPREFIX}/${i}/share/config.site ./configure --prefix=/ --disable-ccache --disable-maintainer-mode --disable-dependency-tracking ${CONFIGFLAGS} CFLAGS="${HOST_CFLAGS}" CXXFLAGS="${HOST_CXXFLAGS}" LDFLAGS="${HOST_LDFLAGS}" CC=${i}-gcc-8 CXX=${i}-g++-8
make ${MAKEOPTS}
make ${MAKEOPTS} -C src check-security
make ${MAKEOPTS} -C src check-symbols

View file

@ -2,14 +2,19 @@
name: "bitcoin-dmg-signer"
distro: "ubuntu"
suites:
- "bionic"
- "focal"
architectures:
- "amd64"
packages:
- "faketime"
- "xorriso"
- "python3-pip"
remotes:
- "url": "https://github.com/bitcoin-core/bitcoin-detached-sigs.git"
"dir": "signature"
- "url": "https://github.com/achow101/signapple.git"
"dir": "signapple"
"commit": "b084cbbf44d5330448ffce0c7d118f75781b64bd"
files:
- "bitcoin-osx-unsigned.tar.gz"
script: |
@ -18,7 +23,7 @@ script: |
WRAP_DIR=$HOME/wrapped
mkdir -p ${WRAP_DIR}
export PATH="$PWD":$PATH
FAKETIME_PROGS="dmg genisoimage"
FAKETIME_PROGS="dmg xorrisofs"
# Create global faketime wrappers
for prog in ${FAKETIME_PROGS}; do
@ -26,15 +31,23 @@ script: |
echo "REAL=\`which -a ${prog} | grep -v ${WRAP_DIR}/${prog} | head -1\`" >> ${WRAP_DIR}/${prog}
echo "export LD_PRELOAD='/usr/\$LIB/faketime/libfaketime.so.1'" >> ${WRAP_DIR}/${prog}
echo "export FAKETIME=\"${REFERENCE_DATETIME}\"" >> ${WRAP_DIR}/${prog}
echo "\$REAL \$@" >> $WRAP_DIR/${prog}
echo "exec \"\$REAL\" \"\$@\"" >> $WRAP_DIR/${prog}
chmod +x ${WRAP_DIR}/${prog}
done
UNSIGNED=bitcoin-osx-unsigned.tar.gz
# Install signapple
cd signapple
python3 -m pip install -U pip setuptools
python3 -m pip install .
export PATH="$HOME/.local/bin":$PATH
cd ..
UNSIGNED_TARBALL=bitcoin-osx-unsigned.tar.gz
UNSIGNED_APP=dist/Bitcoin-Qt.app
SIGNED=bitcoin-osx-signed.dmg
tar -xf ${UNSIGNED}
tar -xf ${UNSIGNED_TARBALL}
OSX_VOLNAME="$(cat osx_volname)"
./detached-sig-apply.sh ${UNSIGNED} signature/osx
${WRAP_DIR}/genisoimage -no-cache-inodes -D -l -probe -V "${OSX_VOLNAME}" -no-pad -r -dir-mode 0755 -apple -o uncompressed.dmg signed-app
./detached-sig-apply.sh ${UNSIGNED_APP} signature/osx/dist
${WRAP_DIR}/xorrisofs -D -l -V "${OSX_VOLNAME}" -no-pad -r -dir-mode 0755 -o uncompressed.dmg signed-app
${WRAP_DIR}/dmg dmg uncompressed.dmg ${OUTDIR}/${SIGNED}

View file

@ -1,9 +1,9 @@
---
name: "elements-osx-0.21"
name: "elements-osx-22"
enable_cache: true
distro: "ubuntu"
suites:
- "bionic"
- "focal"
architectures:
- "amd64"
packages:
@ -23,29 +23,27 @@ packages:
- "bsdmainutils"
- "cmake"
- "imagemagick"
- "libcap-dev"
- "libz-dev"
- "libbz2-dev"
- "python3"
- "python3-dev"
- "python3-pip"
- "python3-setuptools"
- "fonts-tuffy"
- "xorriso"
- "libtinfo5"
remotes:
- "url": "https://github.com/ElementsProject/elements.git"
"dir": "elements"
files:
- "Xcode-11.3.1-11C505-extracted-SDK-with-libcxx-headers.tar.gz"
- "Xcode-12.1-12A7403-extracted-SDK-with-libcxx-headers.tar.gz"
script: |
set -e -o pipefail
WRAP_DIR=$HOME/wrapped
HOSTS="x86_64-apple-darwin18"
CONFIGFLAGS="--enable-reduce-exports --disable-bench --disable-gui-tests GENISOIMAGE=$WRAP_DIR/genisoimage"
CONFIGFLAGS="--enable-reduce-exports --disable-bench --disable-gui-tests --disable-fuzz-binary XORRISOFS=${WRAP_DIR}/xorrisofs DMG=${WRAP_DIR}/dmg"
FAKETIME_HOST_PROGS=""
FAKETIME_PROGS="ar ranlib date dmg genisoimage"
FAKETIME_PROGS="ar ranlib date dmg xorrisofs"
export QT_RCC_TEST=1
export QT_RCC_SOURCE_DATE_OVERRIDE=1
export TZ="UTC"
export BUILD_DIR="$PWD"
mkdir -p ${WRAP_DIR}
@ -64,7 +62,7 @@ script: |
echo "REAL=\`which -a ${prog} | grep -v ${WRAP_DIR}/${prog} | head -1\`" >> ${WRAP_DIR}/${prog}
echo "export LD_PRELOAD='/usr/\$LIB/faketime/libfaketime.so.1'" >> ${WRAP_DIR}/${prog}
echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${prog}
echo "\$REAL \$@" >> $WRAP_DIR/${prog}
echo "exec \"\$REAL\" \"\$@\"" >> $WRAP_DIR/${prog}
chmod +x ${WRAP_DIR}/${prog}
done
}
@ -76,12 +74,14 @@ script: |
echo "REAL=\`which -a ${i}-${prog} | grep -v ${WRAP_DIR}/${i}-${prog} | head -1\`" >> ${WRAP_DIR}/${i}-${prog}
echo "export LD_PRELOAD='/usr/\$LIB/faketime/libfaketime.so.1'" >> ${WRAP_DIR}/${i}-${prog}
echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${i}-${prog}
echo "\$REAL \$@" >> $WRAP_DIR/${i}-${prog}
echo "exec \"\$REAL\" \"\$@\"" >> $WRAP_DIR/${i}-${prog}
chmod +x ${WRAP_DIR}/${i}-${prog}
done
done
}
pip3 install lief==0.11.5
# Faketime for depends so intermediate results are comparable
export PATH_orig=${PATH}
create_global_faketime_wrappers "2000-01-01 12:00:00"
@ -92,7 +92,7 @@ script: |
BASEPREFIX="${PWD}/depends"
mkdir -p ${BASEPREFIX}/SDKs
tar -C ${BASEPREFIX}/SDKs -xf ${BUILD_DIR}/Xcode-11.3.1-11C505-extracted-SDK-with-libcxx-headers.tar.gz
tar -C ${BASEPREFIX}/SDKs -xf ${BUILD_DIR}/Xcode-12.1-12A7403-extracted-SDK-with-libcxx-headers.tar.gz
# Build dependencies for each host
for i in $HOSTS; do
@ -134,21 +134,17 @@ script: |
make osx_volname
make deploydir
OSX_VOLNAME="$(cat osx_volname)"
mkdir -p unsigned-app-${i}
cp osx_volname unsigned-app-${i}/
cp contrib/macdeploy/detached-sig-apply.sh unsigned-app-${i}
cp contrib/macdeploy/detached-sig-create.sh unsigned-app-${i}
cp ${BASEPREFIX}/${i}/native/bin/dmg ${BASEPREFIX}/${i}/native/bin/genisoimage unsigned-app-${i}
cp ${BASEPREFIX}/${i}/native/bin/${i}-codesign_allocate unsigned-app-${i}/codesign_allocate
cp ${BASEPREFIX}/${i}/native/bin/${i}-pagestuff unsigned-app-${i}/pagestuff
cp ${BASEPREFIX}/${i}/native/bin/dmg unsigned-app-${i}
mv dist unsigned-app-${i}
pushd unsigned-app-${i}
find . | sort | tar --mtime="$REFERENCE_DATETIME" --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ${OUTDIR}/${DISTNAME}-osx-unsigned.tar.gz
popd
make deploy
${WRAP_DIR}/dmg dmg "${OSX_VOLNAME}.dmg" ${OUTDIR}/${DISTNAME}-osx-unsigned.dmg
make deploy OSX_DMG="${OUTDIR}/${DISTNAME}-osx-unsigned.dmg"
cd installed

View file

@ -2,7 +2,7 @@
name: "bitcoin-win-signer"
distro: "ubuntu"
suites:
- "bionic"
- "focal"
architectures:
- "amd64"
packages:

View file

@ -1,9 +1,9 @@
---
name: "elements-win-0.21"
name: "elements-win-22"
enable_cache: true
distro: "ubuntu"
suites:
- "bionic"
- "focal"
architectures:
- "amd64"
packages:
@ -26,6 +26,7 @@ packages:
- "zip"
- "ca-certificates"
- "python3"
- "python3-pip"
remotes:
- "url": "https://github.com/ElementsProject/elements.git"
"dir": "elements"
@ -35,14 +36,12 @@ script: |
WRAP_DIR=$HOME/wrapped
HOSTS="x86_64-w64-mingw32"
CONFIGFLAGS="--enable-reduce-exports --disable-bench --disable-gui-tests"
CONFIGFLAGS="--enable-reduce-exports --disable-bench --disable-gui-tests --disable-fuzz-binary"
FAKETIME_HOST_PROGS="ar ranlib nm windres strip objcopy"
FAKETIME_PROGS="date makensis zip"
HOST_CFLAGS="-O2 -g -fno-ident"
HOST_CXXFLAGS="-O2 -g -fno-ident"
export QT_RCC_TEST=1
export QT_RCC_SOURCE_DATE_OVERRIDE=1
export TZ="UTC"
export BUILD_DIR="$PWD"
mkdir -p ${WRAP_DIR}
@ -59,7 +58,7 @@ script: |
echo "REAL=\`which -a ${prog} | grep -v ${WRAP_DIR}/${prog} | head -1\`" >> ${WRAP_DIR}/${prog}
echo "export LD_PRELOAD='/usr/\$LIB/faketime/libfaketime.so.1'" >> ${WRAP_DIR}/${prog}
echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${prog}
echo "\$REAL \$@" >> $WRAP_DIR/${prog}
echo "exec \"\$REAL\" \"\$@\"" >> $WRAP_DIR/${prog}
chmod +x ${WRAP_DIR}/${prog}
done
}
@ -71,7 +70,7 @@ script: |
echo "REAL=\`which -a ${i}-${prog} | grep -v ${WRAP_DIR}/${i}-${prog} | head -1\`" >> ${WRAP_DIR}/${i}-${prog}
echo "export LD_PRELOAD='/usr/\$LIB/faketime/libfaketime.so.1'" >> ${WRAP_DIR}/${i}-${prog}
echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${i}-${prog}
echo "\$REAL \$@" >> $WRAP_DIR/${i}-${prog}
echo "exec \"\$REAL\" \"\$@\"" >> $WRAP_DIR/${i}-${prog}
chmod +x ${WRAP_DIR}/${i}-${prog}
done
done
@ -85,12 +84,14 @@ script: |
echo "REAL=\`which -a ${i}-${prog}-posix | grep -v ${WRAP_DIR}/${i}-${prog} | head -1\`" >> ${WRAP_DIR}/${i}-${prog}
echo "export LD_PRELOAD='/usr/\$LIB/faketime/libfaketime.so.1'" >> ${WRAP_DIR}/${i}-${prog}
echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${i}-${prog}
echo "\$REAL \"\$@\"" >> $WRAP_DIR/${i}-${prog}
echo "exec \"\$REAL\" \"\$@\"" >> $WRAP_DIR/${i}-${prog}
chmod +x ${WRAP_DIR}/${i}-${prog}
done
done
}
pip3 install lief==0.11.5
# Faketime for depends so intermediate results are comparable
export PATH_orig=${PATH}
create_global_faketime_wrappers "2000-01-01 12:00:00"

View file

@ -1,36 +0,0 @@
9D3CC86A72F8494342EA5FD10A41BDC3F4FAFF1C Aaron Clauson (sipsorcery)
617C90010B3BD370B0AC7D424BB42E31C79111B8 Akira Takizawa
E944AE667CF960B1004BC32FCA662BE18B877A60 Andreas Schildbach
152812300785C96444D3334D17565732E08E5E41 Andrew Chow
912FD3228387123DC97E0E57D5566241A0295FA9 BtcDrak
C519EBCF3B926298946783EFF6430754120EC2F4 Christian Decker (cdecker)
F20F56EF6A067F70E8A5C99FFF95FAA971697405 centaur
C060A6635913D98A3587D7DB1C2491FFEB0EF770 Cory Fields
BF6273FAEF7CC0BA1F562E50989F6B3048A116B5 Dev Random
6D3170C1DC2C6FD0AEEBCA6743811D1A26623924 Douglas Roark
9A1689B60D1B3CCE9262307A2F40A9BF167FBA47 Erik Mossberg (erkmos)
D35176BE9264832E4ACA8986BF0792FBE95DC863 fivepiece
01CDF4627A3B88AAE4A571C87588242FBE38D3A8 Gavin Andresen
D1DBF2C4B96F2DEBF4C16654410108112E7EA81F Hennadii Stepanov (hebasto)
D3CC177286005BB8FF673294C5242A1AB3936517 jl2012
82921A4B88FD454B7EB8CE3C796C4109063D4EAF Jon Atack
32EE5C4C3FA15CCADB46ABE529D4BCB6416F53EC Jonas Schnelli
4B4E840451149DD7FB0D633477DFAB5C3108B9A8 Jorge Timon
C42AFF7C61B3E44A1454CD3557AF762DB3353322 Karl-Johan Alm (kallewoof)
E463A93F5F3117EEDE6C7316BD02942421F4889F Luke Dashjr
B8B3F1C0E58C15DB6A81D30C3648A882F4316B9B Marco Falke
07DF3E57A548CCFB7530709189BBB8663E2E65CE Matt Corallo (BlueMatt)
CA03882CB1FC067B5D3ACFE4D300116E1C875A3D MeshCollider
E777299FC265DD04793070EB944D35F9AC3DB76A Michael Ford
9692B91BBF0E8D34DFD33B1882C5C009628ECF0C Michagogo
77E72E69DA7EE0A148C06B21B34821D4944DE5F7 Nils Schneider
D62A803E27E7F43486035ADBBCD04D8E9CCCAC2A Paul Rabahy
37EC7D7B0A217CDB4B4E007E7FAB114267E4FA04 Peter Todd
D762373D24904A3E42F33B08B9A408E71DAAC974 Pieter Wuille (Location: Leuven, Belgium)
133EAC179436F14A5CF1B794860FEB804E669320 Pieter Wuille
A8FC55F3B04BA3146F3492E79303B33A305224CB Sebastian Kung (TheCharlatan)
ED9BDF7AD6A55E232E84524257FF9BDBCC301009 Sjors Provoost
9EDAFF80E080659604F4A76B2EBB056FD847F8A7 Stephan Oeste (Emzy)
AEC1884398647C47413C1C3FB1179EB7347DC10D Warren Togami
79D00BAC68B56D422F945A8F8E3A8F3247DBCBBF Willy Ko
71A3B16735405025D447E8F274810B012346C9A6 Wladimir J. van der Laan

813
contrib/guix/INSTALL.md Normal file
View file

@ -0,0 +1,813 @@
# Guix Installation and Setup
This only needs to be done once per machine. If you have already completed the
installation and setup, please proceed to [perform a build](./README.md).
Otherwise, you may choose from one of the following options to install Guix:
1. Using the official **shell installer script** [⤓ skip to section][install-script]
- Maintained by Guix developers
- Easiest (automatically performs *most* setup)
- Works on nearly all Linux distributions
- Only installs latest release
- Binary installation only, requires high level of trust
- Note: The script needs to be run as root, so it should be inspected before it's run
2. Using the official **binary tarball** [⤓ skip to section][install-bin-tarball]
- Maintained by Guix developers
- Normal difficulty (full manual setup required)
- Works on nearly all Linux distributions
- Installs any release
- Binary installation only, requires high level of trust
3. Using fanquake's **Docker image** [↗︎ external instructions][install-fanquake-docker]
- Maintained by fanquake
- Easy (automatically performs *some* setup)
- Works wherever Docker images work
- Installs any release
- Binary installation only, requires high level of trust
4. Using a **distribution-maintained package** [⤓ skip to section][install-distro-pkg]
- Maintained by distribution's Guix package maintainer
- Normal difficulty (manual setup required)
- Works only on distributions with Guix packaged, see: https://repology.org/project/guix/versions
- Installs a release decided on by package maintainer
- Source or binary installation depending on the distribution
5. Building **from source** [⤓ skip to section][install-source]
- Maintained by you
- Hard, but rewarding
- Can be made to work on most Linux distributions
- Installs any commit (more granular)
- Source installation, requires lower level of trust
## Options 1 and 2: Using the official shell installer script or binary tarball
The installation instructions for both the official shell installer script and
the binary tarballs can be found in the GNU Guix Manual's [Binary Installation
section](https://guix.gnu.org/manual/en/html_node/Binary-Installation.html).
Note that running through the binary tarball installation steps is largely
equivalent to manually performing what the shell installer script does.
Note that at the time of writing (July 5th, 2021), the shell installer script
automatically creates an `/etc/profile.d` entry which the binary tarball
installation instructions do not ask you to create. However, you will likely
need this entry for better desktop integration. Please see [this
section](#add-an-etcprofiled-entry) for instructions on how to add a
`/etc/profile.d/guix.sh` entry.
Regardless of which installation option you chose, the changes to
`/etc/profile.d` will not take effect until the next shell or desktop session,
so you should log out and log back in.
## Option 3: Using fanquake's Docker image
Please refer to fanquake's instructions
[here](https://github.com/fanquake/core-review/tree/master/guix).
Note that the `Dockerfile` is largely equivalent to running through the binary
tarball installation steps.
## Option 4: Using a distribution-maintained package
Note that this section is based on the distro packaging situation at the time of
writing (July 2021). Guix is expected to be more widely packaged over time. For
an up-to-date view on Guix's package status/version across distros, please see:
https://repology.org/project/guix/versions
### Debian 11 (Bullseye)/Ubuntu 21.04 (Hirsute Hippo)
Guix v1.2.0 is available as a distribution package starting in [Debian
11](https://packages.debian.org/bullseye/guix) and [Ubuntu
21.04](https://packages.ubuntu.com/hirsute/guix).
Note that if you intend on using Guix without using any substitutes (more
details [here][security-model]), v1.2.0 has a known problems when building
GnuTLS from source. Solutions and workarounds are documented
[here](#gnutls-test-suite-fail-status-request-revoked).
To install:
```sh
sudo apt install guix
```
For up-to-date information on Debian and Ubuntu's release history:
- [Debian release history](https://www.debian.org/releases/)
- [Ubuntu release history](https://ubuntu.com/about/release-cycle)
### Arch Linux
Guix is available in the AUR as
[`guix`](https://aur.archlinux.org/packages/guix/), please follow the
installation instructions in the Arch Linux Wiki ([live
link](https://wiki.archlinux.org/index.php/Guix#AUR_Package_Installation),
[2021/03/30
permalink](https://wiki.archlinux.org/index.php?title=Guix&oldid=637559#AUR_Package_Installation))
to install Guix.
At the time of writing (2021/03/30), the `check` phase will fail if the path to
guix's build directory is longer than 36 characters due to an anachronistic
character limit on the shebang line. Since the `check` phase happens after the
`build` phase, which may take quite a long time, it is recommended that users
either:
1. Skip the `check` phase
- For `makepkg`: `makepkg --nocheck ...`
- For `yay`: `yay --mflags="--nocheck" ...`
- For `paru`: `paru --nocheck ...`
2. Or, check their build directory's length beforehand
- For those building with `makepkg`: `pwd | wc -c`
## Option 5: Building from source
Building Guix from source is a rather involved process but a rewarding one for
those looking to minimize trust and maximize customizability (e.g. building a
particular commit of Guix). Previous experience with using autotools-style build
systems to build packages from source will be helpful. *hic sunt dracones.*
I strongly urge you to at least skim through the entire section once before you
start issuing commands, as it will save you a lot of unnecessary pain and
anguish.
### Installing common build tools
There are a few basic build tools that are required for most things we'll build,
so let's install them now:
Text transformation/i18n:
- `autopoint` (sometimes packaged in `gettext`)
- `help2man`
- `po4a`
- `texinfo`
Build system tools:
- `g++` w/ C++11 support
- `libtool`
- `autoconf`
- `automake`
- `pkg-config` (sometimes packaged as `pkgconf`)
- `make`
- `cmake`
Miscellaneous:
- `git`
- `gnupg`
- `python3`
### Building and Installing Guix's dependencies
In order to build Guix itself from source, we need to first make sure that the
necessary dependencies are installed and discoverable. The most up-to-date list
of Guix's dependencies is kept in the ["Requirements"
section](https://guix.gnu.org/manual/en/html_node/Requirements.html) of the Guix
Reference Manual.
Depending on your distribution, most or all of these dependencies may already be
packaged and installable without manually building and installing.
For reference, the graphic below outlines Guix v1.3.0's dependency graph:
![bootstrap map](https://user-images.githubusercontent.com/6399679/125064185-a9a59880-e0b0-11eb-82c1-9b8e5dc9950d.png)
#### Guile
##### Choosing a Guile version and sticking to it
One of the first things you need to decide is which Guile version you want to
use: Guile v2.2 or Guile v3.0. Unlike the python2 to python3 transition, Guile
v2.2 and Guile v3.0 are largely compatible, as evidenced by the fact that most
Guile packages and even [Guix
itself](https://guix.gnu.org/en/blog/2020/guile-3-and-guix/) support running on
both.
What is important here is that you **choose one**, and you **remain consistent**
with your choice throughout **all Guile-related packages**, no matter if they
are installed via the distribution's package manager or installed from source.
This is because the files for Guile packages are installed to directories which
are separated based on the Guile version.
###### Example: Checking that Ubuntu's `guile-git` is compatible with your chosen Guile version
On Ubuntu Focal:
```sh
$ apt show guile-git
Package: guile-git
...
Depends: guile-2.2, guile-bytestructures, libgit2-dev
...
```
As you can see, the package `guile-git` depends on `guile-2.2`, meaning that it
was likely built for Guile v2.2. This means that if you decided to use Guile
v3.0 on Ubuntu Focal, you would need to build guile-git from source instead of
using the distribution package.
On Ubuntu Hirsute:
```sh
$ apt show guile-git
Package: guile-git
...
Depends: guile-3.0 | guile-2.2, guile-bytestructures (>= 1.0.7-3~), libgit2-dev (>= 1.0)
...
```
In this case, `guile-git` depends on either `guile-3.0` or `guile-2.2`, meaning
that it would work no matter what Guile version you decided to use.
###### Corner case: Multiple versions of Guile on one system
It is recommended to only install one version of Guile, so that build systems do
not get confused about which Guile to use.
However, if you insist on having both Guile v2.2 and Guile v3.0 installed on
your system, then you need to **consistently** specify one of
`GUILE_EFFECTIVE_VERSION=3.0` or `GUILE_EFFECTIVE_VERSION=2.2` to all
`./configure` invocations for Guix and its dependencies.
##### Installing Guile
Guile is most likely already packaged for your distribution, so after you have
[chosen a Guile version](#choosing-a-guile-version-and-sticking-to-it), install
it via your distribution's package manager.
If your distribution splits packages into `-dev`-suffixed and
non-`-dev`-suffixed sub-packages (as is the case for Debian-derived
distributions), please make sure to install both. For example, to install Guile
v2.2 on Debian/Ubuntu:
```sh
apt install guile-2.2 guile-2.2-dev
```
#### Mixing distribution packages and source-built packages
At the time of writing, most distributions have _some_ of Guix's dependencies
packaged, but not all. This means that you may want to install the distribution
package for some dependencies, and manually build-from-source for others.
Distribution packages usually install to `/usr`, which is different from the
default `./configure` prefix of source-built packages: `/usr/local`.
This means that if you mix-and-match distribution packages and source-built
packages and do not specify exactly `--prefix=/usr` to `./configure` for
source-built packages, you will need to augment the `GUILE_LOAD_PATH` and
`GUILE_LOAD_COMPILED_PATH` environment variables so that Guile will look
under the right prefix and find your source-built packages.
For example, if you are using Guile v2.2, and have Guile packages in the
`/usr/local` prefix, either add the following lines to your `.profile` or
`.bash_profile` so that the environment variable is properly set for all future
shell logins, or paste the lines into a POSIX-style shell to temporarily modify
the environment variables of your current shell session.
```sh
# Help Guile v2.2.x find packages in /usr/local
export GUILE_LOAD_PATH="/usr/local/share/guile/site/2.2${GUILE_LOAD_PATH:+:}$GUILE_LOAD_PATH"
export GUILE_LOAD_COMPILED_PATH="/usr/local/lib/guile/2.2/site-ccache${GUILE_LOAD_COMPILED_PATH:+:}$GUILE_COMPILED_LOAD_PATH"
```
Note that these environment variables are used to check for packages during
`./configure`, so they should be set as soon as possible should you want to use
a prefix other than `/usr`.
<!-- ##### Example: Consistently using Guile 3.0 on Ubuntu -->
<!-- For example, on Ubuntu, if you choose to use Guile 3.0 and install the -->
<!-- `guile-3.0` package, you want to make sure that if you also want to install the -->
<!-- `guile-git` package with `apt` that said `guile-git` package was built for Guile -->
<!-- v3.0. This can be checked by invoking the following: -->
<!-- ``` -->
<!-- apt update -->
<!-- apt show guile-git -->
<!-- ``` -->
#### Building and installing source-built packages
***IMPORTANT**: A few dependencies have non-obvious quirks/erratas which are documented in the
sub-sections immediately below. Please read these sections before proceeding to
build and install these packages.*
Although you should always refer to the README or INSTALL files for the most
accurate information, most of these dependencies use autoconf-style build
systems (check if there's a `configure.ac` file), and will likely do the right
thing with the following:
Clone the repository and check out the latest release:
```sh
git clone <git-repo-of-dependency>/<dependency>.git
cd <dependency>
git tag -l # check for the latest release
git checkout <latest-release>
```
For autoconf-based build systems (if `./autogen.sh` or `configure.ac` exists at
the root of the repository):
```sh
./autogen.sh || autoreconf -vfi
./configure --prefix=<prefix>
make
sudo make install
```
For CMake-based build systems (if `CMakeLists.txt` exists at the root of the
repository):
```sh
mkdir build && cd build
cmake .. -DCMAKE_INSTALL_PREFIX=<prefix>
sudo cmake --build . --target install
```
If you choose not to specify exactly `--prefix=/usr` to `./configure`, please
make sure you've carefully read the [previous section] on mixing distribution
packages and source-built packages.
##### Binding packages require `-dev`-suffixed packages
Relevant for:
- Everyone
When building bindings, the `-dev`-suffixed version of the original package
needs to be installed. For example, building `Guile-zlib` on Debian-derived
distributions requires that `zlib1g-dev` is installed.
When using bindings, the `-dev`-suffixed version of the original package still
needs to be installed. This is particularly problematic when distribution
packages are mispackaged like `guile-sqlite3` is in Ubuntu Focal such that
installing `guile-sqlite3` does not automatically install `libsqlite3-dev` as a
dependency.
Below is a list of relevant Guile bindings and their corresponding `-dev`
packages in Debian at the time of writing.
| Guile binding package | -dev Debian package |
|-----------------------|---------------------|
| guile-gcrypt | libgcrypt-dev |
| guile-git | libgit2-dev |
| guile-lzlib | liblz-dev |
| guile-ssh | libssh-dev |
| guile-sqlite3 | libsqlite3-dev |
| guile-zlib | zlib1g-dev |
##### `guile-git` actually depends on `libgit2 >= 1.1`
Relevant for:
- Those building `guile-git` from source against `libgit2 < 1.1`
- Those installing `guile-git` from their distribution where `guile-git` is
built against `libgit2 < 1.1`
As of v0.4.0, `guile-git` claims to only require `libgit2 >= 0.28.0`, however,
it actually requires `libgit2 >= 1.1`, otherwise, it will be confused by a
reference of `origin/keyring`: instead of interpreting the reference as "the
'keyring' branch of the 'origin' remote", the reference is interpreted as "the
branch literally named 'origin/keyring'"
This is especially notable because Ubuntu Focal packages `libgit2 v0.28.4`, and
`guile-git` is built against it.
Should you be in this situation, you need to build both `libgit2 v1.1.x` and
`guile-git` from source.
Source: http://logs.guix.gnu.org/guix/2020-11-12.log#232527
##### `{scheme,guile}-bytestructures` v1.0.8 and v1.0.9 are broken for Guile v2.2
Relevant for:
- Those building `{scheme,guile}-bytestructures` from source against Guile v2.2
Commit
[707eea3](https://github.com/TaylanUB/scheme-bytestructures/commit/707eea3a85e1e375e86702229ebf73d496377669)
introduced a regression for Guile v2.2 and was first included in v1.0.8, this
was later corrected in commit
[ec9a721](https://github.com/TaylanUB/scheme-bytestructures/commit/ec9a721957c17bcda13148f8faa5f06934431ff7)
and included in v1.1.0.
TL;DR If you decided to use Guile v2.2, do not use `{scheme,guile}-bytestructures` v1.0.8 or v1.0.9.
### Building and Installing Guix itself
Start by cloning Guix:
```
git clone https://git.savannah.gnu.org/git/guix.git
cd guix
```
You will likely want to build the latest release, however, if the latest release
when you're reading this is still 1.2.0 then you may want to use 95aca29 instead
to avoid a problem in the GnuTLS test suite.
```
git branch -a -l 'origin/version-*' # check for the latest release
git checkout <latest-release>
```
Bootstrap the build system:
```
./bootstrap
```
Configure with the recommended `--localstatedir` flag:
```
./configure --localstatedir=/var
```
Note: If you intend to hack on Guix in the future, you will need to supply the
same `--localstatedir=` flag for all future Guix `./configure` invocations. See
the last paragraph of this
[section](https://guix.gnu.org/manual/en/html_node/Requirements.html) for more
details.
Build Guix (this will take a while):
```
make -j$(nproc)
```
Install Guix:
```
sudo make install
```
### Post-"build from source" Setup
#### Creating and starting a `guix-daemon-original` service with a fixed `argv[0]`
At this point, guix will be installed to `${bindir}`, which is likely
`/usr/local/bin` if you did not override directory variables at
`./configure`-time. More information on standard Automake directory variables
can be found
[here](https://www.gnu.org/software/automake/manual/html_node/Standard-Directory-Variables.html).
However, the Guix init scripts and service configurations for Upstart, systemd,
SysV, and OpenRC are installed (in `${libdir}`) to launch
`${localstatedir}/guix/profiles/per-user/root/current-guix/bin/guix-daemon`,
which does not yet exist, and will only exist after [`root` performs their first
`guix pull`](#guix-pull-as-root).
We need to create a `-original` version of these init scripts that's pointed to
the binaries we just built and `make install`'ed in `${bindir}` (normally,
`/usr/local/bin`).
Example for `systemd`, run as `root`:
```sh
# Create guix-daemon-original.service by modifying guix-daemon.service
libdir=# set according to your PREFIX (default is /usr/local/lib)
bindir="$(dirname $(command -v guix-daemon))"
sed -E -e "s|/\S*/guix/profiles/per-user/root/current-guix/bin/guix-daemon|${bindir}/guix-daemon|" "${libdir}"/systemd/system/guix-daemon.service > /etc/systemd/system/guix-daemon-original.service
chmod 664 /etc/systemd/system/guix-daemon-original.service
# Make systemd recognize the new service
systemctl daemon-reload
# Make sure that the non-working guix-daemon.service is stopped and disabled
systemctl stop guix-daemon
systemctl disable guix-daemon
# Make sure that the working guix-daemon-original.service is started and enabled
systemctl enable guix-daemon-original
systemctl start guix-daemon-original
```
#### Creating `guix-daemon` users / groups
Please see the [relevant
section](https://guix.gnu.org/manual/en/html_node/Build-Environment-Setup.html)
in the Guix Reference Manual for more details.
## Optional setup
At this point, you are set up to [use Guix to build Bitcoin
Core](./README.md#usage). However, if you want to polish your setup a bit and
make it "what Guix intended", then read the next few subsections.
### Add an `/etc/profile.d` entry
This section definitely does not apply to you if you installed Guix using:
1. The shell installer script
2. fanquake's Docker image
3. Debian's `guix` package
#### Background
Although Guix knows how to update itself and its packages, it does so in a
non-invasive way (it does not modify `/usr/local/bin/guix`).
Instead, it does the following:
- After a `guix pull`, it updates
`/var/guix/profiles/per-user/$USER/current-guix`, and creates a symlink
targeting this directory at `$HOME/.config/guix/current`
- After a `guix install`, it updates
`/var/guix/profiles/per-user/$USER/guix-profile`, and creates a symlink
targeting this directory at `$HOME/.guix-profile`
Therefore, in order for these operations to affect your shell/desktop sessions
(and for the principle of least astonishment to hold), their corresponding
directories have to be added to well-known environment variables like `$PATH`,
`$INFOPATH`, `$XDG_DATA_DIRS`, etc.
In other words, if `$HOME/.config/guix/current/bin` does not exist in your
`$PATH`, a `guix pull` will have no effect on what `guix` you are using. Same
goes for `$HOME/.guix-profile/bin`, `guix install`, and installed packages.
Helpfully, after a `guix pull` or `guix install`, a message will be printed like
so:
```
hint: Consider setting the necessary environment variables by running:
GUIX_PROFILE="$HOME/.guix-profile"
. "$GUIX_PROFILE/etc/profile"
Alternately, see `guix package --search-paths -p "$HOME/.guix-profile"'.
```
However, this is somewhat tedious to do for both `guix pull` and `guix install`
for each user on the system that wants to properly use `guix`. I recommend that
you instead add an entry to `/etc/profile.d` instead. This is done by default
when installing the Debian package later than 1.2.0-4 and when using the shell
script installer.
#### Instructions
Create `/etc/profile.d/guix.sh` with the following content:
```sh
# _GUIX_PROFILE: `guix pull` profile
_GUIX_PROFILE="$HOME/.config/guix/current"
if [ -L $_GUIX_PROFILE ]; then
export PATH="$_GUIX_PROFILE/bin${PATH:+:}$PATH"
# Export INFOPATH so that the updated info pages can be found
# and read by both /usr/bin/info and/or $GUIX_PROFILE/bin/info
# When INFOPATH is unset, add a trailing colon so that Emacs
# searches 'Info-default-directory-list'.
export INFOPATH="$_GUIX_PROFILE/share/info:$INFOPATH"
fi
# GUIX_PROFILE: User's default profile
GUIX_PROFILE="$HOME/.guix-profile"
[ -L $GUIX_PROFILE ] || return
GUIX_LOCPATH="$GUIX_PROFILE/lib/locale"
export GUIX_PROFILE GUIX_LOCPATH
[ -f "$GUIX_PROFILE/etc/profile" ] && . "$GUIX_PROFILE/etc/profile"
# set XDG_DATA_DIRS to include Guix installations
export XDG_DATA_DIRS="$GUIX_PROFILE/share:${XDG_DATA_DIRS:-/usr/local/share/:/usr/share/}"
```
Please note that this will not take effect until the next shell or desktop
session (log out and log back in).
### `guix pull` as root
Before you do this, you need to read the section on [choosing your security
model][security-model] and adjust `guix` and `guix-daemon` flags according to
your choice, as invoking `guix pull` may pull substitutes from substitute
servers (which you may not want).
As mentioned in a previous section, Guix expects
`${localstatedir}/guix/profiles/per-user/root/current-guix` to be populated with
`root`'s Guix profile, `guix pull`-ed and built by some former version of Guix.
However, this is not the case when we build from source. Therefore, we need to
perform a `guix pull` as `root`:
```sh
sudo --login guix pull --branch=version-<latest-release-version>
# or
sudo --login guix pull --commit=<particular-commit>
```
`guix pull` is quite a long process (especially if you're using
`--no-substitute`). If you encounter build problems, please refer to the
[troubleshooting section](#troubleshooting).
Note that running a bare `guix pull` with no commit or branch specified will
pull the latest commit on Guix's master branch, which is likely fine, but not
recommended.
If you installed Guix from source, you may get an error like the following:
```sh
error: while creating symlink '/root/.config/guix/current' No such file or directory
```
To resolve this, simply:
```
sudo mkdir -p /root/.config/guix
```
Then try the `guix pull` command again.
After the `guix pull` finishes successfully,
`${localstatedir}/guix/profiles/per-user/root/current-guix` should be populated.
#### Using the newly-pulled `guix` by restarting the daemon
Depending on how you installed Guix, you should now make sure that your init
scripts and service configurations point to the newly-pulled `guix-daemon`.
##### If you built Guix from source
If you followed the instructions for [fixing argv\[0\]][fix-argv0], you can now
do the following:
```sh
systemctl stop guix-daemon-original
systemctl disable guix-daemon-original
systemctl enable guix-daemon
systemctl start guix-daemon
```
##### If you installed Guix via the Debian/Ubuntu distribution packages
You will need to create a `guix-daemon-latest` service which points to the new
`guix` rather than a pinned one.
```sh
# Create guix-daemon-latest.service by modifying guix-daemon.service
sed -E -e "s|/usr/bin/guix-daemon|/var/guix/profiles/per-user/root/current-guix/bin/guix-daemon|" /etc/systemd/system/guix-daemon.service > /lib/systemd/system/guix-daemon-latest.service
chmod 664 /lib/systemd/system/guix-daemon-latest.service
# Make systemd recognize the new service
systemctl daemon-reload
# Make sure that the old guix-daemon.service is stopped and disabled
systemctl stop guix-daemon
systemctl disable guix-daemon
# Make sure that the new guix-daemon-latest.service is started and enabled
systemctl enable guix-daemon-latest
systemctl start guix-daemon-latest
```
##### If you installed Guix via lantw44's Arch Linux AUR package
At the time of writing (July 5th, 2021) the systemd unit for "updated Guix" is
`guix-daemon-latest.service`, therefore, you should do the following:
```sh
systemctl stop guix-daemon
systemctl disable guix-daemon
systemctl enable guix-daemon-latest
systemctl start guix-daemon-latest
```
##### Otherwise...
Simply do:
```sh
systemctl restart guix-daemon
```
### Checking everything
If you followed all the steps above to make your Guix setup "prim and proper,"
you can check that you did everything properly by running through this
checklist.
1. `/etc/profile.d/guix.sh` should exist and be sourced at each shell login
2. `guix describe` should not print `guix describe: error: failed to determine
origin`, but rather something like:
```
Generation 38 Feb 22 2021 16:39:31 (current)
guix f350df4
repository URL: https://git.savannah.gnu.org/git/guix.git
branch: version-1.2.0
commit: f350df405fbcd5b9e27e6b6aa500da7f101f41e7
```
3. `guix-daemon` should be running from `${localstatedir}/guix/profiles/per-user/root/current-guix`
# Troubleshooting
## Derivation failed to build
When you see a build failure like below:
```
building /gnu/store/...-foo-3.6.12.drv...
/ 'check' phasenote: keeping build directory `/tmp/guix-build-foo-3.6.12.drv-0'
builder for `/gnu/store/...-foo-3.6.12.drv' failed with exit code 1
build of /gnu/store/...-foo-3.6.12.drv failed
View build log at '/var/log/guix/drvs/../...-foo-3.6.12.drv.bz2'.
cannot build derivation `/gnu/store/...-qux-7.69.1.drv': 1 dependencies couldn't be built
cannot build derivation `/gnu/store/...-bar-3.16.5.drv': 1 dependencies couldn't be built
cannot build derivation `/gnu/store/...-baz-2.0.5.drv': 1 dependencies couldn't be built
guix time-machine: error: build of `/gnu/store/...-baz-2.0.5.drv' failed
```
It means that `guix` failed to build a package named `foo`, which was a
dependency of `qux`, `bar`, and `baz`. Importantly, note that the last "failed"
line is not necessarily the root cause, the first "failed" line is.
Most of the time, the build failure is due to a spurious test failure or the
package's build system/test suite breaking when running multi-threaded. To
rebuild _just_ this derivation in a single-threaded fashion (please don't forget
to add other `guix` flags like `--no-substitutes` as appropriate):
```sh
$ guix build --cores=1 /gnu/store/...-foo-3.6.12.drv
```
If the single-threaded rebuild did not succeed, you may need to dig deeper.
You may view `foo`'s build logs in `less` like so (please replace paths with the
path you see in the build failure output):
```sh
$ bzcat /var/log/guix/drvs/../...-foo-3.6.12.drv.bz2 | less
```
`foo`'s build directory is also preserved and available at
`/tmp/guix-build-foo-3.6.12.drv-0`. However, if you fail to build `foo` multiple
times, it may be `/tmp/...drv-1` or `/tmp/...drv-2`. Always consult the build
failure output for the most accurate, up-to-date information.
### python(-minimal): [Errno 84] Invalid or incomplete multibyte or wide character
This error occurs when your `$TMPDIR` (default: /tmp) exists on a filesystem
which rejects characters not present in the UTF-8 character code set. An example
is ZFS with the utf8only=on option set.
More information: https://bugs.python.org/issue37584
### GnuTLS: test-suite FAIL: status-request-revoked
*The derivation is likely identified by: `/gnu/store/vhphki5sg9xkdhh2pbc8gi6vhpfzryf0-gnutls-3.6.12.drv`*
This unfortunate error is most common for non-substitute builders who installed
Guix v1.2.0. The problem stems from the fact that one of GnuTLS's tests uses a
hardcoded certificate which expired on 2020-10-24.
What's more unfortunate is that this GnuTLS derivation is somewhat special in
Guix's dependency graph and is not affected by the package transformation flags
like `--without-tests=`.
The easiest solution for those encountering this problem is to install a newer
version of Guix. However, there are ways to work around this issue:
#### Workaround 1: Using substitutes for this single derivation
If you've authorized the official Guix build farm's key (more info
[here](./README.md#step-1-authorize-the-signing-keys)), then you can use
substitutes just for this single derivation by invoking the following:
```sh
guix build --substitute-urls="https://ci.guix.gnu.org" /gnu/store/vhphki5sg9xkdhh2pbc8gi6vhpfzryf0-gnutls-3.6.12.drv
```
See [this section](./README.md#removing-authorized-keys) for instructions on how
to remove authorized keys if you don't want to keep the build farm's key
authorized.
#### Workaround 2: Temporarily setting the system clock back
This workaround was described [here](https://issues.guix.gnu.org/44559#5).
Basically:
1. Turn off networking
2. Turn off NTP
3. Set system time to 2020-10-01
4. guix build --no-substitutes /gnu/store/vhphki5sg9xkdhh2pbc8gi6vhpfzryf0-gnutls-3.6.12.drv
5. Set system time back to accurate current time
6. Turn NTP back on
7. Turn networking back on
### coreutils: FAIL: tests/tail-2/inotify-dir-recreate
The inotify-dir-create test fails on "remote" filesystems such as overlayfs
(Docker's default filesystem) due to the filesystem being mistakenly recognized
as non-remote.
A relatively easy workaround to this is to make sure that a somewhat traditional
filesystem is mounted at `/tmp` (where `guix-daemon` performs its builds). For
Docker users, this might mean [using a volume][docker/volumes], [binding
mounting][docker/bind-mnt] from host, or (for those with enough RAM and swap)
[mounting a tmpfs][docker/tmpfs] using the `--tmpfs` flag.
Please see the following links for more details:
- An upstream coreutils bug has been filed: [debbugs#47940](https://debbugs.gnu.org/cgi/bugreport.cgi?bug=47940)
- A Guix bug detailing the underlying problem has been filed: [guix-issues#47935](https://issues.guix.gnu.org/47935)
- A commit to skip this test in Guix has been merged into the core-updates branch:
[savannah/guix@6ba1058](https://git.savannah.gnu.org/cgit/guix.git/commit/?id=6ba1058df0c4ce5611c2367531ae5c3cdc729ab4)
[install-script]: #options-1-and-2-using-the-official-shell-installer-script-or-binary-tarball
[install-bin-tarball]: #options-1-and-2-using-the-official-shell-installer-script-or-binary-tarball
[install-fanquake-docker]: #option-3-using-fanquakes-docker-image
[install-distro-pkg]: #option-4-using-a-distribution-maintained-package
[install-source]: #option-5-building-from-source
[fix-argv0]: #creating-and-starting-a-guix-daemon-original-service-with-a-fixed-argv0
[security-model]: ./README.md#choosing-your-security-model
[docker/volumes]: https://docs.docker.com/storage/volumes/
[docker/bind-mnt]: https://docs.docker.com/storage/bind-mounts/
[docker/tmpfs]: https://docs.docker.com/storage/tmpfs/

View file

@ -9,114 +9,222 @@ downloads.
We achieve bootstrappability by using Guix as a functional package manager.
## Requirements
# Requirements
Conservatively, a x86_64 machine with:
- 4GB of free disk space on the partition that /gnu/store will reside in
- 24GB of free disk space on the partition that the Bitcoin Core git repository
resides in
- 16GB of free disk space on the partition that /gnu/store will reside in
- 8GB of free disk space **per platform triple** you're planning on building
(see the `HOSTS` [environment variable description][env-vars-list])
> Note: these requirements are slightly less onerous than those of Gitian builds
# Installation and Setup
## Setup
If you don't have Guix installed and set up, please follow the instructions in
[INSTALL.md](./INSTALL.md)
### Installing Guix
# Usage
If you're just testing this out, you can use the
[Dockerfile][fanquake/guix-docker] for convenience. It automatically speeds up
your builds by [using substitutes](#speeding-up-builds-with-substitute-servers).
If you don't want this behaviour, refer to the [next
section](#choosing-your-security-model).
If you haven't considered your security model yet, please read [the relevant
section](#choosing-your-security-model) before proceeding to perform a build.
Otherwise, follow the [Guix installation guide][guix/bin-install].
## Making the Xcode SDK available for macOS cross-compilation
> Note: For those who like to keep their filesystems clean, Guix is designed to
> be very standalone and _will not_ conflict with your system's package
> manager/existing setup. It _only_ touches `/var/guix`, `/gnu`, and
> `~/.config/guix`.
In order to perform a build for macOS (which is included in the default set of
platform triples to build), you'll need to extract the macOS SDK tarball using
tools found in the [`macdeploy` directory](../macdeploy/README.md).
### Choosing your security model
Guix allows us to achieve better binary security by using our CPU time to build
everything from scratch. However, it doesn't sacrifice user choice in pursuit of
this: users can decide whether or not to bootstrap and to use substitutes.
After installation, you may want to consider [adding substitute
servers](#speeding-up-builds-with-substitute-servers) to speed up your build if
that fits your security model (say, if you're just testing that this works).
This is skippable if you're using the [Dockerfile][fanquake/guix-docker].
If you prefer not to use any substitutes, make sure to set
`ADDITIONAL_GUIX_ENVIRONMENT_FLAGS` like the following snippet. The first build
will take a while, but the resulting packages will be cached for future builds.
You can then either point to the SDK using the `SDK_PATH` environment variable:
```sh
export ADDITIONAL_GUIX_ENVIRONMENT_FLAGS='--no-substitutes'
# Extract the SDK tarball to /path/to/parent/dir/of/extracted/SDK/Xcode-<foo>-<bar>-extracted-SDK-with-libcxx-headers
tar -C /path/to/parent/dir/of/extracted/SDK -xaf /path/to/Xcode-<foo>-<bar>-extracted-SDK-with-libcxx-headers.tar.gz
# Indicate where to locate the SDK tarball
export SDK_PATH=/path/to/parent/dir/of/extracted/SDK
```
Likewise, to perform a bootstrapped build (takes even longer):
or extract it into `depends/SDKs`:
```sh
export ADDITIONAL_GUIX_ENVIRONMENT_FLAGS='--bootstrap --no-substitutes'
mkdir -p depends/SDKs
tar -C depends/SDKs -xaf /path/to/SDK/tarball
```
### Using a version of Guix with `guix time-machine` capabilities
## Building
> Note: This entire section can be skipped if you are already using a version of
> Guix that has [the `guix time-machine` command][guix/time-machine].
*The author highly recommends at least reading over the [common usage patterns
and examples](#common-guix-build-invocation-patterns-and-examples) section below
before starting a build. For a full list of customization options, see the
[recognized environment variables][env-vars-list] section.*
Once Guix is installed, if it doesn't have the `guix time-machine` command, pull
the latest `guix`.
To build Bitcoin Core reproducibly with all default options, invoke the
following from the top of a clean repository:
```sh
guix pull --max-jobs=4 # change number of jobs accordingly
./contrib/guix/guix-build
```
Make sure that you are using your current profile. (You are prompted to do this
at the end of the `guix pull`)
## Codesigning build outputs
```bash
export PATH="${HOME}/.config/guix/current/bin${PATH:+:}$PATH"
The `guix-codesign` command attaches codesignatures (produced by codesigners) to
existing non-codesigned outputs. Please see the [release process
documentation](/doc/release-process.md) for more context.
It respects many of the same environment variable flags as `guix-build`, with 2
crucial differences:
1. Since only Windows and macOS build outputs require codesigning, the `HOSTS`
environment variable will have a sane default value of `x86_64-w64-mingw32
x86_64-apple-darwin18` instead of all the platforms.
2. The `guix-codesign` command ***requires*** a `DETACHED_SIGS_REPO` flag.
* _**DETACHED_SIGS_REPO**_
Set the directory where detached codesignatures can be found for the current
Bitcoin Core version being built.
_REQUIRED environment variable_
An invocation with all default options would look like:
```
env DETACHED_SIGS_REPO=<path/to/bitcoin-detached-sigs> ./contrib/guix-codesign
```
## Usage
## Cleaning intermediate work directories
### As a Development Environment
By default, `guix-build` leaves all intermediate files or "work directories"
(e.g. `depends/work`, `guix-build-*/distsrc-*`) intact at the end of a build so
that they are available to the user (to aid in debugging, etc.). However, these
directories usually take up a large amount of disk space. Therefore, a
`guix-clean` convenience script is provided which cleans the current `git`
worktree to save disk space:
For a Bitcoin Core depends development environment, simply invoke
```
./contrib/guix/guix-clean
```
## Attesting to build outputs
Much like how Gitian build outputs are attested to in a `gitian.sigs`
repository, Guix build outputs are attested to in the [`guix.sigs`
repository](https://github.com/bitcoin-core/guix.sigs).
After you've cloned the `guix.sigs` repository, to attest to the current
worktree's commit/tag:
```
env GUIX_SIGS_REPO=<path/to/guix.sigs> SIGNER=<gpg-key-name> ./contrib/guix/guix-attest
```
See `./contrib/guix/guix-attest --help` for more information on the various ways
`guix-attest` can be invoked.
## Verifying build output attestations
After at least one other signer has uploaded their signatures to the `guix.sigs`
repository:
```
git -C <path/to/guix.sigs> pull
env GUIX_SIGS_REPO=<path/to/guix.sigs> ./contrib/guix/guix-verify
```
## Common `guix-build` invocation patterns and examples
### Keeping caches and SDKs outside of the worktree
If you perform a lot of builds and have a bunch of worktrees, you may find it
more efficient to keep the depends tree's download cache, build cache, and SDKs
outside of the worktrees to avoid duplicate downloads and unnecessary builds. To
help with this situation, the `guix-build` script honours the `SOURCES_PATH`,
`BASE_CACHE`, and `SDK_PATH` environment variables and will pass them on to the
depends tree so that you can do something like:
```sh
guix environment --manifest=contrib/guix/manifest.scm
env SOURCES_PATH="$HOME/depends-SOURCES_PATH" BASE_CACHE="$HOME/depends-BASE_CACHE" SDK_PATH="$HOME/macOS-SDKs" ./contrib/guix/guix-build
```
And you'll land back in your shell with all the build dependencies required for
a `depends` build injected into your environment.
Note that the paths that these environment variables point to **must be
directories**, and **NOT symlinks to directories**.
### As a Tool for Deterministic Builds
See the [recognized environment variables][env-vars-list] section for more
details.
From the top of a clean Bitcoin Core repository:
### Building a subset of platform triples
Sometimes you only want to build a subset of the supported platform triples, in
which case you can override the default list by setting the space-separated
`HOSTS` environment variable:
```sh
./contrib/guix/guix-build.sh
env HOSTS='x86_64-w64-mingw32 x86_64-apple-darwin18' ./contrib/guix/guix-build
```
After the build finishes successfully (check the status code please), compare
hashes:
See the [recognized environment variables][env-vars-list] section for more
details.
### Controlling the number of threads used by `guix` build commands
Depending on your system's RAM capacity, you may want to decrease the number of
threads used to decrease RAM usage or vice versa.
By default, the scripts under `./contrib/guix` will invoke all `guix` build
commands with `--cores="$JOBS"`. Note that `$JOBS` defaults to `$(nproc)` if not
specified. However, astute manual readers will also notice that `guix` build
commands also accept a `--max-jobs=` flag (which defaults to 1 if unspecified).
Here is the difference between `--cores=` and `--max-jobs=`:
> Note: When I say "derivation," think "package"
`--cores=`
- controls the number of CPU cores to build each derivation. This is the value
passed to `make`'s `--jobs=` flag.
`--max-jobs=`
- controls how many derivations can be built in parallel
- defaults to 1
Therefore, the default is for `guix` build commands to build one derivation at a
time, utilizing `$JOBS` threads.
Specifying the `$JOBS` environment variable will only modify `--cores=`, but you
can also modify the value for `--max-jobs=` by specifying
`$ADDITIONAL_GUIX_COMMON_FLAGS`. For example, if you have a LOT of memory, you
may want to set:
```sh
find output/ -type f -print0 | sort -z | xargs -r0 sha256sum
export ADDITIONAL_GUIX_COMMON_FLAGS='--max-jobs=8'
```
#### Recognized environment variables
Which allows for a maximum of 8 derivations to be built at the same time, each
utilizing `$JOBS` threads.
Or, if you'd like to avoid spurious build failures caused by issues with
parallelism within a single package, but would still like to build multiple
packages when the dependency graph allows for it, you may want to try:
```sh
export JOBS=1 ADDITIONAL_GUIX_COMMON_FLAGS='--max-jobs=8'
```
See the [recognized environment variables][env-vars-list] section for more
details.
## Recognized environment variables
* _**HOSTS**_
Override the space-separated list of platform triples for which to perform a
bootstrappable build. _(defaults to "x86\_64-linux-gnu
arm-linux-gnueabihf aarch64-linux-gnu riscv64-linux-gnu")_
bootstrappable build.
> Windows and OS X platform triplet support are WIP.
_(defaults to "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-darwin18")_
* _**SOURCES_PATH**_
@ -124,18 +232,48 @@ find output/ -type f -print0 | sort -z | xargs -r0 sha256sum
depends tree. Setting this to the same directory across multiple builds of the
depends tree can eliminate unnecessary redownloading of package sources.
* _**MAX_JOBS**_
The path that this environment variable points to **must be a directory**, and
**NOT a symlink to a directory**.
Override the maximum number of jobs to run simultaneously, you might want to
do so on a memory-limited machine. This may be passed to `make` as in `make
--jobs="$MAX_JOBS"` or `xargs` as in `xargs -P"$MAX_JOBS"`. _(defaults to the
value of `nproc` outside the container)_
* _**BASE_CACHE**_
Set the depends tree cache for built packages. This is passed through to the
depends tree. Setting this to the same directory across multiple builds of the
depends tree can eliminate unnecessary building of packages.
The path that this environment variable points to **must be a directory**, and
**NOT a symlink to a directory**.
* _**SDK_PATH**_
Set the path where _extracted_ SDKs can be found. This is passed through to
the depends tree. Note that this is should be set to the _parent_ directory of
the actual SDK (e.g. `SDK_PATH=$HOME/Downloads/macOS-SDKs` instead of
`$HOME/Downloads/macOS-SDKs/Xcode-12.1-12A7403-extracted-SDK-with-libcxx-headers`).
The path that this environment variable points to **must be a directory**, and
**NOT a symlink to a directory**.
* _**JOBS**_
Override the number of jobs to run simultaneously, you might want to do so on
a memory-limited machine. This may be passed to:
- `guix` build commands as in `guix environment --cores="$JOBS"`
- `make` as in `make --jobs="$JOBS"`
- `xargs` as in `xargs -P"$JOBS"`
See [here](#controlling-the-number-of-threads-used-by-guix-build-commands) for
more details.
_(defaults to the value of `nproc` outside the container)_
* _**SOURCE_DATE_EPOCH**_
Override the reference UNIX timestamp used for bit-for-bit reproducibility,
the variable name conforms to [standard][r12e/source-date-epoch]. _(defaults
to the output of `$(git log --format=%at -1)`)_
the variable name conforms to [standard][r12e/source-date-epoch].
_(defaults to the output of `$(git log --format=%at -1)`)_
* _**V**_
@ -147,74 +285,188 @@ find output/ -type f -print0 | sort -z | xargs -r0 sha256sum
string) is interpreted the same way as not setting `V` at all, and that `V=0`
has the same effect as `V=1`.
* _**SUBSTITUTE_URLS**_
A whitespace-delimited list of URLs from which to download pre-built packages.
A URL is only used if its signing key is authorized (refer to the [substitute
servers section](#option-1-building-with-substitutes) for more details).
* _**ADDITIONAL_GUIX_COMMON_FLAGS**_
Additional flags to be passed to all `guix` commands.
* _**ADDITIONAL_GUIX_TIMEMACHINE_FLAGS**_
Additional flags to be passed to `guix time-machine`.
* _**ADDITIONAL_GUIX_ENVIRONMENT_FLAGS**_
Additional flags to be passed to `guix environment`. For a fully-bootstrapped
build, set this to `--bootstrap --no-substitutes` (refer to the [security
model section](#choosing-your-security-model) for more details). Note that a
fully-bootstrapped build will take quite a long time on the first run.
Additional flags to be passed to the invocation of `guix environment` inside
`guix time-machine`.
## Tips and Tricks
# Choosing your security model
### Speeding up builds with substitute servers
No matter how you installed Guix, you need to decide on your security model for
building packages with Guix.
_This whole section is automatically done in the convenience
[Dockerfiles][fanquake/guix-docker]_
Guix allows us to achieve better binary security by using our CPU time to build
everything from scratch. However, it doesn't sacrifice user choice in pursuit of
this: users can decide whether or not to use **substitutes** (pre-built
packages).
For those who are used to life in the fast _(and trustful)_ lane, you can use
[substitute servers][guix/substitutes] to enable binary downloads of packages.
## Option 1: Building with substitutes
> For those who only want to use substitutes from the official Guix build farm
> and have authorized the build farm's signing key during Guix's installation,
> you don't need to do anything.
### Step 1: Authorize the signing keys
#### Authorize the signing keys
Depending on the installation procedure you followed, you may have already
authorized the Guix build farm key. In particular, the official shell installer
script asks you if you want the key installed, and the debian distribution
package authorized the key during installation.
For the official Guix build farm at https://ci.guix.gnu.org, run as root:
You can check the current list of authorized keys at `/etc/guix/acl`.
At the time of writing, a `/etc/guix/acl` with just the Guix build farm key
authorized looks something like:
```lisp
(acl
(entry
(public-key
(ecc
(curve Ed25519)
(q #8D156F295D24B0D9A86FA5741A840FF2D24F60F7B6C4134814AD55625971B394#)
)
)
(tag
(guix import)
)
)
)
```
If you've determined that the official Guix build farm key hasn't been
authorized, and you would like to authorize it, run the following as root:
```
guix archive --authorize < ~root/.config/guix/current/share/guix/ci.guix.gnu.org.pub
guix archive --authorize < /var/guix/profiles/per-user/root/current-guix/share/guix/ci.guix.gnu.org.pub
```
If
`/var/guix/profiles/per-user/root/current-guix/share/guix/ci.guix.gnu.org.pub`
doesn't exist, try:
```sh
guix archive --authorize < <PREFIX>/share/guix/ci.guix.gnu.org.pub
```
Where `<PREFIX>` is likely:
- `/usr` if you installed from a distribution package
- `/usr/local` if you installed Guix from source and didn't supply any
prefix-modifying flags to Guix's `./configure`
For dongcarl's substitute server at https://guix.carldong.io, run as root:
```sh
wget -qO- 'https://guix.carldong.io/signing-key.pub' | guix archive --authorize
```
#### Use the substitute servers
#### Removing authorized keys
The official Guix build farm at https://ci.guix.gnu.org is automatically used
unless the `--no-substitutes` flag is supplied.
To remove previously authorized keys, simply edit `/etc/guix/acl` and remove the
`(entry (public-key ...))` entry.
This can be overridden for all `guix` invocations by passing the
`--substitute-urls` option to your invocation of `guix-daemon`. This can also be
overridden on a call-by-call basis by passing the same `--substitute-urls`
option to client tools such at `guix environment`.
### Step 2: Specify the substitute servers
To use dongcarl's substitute server for Bitcoin Core builds after having
[authorized his signing key](#authorize-the-signing-keys):
Once its key is authorized, the official Guix build farm at
https://ci.guix.gnu.org is automatically used unless the `--no-substitutes` flag
is supplied. This default list of substitute servers is overridable both on a
`guix-daemon` level and when you invoke `guix` commands. See examples below for
the various ways of adding dongcarl's substitute server after having [authorized
his signing key](#authorize-the-signing-keys).
```
export ADDITIONAL_GUIX_ENVIRONMENT_FLAGS='--substitute-urls="https://guix.carldong.io https://ci.guix.gnu.org"'
Change the **default list** of substitute servers by starting `guix-daemon` with
the `--substitute-urls` option (you will likely need to edit your init script):
```sh
guix-daemon <cmd> --substitute-urls='https://guix.carldong.io https://ci.guix.gnu.org'
```
## FAQ
Override the default list of substitute servers by passing the
`--substitute-urls` option for invocations of `guix` commands:
### How can I trust the binary installation?
```sh
guix <cmd> --substitute-urls='https://guix.carldong.io https://ci.guix.gnu.org'
```
As mentioned at the bottom of [this manual page][guix/bin-install]:
For scripts under `./contrib/guix`, set the `SUBSTITUTE_URLS` environment
variable:
> The binary installation tarballs can be (re)produced and verified simply by
> running the following command in the Guix source tree:
>
> make guix-binary.x86_64-linux.tar.xz
```sh
export SUBSTITUTE_URLS='https://guix.carldong.io https://ci.guix.gnu.org'
```
### When will Guix be packaged in debian?
## Option 2: Disabling substitutes on an ad-hoc basis
Vagrant Cascadian has been making good progress on this
[here][debian/guix-package]. We have all the pieces needed to put up an APT
repository and will likely put one up soon.
If you prefer not to use any substitutes, make sure to supply `--no-substitutes`
like in the following snippet. The first build will take a while, but the
resulting packages will be cached for future builds.
For direct invocations of `guix`:
```sh
guix <cmd> --no-substitutes
```
For the scripts under `./contrib/guix/`:
```sh
export ADDITIONAL_GUIX_COMMON_FLAGS='--no-substitutes'
```
## Option 3: Disabling substitutes by default
`guix-daemon` accepts a `--no-substitutes` flag, which will make sure that,
unless otherwise overridden by a command line invocation, no substitutes will be
used.
If you start `guix-daemon` using an init script, you can edit said script to
supply this flag.
# Purging/Uninstalling Guix
In the extraordinarily rare case where you messed up your Guix installation in
an irreversible way, you may want to completely purge Guix from your system and
start over.
1. Uninstall Guix itself according to the way you installed it. (e.g. `sudo apt
purge guix` for Ubuntu packaging, `sudo make uninstall` for
built-from-source).
2. Remove all build users and groups
You may check for relevant users and groups using:
```
getent passwd | grep guix
getent group | grep guix
```
Then, you may remove users and groups using:
```
sudo userdel <user>
sudo groupdel <group>
```
3. Remove all possible Guix-related directories
- `/var/guix/`
- `/var/log/guix/`
- `/gnu/`
- `/etc/guix/`
- `/home/*/.config/guix/`
- `/home/*/.cache/guix/`
- `/home/*/.guix-profile/`
- `/root/.config/guix/`
- `/root/.cache/guix/`
- `/root/.guix-profile/`
[b17e]: http://bootstrappable.org/
[r12e/source-date-epoch]: https://reproducible-builds.org/docs/source-date-epoch/
@ -226,5 +478,8 @@ repository and will likely put one up soon.
[guix/substitute-server-auth]: https://www.gnu.org/software/guix/manual/en/html_node/Substitute-Server-Authorization.html
[guix/time-machine]: https://guix.gnu.org/manual/en/html_node/Invoking-guix-time_002dmachine.html
[debian/guix-package]: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=850644
[debian/guix-bullseye]: https://packages.debian.org/bullseye/guix
[ubuntu/guix-hirsute]: https://packages.ubuntu.com/hirsute/guix
[fanquake/guix-docker]: https://github.com/fanquake/core-review/tree/master/guix
[env-vars-list]: #recognized-environment-variables

258
contrib/guix/guix-attest Executable file
View file

@ -0,0 +1,258 @@
#!/usr/bin/env bash
export LC_ALL=C
set -e -o pipefail
# Source the common prelude, which:
# 1. Checks if we're at the top directory of the Bitcoin Core repository
# 2. Defines a few common functions and variables
#
# shellcheck source=libexec/prelude.bash
source "$(dirname "${BASH_SOURCE[0]}")/libexec/prelude.bash"
###################
## Sanity Checks ##
###################
################
# Required non-builtin commands should be invokable
################
check_tools cat env basename mkdir diff sort
if [ -z "$NO_SIGN" ]; then
check_tools gpg
fi
################
# Required env vars should be non-empty
################
cmd_usage() {
cat <<EOF
Synopsis:
env GUIX_SIGS_REPO=<path/to/guix.sigs> \\
SIGNER=GPG_KEY_NAME[=SIGNER_NAME] \\
[ NO_SIGN=1 ]
./contrib/guix/guix-attest
Example w/o overriding signing name:
env GUIX_SIGS_REPO=/home/achow101/guix.sigs \\
SIGNER=achow101 \\
./contrib/guix/guix-attest
Example overriding signing name:
env GUIX_SIGS_REPO=/home/dongcarl/guix.sigs \\
SIGNER=0x96AB007F1A7ED999=dongcarl \\
./contrib/guix/guix-attest
Example w/o signing, just creating SHA256SUMS:
env GUIX_SIGS_REPO=/home/achow101/guix.sigs \\
SIGNER=achow101 \\
NO_SIGN=1 \\
./contrib/guix/guix-attest
EOF
}
if [ -z "$GUIX_SIGS_REPO" ] || [ -z "$SIGNER" ]; then
cmd_usage
exit 1
fi
################
# GUIX_SIGS_REPO should exist as a directory
################
if [ ! -d "$GUIX_SIGS_REPO" ]; then
cat << EOF
ERR: The specified GUIX_SIGS_REPO is not an existent directory:
'$GUIX_SIGS_REPO'
Hint: Please clone the guix.sigs repository and point to it with the
GUIX_SIGS_REPO environment variable.
EOF
cmd_usage
exit 1
fi
################
# The key specified in SIGNER should be usable
################
IFS='=' read -r gpg_key_name signer_name <<< "$SIGNER"
if [ -z "${signer_name}" ]; then
signer_name="$gpg_key_name"
fi
if [ -z "$NO_SIGN" ] && ! gpg --dry-run --list-secret-keys "${gpg_key_name}" >/dev/null 2>&1; then
echo "ERR: GPG can't seem to find any key named '${gpg_key_name}'"
exit 1
fi
################
# We should be able to find at least one output
################
echo "Looking for build output SHA256SUMS fragments in ${OUTDIR_BASE}"
shopt -s nullglob
sha256sum_fragments=( "$OUTDIR_BASE"/*/SHA256SUMS.part ) # This expands to an array of directories...
shopt -u nullglob
noncodesigned_fragments=()
codesigned_fragments=()
if (( ${#sha256sum_fragments[@]} )); then
echo "Found build output SHA256SUMS fragments:"
for outdir in "${sha256sum_fragments[@]}"; do
echo " '$outdir'"
case "$outdir" in
"$OUTDIR_BASE"/*-codesigned/SHA256SUMS.part)
codesigned_fragments+=("$outdir")
;;
*)
noncodesigned_fragments+=("$outdir")
;;
esac
done
echo
else
echo "ERR: Could not find any build output SHA256SUMS fragments in ${OUTDIR_BASE}"
exit 1
fi
##############
## Attest ##
##############
# Usage: out_name $outdir
#
# HOST: The output directory being attested
#
out_name() {
basename "$(dirname "$1")"
}
shasum_already_exists() {
cat <<EOF
--
ERR: An ${1} file already exists for '${VERSION}' and attests
differently. You likely previously attested to a partial build (e.g. one
where you specified the HOST environment variable).
See the diff above for more context.
Hint: You may wish to remove the existing attestations and their signatures by
invoking:
rm '${PWD}/${1}'{,.asc}
Then try running this script again.
EOF
}
# Given a document with unix line endings (just <LF>) in stdin, make all lines
# end in <CR><LF> and make sure there's no trailing <LF> at the end of the file.
#
# This is necessary as cleartext signatures are calculated on text after their
# line endings are canonicalized.
#
# For more information:
# 1. https://security.stackexchange.com/a/104261
# 2. https://datatracker.ietf.org/doc/html/rfc4880#section-7.1
#
rfc4880_normalize_document() {
sed 's/$/\r/' | head -c -2
}
echo "Attesting to build outputs for version: '${VERSION}'"
echo ""
outsigdir="$GUIX_SIGS_REPO/$VERSION/$signer_name"
mkdir -p "$outsigdir"
(
cd "$outsigdir"
temp_noncodesigned="$(mktemp)"
trap 'rm -rf -- "$temp_noncodesigned"' EXIT
if (( ${#noncodesigned_fragments[@]} )); then
cat "${noncodesigned_fragments[@]}" \
| sort -u \
| sort -k2 \
| rfc4880_normalize_document \
> "$temp_noncodesigned"
if [ -e noncodesigned.SHA256SUMS ]; then
# The SHA256SUMS already exists, make sure it's exactly what we
# expect, error out if not
if diff -u noncodesigned.SHA256SUMS "$temp_noncodesigned"; then
echo "A noncodesigned.SHA256SUMS file already exists for '${VERSION}' and is up-to-date."
else
shasum_already_exists noncodesigned.SHA256SUMS
exit 1
fi
else
mv "$temp_noncodesigned" noncodesigned.SHA256SUMS
fi
else
echo "ERR: No noncodesigned outputs found for '${VERSION}', exiting..."
exit 1
fi
temp_codesigned="$(mktemp)"
trap 'rm -rf -- "$temp_codesigned"' EXIT
if (( ${#codesigned_fragments[@]} )); then
# Note: all.SHA256SUMS attests to all of $sha256sum_fragments, but is
# not needed if there are no $codesigned_fragments
cat "${sha256sum_fragments[@]}" \
| sort -u \
| sort -k2 \
| sed 's/$/\r/' \
| rfc4880_normalize_document \
> "$temp_codesigned"
if [ -e codesigned.SHA256SUMS ]; then
# The SHA256SUMS already exists, make sure it's exactly what we
# expect, error out if not
if diff -u all.SHA256SUMS "$temp_codesigned"; then
echo "An all.SHA256SUMS file already exists for '${VERSION}' and is up-to-date."
else
shasum_already_exists all.SHA256SUMS
exit 1
fi
else
mv "$temp_codesigned" codesigned.SHA256SUMS
fi
else
# It is fine to have the codesigned outputs be missing (perhaps the
# detached codesigs have not been published yet), just print a log
# message instead of erroring out
echo "INFO: No codesigned outputs found for '${VERSION}', skipping..."
fi
if [ -z "$NO_SIGN" ]; then
echo "Signing SHA256SUMS to produce SHA256SUMS.asc"
for i in *.SHA256SUMS; do
if [ ! -e "$i".asc ]; then
gpg --detach-sign \
--digest-algo sha256 \
--local-user "$gpg_key_name" \
--armor \
--output "$i".asc "$i"
else
echo "Signature already there"
fi
done
else
echo "Not signing SHA256SUMS as \$NO_SIGN is not empty"
fi
echo ""
)

477
contrib/guix/guix-build Executable file
View file

@ -0,0 +1,477 @@
#!/usr/bin/env bash
export LC_ALL=C
set -e -o pipefail
# Source the common prelude, which:
# 1. Checks if we're at the top directory of the Bitcoin Core repository
# 2. Defines a few common functions and variables
#
# shellcheck source=libexec/prelude.bash
source "$(dirname "${BASH_SOURCE[0]}")/libexec/prelude.bash"
###################
## SANITY CHECKS ##
###################
################
# Required non-builtin commands should be invocable
################
check_tools cat mkdir make getent curl git guix
################
# GUIX_BUILD_OPTIONS should be empty
################
#
# GUIX_BUILD_OPTIONS is an environment variable recognized by guix commands that
# can perform builds. This seems like what we want instead of
# ADDITIONAL_GUIX_COMMON_FLAGS, but the value of GUIX_BUILD_OPTIONS is actually
# _appended_ to normal command-line options. Meaning that they will take
# precedence over the command-specific ADDITIONAL_GUIX_<CMD>_FLAGS.
#
# This seems like a poor user experience. Thus we check for GUIX_BUILD_OPTIONS's
# existence here and direct users of this script to use our (more flexible)
# custom environment variables.
if [ -n "$GUIX_BUILD_OPTIONS" ]; then
cat << EOF
Error: Environment variable GUIX_BUILD_OPTIONS is not empty:
'$GUIX_BUILD_OPTIONS'
Unfortunately this script is incompatible with GUIX_BUILD_OPTIONS, please unset
GUIX_BUILD_OPTIONS and use ADDITIONAL_GUIX_COMMON_FLAGS to set build options
across guix commands or ADDITIONAL_GUIX_<CMD>_FLAGS to set build options for a
specific guix command.
See contrib/guix/README.md for more details.
EOF
exit 1
fi
################
# The git worktree should not be dirty
################
if ! git diff-index --quiet HEAD -- && [ -z "$FORCE_DIRTY_WORKTREE" ]; then
cat << EOF
ERR: The current git worktree is dirty, which may lead to broken builds.
Aborting...
Hint: To make your git worktree clean, You may want to:
1. Commit your changes,
2. Stash your changes, or
3. Set the 'FORCE_DIRTY_WORKTREE' environment variable if you insist on
using a dirty worktree
EOF
exit 1
fi
mkdir -p "$VERSION_BASE"
################
# Build directories should not exist
################
# 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-darwin18}"
# Usage: distsrc_for_host HOST
#
# HOST: The current platform triple we're building for
#
distsrc_for_host() {
echo "${DISTSRC_BASE}/distsrc-${VERSION}-${1}"
}
# Accumulate a list of build directories that already exist...
hosts_distsrc_exists=""
for host in $HOSTS; do
if [ -e "$(distsrc_for_host "$host")" ]; then
hosts_distsrc_exists+=" ${host}"
fi
done
if [ -n "$hosts_distsrc_exists" ]; then
# ...so that we can print them out nicely in an error message
cat << EOF
ERR: Build directories for this commit already exist for the following platform
triples you're attempting to build, probably because of previous builds.
Please remove, or otherwise deal with them prior to starting another build.
Aborting...
Hint: To blow everything away, you may want to use:
$ ./contrib/guix/guix-clean
Specifically, this will remove all files without an entry in the index,
excluding the SDK directory, the depends download cache, the depends built
packages cache, the garbage collector roots for Guix environments, and the
output directory.
EOF
for host in $hosts_distsrc_exists; do
echo " ${host} '$(distsrc_for_host "$host")'"
done
exit 1
else
mkdir -p "$DISTSRC_BASE"
fi
################
# When building for darwin, the macOS SDK should exists
################
for host in $HOSTS; do
case "$host" in
*darwin*)
OSX_SDK="$(make -C "${PWD}/depends" --no-print-directory HOST="$host" print-OSX_SDK | sed 's@^[^=]\+=@@g')"
if [ -e "$OSX_SDK" ]; then
echo "Found macOS SDK at '${OSX_SDK}', using..."
else
echo "macOS SDK does not exist at '${OSX_SDK}', please place the extracted, untarred SDK there to perform darwin builds, exiting..."
exit 1
fi
;;
esac
done
################
# VERSION_BASE should have enough space
################
avail_KiB="$(df -Pk "$VERSION_BASE" | sed 1d | tr -s ' ' | cut -d' ' -f4)"
total_required_KiB=0
for host in $HOSTS; do
case "$host" in
*darwin*) required_KiB=440000 ;;
*mingw*) required_KiB=7600000 ;;
*) required_KiB=6400000 ;;
esac
total_required_KiB=$((total_required_KiB+required_KiB))
done
if (( total_required_KiB > avail_KiB )); then
total_required_GiB=$((total_required_KiB / 1048576))
avail_GiB=$((avail_KiB / 1048576))
echo "Performing a Bitcoin Core Guix build for the selected HOSTS requires ${total_required_GiB} GiB, however, only ${avail_GiB} GiB is available. Please free up some disk space before performing the build."
exit 1
fi
################
# Check that we can connect to the guix-daemon
################
cat << EOF
Checking that we can connect to the guix-daemon...
Hint: If this hangs, you may want to try turning your guix-daemon off and on
again.
EOF
if ! guix gc --list-failures > /dev/null; then
cat << EOF
ERR: Failed to connect to the guix-daemon, please ensure that one is running and
reachable.
EOF
exit 1
fi
# Developer note: we could use `guix repl` for this check and run:
#
# (import (guix store)) (close-connection (open-connection))
#
# However, the internal API is likely to change more than the CLI invocation
################
# Services database must have basic entries
################
if ! getent services http https ftp; then
cat << EOF
ERR: Your system's C library can not find service database entries for at least
one of the following services: http, https, ftp.
Hint: Most likely, /etc/services does not exist yet (common for docker images
and minimal distros), or you don't have permissions to access it.
If /etc/services does not exist yet, you may want to install the
appropriate package for your distro which provides it.
On Debian/Ubuntu: netbase
On Arch Linux: iana-etc
For more information, see: getent(1), services(5)
EOF
fi
#########
# SETUP #
#########
# Determine the maximum number of jobs to run simultaneously (overridable by
# environment)
JOBS="${JOBS:-$(nproc)}"
# Usage: host_to_commonname HOST
#
# HOST: The current platform triple we're building for
#
host_to_commonname() {
case "$1" in
*darwin*) echo osx ;;
*mingw*) echo win ;;
*linux*) echo linux ;;
*) exit 1 ;;
esac
}
# Determine the reference time used for determinism (overridable by environment)
SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH:-$(git log --format=%at -1)}"
# Execute "$@" in a pinned, possibly older version of Guix, for reproducibility
# across time.
time-machine() {
# shellcheck disable=SC2086
guix time-machine --url=https://git.savannah.gnu.org/git/guix.git \
--commit=aa34d4d28dfe25ba47d5800d05000fb7221788c0 \
--cores="$JOBS" \
--keep-failed \
--fallback \
${SUBSTITUTE_URLS:+--substitute-urls="$SUBSTITUTE_URLS"} \
${ADDITIONAL_GUIX_COMMON_FLAGS} ${ADDITIONAL_GUIX_TIMEMACHINE_FLAGS} \
-- "$@"
}
# Precious directories are those which should not be cleaned between successive
# guix builds
depends_precious_dir_names='SOURCES_PATH BASE_CACHE SDK_PATH'
precious_dir_names="${depends_precious_dir_names} OUTDIR_BASE PROFILES_BASE"
# Usage: contains IFS-SEPARATED-LIST ITEM
contains() {
for i in ${1}; do
if [ "$i" = "${2}" ]; then
return 0 # Found!
fi
done
return 1
}
# If the user explicitly specified a precious directory, create it so we
# can map it into the container
for precious_dir_name in $precious_dir_names; do
precious_dir_path="${!precious_dir_name}"
if [ -n "$precious_dir_path" ]; then
if [ ! -e "$precious_dir_path" ]; then
mkdir -p "$precious_dir_path"
elif [ -L "$precious_dir_path" ]; then
echo "ERR: ${precious_dir_name} cannot be a symbolic link"
exit 1
elif [ ! -d "$precious_dir_path" ]; then
echo "ERR: ${precious_dir_name} must be a directory"
exit 1
fi
fi
done
mkdir -p "$VAR_BASE"
# Record the _effective_ values of precious directories such that guix-clean can
# avoid clobbering them if appropriate.
#
# shellcheck disable=SC2046,SC2086
{
# Get depends precious dir definitions from depends
make -C "${PWD}/depends" \
--no-print-directory \
-- $(printf "print-%s\n" $depends_precious_dir_names)
# Get remaining precious dir definitions from the environment
for precious_dir_name in $precious_dir_names; do
precious_dir_path="${!precious_dir_name}"
if ! contains "$depends_precious_dir_names" "$precious_dir_name"; then
echo "${precious_dir_name}=${precious_dir_path}"
fi
done
} > "${VAR_BASE}/precious_dirs"
# Make sure an output directory exists for our builds
OUTDIR_BASE="${OUTDIR_BASE:-${VERSION_BASE}/output}"
mkdir -p "$OUTDIR_BASE"
# Download the depends sources now as we won't have internet access in the build
# container
for host in $HOSTS; do
make -C "${PWD}/depends" -j"$JOBS" download-"$(host_to_commonname "$host")" ${V:+V=1} ${SOURCES_PATH:+SOURCES_PATH="$SOURCES_PATH"}
done
# Usage: outdir_for_host HOST SUFFIX
#
# HOST: The current platform triple we're building for
#
outdir_for_host() {
echo "${OUTDIR_BASE}/${1}${2:+-${2}}"
}
# Usage: profiledir_for_host HOST SUFFIX
#
# HOST: The current platform triple we're building for
#
profiledir_for_host() {
echo "${PROFILES_BASE}/${1}${2:+-${2}}"
}
#########
# BUILD #
#########
# Function to be called when building for host ${1} and the user interrupts the
# build
int_trap() {
cat << EOF
** INT received while building ${1}, you may want to clean up the relevant
work directories (e.g. distsrc-*) before rebuilding
Hint: To blow everything away, you may want to use:
$ ./contrib/guix/guix-clean
Specifically, this will remove all files without an entry in the index,
excluding the SDK directory, the depends download cache, the depends built
packages cache, the garbage collector roots for Guix environments, and the
output directory.
EOF
}
# Deterministically build Bitcoin Core
# shellcheck disable=SC2153
for host in $HOSTS; do
# Display proper warning when the user interrupts the build
trap 'int_trap ${host}' INT
(
# Required for 'contrib/guix/manifest.scm' to output the right manifest
# for the particular $HOST we're building for
export HOST="$host"
# shellcheck disable=SC2030
cat << EOF
INFO: Building ${VERSION:?not set} for platform triple ${HOST:?not set}:
...using reference timestamp: ${SOURCE_DATE_EPOCH:?not set}
...running at most ${JOBS:?not set} jobs
...from worktree directory: '${PWD}'
...bind-mounted in container to: '/bitcoin'
...in build directory: '$(distsrc_for_host "$HOST")'
...bind-mounted in container to: '$(DISTSRC_BASE=/distsrc-base && distsrc_for_host "$HOST")'
...outputting in: '$(outdir_for_host "$HOST")'
...bind-mounted in container to: '$(OUTDIR_BASE=/outdir-base && outdir_for_host "$HOST")'
EOF
# Run the build script 'contrib/guix/libexec/build.sh' in the build
# container specified by 'contrib/guix/manifest.scm'.
#
# Explanation of `guix environment` flags:
#
# --container run command within an isolated container
#
# Running in an isolated container minimizes build-time differences
# between machines and improves reproducibility
#
# --pure unset existing environment variables
#
# Same rationale as --container
#
# --no-cwd do not share current working directory with an
# isolated container
#
# When --container is specified, the default behavior is to share
# the current working directory with the isolated container at the
# same exact path (e.g. mapping '/home/satoshi/bitcoin/' to
# '/home/satoshi/bitcoin/'). This means that the $PWD inside the
# container becomes a source of irreproducibility. --no-cwd disables
# this behaviour.
#
# --share=SPEC for containers, share writable host file system
# according to SPEC
#
# --share="$PWD"=/bitcoin
#
# maps our current working directory to /bitcoin
# inside the isolated container, which we later cd
# into.
#
# While we don't want to map our current working directory to the
# same exact path (as this introduces irreproducibility), we do want
# it to be at a _fixed_ path _somewhere_ inside the isolated
# container so that we have something to build. '/bitcoin' was
# chosen arbitrarily.
#
# ${SOURCES_PATH:+--share="$SOURCES_PATH"}
#
# make the downloaded depends sources path available
# inside the isolated container
#
# The isolated container has no network access as it's in a
# different network namespace from the main machine, so we have to
# make the downloaded depends sources available to it. The sources
# should have been downloaded prior to this invocation.
#
# --keep-failed keep build tree of failed builds
#
# When builds of the Guix environment itself (not Bitcoin Core)
# fail, it is useful for the build tree to be kept for debugging
# purposes.
#
# ${SUBSTITUTE_URLS:+--substitute-urls="$SUBSTITUTE_URLS"}
#
# fetch substitute from SUBSTITUTE_URLS if they are
# authorized
#
# Depending on the user's security model, it may be desirable to use
# substitutes (pre-built packages) from servers that the user trusts.
# Please read the README.md in the same directory as this file for
# more information.
#
# shellcheck disable=SC2086,SC2031
time-machine environment --manifest="${PWD}/contrib/guix/manifest.scm" \
--container \
--pure \
--no-cwd \
--share="$PWD"=/bitcoin \
--share="$DISTSRC_BASE"=/distsrc-base \
--share="$OUTDIR_BASE"=/outdir-base \
--expose="$(git rev-parse --git-common-dir)" \
${SOURCES_PATH:+--share="$SOURCES_PATH"} \
${BASE_CACHE:+--share="$BASE_CACHE"} \
${SDK_PATH:+--share="$SDK_PATH"} \
--cores="$JOBS" \
--keep-failed \
--fallback \
--link-profile \
--root="$(profiledir_for_host "${HOST}")" \
${SUBSTITUTE_URLS:+--substitute-urls="$SUBSTITUTE_URLS"} \
${ADDITIONAL_GUIX_COMMON_FLAGS} ${ADDITIONAL_GUIX_ENVIRONMENT_FLAGS} \
-- env HOST="$host" \
DISTNAME="$DISTNAME" \
JOBS="$JOBS" \
SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH:?unable to determine value}" \
${V:+V=1} \
${SOURCES_PATH:+SOURCES_PATH="$SOURCES_PATH"} \
${BASE_CACHE:+BASE_CACHE="$BASE_CACHE"} \
${SDK_PATH:+SDK_PATH="$SDK_PATH"} \
DISTSRC="$(DISTSRC_BASE=/distsrc-base && distsrc_for_host "$HOST")" \
OUTDIR="$(OUTDIR_BASE=/outdir-base && outdir_for_host "$HOST")" \
DIST_ARCHIVE_BASE=/outdir-base/dist-archive \
bash -c "cd /bitcoin && bash contrib/guix/libexec/build.sh"
)
done

View file

@ -1,119 +0,0 @@
#!/usr/bin/env bash
export LC_ALL=C
set -e -o pipefail
# Determine the maximum number of jobs to run simultaneously (overridable by
# environment)
MAX_JOBS="${MAX_JOBS:-$(nproc)}"
# Download the depends sources now as we won't have internet access in the build
# container
make -C "${PWD}/depends" -j"$MAX_JOBS" download ${V:+V=1} ${SOURCES_PATH:+SOURCES_PATH="$SOURCES_PATH"}
# Determine the reference time used for determinism (overridable by environment)
SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH:-$(git log --format=%at -1)}"
# Execute "$@" in a pinned, possibly older version of Guix, for reproducibility
# across time.
time-machine() {
guix time-machine --url=https://github.com/dongcarl/guix.git \
--commit=b066c25026f21fb57677aa34692a5034338e7ee3 \
-- "$@"
}
# Function to be called when building for host ${1} and the user interrupts the
# build
int_trap() {
cat << EOF
** INT received while building ${1}, you may want to clean up the relevant
output, deploy, and distsrc-* directories before rebuilding
Hint: To blow everything away, you may want to use:
$ git clean -xdff --exclude='/depends/SDKs/*'
Specifically, this will remove all files without an entry in the index,
excluding the SDK directory. Practically speaking, this means that all ignored
and untracked files and directories will be wiped, allowing you to start anew.
EOF
}
# Deterministically build Bitcoin Core for HOSTs (overridable by environment)
# shellcheck disable=SC2153
for host in ${HOSTS=x86_64-linux-gnu arm-linux-gnueabihf aarch64-linux-gnu riscv64-linux-gnu x86_64-w64-mingw32}; do
# Display proper warning when the user interrupts the build
trap 'int_trap ${host}' INT
(
# Required for 'contrib/guix/manifest.scm' to output the right manifest
# for the particular $HOST we're building for
export HOST="$host"
# Run the build script 'contrib/guix/libexec/build.sh' in the build
# container specified by 'contrib/guix/manifest.scm'.
#
# Explanation of `guix environment` flags:
#
# --container run command within an isolated container
#
# Running in an isolated container minimizes build-time differences
# between machines and improves reproducibility
#
# --pure unset existing environment variables
#
# Same rationale as --container
#
# --no-cwd do not share current working directory with an
# isolated container
#
# When --container is specified, the default behavior is to share
# the current working directory with the isolated container at the
# same exact path (e.g. mapping '/home/satoshi/bitcoin/' to
# '/home/satoshi/bitcoin/'). This means that the $PWD inside the
# container becomes a source of irreproducibility. --no-cwd disables
# this behaviour.
#
# --share=SPEC for containers, share writable host file system
# according to SPEC
#
# --share="$PWD"=/bitcoin
#
# maps our current working directory to /bitcoin
# inside the isolated container, which we later cd
# into.
#
# While we don't want to map our current working directory to the
# same exact path (as this introduces irreproducibility), we do want
# it to be at a _fixed_ path _somewhere_ inside the isolated
# container so that we have something to build. '/bitcoin' was
# chosen arbitrarily.
#
# ${SOURCES_PATH:+--share="$SOURCES_PATH"}
#
# make the downloaded depends sources path available
# inside the isolated container
#
# The isolated container has no network access as it's in a
# different network namespace from the main machine, so we have to
# make the downloaded depends sources available to it. The sources
# should have been downloaded prior to this invocation.
#
# shellcheck disable=SC2086
time-machine environment --manifest="${PWD}/contrib/guix/manifest.scm" \
--container \
--pure \
--no-cwd \
--share="$PWD"=/bitcoin \
--expose="$(git rev-parse --git-common-dir)" \
${SOURCES_PATH:+--share="$SOURCES_PATH"} \
${ADDITIONAL_GUIX_ENVIRONMENT_FLAGS} \
-- env HOST="$host" \
MAX_JOBS="$MAX_JOBS" \
SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH:?unable to determine value}" \
${V:+V=1} \
${SOURCES_PATH:+SOURCES_PATH="$SOURCES_PATH"} \
bash -c "cd /bitcoin && bash contrib/guix/libexec/build.sh"
)
done

83
contrib/guix/guix-clean Executable file
View file

@ -0,0 +1,83 @@
#!/usr/bin/env bash
export LC_ALL=C
set -e -o pipefail
# Source the common prelude, which:
# 1. Checks if we're at the top directory of the Bitcoin Core repository
# 2. Defines a few common functions and variables
#
# shellcheck source=libexec/prelude.bash
source "$(dirname "${BASH_SOURCE[0]}")/libexec/prelude.bash"
###################
## Sanity Checks ##
###################
################
# Required non-builtin commands should be invokable
################
check_tools cat mkdir make git guix
#############
## Clean ##
#############
# Usage: under_dir MAYBE_PARENT MAYBE_CHILD
#
# If MAYBE_CHILD is a subdirectory of MAYBE_PARENT, print the relative path
# from MAYBE_PARENT to MAYBE_CHILD. Otherwise, return 1 as the error code.
#
# NOTE: This does not perform any symlink-resolving or path canonicalization.
#
under_dir() {
local path_residue
path_residue="${2##${1}}"
if [ -z "$path_residue" ] || [ "$path_residue" = "$2" ]; then
return 1
else
echo "$path_residue"
fi
}
# Usage: dir_under_git_root MAYBE_CHILD
#
# If MAYBE_CHILD is under the current git repository and exists, print the
# relative path from the git repository's top-level directory to MAYBE_CHILD,
# otherwise, exit with an error code.
#
dir_under_git_root() {
local rv
rv="$(under_dir "$(git_root)" "$1")"
[ -n "$rv" ] && echo "$rv"
}
shopt -s nullglob
found_precious_dirs_files=( "${version_base_prefix}"*/"${var_base_basename}/precious_dirs" ) # This expands to an array of directories...
shopt -u nullglob
exclude_flags=()
for precious_dirs_file in "${found_precious_dirs_files[@]}"; do
# Make sure the precious directories (e.g. SOURCES_PATH, BASE_CACHE, SDK_PATH)
# are excluded from git-clean
echo "Found precious_dirs file: '${precious_dirs_file}'"
# Exclude the precious_dirs file itself
if dirs_file_exclude_fragment=$(dir_under_git_root "$(dirname "$precious_dirs_file")"); then
exclude_flags+=( --exclude="${dirs_file_exclude_fragment}/precious_dirs" )
fi
# Read each 'name=dir' pair from the precious_dirs file
while IFS='=' read -r name dir; do
# Add an exclusion flag if the precious directory is under the git root.
if under=$(dir_under_git_root "$dir"); then
echo "Avoiding ${name}: ${under}"
exclude_flags+=( --exclude="$under" )
fi
done < "$precious_dirs_file"
done
git clean -xdff "${exclude_flags[@]}"

Some files were not shown because too many files have changed in this diff Show more