diff --git a/.github/download-ROOT-source.rb b/.github/download-ROOT-source.rb
deleted file mode 100755
index 955da806..00000000
--- a/.github/download-ROOT-source.rb
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/usr/bin/env ruby
-# download the ROOT source code
-
-if ARGV.empty?
- $stderr.puts "USAGE: #{$0} [tag]"
- exit 2
-end
-TAG = ARGV.first
-REPO = 'root-project/ROOT'
-
-info = Hash.new
-case TAG
-when 'latest'
- info = {
- :api_url => "https://api.github.com/repos/#{REPO}/releases/latest",
- :jq_filter => '.tarball_url',
- }
-else
- info = {
- :api_url => "https://api.github.com/repos/#{REPO}/tags",
- :jq_filter => ".[] | select (.name==\"#{TAG}\") | .tarball_url",
- }
-end
-
-api_args = [
- '--silent',
- '-L',
- '-H "Accept: application/vnd.github+json"',
- '-H "X-GitHub-Api-Version: 2022-11-28"',
- info[:api_url],
-]
-cmd = "curl #{api_args.join ' '} | jq -r '#{info[:jq_filter]}'"
-puts """API call:
-#{'='*82}
-#{cmd}
-#{'='*82}"""
-
-error = Proc.new do |msg|
- $stderr.puts "ERROR: #{msg}"
- exit 1
-end
-
-payload = `#{cmd}`
-error.call 'GitHub API call failure' unless $?.success?
-error.call "GitHub API call returned empty string, perhaps tag '#{TAG}' does not exist?" if payload.empty?
-url = payload.chomp
-puts "TARBALL URL = #{url}"
-
-puts "Downloading ROOT version '#{TAG}'..."
-exec "wget -nv --no-check-certificate --output-document root.tar.gz #{url}"
diff --git a/.github/download-ROOT-source.sh b/.github/download-ROOT-source.sh
new file mode 100755
index 00000000..c83ca582
--- /dev/null
+++ b/.github/download-ROOT-source.sh
@@ -0,0 +1,27 @@
+#!/usr/bin/env bash
+# download the ROOT source code
+
+set -euo pipefail
+
+if [ $# -ne 1 ]; then
+ echo "USAGE: $0 [TAG]" >&2
+ exit 1
+fi
+
+tag=$1
+curl_cmd='curl --silent -L -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28"'
+
+echo "Download ROOT tag '$tag' from:"
+case $tag in
+ latest)
+ url=$($curl_cmd https://api.github.com/repos/root-project/ROOT/releases/latest | jq -r '.tarball_url')
+ ;;
+ *)
+ url=$($curl_cmd https://api.github.com/repos/root-project/ROOT/tags | jq -r '.[] | select (.name=="'$tag'") | .tarball_url')
+ ;;
+esac
+
+echo " $url"
+[ -z "$url" ] && echo "ERROR: GitHub API call returned empty string, perhaps tag '$tag' does not exist?" && exit 1
+echo "downloading ..."
+wget -nv --no-check-certificate --output-document root.tar.gz $url
diff --git a/.github/install-dependency-packages.sh b/.github/install-dependency-packages.sh
index 318493e9..7e18e4ca 100755
--- a/.github/install-dependency-packages.sh
+++ b/.github/install-dependency-packages.sh
@@ -7,7 +7,6 @@ set -e
##############################
GENERAL_PACKAGE_LIST_LINUX=(
python
- ruby
gcc
gcc-fortran
clang
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index ca8c2e30..d44a3f1d 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -113,7 +113,7 @@ jobs:
- name: download ROOT source code
if: ${{ steps.cache.outputs.cache-hit != 'true' }}
run: |
- iguana_src/.github/download-ROOT-source.rb ${{ steps.key.outputs.root_version }}
+ iguana_src/.github/download-ROOT-source.sh ${{ steps.key.outputs.root_version }}
tar xf $(ls -t *.gz | head -n1)
ls -t
mv -v $(ls -td root-* | head -n1) root_src
@@ -199,6 +199,51 @@ jobs:
key: ${{ steps.key.outputs.key }}---${{ matrix.root_dep }}
path: hipo.tar.zst
+ build_ruby_minver:
+ name: Build Minver Ruby
+ runs-on: ${{ inputs.runner }}
+ container:
+ image: ${{ inputs.container }}
+ outputs:
+ key: ${{ steps.key.outputs.key }}
+ steps:
+ - name: checkout iguana
+ if: ${{ inputs.verset == 'minver' }}
+ uses: actions/checkout@v4
+ with:
+ path: iguana_src
+ - name: key
+ if: ${{ inputs.verset == 'minver' }}
+ id: key
+ run: |
+ ver=$(iguana_src/meson/minimum-version.sh ruby)
+ echo ver=$ver >> $GITHUB_OUTPUT
+ echo key=ruby---${{ inputs.id }}---${ver}---$(date +%Y-week%U) >> $GITHUB_OUTPUT
+ - uses: actions/cache/restore@v4
+ if: ${{ inputs.verset == 'minver' }}
+ id: cache
+ with:
+ key: ${{ steps.key.outputs.key }}
+ path: ruby.tar.zst
+ lookup-only: true
+ - name: build ruby
+ if: ${{ steps.cache.outputs.cache-hit != 'true' && inputs.verset == 'minver' }}
+ run: |
+ iguana_src/.github/install-dependency-packages.sh ${{ inputs.runner }} ${{ inputs.verset }}
+ export RBENV_ROOT=$(pwd)/.rbenv
+ git clone https://github.com/rbenv/rbenv.git $RBENV_ROOT
+ eval "$($RBENV_ROOT/bin/rbenv init - bash)"
+ git clone https://github.com/rbenv/ruby-build.git $(rbenv root)/plugins/ruby-build
+ rbenv install ${{ steps.key.outputs.ver }}
+ rbenv global ${{ steps.key.outputs.ver }}
+ tar cavf ruby.tar.zst .rbenv
+ - uses: actions/cache/save@v4
+ if: ${{ steps.cache.outputs.cache-hit != 'true' && inputs.verset == 'minver' }}
+ id: cache_save
+ with:
+ key: ${{ steps.key.outputs.key }}
+ path: ruby.tar.zst
+
# build and test Iguana
#########################################################
@@ -208,6 +253,7 @@ jobs:
- download_test_data
- build_hipo
- build_root
+ - build_ruby_minver
runs-on: ${{ inputs.runner }}
container:
image: ${{ inputs.container }}
@@ -235,6 +281,26 @@ jobs:
###### system
- name: install dependency packages
run: iguana_src/.github/install-dependency-packages.sh ${{ inputs.runner }} ${{ inputs.verset }}
+ ###### ruby
+ - name: install ruby from linux package manager
+ if: ${{ inputs.id != 'macOS' && inputs.verset != 'minver' }}
+ run: pacman -S --noconfirm ruby
+ - name: install ruby from cached minver build
+ if: ${{ inputs.id != 'macOS' && inputs.verset == 'minver' }}
+ uses: actions/cache/restore@v4
+ with:
+ key: ${{ needs.build_ruby_minver.outputs.key }}
+ path: ruby.tar.zst
+ - name: source ruby from cached minver build
+ if: ${{ inputs.id != 'macOS' && inputs.verset == 'minver' }}
+ run: |
+ tar xf ruby.tar.zst
+ export RBENV_ROOT=$(pwd)/.rbenv
+ echo RBENV_ROOT=$RBENV_ROOT >> $GITHUB_ENV
+ eval "$($RBENV_ROOT/bin/rbenv init - bash)"
+ echo "ruby --version:"
+ ruby --version
+ echo PATH=$PATH >> $GITHUB_ENV
###### python bindings
- name: install python bindings dependencies
if: ${{ matrix.id == 'python' }}
@@ -289,6 +355,7 @@ jobs:
echo '| --- | --- |' >> $GITHUB_STEP_SUMMARY
echo "| \`hipo\` | ${{ env.hipo_ref }} |" >> $GITHUB_STEP_SUMMARY
echo "| \`root\` | $(root --version 2>&1 | head -n1) |" >> $GITHUB_STEP_SUMMARY
+ echo "| \`ruby\` | $(ruby --version) |" >> $GITHUB_STEP_SUMMARY
cat pkg_summary.md >> $GITHUB_STEP_SUMMARY
### build
- name: meson setup
diff --git a/doc/setup.md b/doc/setup.md
index 55b5092c..4b186775 100644
--- a/doc/setup.md
+++ b/doc/setup.md
@@ -52,6 +52,12 @@ cmake --build build-hipo
cmake --install build-hipo
```
+### 🟩 Optional: `ruby`: programming language
+
+- Likely available in your package manager, likely as `ruby`
+- This is only needed if you intend to use Iguana with languages other than C++
+ - Bindings to other programming languages are generated by [`chameleon`](/src/chameleon), a local Ruby program
+
### 🟩 Optional: `ROOT`: Data analysis framework
- ROOT is an **optional** dependency: some algorithms and test code depends on ROOT, but if you do not
diff --git a/meson.build b/meson.build
index 780cef9d..a37d5031 100644
--- a/meson.build
+++ b/meson.build
@@ -21,29 +21,40 @@ project_description = 'Implementation Guardian of Analysis Algorithms'
# initialize binding languanges
add_languages('fortran', native: false, required: get_option('bind_fortran'))
+use_chameleon = get_option('bind_fortran')
# meson modules
pkg = import('pkgconfig')
fs = import('fs')
# resolve dependencies
+prog_minver = find_program('meson' / 'minimum-version.sh')
# NOTE: those that are typically installed by package managers should use `meson/minimum-version.sh`
fmt_dep = dependency(
'fmt',
method: 'pkg-config',
- version: run_command('meson' / 'minimum-version.sh', 'fmt', check: true).stdout().strip(),
+ version: '>=' + run_command(prog_minver, 'fmt', check: true).stdout().strip(),
)
yamlcpp_dep = dependency(
'yaml-cpp',
method: 'pkg-config',
- version: run_command('meson' / 'minimum-version.sh', 'yaml-cpp', check: true).stdout().strip(),
+ version: '>=' + run_command(prog_minver, 'yaml-cpp', check: true).stdout().strip(),
+)
+hipo_dep = dependency(
+ 'hipo4',
+ method: 'pkg-config',
+ version: '>=4.1.0'
)
-hipo_dep = dependency('hipo4', method: 'pkg-config', version: '>=4.1.0')
ROOT_dep = dependency(
'ROOT',
required: get_option('z_require_root'),
method: 'cmake',
- version: run_command('meson' / 'minimum-version.sh', 'ROOT', check: true).stdout().strip(),
+ version: '>=' + run_command(prog_minver, 'ROOT', check: true).stdout().strip(),
+)
+prog_ruby = find_program(
+ 'ruby',
+ version: '>=' + run_command(prog_minver, 'ruby', check: true).stdout().strip(),
+ required: use_chameleon,
)
# list of dependencies
@@ -169,7 +180,6 @@ add_project_arguments(
)
# start chameleon
-use_chameleon = get_option('bind_fortran')
if use_chameleon
subdir('src/chameleon')
endif
diff --git a/meson/minimum-version.sh b/meson/minimum-version.sh
index 823aef85..1d955ffc 100755
--- a/meson/minimum-version.sh
+++ b/meson/minimum-version.sh
@@ -1,12 +1,12 @@
#!/usr/bin/env bash
if [ $# -eq 0 ]; then
- echo """USAGE: $0 [package] [command(default=meson)]
+ echo """USAGE: $0 [package] [command(default=ver)]
package: the package name; since this varies between package manager
repositories, we prefer to use the name from that used by the CI
- command: meson return a string for meson function \`dependency()\`
+ command: ver return the minimum version number
ALA return a URL for the Arch Linux Archive (ALA), for CI
https://archive.archlinux.org/
@@ -16,7 +16,7 @@ if [ $# -eq 0 ]; then
exit 2
fi
dep=$1
-[ $# -ge 2 ] && cmd=$2 || cmd=meson
+[ $# -ge 2 ] && cmd=$2 || cmd=ver
not_used() {
[ "$cmd" = "$1" ] && echo "ERROR: command '$cmd' is not used for '$dep'" >&2 && exit 1
@@ -26,20 +26,25 @@ not_used() {
case $dep in
fmt)
- result_meson='>=9.1.0'
+ result_ver='9.1.0'
result_ala='https://archive.archlinux.org/packages/f/fmt/fmt-9.1.0-4-x86_64.pkg.tar.zst'
not_used 'tag'
;;
yaml-cpp)
- result_meson='>=0.7.0'
+ result_ver='0.7.0'
result_ala='https://archive.archlinux.org/packages/y/yaml-cpp/yaml-cpp-0.7.0-2-x86_64.pkg.tar.zst'
not_used 'tag'
;;
root|ROOT)
- result_meson='>=6.28.12'
+ result_ver='6.28.12'
result_tag='v6-28-12'
not_used 'ALA'
;;
+ ruby)
+ result_ver='2.7.2'
+ not_used 'ALA'
+ not_used 'tag'
+ ;;
*)
echo "ERROR: dependency '$dep' is unknown" >&2
exit 1
@@ -49,9 +54,9 @@ esac
#############################################
case $cmd in
- meson) echo $result_meson ;;
- ALA) echo $result_ala ;;
- tag) echo $result_tag ;;
+ ver) echo $result_ver ;;
+ ALA) echo $result_ala ;;
+ tag) echo $result_tag ;;
*)
echo "ERROR: command '$cmd' is unknown" >&2
exit 1
diff --git a/src/chameleon/meson.build b/src/chameleon/meson.build
index 44163b94..ebb37fde 100644
--- a/src/chameleon/meson.build
+++ b/src/chameleon/meson.build
@@ -4,5 +4,4 @@ chameleon_sources = files(
'src' / 'bind_c.rb',
)
-ruby = find_program('ruby', version: '>=3.0.0', required: use_chameleon)
-chameleon_gen = find_program(chameleon_sources[0], required: use_chameleon)
+prog_chameleon = find_program(chameleon_sources[0], required: use_chameleon)
diff --git a/src/iguana/algorithms/meson.build b/src/iguana/algorithms/meson.build
index 37186cf4..08fc9ac6 100644
--- a/src/iguana/algorithms/meson.build
+++ b/src/iguana/algorithms/meson.build
@@ -132,7 +132,7 @@ foreach algo : algo_dict
input: [ algo_dir / 'Action.yaml', chameleon_sources ],
output: [ target_name + '_bind.cc' ],
command: [
- chameleon_gen,
+ prog_chameleon,
'--input', '@INPUT0@',
'--output', '@OUTDIR@',
'--prefix', target_name,