Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

build: decouple examples from main project and test dependence #55

Merged
merged 33 commits into from
Dec 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
eb8a24f
build: decouple examples from main project
c-dilks Dec 12, 2023
c50826e
build: begin structuring new examples dir
c-dilks Dec 12, 2023
276820b
feat: generate `pkg-config` file
c-dilks Dec 12, 2023
2d619ed
build: separate include dir
c-dilks Dec 13, 2023
809e221
ci: make it fail until we update it
c-dilks Dec 13, 2023
9b33d79
feat: examples how to build dependents
c-dilks Dec 13, 2023
6061756
ci: test dependent builds
c-dilks Dec 13, 2023
d37c11c
fix: doxyfile include
c-dilks Dec 13, 2023
577166f
fix(ci): checkout
c-dilks Dec 13, 2023
4449227
fix: drop `fmt` from dependent builds
c-dilks Dec 13, 2023
1da2144
Revert "fix: drop `fmt` from dependent builds"
c-dilks Dec 13, 2023
f8d1345
doc: `pkg-config` commands
c-dilks Dec 13, 2023
2a80872
doc: don't provide `test.sh` examples
c-dilks Dec 13, 2023
690a120
doc: formatting
c-dilks Dec 13, 2023
152d022
modified: doc/dependency_resolution.md
c-dilks Dec 13, 2023
cf35021
fix: varname
c-dilks Dec 13, 2023
dab4b87
fix: move `fmt` to `.pc` file
c-dilks Dec 13, 2023
d89cd77
feat: `cmake` dependent build example
c-dilks Dec 13, 2023
aa07a45
fix: use `IMPORTED_TARGET` for pkg-config target
c-dilks Dec 13, 2023
06aa72a
build: reduce minimum `cmake` version
c-dilks Dec 13, 2023
6ed3282
refactor: combine `src/` and `include/`
c-dilks Dec 14, 2023
9a22ed8
fix: doxygen
c-dilks Dec 14, 2023
11f26e5
feat: generate documentation with `meson`
c-dilks Dec 14, 2023
8e580d1
doc: `./`
c-dilks Dec 14, 2023
ae97171
fix: install documentation
c-dilks Dec 14, 2023
cc62341
doc: update dependency_resolution.md
c-dilks Dec 15, 2023
46eae57
refactor: prioritize build options over env vars
c-dilks Dec 15, 2023
3ad5865
fix: doc/dependency_resolution.md
c-dilks Dec 15, 2023
ccdfc99
doc: doc/dependency_resolution.md
c-dilks Dec 15, 2023
117f9f6
doc: doc/dependency_resolution.md
c-dilks Dec 15, 2023
f3f4e9b
fix: `fmt_dep`
c-dilks Dec 15, 2023
78fa8ce
fix: include path
c-dilks Dec 15, 2023
3cff4c3
fix: cleanup includes
c-dilks Dec 15, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions .github/test-dependent-build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#!/bin/bash
# CI test of building iguana-dependent code

set -e

# args
[ $# -lt 1 ] && echo "USAGE: $0 [tool] [test args]..." >&2 && exit 2
tool=$1
shift

# dependencies: assumed to be in `./<dependency>`
fmt_dep=$(realpath fmt)
iguana_dep=$(realpath iguana)
hipo_dep=$(realpath hipo)

# dependency resolution objects
pkg_config_path=(
$fmt_dep/lib/pkgconfig
$iguana_dep/lib/pkgconfig
)
cmake_prefix_path=(
$hipo_dep
)
ld_library_path=(
$hipo_dep/lib
$fmt_dep/lib
$iguana_dep/lib
)

# source, build, and install directories
source_dir=examples/build_with_$tool
build_dir=build-dependent
install_dir=install-dependent
mkdir -p $install_dir
install_dir=$(realpath $install_dir)

# executable
test_executable=iguana-example-00-basic

# join items in a list to a string delimited by $1
joinList() {
d=$1
shift
echo "$@" | sed "s/ /$d/g"
}

# print and execute a command
exe() {
echo "--------------------------------------------------"
echo "$@"
echo "--------------------------------------------------"
"$@"
}

# build and test
case $tool in
cmake)
exe \
cmake \
-DCMAKE_PREFIX_PATH="$(joinList ';' ${cmake_prefix_path[*]} $fmt_dep $iguana_dep)" \
-S $source_dir -B $build_dir
exe cmake --build $build_dir
exe cmake --install $build_dir --prefix $install_dir
exe $install_dir/bin/$test_executable "$@"
;;
make)
export PKG_CONFIG_PATH=$(joinList ':' ${pkg_config_path[*]})
export HIPO=$hipo_dep
env | grep -wE '^PKG_CONFIG_PATH|^HIPO'
pushd $source_dir
exe make
popd
export LD_LIBRARY_PATH=$(joinList ':' ${ld_library_path[*]})
env | grep -wE '^LD_LIBRARY_PATH'
exe $source_dir/bin/$test_executable "$@"
;;
meson)
exe \
meson setup \
--prefix=$install_dir \
-Dcmake_prefix_path=$(joinList ',' ${cmake_prefix_path[*]}) \
-Dpkg_config_path=$(joinList ',' ${pkg_config_path[*]}) \
$build_dir $source_dir
exe meson install -C $build_dir
exe $install_dir/bin/$test_executable "$@"
;;
*)
echo "ERROR: unknown tool '$tool'" >&2
exit 1
;;
esac
33 changes: 32 additions & 1 deletion .github/workflows/linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ jobs:
run: ls *.tar.gz | xargs -I{} tar xzvf {}
- run: tree
- name: configure
run: ./configure.py --hipo hipo --fmt fmt
run: ./configure.py --hipo hipo --fmt fmt --examples --no-documentation
- name: build
run: ./install-iguana.sh
- name: dump build log
Expand Down Expand Up @@ -171,6 +171,37 @@ jobs:
$exe $test_file
done

test_dependent_builds:
name: Test Dependent Builds
needs:
- download_validation_files
- build_iguana
runs-on: ubuntu-latest
strategy:
fail-fast: true
matrix:
tool: [ cmake, make, meson ]
steps:
- uses: actions/checkout@v4
- name: setup meson
run: python -m pip install meson ninja
- name: get build artifacts
uses: actions/download-artifact@v3
with:
name: build
- name: get test data
uses: actions/download-artifact@v3
with:
name: validation_files
- name: untar artifacts
run: |
ls *.tar.gz | xargs -I{} tar xzvf {}
rm -v *.tar.gz
- name: build and run
run: |
test_file=$(find validation_files -name "*.hipo" | head -n1)
.github/test-dependent-build.sh ${{ matrix.tool }} $test_file 1

# documentation
#########################################################

Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
install-iguana.sh
/build*/
/iguana
/install*/

# local dependency builds
/fmt
/hipo

# doxygen artifacts
/doc/api
Expand Down
36 changes: 25 additions & 11 deletions configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
from configparser import ConfigParser
import argparse, os, sys, textwrap

SYSTEM_ASSUMPTION = 'assume system installation'
SEPARATOR = '-'*50
# constants
SYSTEM_ASSUMPTION = 'assume system installation'
SEPARATOR = '-'*50
PKGCONFIG_RELOCATABLE = True

# parse user options
class Formatter(argparse.ArgumentDefaultsHelpFormatter, argparse.RawDescriptionHelpFormatter): pass
Expand All @@ -17,14 +19,20 @@ class Formatter(argparse.ArgumentDefaultsHelpFormatter, argparse.RawDescriptionH
formatter_class = Formatter
)
parser_deps = parser.add_argument_group('dependency installation paths')
parser_deps.add_argument( '--hipo', default=SYSTEM_ASSUMPTION, type=str, help='path to `hipo` installation' )
parser_deps.add_argument( '--fmt', default=SYSTEM_ASSUMPTION, type=str, help='path to `fmt` installation' )
parser_build = parser.add_argument_group('iguana build settings')
parser_build.add_argument( '--prefix', default='iguana', type=str, help='iguana installation prefix' )
parser_build.add_argument( '--build', default='build-iguana', type=str, help='iguana buildsystem directory' )
parser_build.add_argument( '--ini', default='build-iguana.ini', type=str, help='name of the output config INI file' )
parser_deps.add_argument( '--hipo', default=SYSTEM_ASSUMPTION, type=str, help='path to `hipo` installation')
parser_deps.add_argument( '--fmt', default=SYSTEM_ASSUMPTION, type=str, help='path to `fmt` installation')
parser_build = parser.add_argument_group('build settings')
parser_build.add_argument( '--prefix', default='iguana', type=str, help='iguana installation prefix')
parser_build.add_argument( '--examples', default=False, action=argparse.BooleanOptionalAction, help='build examples or not')
parser_build.add_argument( '--documentation', default=False, action=argparse.BooleanOptionalAction, help='generate API documentation or not')
parser_build = parser.add_argument_group('advanced settings')
parser_build.add_argument( '--build', default='build-iguana', type=str, help='iguana buildsystem directory')
parser_build.add_argument( '--ini', default='build-iguana.ini', type=str, help='name of the output config INI file')
args = parser.parse_args()

# get prefix absolute path
prefix = os.path.realpath(args.prefix)

# set dependency paths
cmake_prefix_path = []
cmake_deps = []
Expand All @@ -46,13 +54,19 @@ def meson_string_array(arr):
config = ConfigParser(allow_no_value=True)
config.add_section('built-in options')
if(len(cmake_prefix_path) > 0):
config.set('built-in options', '; dependency paths for: ' + ','.join(cmake_deps))
config.set('built-in options', '; path to dependencies: ' + ','.join(cmake_deps))
config.set('built-in options', 'cmake_prefix_path', meson_string_array(cmake_prefix_path))
if(len(pkg_config_path) > 0):
config.set('built-in options', '; dependency paths for: ' + ','.join(pkg_config_deps))
config.set('built-in options', '; path to dependencies: ' + ','.join(pkg_config_deps))
config.set('built-in options', 'pkg_config_path', meson_string_array(pkg_config_path))
config.set('built-in options', '; installation settings')
config.set('built-in options', 'prefix', f'\'{os.path.realpath(args.prefix)}\'')
config.set('built-in options', 'prefix', f'\'{prefix}\'')
config.set('built-in options', 'libdir', '\'lib\'') # make all systems use lib/
config.set('built-in options', 'pkgconfig.relocatable', f'{PKGCONFIG_RELOCATABLE}')
config.set('built-in options', 'examples', f'{args.examples}')
config.set('built-in options', 'documentation', f'{args.documentation}')

# write the INI file
with open(args.ini, 'w') as fp:
config.write(fp)
print(f'Wrote build configuration file {args.ini}:')
Expand Down
40 changes: 40 additions & 0 deletions doc/dependency_resolution.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Dependency Resolution

The dependencies in [the setup guide](setup.md) must be locatable by `iguana`, or
by anything that depends on `iguana`.

Assuming a dependency is installed in `$prefix`, it uses one or more of the following:
- `pkg-config`: a `.pc` file in `$prefix/lib/pkgconfig`
- `.cmake` files in `$prefix/lib/cmake`

Take a look at each dependency's installation prefix to see which of these options
are available.

To use these dependencies with your software, they must be findable by its build system.
The following sections explain how to do so with each.

### Meson
For `iguana`, the build system is `meson`, which accepts the build options
```bash
-Dpkg_config_path=$prefix/lib/pkgconfig
-Dcmake_prefix_path=$prefix
```
(where multiple paths are delimited by commas).

### CMake
For `cmake`, the `pkg-config` path can be combined with the `cmake` path, so only the
build option
```bash
-DCMAKE_PREFIX_PATH="$prefix"
```
is needed; this assumes:
- all dependencies are in `$prefix` (delimit multiple paths with semicolons)
- `PKG_CONFIG_USE_CMAKE_PREFIX_PATH` has not been disabled.

### General Case
Environment variables may be used instead of build options for a general approach:
```bash
export PKG_CONFIG_PATH=$prefix/lib/pkgconfig
export CMAKE_PREFIX_PATH=$prefix
```
(where multiple paths are delimited by colons).
2 changes: 1 addition & 1 deletion doc/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ flowchart LR
classDef other fill:#ff88ff,color:black

subgraph services
Algorithm:::cls
Logger:::cls
Object:::cls
end

subgraph algorithms
Algorithm:::cls
FiducialCuts:::algo
MomentumCorrection:::algo
AlgorithmSequence:::algo
Expand Down
22 changes: 19 additions & 3 deletions doc/setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,15 @@ cmake --install build-hipo
```

## Building and Installing

- For convenience, a configuration script is provided.
- Advanced users who want more control may skip to the "Using Meson Directly" section.

### Using the Configuration Script

First, configure your `iguana` build using `configure.py`:
```bash
configure.py --help
./configure.py --help
```
The `--help` option will print the usage guide.
Unless the dependencies are installed in one of the system default locations, you will need to specify the path to each of them, _e.g._,
Expand All @@ -47,5 +53,15 @@ Inspect both of them, and if they look correct, proceed with building and instal
./install-iguana.sh
```

### Note for advanced users
If you are comfortable with `meson` and dependency resolution, there is no need to run `configure.py` or `install-iguana.sh`; you may instead run `meson` commands with your preferred options.
### Using Meson Directly

Instead of `configure.py`, use `meson` directly for more control:

1. Follow the [note on dependency resolution](dependency_resolution.md)
2. Build with `meson`, for example
```bash
meson setup --prefix=$(pwd)/iguana build-iguana /path/to/iguana/repository
meson install -C build-iguana
```
**NOTE**: `configure.py` produces a native file (`.ini`) which may be used by
`meson setup` option `--native-file`.
11 changes: 11 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Examples

All of the examples (`*.cc`) in this directory may be built using the
`--examples` option of `configure.py`; they will be installed in the `bin/`
subdirectory of your `iguana` installation.

If you would like to integrate `iguana` into an existing analysis, you'll need
to add `iguana` as a dependency. The `build_with_*/` subdirectories are
standalone examples demonstrating how to do this, by showing how to build an
executable that depends on `iguana` libraries. Each subdirectory is for a
different build system tool.
26 changes: 26 additions & 0 deletions examples/build_with_cmake/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
cmake_minimum_required(VERSION 3.6)

project(
iguana-build-example
LANGUAGES CXX
VERSION 1.0.0
)

# find dependencies
# - iguana doesn't create a `iguanaConfig.cmake` file, but it does create a pkg-config `.pc` file;
# the target will be imported as `PkgConfig::iguana`
find_package(hipo4 REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(iguana REQUIRED IMPORTED_TARGET iguana)

# set the rpath to use the link path
# - this is so that the executable knows where the dependency libraries are
# - alternatively, set $LD_LIBRARY_PATH before running your executables
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)

# build and install the executable
set(EXAMPLE_BIN iguana-example-00-basic)
add_executable(${EXAMPLE_BIN})
target_sources(${EXAMPLE_BIN} PRIVATE ${EXAMPLE_BIN}.cc)
target_link_libraries(${EXAMPLE_BIN} PUBLIC PkgConfig::iguana hipo4)
install(TARGETS ${EXAMPLE_BIN})
6 changes: 6 additions & 0 deletions examples/build_with_cmake/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Example Building with CMake

This example [`CMakeLists.txt`](CMakeLists.txt) demonstrates how to build an executable that depends on `iguana`.

See [note on dependency resolution](../../doc/dependency_resolution.md) first.
Then you may use the `find_package()` and `pkg_check_modules()` commands to include dependencies.
1 change: 1 addition & 0 deletions examples/build_with_cmake/iguana-example-00-basic.cc
1 change: 1 addition & 0 deletions examples/build_with_make/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bin
23 changes: 23 additions & 0 deletions examples/build_with_make/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# compiler
CXX := g++

# dependency libraries
DEP_LIBRARIES = $(shell pkg-config --libs iguana)
DEP_LIBRARIES += -L${HIPO}/lib -lhipo4

# dependency headers
DEP_INCLUDES = $(shell pkg-config --cflags iguana)
DEP_INCLUDES += -I${HIPO}/include

# assume each .cc file has `main`; install it to ./bin/
BINDIR = bin
EXECUTABLES := $(addprefix $(BINDIR)/, $(basename $(wildcard *.cc)))

# build executable
# - NOTE: we haven't set an rpath here, so the user will need
# to make sure dependency libraries are found in $LD_LIBRARY_PATH
$(EXECUTABLES): $(BINDIR)/%: %.cc
mkdir -p $(BINDIR)
$(CXX) -c $< -o [email protected] $(DEP_INCLUDES)
$(CXX) -o $@ [email protected] $(DEP_LIBRARIES)
$(RM) [email protected]
15 changes: 15 additions & 0 deletions examples/build_with_make/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Example Building with a Makefile

This example [`Makefile`](Makefile) demonstrates how to build an executable that depends on `iguana`.

See [note on dependency resolution](../../doc/dependency_resolution.md) first.

You need to include the headers and libraries with the appropriate `-I`, `-L`,
and `-l` flags. For dependencies with a `pkg-config` file, such as `iguana`,
you can use `pkg-config` to get these flags:
```bash
pkg-config --libs iguana
pkg-config --cflags iguana
```
- These commands are used in the example `Makefile`
- `hipo` is assumed to be installed in `$HIPO`.
1 change: 1 addition & 0 deletions examples/build_with_make/iguana-example-00-basic.cc
Loading