diff --git a/.github/workflows/manual-release.yml b/.github/workflows/manual-release.yml new file mode 100644 index 00000000..b9c79b78 --- /dev/null +++ b/.github/workflows/manual-release.yml @@ -0,0 +1,592 @@ +############################################################################### +# Copyright (c) 2014-2026 libbitcoin-server developers (see COPYING). +# +# SOON TO BE GENERATED CODE, DO NOT EDIT EXCEPT EXPERIMENTALLY +# +############################################################################### + +name: Manual Release Candidate Generation + +on: + workflow_dispatch: + inputs: + tag-system: + description: "libbitcoin-system tag used for release generation." + required: true + type: string + tag-database: + description: "libbitcoin-database tag used for release generation." + required: true + type: string + tag-network: + description: "libbitcoin-network tag used for release generation." + required: true + type: string + tag-node: + description: "libbitcoin-node tag used for release generation." + required: true + type: string + tag-server: + description: "libbitcoin-server tag used for release generation." + required: true + type: string + +permissions: + contents: read + +jobs: + + validate-tags: + runs-on: ubuntu-latest + + steps: + - name: checkout server + uses: actions/checkout@v6 + with: + fetch-depth: 1 + path: 'libbitcoin-server' + ref: ${{ github.event.inputs.tag-server }} + repository: ${{ github.repository }} + + - name: checkout node + uses: actions/checkout@v6 + with: + fetch-depth: 1 + path: 'libbitcoin-node' + ref: ${{ github.event.inputs.tag-node }} + repository: ${{ github.repository_owner }}/libbitcoin-node + + - name: checkout network + uses: actions/checkout@v6 + with: + fetch-depth: 1 + path: 'libbitcoin-network' + ref: ${{ github.event.inputs.tag-network }} + repository: ${{ github.repository_owner }}/libbitcoin-network + + - name: checkout database + uses: actions/checkout@v6 + with: + fetch-depth: 1 + path: 'libbitcoin-database' + ref: ${{ github.event.inputs.tag-database }} + repository: ${{ github.repository_owner }}/libbitcoin-database + + - name: checkout system + uses: actions/checkout@v6 + with: + fetch-depth: 1 + path: 'libbitcoin-system' + ref: ${{ github.event.inputs.tag-system }} + repository: ${{ github.repository_owner }}/libbitcoin-system + + - name: Verify tag server + shell: bash + working-directory: libbitcoin-server + run: | + if ! git rev-parse --verify "refs/tags/${{ github.event.inputs.tag-server }}" > /dev/null 2>&1; then + echo "Tag '${{ github.event.inputs.tag-server }}' does not exist in the repository." + exit 1 + fi + echo "Validated tag '${{ github.event.inputs.tag-server }}'." + + - name: Verify tag node + shell: bash + working-directory: libbitcoin-node + run: | + if ! git rev-parse --verify "refs/tags/${{ github.event.inputs.tag-node }}" > /dev/null 2>&1; then + echo "Tag '${{ github.event.inputs.tag-node }}' does not exist in the repository." + exit 1 + fi + echo "Validated tag '${{ github.event.inputs.tag-node }}'." + + - name: Verify tag network + shell: bash + working-directory: libbitcoin-network + run: | + if ! git rev-parse --verify "refs/tags/${{ github.event.inputs.tag-network }}" > /dev/null 2>&1; then + echo "Tag '${{ github.event.inputs.tag-network }}' does not exist in the repository." + exit 1 + fi + echo "Validated tag '${{ github.event.inputs.tag-network }}'." + + - name: Verify tag database + shell: bash + working-directory: libbitcoin-database + run: | + if ! git rev-parse --verify "refs/tags/${{ github.event.inputs.tag-database }}" > /dev/null 2>&1; then + echo "Tag '${{ github.event.inputs.tag-database }}' does not exist in the repository." + exit 1 + fi + echo "Validated tag '${{ github.event.inputs.tag-database }}'." + + - name: Verify tag system + shell: bash + working-directory: libbitcoin-system + run: | + if ! git rev-parse --verify "refs/tags/${{ github.event.inputs.tag-system }}" > /dev/null 2>&1; then + echo "Tag '${{ github.event.inputs.tag-system }}' does not exist in the repository." + exit 1 + fi + echo "Validated tag '${{ github.event.inputs.tag-system }}'." + + build-candidates: + + needs: validate-tags + + outputs: + candidate_identifier: ${{ steps.normalizer.outputs.candidate_identifier }} + + runs-on: ${{ matrix.image }} + + strategy: + fail-fast: false + + matrix: + include: + - image: ubuntu-latest + toolchain: gnu + cc: "gcc" + cxx: "g++" + configuration: debug + link: static + options: "--enable-avx2" + basename: "bs-StaticDebug" + + - image: ubuntu-latest + toolchain: cmake + cc: "clang" + cxx: "clang++" + configuration: release + link: static + options: "-Denable-avx2=ON" + basename: "bs-StaticRelease" + + - image: ubuntu-latest + toolchain: gnu + cc: "gcc" + cxx: "g++" + configuration: debug + link: static + options: "--enable-shani" + basename: "bs-StaticDebug-shani" + + - image: ubuntu-latest + toolchain: cmake + cc: "clang" + cxx: "clang++" + configuration: release + link: static + options: "-Denable-shani=ON" + basename: "bs-StaticRelease-shani" + + - image: ubuntu-latest + toolchain: gnu + cc: "gcc" + cxx: "g++" + configuration: debug + link: static + options: "--enable-avx512" + basename: "bs-StaticDebug-avx512" + + - image: ubuntu-latest + toolchain: cmake + cc: "clang" + cxx: "clang++" + configuration: release + link: static + options: "-Denable-avx512=ON" + basename: "bs-StaticRelease-avx512" + + - image: windows-latest + toolchain: msbuild + configuration: StaticDebug + platform: "x64" + version: "vs2022" + basename: "bs-StaticDebug" + + - image: windows-latest + toolchain: msbuild + configuration: StaticRelease + platform: "x64" + version: "vs2022" + basename: "bs-StaticRelease" + + - image: windows-latest + toolchain: msbuild + configuration: StaticDebug + platform: "x64" + version: "vs2022" + options: "/p:Option-sha" + basename: "bs-StaticDebug-shani" + + - image: windows-latest + toolchain: msbuild + configuration: StaticRelease + platform: "x64" + version: "vs2022" + options: "/p:Option-sha" + basename: "bs-StaticRelease-shani" + + - image: windows-latest + toolchain: msbuild + configuration: StaticDebug + platform: "x64" + version: "vs2022" + options: "/arch:AVX512" + basename: "bs-StaticDebug-avx512" + + - image: windows-latest + toolchain: msbuild + configuration: StaticRelease + platform: "x64" + version: "vs2022" + options: "/arch:AVX512" + basename: "bs-StaticRelease-avx512" + + steps: + - name: checkout server + uses: actions/checkout@v6 + with: + fetch-depth: 1 + path: 'libbitcoin-server' + ref: ${{ github.event.inputs.tag-server }} + repository: ${{ github.repository }} + + - name: checkout node + uses: actions/checkout@v6 + with: + fetch-depth: 1 + path: 'libbitcoin-node' + ref: ${{ github.event.inputs.tag-node }} + repository: ${{ github.repository_owner }}/libbitcoin-node + + - name: checkout network + uses: actions/checkout@v6 + with: + fetch-depth: 1 + path: 'libbitcoin-network' + ref: ${{ github.event.inputs.tag-network }} + repository: ${{ github.repository_owner }}/libbitcoin-network + + - name: checkout database + uses: actions/checkout@v6 + with: + fetch-depth: 1 + path: 'libbitcoin-database' + ref: ${{ github.event.inputs.tag-database }} + repository: ${{ github.repository_owner }}/libbitcoin-database + + - name: checkout system + uses: actions/checkout@v6 + with: + fetch-depth: 1 + path: 'libbitcoin-system' + ref: ${{ github.event.inputs.tag-system }} + repository: ${{ github.repository_owner }}/libbitcoin-system + + - name: Prepare toolchain [linux] + if: ${{ startsWith(matrix.image, 'ubuntu') }} + shell: bash + run: | + sudo apt-get update + sudo apt-get install -y ${{ matrix.packages || '' }} git build-essential autoconf automake libtool pkg-config + + - name: Prepare toolchain [macos] + if: ${{ startsWith(matrix.image, 'macos') }} + shell: bash + run: | + brew install ${{ matrix.packages || '' }} autoconf automake libtool + if [[ -n "${{ matrix.llvm }}" ]]; then + echo "PATH=/opt/homebrew/opt/${{ matrix.llvm }}/bin:${PATH}" >> $GITHUB_ENV + fi + + - name: Prepare toolchain [windows] + if: ${{ startsWith(matrix.image, 'windows') }} + uses: microsoft/setup-msbuild@v3 + with: + msbuild-architecture: x64 + + - name: Environmental Variable Computation + if: ${{ matrix.toolchain == 'cmake' || matrix.toolchain == 'gnu' || matrix.toolchain == 'presets' }} + shell: bash + run: | + if [[ "${{ matrix.link }}" == "dynamic" ]]; then + echo "LDFLAGS=-Wl,-rpath,${{ github.workspace }}/prefix/lib" >> $GITHUB_ENV + fi + + - name: Execute build [cmake] + if: ${{ matrix.toolchain == 'cmake' }} + shell: bash + run: > + ./libbitcoin-server/builds/cmake/install-cmake.sh + --build-use-local-src + --build-src-dir="${{ github.workspace }}" + --prefix="${{ github.workspace }}/prefix" + --build-obj-dir="obj" + --build-obj-dir-relative + --build-config="${{ matrix.configuration }}" + --build-link="${{ matrix.link }}" + --build-skip-tests + --build-boost + --build-secp256k1 + ${{ matrix.options }} + + - name: Execute build [gnu] + if: ${{ matrix.toolchain == 'gnu' }} + shell: bash + run: > + ./libbitcoin-server/builds/gnu/install-gnu.sh + --build-use-local-src + --build-src-dir="${{ github.workspace }}" + --prefix="${{ github.workspace }}/prefix" + --build-obj-dir="obj" + --build-obj-dir-relative + --build-config="${{ matrix.configuration }}" + --build-link="${{ matrix.link }}" + --build-skip-tests + --build-boost + --build-secp256k1 + ${{ matrix.options }} + + - name: Execute build [msbuild] + if: ${{ matrix.toolchain == 'msbuild' }} + shell: cmd + run: > + .\libbitcoin-server\builds\msvc\build-msvc.cmd + --build-src-dir "${{ github.workspace }}" + --build-config ${{ matrix.configuration }} + --build-platform ${{ matrix.platform }} + --build-version ${{ matrix.version }} + --build-use-local-src + --build-skip-tests + ${{ matrix.options }} + + - name: Execute build [presets] + if: ${{ matrix.toolchain == 'presets' }} + shell: bash + run: > + ./libbitcoin-server/builds/cmake/install-presets.sh + --build-use-local-src + --build-src-dir="${{ github.workspace }}" + --build-preset="${{ matrix.preset }}" + --build-skip-tests + --build-boost + --build-secp256k1 + ${{ matrix.options }} + + - name: Execute tests [msbuild] + if: ${{ matrix.toolchain == 'disabled' }} + shell: powershell + run: | + Write-Host "Locating test executables..." -ForegroundColor Yellow; + $BC_TEST_EXES = @(Get-ChildItem -Path "$env:${{ github.workspace }}\libbitcoin-server\bin" -recurse | Where-Object { $_.Name -eq "libbitcoin-server-test.exe" }); + If ($BC_TEST_EXES.Count -ne 1) { + Write-Host "Failure, invalid count of test executables." -ForegroundColor Red; + exit 1; + } + Write-Host "Found single test executable: " $BC_TEST_EXES.FullName -ForegroundColor Green; + $BC_TEST_SINGLETON = $BC_TEST_EXES.FullName; + Write-Host "Executing $BC_TEST_SINGLETON $env:BOOST_UNIT_TEST_OPTIONS" -ForegroundColor Yellow; + try { + Invoke-Expression "$BC_TEST_SINGLETON --log_level=warning --run_test=${{ matrix.tests }} $env:BOOST_UNIT_TEST_OPTIONS" + } + catch { + $ERR = $_; + Write-Host "Test execution failure: " $ERR -ForegroundColor Red; + exit $ERR; + } + Write-Host "Test execution complete." -ForegroundColor Green; + + - name: Normalize output location + id: normalizer + shell: bash + run: | + mkdir candidate + if [[ "${{ matrix.toolchain }}" == "cmake" ]]; then + CANDIDATE="prefix/bin/bs" + CANONICAL="${{ matrix.basename }}" + elif [[ ${{ matrix.toolchain }} == "gnu" ]]; then + CANDIDATE="prefix/bin/bs" + CANONICAL="${{ matrix.basename }}" + elif [[ ${{ matrix.toolchain }} == "presets" ]]; then + CANDIDATE="prefix/${{ matrix.preset }}/bin/bs" + CANONICAL="${{ matrix.basename }}" + elif [[ ${{ matrix.toolchain }} == "msbuild" ]]; then + if [[ "${{ matrix.configuration }}" == *Debug* ]]; then + CONFIG="Debug" + elif [[ "${{ matrix.configuration }}" == *Release* ]]; then + CONFIG="Release" + else + echo "Configuration unexpected." + exit 1 + fi + CANDIDATE="libbitcoin-server/bin/x64/${CONFIG}/v143/static/bs.exe" + CANONICAL="${{ matrix.basename }}.exe" + else + echo "\e[0;91mUnexpected toolchain provided.\e[0m" + exit 1 + fi + cp --dereference --no-clobber ${CANDIDATE} candidate/${CANONICAL} + echo "candidate_identifier=${CANONICAL}" >> "$GITHUB_OUTPUT" + + - name: Strip symbols from binaries + if: ${{ matrix.toolchain != 'msbuild' }} + shell: bash + run: | + echo "Stripping debug symbols to reduce binary size..." + find candidate -type f \ + \( -perm -111 -o -name "*.so" -o -name "*.dylib" \) \ + ! -path "*/.git/*" \ + ! -name "*.a" \ + -exec sh -c ' + file "{}" | grep -qE "ELF|Mach-O|PE32" && + strip --strip-unneeded --preserve-dates "{}" && + echo "Stripped: {}" + ' \; || true + + - name: Inventory results + working-directory: candidate + shell: bash + run: | + ls -lahR + + - name: Upload artifacts + uses: actions/upload-artifact@v7.0.1 + with: + name: ${{ steps.normalizer.outputs.candidate_identifier }} + path: candidate/* + retention-days: 1 + if-no-files-found: error + + sign: + + name: Sign artifacts + + needs: build-candidates + + environment: release + + permissions: + contents: write + + runs-on: ubuntu-latest + + steps: + - name: Retrieve artifacts + uses: actions/download-artifact@v8.0.1 + with: + path: artifacts + + - name: GPG Keyring Initialization + env: + SIGNING_PRIVATE_KEY: ${{ secrets.SIGNING_KEY }} + run: | + echo "Importing GPG signing key..." + # Import the private key + echo "$SIGNING_PRIVATE_KEY" | gpg --batch --import --pinentry-mode loopback + # Get the key fingerprint (first secret key) + KEY_FINGERPRINT=$(gpg --list-secret-keys --with-colons | grep '^sec' | head -n1 | cut -d: -f5) + if [ -z "$KEY_FINGERPRINT" ]; then + echo "Error: No secret key found after import" + exit 1 + fi + echo "Imported key fingerprint: $KEY_FINGERPRINT" + # Set ultimate trust (required for non-interactive signing) + echo -e "5\ny\n" | gpg --batch --command-fd 0 --edit-key "$KEY_FINGERPRINT" trust >/dev/null 2>&1 + # Configure gpg-agent for loopback pinentry (handles passphrase non-interactively) + mkdir -p ~/.gnupg + echo "allow-loopback-pinentry" > ~/.gnupg/gpg-agent.conf + echo "use-agent" > ~/.gnupg/gpg.conf + # Reload agent + gpgconf --kill gpg-agent + gpgconf --launch gpg-agent + + - name: execute signature + working-directory: artifacts + shell: bash + run: | + echo "Signing artifacts..." + find . -mindepth 1 -maxdepth 1 -type d ! -name '.*' -print0 | \ + while IFS= read -r -d '' dir; do + dir_name="${dir#./}" # remove leading ./ + echo "📁 Directory: $dir_name" + # Walk files inside this directory (only direct children, not recursive) + find "$dir" -maxdepth 1 -type f -print0 | \ + while IFS= read -r -d '' file; do + file_name=$(basename "$file") + echo " 📄 $file_name" + gpg --batch --yes --detach-sign --armor "$file" + done + done + + - name: GPG Keyring Cleanup + if: always() + run: | + echo "Cleaning up GPG keyring..." + gpg --batch \ + --yes \ + --delete-secret-keys \ + --delete-keys \ + "$(gpg --list-secret-keys --with-colons | grep '^sec' | cut -d: -f5)" 2>/dev/null || true + rm -rf ~/.gnupg + echo "Cleanup complete." + + - name: Inventory results + working-directory: artifacts + shell: bash + run: | + ls -lahR + + - name: Upload signed artifacts + uses: actions/upload-artifact@v7.0.1 + with: + if-no-files-found: error + name: server-${{ github.event.inputs.tag-server }}-signed-artifacts + path: artifacts/*/* + retention-days: 1 + + publish: + + name: Publish release + + needs: sign + + environment: release + + permissions: + contents: write + + runs-on: ubuntu-latest + + steps: + - name: Download signed artifacts + uses: actions/download-artifact@v8.0.1 + with: + name: server-${{ github.event.inputs.tag-server }}-signed-artifacts + path: signed-release + + - name: Inventory results + working-directory: signed-release + shell: bash + run: | + ls -lahR + + - name: Populate release + uses: softprops/action-gh-release@v3.0.0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ github.event.inputs.tag-server }} + draft: true + prerelease: true + overwrite_files: false + files: | + signed-release/*/* + body: | + **libbitcoin-server ${{ github.event.inputs.tag-server }}** + Built from: + - system: ${{ github.event.inputs.tag-system }} + - database: ${{ github.event.inputs.tag-database }} + - network: ${{ github.event.inputs.tag-network }} + - node: ${{ github.event.inputs.tag-node }} diff --git a/.github/workflows/mock-manual-release.yml b/.github/workflows/mock-manual-release.yml new file mode 100644 index 00000000..2abe0f0a --- /dev/null +++ b/.github/workflows/mock-manual-release.yml @@ -0,0 +1,419 @@ +############################################################################### +# Copyright (c) 2014-2026 libbitcoin-server developers (see COPYING). +# +# SOON TO BE GENERATED CODE, DO NOT EDIT EXCEPT EXPERIMENTALLY +# +############################################################################### + +name: Mock Manual Release Candidate Generation + +on: + workflow_dispatch: + inputs: + tag-system: + description: "libbitcoin-system tag used for release generation." + required: true + type: string + tag-database: + description: "libbitcoin-database tag used for release generation." + required: true + type: string + tag-network: + description: "libbitcoin-network tag used for release generation." + required: true + type: string + tag-node: + description: "libbitcoin-node tag used for release generation." + required: true + type: string + tag-server: + description: "libbitcoin-server tag used for release generation." + required: true + type: string + +permissions: + contents: read + +jobs: + + validate-tags: + runs-on: ubuntu-latest + + steps: + - name: checkout server + uses: actions/checkout@v6 + with: + fetch-depth: 1 + path: 'libbitcoin-server' + ref: ${{ github.event.inputs.tag-server }} + repository: ${{ github.repository }} + + - name: checkout node + uses: actions/checkout@v6 + with: + fetch-depth: 1 + path: 'libbitcoin-node' + ref: ${{ github.event.inputs.tag-node }} + repository: ${{ github.repository_owner }}/libbitcoin-node + + - name: checkout network + uses: actions/checkout@v6 + with: + fetch-depth: 1 + path: 'libbitcoin-network' + ref: ${{ github.event.inputs.tag-network }} + repository: ${{ github.repository_owner }}/libbitcoin-network + + - name: checkout database + uses: actions/checkout@v6 + with: + fetch-depth: 1 + path: 'libbitcoin-database' + ref: ${{ github.event.inputs.tag-database }} + repository: ${{ github.repository_owner }}/libbitcoin-database + + - name: checkout system + uses: actions/checkout@v6 + with: + fetch-depth: 1 + path: 'libbitcoin-system' + ref: ${{ github.event.inputs.tag-system }} + repository: ${{ github.repository_owner }}/libbitcoin-system + + - name: Verify tag server + shell: bash + working-directory: libbitcoin-server + run: | + if ! git rev-parse --verify "refs/tags/${{ github.event.inputs.tag-server }}" > /dev/null 2>&1; then + echo "Tag '${{ github.event.inputs.tag-server }}' does not exist in the repository." + exit 1 + fi + echo "Validated tag '${{ github.event.inputs.tag-server }}'." + + - name: Verify tag node + shell: bash + working-directory: libbitcoin-node + run: | + if ! git rev-parse --verify "refs/tags/${{ github.event.inputs.tag-node }}" > /dev/null 2>&1; then + echo "Tag '${{ github.event.inputs.tag-node }}' does not exist in the repository." + exit 1 + fi + echo "Validated tag '${{ github.event.inputs.tag-node }}'." + + - name: Verify tag network + shell: bash + working-directory: libbitcoin-network + run: | + if ! git rev-parse --verify "refs/tags/${{ github.event.inputs.tag-network }}" > /dev/null 2>&1; then + echo "Tag '${{ github.event.inputs.tag-network }}' does not exist in the repository." + exit 1 + fi + echo "Validated tag '${{ github.event.inputs.tag-network }}'." + + - name: Verify tag database + shell: bash + working-directory: libbitcoin-database + run: | + if ! git rev-parse --verify "refs/tags/${{ github.event.inputs.tag-database }}" > /dev/null 2>&1; then + echo "Tag '${{ github.event.inputs.tag-database }}' does not exist in the repository." + exit 1 + fi + echo "Validated tag '${{ github.event.inputs.tag-database }}'." + + - name: Verify tag system + shell: bash + working-directory: libbitcoin-system + run: | + if ! git rev-parse --verify "refs/tags/${{ github.event.inputs.tag-system }}" > /dev/null 2>&1; then + echo "Tag '${{ github.event.inputs.tag-system }}' does not exist in the repository." + exit 1 + fi + echo "Validated tag '${{ github.event.inputs.tag-system }}'." + + build-candidates: + + needs: validate-tags + + outputs: + candidate_identifier: ${{ steps.normalizer.outputs.candidate_identifier }} + + runs-on: ${{ matrix.image }} + + strategy: + fail-fast: false + + matrix: + include: + - image: ubuntu-latest + toolchain: gnu + cc: "gcc" + cxx: "g++" + configuration: debug + link: static + + - image: ubuntu-latest + toolchain: cmake + cc: "clang" + cxx: "clang++" + configuration: release + link: static + + - image: windows-latest + toolchain: msbuild + configuration: StaticDebug + platform: "x64" + version: "vs2022" + tests: "*" + + - image: windows-latest + toolchain: msbuild + configuration: StaticRelease + platform: "x64" + version: "vs2022" + tests: "*" + + steps: + - name: checkout server + uses: actions/checkout@v6 + with: + fetch-depth: 1 + path: 'libbitcoin-server' + ref: ${{ github.event.inputs.tag-server }} + repository: ${{ github.repository }} + + - name: checkout node + uses: actions/checkout@v6 + with: + fetch-depth: 1 + path: 'libbitcoin-node' + ref: ${{ github.event.inputs.tag-node }} + repository: ${{ github.repository_owner }}/libbitcoin-node + + - name: checkout network + uses: actions/checkout@v6 + with: + fetch-depth: 1 + path: 'libbitcoin-network' + ref: ${{ github.event.inputs.tag-network }} + repository: ${{ github.repository_owner }}/libbitcoin-network + + - name: checkout database + uses: actions/checkout@v6 + with: + fetch-depth: 1 + path: 'libbitcoin-database' + ref: ${{ github.event.inputs.tag-database }} + repository: ${{ github.repository_owner }}/libbitcoin-database + + - name: checkout system + uses: actions/checkout@v6 + with: + fetch-depth: 1 + path: 'libbitcoin-system' + ref: ${{ github.event.inputs.tag-system }} + repository: ${{ github.repository_owner }}/libbitcoin-system + + - name: Prepare toolchain [linux] + if: ${{ startsWith(matrix.image, 'ubuntu') }} + shell: bash + run: | + sudo apt-get update + sudo apt-get install -y ${{ matrix.packages || '' }} git build-essential autoconf automake libtool pkg-config + + - name: Prepare toolchain [macos] + if: ${{ startsWith(matrix.image, 'macos') }} + shell: bash + run: | + brew install ${{ matrix.packages || '' }} autoconf automake libtool + if [[ -n "${{ matrix.llvm }}" ]]; then + echo "PATH=/opt/homebrew/opt/${{ matrix.llvm }}/bin:${PATH}" >> $GITHUB_ENV + fi + - name: Prepare toolchain [windows] + if: ${{ startsWith(matrix.image, 'windows') }} + uses: microsoft/setup-msbuild@v3 + with: + msbuild-architecture: x64 + + - name: Environmental Variable Computation + if: ${{ matrix.toolchain == 'cmake' || matrix.toolchain == 'gnu' || matrix.toolchain == 'presets' }} + shell: bash + run: | + if [[ "${{ matrix.link }}" == "dynamic" ]]; then + echo "LDFLAGS=-Wl,-rpath,${{ github.workspace }}/prefix/lib" >> $GITHUB_ENV + fi + + - name: Normalize output location + id: normalizer + shell: bash + run: | + mkdir candidate + if [[ "${{ matrix.toolchain }}" == "cmake" ]]; then + CANDIDATE="prefix/bin/bs" + CANONICAL="bs-${{ matrix.toolchain }}-${{ matrix.link }}-${{ matrix.configuration }}" + elif [[ ${{ matrix.toolchain }} == "gnu" ]]; then + CANDIDATE="prefix/bin/bs" + CANONICAL="bs-${{ matrix.toolchain }}-${{ matrix.link }}-${{ matrix.configuration }}" + elif [[ ${{ matrix.toolchain }} == "presets" ]]; then + CANDIDATE="prefix/${{ matrix.preset }}/bin/bs" + CANONICAL="bs-${{ matrix.toolchain }}-${{ matrix.link }}-${{ matrix.configuration }}" + elif [[ ${{ matrix.toolchain }} == "msbuild" ]]; then + if [[ "${{ matrix.configuration }}" == *Debug* ]]; then + CONFIG="Debug" + elif [[ "${{ matrix.configuration }}" == *Release* ]]; then + CONFIG="Release" + else + echo "Configuration unexpected." + exit 1 + fi + CANDIDATE="libbitcoin-server/bin/x64/${CONFIG}/v143/static/bs.exe" + CANONICAL="bs-${{ matrix.toolchain }}-${{ matrix.platform }}-${{ matrix.version }}-${{ matrix.configuration }}.exe" + else + echo "\e[0;91mUnexpected toolchain provided.\e[0m" + exit 1 + fi + echo "PAYLOAD" >> candidate/${CANONICAL} + echo "candidate_identifier=${CANONICAL}" >> "$GITHUB_OUTPUT" + + - name: Inventory results + working-directory: candidate + shell: bash + run: | + ls -lahR + + - name: Upload artifacts + uses: actions/upload-artifact@v7.0.1 + with: + name: ${{ steps.normalizer.outputs.candidate_identifier }} + path: candidate/* + retention-days: 1 + if-no-files-found: error + + sign: + name: Sign artifacts + + needs: build-candidates + + environment: release + + permissions: + contents: write + + runs-on: ubuntu-latest + + steps: + - name: Retrieve artifacts + uses: actions/download-artifact@v8.0.1 + with: + path: artifacts + + - name: GPG Keyring Initialization + env: + SIGNING_PRIVATE_KEY: ${{ secrets.SIGNING_KEY }} + run: | + echo "Importing GPG signing key..." + # Import the private key + echo "$SIGNING_PRIVATE_KEY" | gpg --batch --import --pinentry-mode loopback + # Get the key fingerprint (first secret key) + KEY_FINGERPRINT=$(gpg --list-secret-keys --with-colons | grep '^sec' | head -n1 | cut -d: -f5) + if [ -z "$KEY_FINGERPRINT" ]; then + echo "Error: No secret key found after import" + exit 1 + fi + echo "Imported key fingerprint: $KEY_FINGERPRINT" + # Set ultimate trust (required for non-interactive signing) + echo -e "5\ny\n" | gpg --batch --command-fd 0 --edit-key "$KEY_FINGERPRINT" trust >/dev/null 2>&1 + # Configure gpg-agent for loopback pinentry (handles passphrase non-interactively) + mkdir -p ~/.gnupg + echo "allow-loopback-pinentry" > ~/.gnupg/gpg-agent.conf + echo "use-agent" > ~/.gnupg/gpg.conf + # Reload agent + gpgconf --kill gpg-agent + gpgconf --launch gpg-agent + + - name: execute signature + working-directory: artifacts + shell: bash + run: | + echo "Signing artifacts..." + find . -mindepth 1 -maxdepth 1 -type d ! -name '.*' -print0 | \ + while IFS= read -r -d '' dir; do + dir_name="${dir#./}" # remove leading ./ + echo "📁 Directory: $dir_name" + # Walk files inside this directory (only direct children, not recursive) + find "$dir" -maxdepth 1 -type f -print0 | \ + while IFS= read -r -d '' file; do + file_name=$(basename "$file") + echo " 📄 $file_name" + gpg --batch --yes --detach-sign --armor "$file" + done + done + + - name: GPG Keyring Cleanup + if: always() + run: | + echo "Cleaning up GPG keyring..." + gpg --batch \ + --yes \ + --delete-secret-keys \ + --delete-keys \ + "$(gpg --list-secret-keys --with-colons | grep '^sec' | cut -d: -f5)" 2>/dev/null || true + rm -rf ~/.gnupg + echo "Cleanup complete." + + - name: Inventory results + working-directory: artifacts + shell: bash + run: | + ls -lahR + + - name: Upload signed artifacts + uses: actions/upload-artifact@v7.0.1 + with: + if-no-files-found: error + name: server-${{ github.event.inputs.tag-server }}-signed-artifacts + path: artifacts/*/* + retention-days: 1 + + publish: + name: Publish release + + needs: sign + + environment: release + + permissions: + contents: write + + runs-on: ubuntu-latest + + steps: + - name: Download signed artifacts + uses: actions/download-artifact@v8.0.1 + with: + name: server-${{ github.event.inputs.tag-server }}-signed-artifacts + path: signed-release + + - name: Inventory results + working-directory: signed-release + shell: bash + run: | + ls -lahR + + - name: Populate release + uses: softprops/action-gh-release@v3.0.0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ github.event.inputs.tag-server }} + draft: true + prerelease: true + overwrite_files: false + files: | + signed-release/*/* + body: | + **libbitcoin-server ${{ github.event.inputs.tag-server }}** + Built from: + - system: ${{ github.event.inputs.tag-system }} + - database: ${{ github.event.inputs.tag-database }} + - network: ${{ github.event.inputs.tag-network }} + - node: ${{ github.event.inputs.tag-node }} diff --git a/builds/cmake/install-cmake.sh b/builds/cmake/install-cmake.sh index d3428f2f..31e57757 100755 --- a/builds/cmake/install-cmake.sh +++ b/builds/cmake/install-cmake.sh @@ -105,6 +105,7 @@ main() (--build-full-repositories) BUILD_FULL_REPOSITORIES="yes";; (--build-use-local-src) BUILD_USE_LOCAL_SRC="yes";; (--build-parallel=*) PARALLEL="${OPTION#*=}";; + (--build-skip-tests) BUILD_SKIP_TESTS="yes";; (--prefix=*) PREFIX="${OPTION#*=}";; (--verbose) DISPLAY_VERBOSE="yes";; (--help|-h) DISPLAY_HELP="yes";; @@ -323,8 +324,7 @@ main() msg_verbose "Exporting CFLAGS '${CFLAGS}'" else msg_verbose "CFLAGS initially '${CFLAGS}'" - SANITIZED_CFLAGS=$(strip_optimization "$CFLAGS") - export CFLAGS="${SANITIZED_CFLAGS} ${BUILD_FLAGS}" + export CFLAGS="${CFLAGS} ${BUILD_FLAGS}" msg_verbose "CFLAGS modified to '${CFLAGS}'" fi @@ -333,8 +333,7 @@ main() msg_verbose "Exporting CXXFLAGS '${CXXFLAGS}'" else msg_verbose "CXXFLAGS initially '${CXXFLAGS}'" - SANITIZED_CXXFLAGS=$(strip_optimization "$CXXFLAGS") - export CXXFLAGS="${SANITIZED_CXXFLAGS} ${BUILD_FLAGS}" + export CXXFLAGS="${CXXFLAGS} ${BUILD_FLAGS}" msg_verbose "CXXFLAGS modified to '${CXXFLAGS}'" fi fi @@ -494,7 +493,9 @@ main() local SAVE_CPPFLAGS="${CPPFLAGS}" export CPPFLAGS="${CPPFLAGS} ${libbitcoin_server_FLAGS[@]}" build_cmake "libbitcoin-server" "builds/cmake" "${PARALLEL}" "${libbitcoin_server_OPTIONS[@]}" "${CONFIGURE_OPTIONS[@]}" - test_make "libbitcoin-server" "test" "${PARALLEL}" + if ! [[ "${BUILD_SKIP_TESTS}" == "yes" ]]; then + test_make "libbitcoin-server" "test" "${PARALLEL}" + fi install_make "libbitcoin-server" export CPPFLAGS="${SAVE_CPPFLAGS}" @@ -806,6 +807,7 @@ display_build_variables() msg "BUILD_LINK : ${BUILD_LINK}" msg "BUILD_FULL_REPOSITORIES : ${BUILD_FULL_REPOSITORIES}" msg "BUILD_USE_LOCAL_SRC : ${BUILD_USE_LOCAL_SRC}" + msg "BUILD_SKIP_TESTS : ${BUILD_SKIP_TESTS}" msg "PARALLEL : ${PARALLEL}" msg "PREFIX : ${PREFIX}" msg "DISPLAY_VERBOSE : ${DISPLAY_VERBOSE}" @@ -908,16 +910,6 @@ disable_exit_on_error() eval "${OPTS_DISABLE}" } -strip_optimization() -{ - echo "$1" | sed -E ' - s/-O([0-3]|s|fast|g|z|size|speed)?b?/ /g - s/-g([0-3]|gdb|dwarf[0-9]*)?b?/ /g - s/[[:space:]]+/ /g - s/^ | $//g - ' -} - create_directory() { local DIRECTORY="$1" diff --git a/builds/cmake/install-presets.sh b/builds/cmake/install-presets.sh index 2402e675..aa920ac0 100755 --- a/builds/cmake/install-presets.sh +++ b/builds/cmake/install-presets.sh @@ -93,6 +93,7 @@ main() (--build-full-repositories) BUILD_FULL_REPOSITORIES="yes";; (--build-use-local-src) BUILD_USE_LOCAL_SRC="yes";; (--build-parallel=*) PARALLEL="${OPTION#*=}";; + (--build-skip-tests) BUILD_SKIP_TESTS="yes";; (--verbose) DISPLAY_VERBOSE="yes";; (--help|-h) DISPLAY_HELP="yes";; (-DCMAKE_PREFIX_PATH=*) CMAKE_PREFIX_PATH="${OPTION#*=}";; @@ -344,8 +345,7 @@ main() msg_verbose "Exporting CFLAGS '${CFLAGS}'" else msg_verbose "CFLAGS initially '${CFLAGS}'" - SANITIZED_CFLAGS=$(strip_optimization "$CFLAGS") - export CFLAGS="${SANITIZED_CFLAGS} ${BUILD_FLAGS}" + export CFLAGS="${CFLAGS} ${BUILD_FLAGS}" msg_verbose "CFLAGS modified to '${CFLAGS}'" fi @@ -354,8 +354,7 @@ main() msg_verbose "Exporting CXXFLAGS '${CXXFLAGS}'" else msg_verbose "CXXFLAGS initially '${CXXFLAGS}'" - SANITIZED_CXXFLAGS=$(strip_optimization "$CXXFLAGS") - export CXXFLAGS="${SANITIZED_CXXFLAGS} ${BUILD_FLAGS}" + export CXXFLAGS="${CXXFLAGS} ${BUILD_FLAGS}" msg_verbose "CXXFLAGS modified to '${CXXFLAGS}'" fi fi @@ -515,7 +514,9 @@ main() local SAVE_CPPFLAGS="${CPPFLAGS}" export CPPFLAGS="${CPPFLAGS} ${libbitcoin_server_FLAGS[@]}" build_preset "libbitcoin-server" "builds/cmake" "${PARALLEL}" "${libbitcoin_server_OPTIONS[@]}" "${CONFIGURE_OPTIONS[@]}" - test_make "libbitcoin-server" "test" "${PARALLEL}" + if ! [[ "${BUILD_SKIP_TESTS}" == "yes" ]]; then + test_make "libbitcoin-server" "test" "${PARALLEL}" + fi install_make "libbitcoin-server" export CPPFLAGS="${SAVE_CPPFLAGS}" @@ -878,6 +879,7 @@ display_build_variables() msg "BUILD_LINK : ${BUILD_LINK}" msg "BUILD_FULL_REPOSITORIES : ${BUILD_FULL_REPOSITORIES}" msg "BUILD_USE_LOCAL_SRC : ${BUILD_USE_LOCAL_SRC}" + msg "BUILD_SKIP_TESTS : ${BUILD_SKIP_TESTS}" msg "PARALLEL : ${PARALLEL}" msg "PREFIX : ${PREFIX}" msg "DISPLAY_VERBOSE : ${DISPLAY_VERBOSE}" @@ -971,16 +973,6 @@ disable_exit_on_error() eval "${OPTS_DISABLE}" } -strip_optimization() -{ - echo "$1" | sed -E ' - s/-O([0-3]|s|fast|g|z|size|speed)?b?/ /g - s/-g([0-3]|gdb|dwarf[0-9]*)?b?/ /g - s/[[:space:]]+/ /g - s/^ | $//g - ' -} - create_directory() { local DIRECTORY="$1" diff --git a/builds/gnu/install-gnu.sh b/builds/gnu/install-gnu.sh index e1042d6c..c58ee9d4 100755 --- a/builds/gnu/install-gnu.sh +++ b/builds/gnu/install-gnu.sh @@ -105,6 +105,7 @@ main() (--build-full-repositories) BUILD_FULL_REPOSITORIES="yes";; (--build-use-local-src) BUILD_USE_LOCAL_SRC="yes";; (--build-parallel=*) PARALLEL="${OPTION#*=}";; + (--build-skip-tests) BUILD_SKIP_TESTS="yes";; (--prefix=*) PREFIX="${OPTION#*=}";; (--verbose) DISPLAY_VERBOSE="yes";; (--help|-h) DISPLAY_HELP="yes";; @@ -302,8 +303,7 @@ main() msg_verbose "Exporting CFLAGS '${CFLAGS}'" else msg_verbose "CFLAGS initially '${CFLAGS}'" - SANITIZED_CFLAGS=$(strip_optimization "$CFLAGS") - export CFLAGS="${SANITIZED_CFLAGS} ${BUILD_FLAGS}" + export CFLAGS="${CFLAGS} ${BUILD_FLAGS}" msg_verbose "CFLAGS modified to '${CFLAGS}'" fi @@ -312,8 +312,7 @@ main() msg_verbose "Exporting CXXFLAGS '${CXXFLAGS}'" else msg_verbose "CXXFLAGS initially '${CXXFLAGS}'" - SANITIZED_CXXFLAGS=$(strip_optimization "$CXXFLAGS") - export CXXFLAGS="${SANITIZED_CXXFLAGS} ${BUILD_FLAGS}" + export CXXFLAGS="${CXXFLAGS} ${BUILD_FLAGS}" msg_verbose "CXXFLAGS modified to '${CXXFLAGS}'" fi fi @@ -485,7 +484,9 @@ main() local SAVE_CPPFLAGS="${CPPFLAGS}" export CPPFLAGS="${CPPFLAGS} ${libbitcoin_server_FLAGS[@]}" build_gnu "libbitcoin-server" "." "${PARALLEL}" "${libbitcoin_server_OPTIONS[@]}" "${CONFIGURE_OPTIONS[@]}" - test_make "libbitcoin-server" "check" "${PARALLEL}" + if ! [[ "${BUILD_SKIP_TESTS}" == "yes" ]]; then + test_make "libbitcoin-server" "check" "${PARALLEL}" + fi install_make "libbitcoin-server" export CPPFLAGS="${SAVE_CPPFLAGS}" @@ -802,6 +803,7 @@ display_build_variables() msg "BUILD_LINK : ${BUILD_LINK}" msg "BUILD_FULL_REPOSITORIES : ${BUILD_FULL_REPOSITORIES}" msg "BUILD_USE_LOCAL_SRC : ${BUILD_USE_LOCAL_SRC}" + msg "BUILD_SKIP_TESTS : ${BUILD_SKIP_TESTS}" msg "PARALLEL : ${PARALLEL}" msg "PREFIX : ${PREFIX}" msg "DISPLAY_VERBOSE : ${DISPLAY_VERBOSE}" @@ -900,16 +902,6 @@ disable_exit_on_error() eval "${OPTS_DISABLE}" } -strip_optimization() -{ - echo "$1" | sed -E ' - s/-O([0-3]|s|fast|g|z|size|speed)?b?/ /g - s/-g([0-3]|gdb|dwarf[0-9]*)?b?/ /g - s/[[:space:]]+/ /g - s/^ | $//g - ' -} - create_directory() { local DIRECTORY="$1" diff --git a/builds/msvc/build-msvc.cmd b/builds/msvc/build-msvc.cmd index a1d808a7..13cfbb1e 100644 --- a/builds/msvc/build-msvc.cmd +++ b/builds/msvc/build-msvc.cmd @@ -17,6 +17,10 @@ REM --build-version version Build MSVC version. REM --build-src-dir path Location of sources. REM --build-full-repositories Sync full github repositories. REM --build-use-local-src Use existing sources in build-src-dir path. +REM --build-mode mode Determines action on target. +REM Default: Rebuild +REM --build-symbols mode Determines treatment of symbols. +REM Values: default, disabled, public-only REM --verbose Display verbose script output. REM --help, -h Display usage, overriding script execution. REM @@ -134,6 +138,20 @@ if "!libbitcoin_server_TAG!" == "" ( ) ) + if "!BUILD_SYMBOLS!" == "" ( + call :msg_verbose "BUILD_SYMBOLS not defined or empty, defaulting to 'default' behavior." + ) else if "!BUILD_SYMBOLS!" == "default" ( + call :msg_verbose "BUILD_SYMBOLS 'default'." + ) else if "!BUILD_SYMBOLS!" == "disabled" ( + call :msg_verbose "BUILD_SYMBOLS 'disabled'." + ) else if "!BUILD_SYMBOLS!" == "public-only" ( + call :msg_verbose "BUILD_SYMBOLS 'public-only'." + ) else ( + call :msg_error "BUILD_SYMBOLS value '!BUILD_SYMBOLS!' unrecognized." + call :help + exit /b 1 + ) + call :msg_heading "Configuration" call :display_build_variables @@ -190,10 +208,20 @@ if "!libbitcoin_server_TAG!" == "" ( if %ERRORLEVEL% neq 0 ( exit /b %ERRORLEVEL% ) - call :build_msbuild "libbitcoin-server" "builds\msvc\%proj_version%" + call :build_msbuild "libbitcoin-server" "builds\msvc\%proj_version%" "libbitcoin-server" + if %ERRORLEVEL% neq 0 ( + exit /b %ERRORLEVEL% + ) + call :build_msbuild "libbitcoin-server" "builds\msvc\%proj_version%" "bs" + if %ERRORLEVEL% neq 0 ( + exit /b %ERRORLEVEL% + ) + if not "!BUILD_SKIP_TESTS!" == "yes" ( + call :build_msbuild "libbitcoin-server" "builds\msvc\%proj_version%" "libbitcoin-server-test" if %ERRORLEVEL% neq 0 ( exit /b %ERRORLEVEL% ) + ) call :pop_directory if %ERRORLEVEL% neq 0 ( @@ -222,10 +250,18 @@ if "!libbitcoin_server_TAG!" == "" ( ) else if "%~1" == "--build-version" ( set "BUILD_VERSION=%~2" shift + ) else if "%!1" == "--build-mode" ( + set "BUILD_MODE=%~2" + shift + ) else if "%!1" == "--build-symbols" ( + set "BUILD_SYMBOLS=%~2" + shift ) else if "%~1" == "--build-full-repositories" ( set "BUILD_FULL_REPOSITORIES=yes" ) else if "%~1" == "--build-use-local-src" ( set "BUILD_USE_LOCAL_SRC=yes" + ) else if "%~1" == "--build-skip-tests" ( + set "BUILD_SKIP_TESTS=yes" ) else if "%~1" == "--verbose" ( set "DISPLAY_VERBOSE=yes" ) else if "%~1" == "-v" ( @@ -234,6 +270,12 @@ if "!libbitcoin_server_TAG!" == "" ( set "SHOW_HELP=yes" ) else if "%~1" == "-h" ( set "SHOW_HELP=yes" + ) else ( + if "!UNHANDLED_ARGS!" == "" ( + set "UNHANDLED_ARGS=%1" + ) else ( + set "UNHANDLED_ARGS=!UNHANDLED_ARGS! %1" + ) ) shift @@ -289,10 +331,23 @@ if "!libbitcoin_server_TAG!" == "" ( set "RELATIVE_PATH=%~2" set "TARGET=%~3" - if "%TARGET%" == "" ( - set "TARGET_ARG=" + if not "%TARGET%" == "" ( + if not "!BUILD_MODE!" == "" ( + set "TARGET_ARG=/target:%TARGET%:!BUILD_MODE!" + ) else ( + set "TARGET_ARG=/target:%TARGET%" + ) ) else ( - set "TARGET_ARG=/target:%TARGET%:Rebuild" + if not "!BUILD_MODE!" == "" ( + set "TARGET_ARG=/target:!BUILD_MODE!" + ) + ) + + set "SYMBOLS_ARG=" + if "!BUILD_SYMBOLS!" == "disabled" ( + set "SYMBOLS_ARG=/p:LinkerOptions=/PDBSTRIPPED " + ) else if "!BUILD_SYMBOLS!" == "public-only" ( + set "SYMBOLS_ARG=/p:DebugSymbols=false " ) call :push_directory "!BUILD_SRC_DIR!\%PROJECT%\%RELATIVE_PATH%\!BUILD_VERSION!" @@ -305,10 +360,10 @@ if "!libbitcoin_server_TAG!" == "" ( exit /b %ERRORLEVEL% ) - !MSBUILD_EXE! /verbosity:!MSBUILD_VERBOSE! /p:Platform=!BUILD_PLATFORM! /p:Configuration=!BUILD_CONFIG! /p:PreferredToolArchitecture=x64 %TARGET_ARG% %PROJECT%.sln /p:PreBuildEventUseInBuild=false /p:PostBuildEventUseInBuild=false + !MSBUILD_EXE! /verbosity:!MSBUILD_VERBOSE! !SYMBOLS_ARG!/p:Platform=!BUILD_PLATFORM! /p:Configuration=!BUILD_CONFIG! /p:PreferredToolArchitecture=x64 %TARGET_ARG% %PROJECT%.sln /p:PreBuildEventUseInBuild=false /p:PostBuildEventUseInBuild=false !UNHANDLED_ARGS! if %ERRORLEVEL% neq 0 ( - call :msg_error "!MSBUILD_EXE! /verbosity:!MSBUILD_VERBOSE! /p:Platform=!BUILD_PLATFORM! /p:Configuration=!BUILD_CONFIG! /p:PreferredToolArchitecture=x64 %TARGET_ARG% %PROJECT%.sln /p:PreBuildEventUseInBuild=false /p:PostBuildEventUseInBuild=false" + call :msg_error "!MSBUILD_EXE! /verbosity:!MSBUILD_VERBOSE! !SYMBOLS_ARG!/p:Platform=!BUILD_PLATFORM! /p:Configuration=!BUILD_CONFIG! /p:PreferredToolArchitecture=x64 %TARGET_ARG% %PROJECT%.sln /p:PreBuildEventUseInBuild=false /p:PostBuildEventUseInBuild=false !UNHANDLED_ARGS!" call :pop_directory exit /b 1 ) @@ -335,6 +390,8 @@ if "!libbitcoin_server_TAG!" == "" ( call :msg "BUILD_SRC_DIR : !BUILD_SRC_DIR!" call :msg "BUILD_FULL_REPOSITORIES : !BUILD_FULL_REPOSITORIES!" call :msg "BUILD_USE_LOCAL_SRC : !BUILD_USE_LOCAL_SRC!" + call :msg "BUILD_MODE : !BUILD_MODE!" + call :msg "BUILD_SYMBOLS : !BUILD_SYMBOLS!" call :msg "DISPLAY_VERBOSE : !DISPLAY_VERBOSE!" call :msg "SHOW_HELP : !SHOW_HELP!" exit /b %ERRORLEVEL% @@ -368,6 +425,10 @@ if "!libbitcoin_server_TAG!" == "" ( call :msg "--build-src-dir path Location of sources." call :msg "--build-full-repositories Sync full github repositories." call :msg "--build-use-local-src Use existing sources in build-src-dir path." + call :msg "--build-mode mode Determines action on target." + call :msg " Default: Rebuild" + call :msg "--build-symbols mode Determines treatment of symbols." + call :msg " Values: default, disabled, public-only" call :msg "--verbose Display verbose script output." call :msg "--help, -h Display usage, overriding script execution." exit /b %ERRORLEVEL%