diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 33d95367..b26c578b 100755 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,26 +18,29 @@ jobs: - os: ubuntu-latest script: generate4.sh branch: master + shell: bash - os: macos-latest script: generate4.sh branch: master + shell: bash - os: windows-latest script: generate4.cmd branch: master + shell: cmd runs-on: ${{ matrix.os }} steps: - - name: Checkout repository + - name: Checkout repository [build] uses: actions/checkout@v6 with: fetch-depth: 1 path: 'libbitcoin-build' repository: ${{ github.repository }} - - name: Checkout repository + - name: Checkout repository [system] uses: actions/checkout@v6 with: fetch-depth: 1 @@ -45,23 +48,7 @@ jobs: repository: '${{ github.repository_owner }}/libbitcoin-system' ref: ${{ matrix.branch }} - - name: Checkout repository - uses: actions/checkout@v6 - with: - fetch-depth: 1 - path: 'libbitcoin-protocol' - repository: '${{ github.repository_owner }}/libbitcoin-protocol' - ref: ${{ matrix.branch }} - - - name: Checkout repository - uses: actions/checkout@v6 - with: - fetch-depth: 1 - path: 'libbitcoin-client' - repository: '${{ github.repository_owner }}/libbitcoin-client' - ref: ${{ matrix.branch }} - - - name: Checkout repository + - name: Checkout repository [explorer] uses: actions/checkout@v6 with: fetch-depth: 1 @@ -69,7 +56,7 @@ jobs: repository: '${{ github.repository_owner }}/libbitcoin-explorer' ref: ${{ matrix.branch }} - - name: Checkout repository + - name: Checkout repository [network] uses: actions/checkout@v6 with: fetch-depth: 1 @@ -77,15 +64,7 @@ jobs: repository: '${{ github.repository_owner }}/libbitcoin-network' ref: ${{ matrix.branch }} - - name: Checkout repository - uses: actions/checkout@v6 - with: - fetch-depth: 1 - path: 'libbitcoin-consensus' - repository: '${{ github.repository_owner }}/libbitcoin-consensus' - ref: ${{ matrix.branch }} - - - name: Checkout repository + - name: Checkout repository [database] uses: actions/checkout@v6 with: fetch-depth: 1 @@ -93,15 +72,7 @@ jobs: repository: '${{ github.repository_owner }}/libbitcoin-database' ref: ${{ matrix.branch }} - - name: Checkout repository - uses: actions/checkout@v6 - with: - fetch-depth: 1 - path: 'libbitcoin-blockchain' - repository: '${{ github.repository_owner }}/libbitcoin-blockchain' - ref: ${{ matrix.branch }} - - - name: Checkout repository + - name: Checkout repository [node] uses: actions/checkout@v6 with: fetch-depth: 1 @@ -109,7 +80,7 @@ jobs: repository: '${{ github.repository_owner }}/libbitcoin-node' ref: ${{ matrix.branch }} - - name: Checkout repository + - name: Checkout repository [server] uses: actions/checkout@v6 with: fetch-depth: 1 @@ -117,7 +88,7 @@ jobs: repository: '${{ github.repository_owner }}/libbitcoin-server' ref: ${{ matrix.branch }} - - name: Checkout repository + - name: Checkout repository [zeromq/gsl] if: ${{ startsWith(matrix.os, 'macos') || startsWith(matrix.os, 'ubuntu') }} uses: actions/checkout@v6 with: @@ -125,30 +96,30 @@ jobs: path: 'gsl' repository: 'zeromq/gsl' - - name: Prepare toolchain [macos] + - name: Prepare platform toolchain [macos] if: ${{ startsWith(matrix.os, 'macos') }} run: | brew install pcre - - name: Prepare toolchain [ubuntu] + - name: Prepare platform toolchain [ubuntu] if: ${{ startsWith(matrix.os, 'ubuntu') }} run: | sudo apt-get update sudo apt-get install libpcre3-dev - - name: Prepare toolchain [windows] + - name: Prepare platform toolchain [windows] if: ${{ startsWith(matrix.os, 'windows') }} uses: microsoft/setup-msbuild@v3 - - name: Build gsl [macos] + - name: Aquire gsl [macos] if: ${{ startsWith(matrix.os, 'macos') }} run: | pushd "gsl/src" CPPFLAGS="-I/opt/homebrew/include ${CPPFLAGS}" make --silent sudo make install popd - - - name: Build gsl [ubuntu] + + - name: Aquire gsl [ubuntu] if: ${{ startsWith(matrix.os, 'ubuntu') }} run: | pushd "gsl/src" @@ -156,21 +127,28 @@ jobs: sudo make install popd - - name: Retrieve gsl binary [windows] + - name: Aquire gsl [windows] if: ${{ startsWith(matrix.os, 'windows') }} shell: powershell run: | - Invoke-WebRequest -Uri "https://github.com/imatix/gsl/releases/download/NuGet-4.1.0.1/gsl.exe" -OutFile "${{ github.workspace }}\libbitcoin-build\gsl.exe" + echo "${{ github.workspace }}\libbitcoin-build\bin\winx64" | Out-File -Append -FilePath $env:GITHUB_PATH -Encoding utf8 - - name: Execute generation [macos, ubuntu] - if: ${{ startsWith(matrix.os, 'macos') || startsWith(matrix.os, 'ubuntu') }} - run: | - pushd libbitcoin-build + - name: Execute generation [bash] + if: ${{ startsWith(matrix.shell, 'bash') }} + shell: bash + working-directory: ${{ github.workspace }}/libbitcoin-build + run: > ./${{ matrix.script }} - popd - - name: Execute generation [windows] - if: ${{ startsWith(matrix.os, 'windows') }} + - name: Execute generation [cmd] + if: ${{ startsWith(matrix.shell, 'cmd') }} shell: cmd - run: .\libbitcoin-build\${{ matrix.script }} + working-directory: ${{ github.workspace }}\libbitcoin-build + run: .\\${{ matrix.script }} + + - name: Execute generation [powershell] + if: ${{ startsWith(matrix.shell, 'powershell') }} + shell: pwsh + working-directory: ${{ github.workspace }}\libbitcoin-build + run: .\\${{ matrix.script }} diff --git a/bin/winx64/gsl.exe b/bin/winx64/gsl.exe new file mode 100755 index 00000000..bab148f8 Binary files /dev/null and b/bin/winx64/gsl.exe differ diff --git a/generate.cmd b/generate.cmd index af85ffd1..74b7bee0 100644 --- a/generate.cmd +++ b/generate.cmd @@ -1,6 +1,5 @@ @echo off setlocal EnableDelayedExpansion - REM ########################################################################### REM Copyright (c) 2014-2026 libbitcoin developers (see COPYING). REM @@ -16,54 +15,98 @@ REM ########################################################################### REM Do everything relative to this file location. pushd %~dp0 +set "GSL_EXE=gsl -q" + if "%~1"=="" ( - echo Usage: %~nx0 configuration [targets...] - echo. - echo configuration required xml file - echo targets all targets to be copied + call :msg "Usage: %~nx0 configuration [targets...]" + call :msg "" + call :msg " configuration required xml file" + call :msg " targets all targets to be copied" exit /b 1 ) -set "configuration=%~1" +set "CONFIG=%~1" shift -set "targets=" +set "TARGETS=" call :populate_targets %* -set "names[1]=generate_artifacts" -set "names[2]=copy_statics" -set "names[3]=copy_projects" -set "names.length=3" - -for /L %%i in (1,1,%names.length%) do ( - echo gsl -q -script:"process\!names[%%i]!.cmd.gsl" "!configuration!" - gsl -q -script:"process\!names[%%i]!.cmd.gsl" "!configuration!" - if %errorlevel% neq 0 ( - echo FAILURE: evaluating "process\!names[%%i]!.cmd.gsl". - exit /b %errorlevel% +set "NAMES[1]=generate_artifacts" +set "NAMES[2]=copy_statics" +set "NAMES[3]=copy_projects" +set "NAMES.length=3" + +for /L %%i in (1,1,%NAMES.length%) do ( + call :msg "!GSL_EXE! -q -script:'process\!NAMES[%%i]!.cmd.gsl' '!CONFIG!'" + !GSL_EXE! -q -script:"process\!NAMES[%%i]!.cmd.gsl" "!CONFIG!" + if %ERRORLEVEL% neq 0 ( + echo FAILURE: evaluating "process\!NAMES[%%i]!.cmd.gsl". + exit /b %ERRORLEVEL% ) ) REM Execute process scripts (explicit enumeration). pushd process -for /L %%i in (1,1,%names.length%) do ( - call !names[%%i]!.cmd !targets! - if %errorlevel% neq 0 ( - exit /b %errorlevel% +for /L %%i in (1,1,%NAMES.length%) do ( + call !NAMES[%%i]!.cmd !targets! + if %ERRORLEVEL% neq 0 ( + exit /b %ERRORLEVEL% ) ) popd -echo "Generation for configuration %CONFIGURATION% complete." -::pause +echo "Generation for configuration %CONFIG% complete." +REM Commented out until calling script is obsolete +REM if not defined CI ( +REM pause +REM ) + exit /b 0 + + :populate_targets shift - :begin +:begin if "%1"=="" goto done - set "targets=%targets% %~1" + set "TARGETS=!TARGETS! %~1" shift goto begin - :done +:done exit /b 0 + +:msg_heading + call :msg "***************************************************************************" + call :msg "%~1" + call :msg "***************************************************************************" + exit /b %ERRORLEVEL% + +:msg + if "%~1" == "" ( + echo. + ) else ( + echo %~1 + ) + exit /b %ERRORLEVEL% + +:msg_empty + echo. + exit /b %ERRORLEVEL% + +:msg_verbose + if "!DISPLAY_VERBOSE!" == "yes" ( + echo %~1 + ) + exit /b %ERRORLEVEL% + +:msg_success + echo %~1 + exit /b %ERRORLEVEL% + +:msg_warn + echo %~1 + exit /b %ERRORLEVEL% + +:msg_error + echo %~1 + exit /b %ERRORLEVEL% diff --git a/generate.sh b/generate.sh index dac6ef50..1512db25 100755 --- a/generate.sh +++ b/generate.sh @@ -8,44 +8,141 @@ # See https://github.com/imatix/gsl for details. ############################################################################### -generate_input() +OPTS_ENABLE="set -eo pipefail" +OPTS_DISABLE="set +e" + +eval "${OPTS_ENABLE}" +trap 'msg_error "FATAL ERROR: Command failed at line ${LINENO}: ${BASH_COMMAND}" >&2' ERR + +GSL="gsl -q" +COLOR_CYAN='\e[0;96m' +COLOR_GREEN='\e[0;92m' +COLOR_RED='\e[0;91m' +COLOR_YELLOW='\e[0;93m' +COLOR_RESET='\e[0m' + +main() { if [[ $# -eq 0 ]]; then - echo "Usage: ${BASH_SOURCE[0]##*/} configuration [targets...]" - echo "" - echo " configuration required xml file" - echo " targets all targets to be copied" + display_usage exit 1 fi CONFIGURATION=$1 shift - echo "Generating for configuration ${CONFIGURATION}..." + # Do everything relative to this file location. + BUILD_PATH=`dirname "$0"` + push_directory ${BUILD_PATH} + + msg "Generating for configuration ${CONFIGURATION}..." # Generate process scripts (explict enumeration). - eval gsl -q -script:process/generate_artifacts.sh.gsl ${CONFIGURATION} - eval gsl -q -script:process/copy_statics.sh.gsl ${CONFIGURATION} - eval gsl -q -script:process/copy_projects.sh.gsl ${CONFIGURATION} + msg_warn "${GSL} -script:process/generate_artifacts.sh.gsl ${CONFIGURATION}" + eval ${GSL} -script:process/generate_artifacts.sh.gsl ${CONFIGURATION} + msg_warn "${GSL} -script:process/copy_statics.sh.gsl ${CONFIGURATION}" + eval ${GSL} -script:process/copy_statics.sh.gsl ${CONFIGURATION} + msg_warn "${GSL} -script:process/copy_projects.sh.gsl ${CONFIGURATION}" + eval ${GSL} -script:process/copy_projects.sh.gsl ${CONFIGURATION} # Make process scripts executable. + msg_verbose "Modifying properties of shell scripts." eval chmod +x process/*.sh # Execute process scripts (explicit enumeration). - echo "Generating artifacts for configuration ${CONFIGURATION}..." + msg_warn "Generating artifacts for configuration ${CONFIGURATION}..." eval ./process/generate_artifacts.sh - pushd process + push_directory process eval ./copy_statics.sh "$@" eval ./copy_projects.sh "$@" - popd - echo "Generation for configuration ${CONFIGURATION} complete." + pop_directory + pop_directory + msg_success "Generation for configuration ${CONFIGURATION} completed successfully." } -# Exit this script on the first build error. -set -e +create_directory() +{ + local DIRECTORY="$1" + local MODE="$2" + + if [[ -d "${DIRECTORY}" ]]; then + if [[ ${MODE} == "-f" ]]; then + msg_warn "Reinitializing '${DIRECTORY}'..." + rm -rf "${DIRECTORY}" + mkdir -p "${DIRECTORY}" + else + msg_warn "Reusing existing '${DIRECTORY}'..." + fi + else + msg "Initializing '${DIRECTORY}'..." + mkdir -p "${DIRECTORY}" + fi +} + +display_usage() +{ + msg "Usage: ${BASH_SOURCE[0]##*/} configuration [targets...]" + msg "" + msg " configuration required xml file" + msg " targets all targets to be copied" +} -# Do everything relative to this file location. -BUILD_PATH=`dirname "$0"` -pushd ${BUILD_PATH} +create_directory_force() +{ + create_directory "$@" -f +} + +pop_directory() +{ + msg_verbose "*** move pre: '$(pwd)'" + popd >/dev/null + msg_verbose "*** move post: '$(pwd)'" +} + +push_directory() +{ + msg_verbose "*** move pre: '$(pwd)'" + local DIRECTORY="$1" + pushd "${DIRECTORY}" >/dev/null + msg_verbose "*** move post: '$(pwd)'" +} + +remove_directory_force() +{ + msg_verbose "*** removing: '$@'" + rm -rf "$@" +} + +msg_heading() +{ + printf "\n********************** %b **********************\n" "$@" +} + +msg_verbose() +{ + if [[ "${DISPLAY_VERBOSE}" == "yes" ]]; then + printf "${COLOR_CYAN}%b${COLOR_RESET}\n" "$@" + fi +} + +msg() +{ + printf "%b\n" "$@" +} + +msg_success() +{ + printf "${COLOR_GREEN}%b${COLOR_RESET}\n" "$@" +} + +msg_warn() +{ + printf "${COLOR_YELLOW}%b${COLOR_RESET}\n" "$@" +} + +msg_error() +{ + >&2 printf "${COLOR_RED}%b${COLOR_RESET}\n" "$@" +} -generate_input "$@" +main "$@" diff --git a/generate4.cmd b/generate4.cmd index 3cd2f946..c62b04c8 100644 --- a/generate4.cmd +++ b/generate4.cmd @@ -1,4 +1,6 @@ @echo off +setlocal EnableDelayedExpansion +setlocal EnableExtensions REM ########################################################################### REM Copyright (c) 2014-2026 libbitcoin developers (see COPYING). REM @@ -12,29 +14,137 @@ REM Extract gsl.exe from package using NuGet's File > Export REM ########################################################################### REM Do everything relative to this file location. +set "PATH_INITIAL=!CD!" pushd %~dp0 +set "PATH_FILE=!CD!" +set "GSL_EXE=gsl -q" REM Clean directories for generated build artifacts. rmdir /s /q "output" 2>NUL -REM Generate property copiers and artifact generators. -gsl -q -script:gsl.copy_properties.cmd generate4.xml -gsl -q -script:gsl.generate_artifacts.cmd generate4.xml +call :msg "Current directory: !CD!" +if not exist "!CD!\generate4.xml" ( + call :msg_error "Error: 'generate4.xml' not found in '!CD!'." + exit /b 1 +) else ( + call :msg_success "File 'generate4.xml' appears in '!CD!'." +) -REM Generate bindings from generated binding generators. -REM The path to swig.exe must be in our path. -REM for generate.repository by name as _repo -REM call ..\\$(_repo.name)\\bindings.bat -REM endfor +call :msg_heading "Begin Execution context" +call :msg "PATH_INITIAL : !PATH_INITIAL!" +call :msg "PATH_FILE : !PATH_FILE!" +call :msg "GSL_EXE : !GSL_EXE!" +call :msg "GITHUB_PATH : !GITHUB_PATH!" +call :msg_heading "End Execution context" -REM Execute property copiers and artifact generators. -call copy_properties.cmd -call generate_artifacts.cmd -call generate.cmd version4.xml %* -call copy_projects.cmd %* +!GSL_EXE! -q -script:"!CD!\gsl.copy_properties.cmd" "!CD!\generate4.xml" +if %ERRORLEVEL% neq 0 ( + call :msg_error "GSL execution failure." + exit /b 1 +) + +!GSL_EXE! -q -script:"!CD!\gsl.generate_artifacts.cmd" "!CD!\generate4.xml" +if %ERRORLEVEL% neq 0 ( + call :msg_error "GSL execution failure." + exit /b 1 +) + +if not exist "!CD!\copy_properties.cmd" ( + call :msg_error "Error: 'copy_properties.cmd' not found in '!CD!'." + exit /b 1 +) + +call :msg "Execute copy_properties.cmd..." +call "!CD!\copy_properties.cmd" +if %ERRORLEVEL% neq 0 ( + call :msg_error "Failure calling 'copy_properties.cmd'." + exit /b 1 +) + +if not exist "!CD!\generate_artifacts.cmd" ( + call :msg_error "Error: 'generate_artifacts.cmd' not found in '!CD!'." + exit /b 1 +) + +call :msg "Execute generate_artifacts.cmd..." +call "!CD!\generate_artifacts.cmd" +if %ERRORLEVEL% neq 0 ( + call :msg_error "Failure calling 'generate_artifacts.cmd'." + exit /b 1 +) + +if not exist "!CD!\generate.cmd" ( + call :msg_error "Error: 'generate.cmd' not found in '!CD!'." + exit /b 1 +) + +if not exist "!CD!\version4.xml" ( + call :msg_error "Error: 'version4.xml' not found in '!CD!'." + exit /b 1 +) + +call :msg "Execute generate.cmd..." +call "!CD!\generate.cmd" "!CD!\version4.xml" %* +if %ERRORLEVEL% neq 0 ( + call :msg_error "Failure calling 'generate.cmd'." + exit /b 1 +) + +if not exist "!CD!\copy_projects.cmd" ( + call :msg_error "Error: 'copy_projects.cmd' not found in '!CD!'." + exit /b 1 +) + +call :msg "Execute copy_projects.cmd..." +call "!CD!\copy_projects.cmd" %* +if %ERRORLEVEL% neq 0 ( + call :msg_error "Failure calling 'copy_projects.cmd'." + exit /b 1 +) REM Restore directory. popd +call :msg_success "Script execution completed successfully." REM Delay for manual confirmation. -call pause +if not defined CI ( + pause +) + +exit /b 0 + +:msg_heading + call :msg "***************************************************************************" + call :msg "%~1" + call :msg "***************************************************************************" + exit /b %ERRORLEVEL% + +:msg + if "%~1" == "" ( + echo. + ) else ( + echo %~1 + ) + exit /b %ERRORLEVEL% + +:msg_empty + echo. + exit /b %ERRORLEVEL% + +:msg_verbose + if "!DISPLAY_VERBOSE!" == "yes" ( + echo %~1 + ) + exit /b %ERRORLEVEL% + +:msg_success + echo %~1 + exit /b %ERRORLEVEL% + +:msg_warn + echo %~1 + exit /b %ERRORLEVEL% + +:msg_error + echo %~1 + exit /b %ERRORLEVEL% diff --git a/generate4.sh b/generate4.sh index d14a2d2f..745f385b 100755 --- a/generate4.sh +++ b/generate4.sh @@ -8,31 +8,128 @@ # See https://github.com/imatix/gsl for details. ############################################################################### -# Exit this script on the first build error. -set -e - -# Do everything relative to this file location. -cd `dirname "$0"` - -# Clean directories for generated build artifacts. -eval rm -rf "output" - -# Generate property copiers and artifact generators. -eval gsl -q -script:gsl.copy_properties.sh generate4.xml -eval gsl -q -script:gsl.generate_artifacts.sh generate4.xml - -# Generate bindings from generated binding generators. -# The path to swig must be in our path. -# for generate.repository by name as _repo -# eval ../$(_repo.name)/bindings.sh -# endfor - -# Make property copiers and artifact generators executable. -eval chmod +x copy_properties.sh -eval chmod +x generate_artifacts.sh - -# Execute property copiers and artifact generators. -eval ./copy_properties.sh -eval ./generate_artifacts.sh -eval ./generate.sh version4.xml -eval ./copy_projects.sh "$@" +OPTS_ENABLE="set -eo pipefail" +OPTS_DISABLE="set +e" + +eval "${OPTS_ENABLE}" +trap 'msg_error "FATAL ERROR: Command failed at line ${LINENO}: ${BASH_COMMAND}" >&2' ERR + +GSL="gsl -q" +COLOR_CYAN='\e[0;96m' +COLOR_GREEN='\e[0;92m' +COLOR_RED='\e[0;91m' +COLOR_YELLOW='\e[0;93m' +COLOR_RESET='\e[0m' + +main() +{ + # Do everything relative to this file location. + push_directory `dirname "$0"` + + # Clean directories for generated build artifacts. + remove_directory_force "output" + + # Generate property copiers and artifact generators. + msg_warn "${GSL} -script:gsl.copy_properties.sh generate4.xml" + eval ${GSL} -script:gsl.copy_properties.sh generate4.xml + msg_warn "${GSL} -script:gsl.generate_artifacts.sh generate4.xml" + eval ${GSL} -script:gsl.generate_artifacts.sh generate4.xml + + # Make property copiers and artifact generators executable. + msg_verbose "Modifying properties of shell scripts." + eval chmod +x copy_properties.sh + eval chmod +x generate_artifacts.sh + + # Execute property copiers and artifact generators. + + msg "Execute copy_properties.sh..." + eval ./copy_properties.sh + msg "Execute generate_artifacts.sh..." + eval ./generate_artifacts.sh + msg "Execute generate.sh..." + eval ./generate.sh version4.xml + msg "Execute copy_projects.sh..." + eval ./copy_projects.sh "$@" + + pop_directory + msg_success "Script execution completed successfully." +} + +create_directory() +{ + local DIRECTORY="$1" + local MODE="$2" + + if [[ -d "${DIRECTORY}" ]]; then + if [[ ${MODE} == "-f" ]]; then + msg_warn "Reinitializing '${DIRECTORY}'..." + rm -rf "${DIRECTORY}" + mkdir -p "${DIRECTORY}" + else + msg_warn "Reusing existing '${DIRECTORY}'..." + fi + else + msg "Initializing '${DIRECTORY}'..." + mkdir -p "${DIRECTORY}" + fi +} + +create_directory_force() +{ + create_directory "$@" -f +} + +pop_directory() +{ + msg_verbose "*** move pre: '$(pwd)'" + popd >/dev/null + msg_verbose "*** move post: '$(pwd)'" +} + +push_directory() +{ + msg_verbose "*** move pre: '$(pwd)'" + local DIRECTORY="$1" + pushd "${DIRECTORY}" >/dev/null + msg_verbose "*** move post: '$(pwd)'" +} + +remove_directory_force() +{ + msg_verbose "*** removing: '$@'" + rm -rf "$@" +} + +msg_heading() +{ + printf "\n********************** %b **********************\n" "$@" +} + +msg_verbose() +{ + if [[ "${DISPLAY_VERBOSE}" == "yes" ]]; then + printf "${COLOR_CYAN}%b${COLOR_RESET}\n" "$@" + fi +} + +msg() +{ + printf "%b\n" "$@" +} + +msg_success() +{ + printf "${COLOR_GREEN}%b${COLOR_RESET}\n" "$@" +} + +msg_warn() +{ + printf "${COLOR_YELLOW}%b${COLOR_RESET}\n" "$@" +} + +msg_error() +{ + >&2 printf "${COLOR_RED}%b${COLOR_RESET}\n" "$@" +} + +main "$@" diff --git a/generate4.xml b/generate4.xml index f86abe3e..757c679f 100644 --- a/generate4.xml +++ b/generate4.xml @@ -193,7 +193,7 @@