Skip to content
Snippets Groups Projects
Commit 48d15904 authored by Ammar Nejati's avatar Ammar Nejati
Browse files

[improveCMakeScripts] Major Improvements to the CI mechanism (Closes #495)

Merging branch 'improveCMakeScripts'  into 'main'.

* MacOS:
  * Updated the build parameters for Mac CI-machines.
  * Added the 1st-order dependencies of the relatively-referenced Qt libraries (if any). [resolves #495]
  * Added a proper path for the man package on MacOS to prevent an error during package building.

* Python package: Changed the wheel producing command according to the latest pip documentation
to reduce the Python dependencies.

* Added a fatal error message in case `libformfactor` is not found.

Closes #495

See merge request !1499
parents 3e23800d 1a15a229
No related branches found
No related tags found
1 merge request!1499Major Improvements to the CI mechanism
Pipeline #93379 passed
stages:
- build
# global variables
variables:
GIT_DEPTH: "1"
native_Debian_clang:
tags: &native
- Debian
......@@ -14,6 +18,7 @@ native_Debian_clang:
- clang --version
stage: build
script: &native_scr
- env
- mkdir build
- cd build
- time cmake .. -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DBA_PY_PACKAGE=ON -DCMAKE_PREFIX_PATH=$QCMAKE -DZERO_TOLERANCE=ON
......@@ -46,38 +51,42 @@ versiondocs:
- hugo
- cp -fr public/* ~www/ba/www/
# mac10_15:
# tags:
# - macbuild3
# stage: build
# before_script:
# - export NPROC=3
# script: &mac_script
# - export PYTHONPATH=$CI_PROJECT_DIR/build/lib:$PYTHONPATH
# - export NOPLOT=ON
# - export QTDIR=/usr/local/Cellar/qt/6.3.1_4
# - echo $PYTHONPATH
# - mkdir build
# - cd build
# - cmake .. -D CMAKE_PREFIX_PATH="$QTDIR/lib/cmake" -D CMAKE_CXX_COMPILER_LAUNCHER=ccache -DBA_APPLE_BUNDLE=ON -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_INSTALL_PREFIX=. -DBA_PY_PACKAGE=ON
# - make -j$NPROC
# - ctest -j3 --output-on-failure
# - zsh var/mk_pypack_macos.zsh
# - cpack .
# artifacts: &mac_artifacts
# paths:
# - build/*.dmg
# - build/PythonPackage/py*/wheel/*.whl
# expire_in: 10 days
#
# mac12_2:
# tags:
# - scgmac4
# stage: build
# before_script:
# - export NPROC=12
# script: *mac_script
# artifacts: *mac_artifacts
mac_x64:
tags:
- mac_x64
stage: build
before_script:
# obtain nr of logical CPUs via `sysctl hw.logicalcpu`
- NPROC=6
- QTDIR=/usr/local/opt/qt
script: &mac_script
- NOPLOT=ON
- OPTDIR="/Users/Shared/Software"
# print environmental variables
- env
- mkdir build
- cd build
- cmake .. -DCMAKE_PREFIX_PATH="$OPTDIR;$QTDIR/lib/cmake" -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DBA_APPLE_BUNDLE=ON -DCMAKE_OSX_DEPLOYMENT_TARGET=11 -DCMAKE_INSTALL_PREFIX=/tmp/ba -DBA_PY_PACKAGE=ON
- make -j$NPROC
- ctest -j3 --output-on-failure
- zsh var/mk_pypack_macos.zsh
- cpack .
artifacts: &mac_artifacts
paths:
- build/*.dmg
- build/PythonPackage/py*/wheel/*.whl
expire_in: 10 days
mac_arm:
tags:
- mac_arm
stage: build
before_script:
- QTDIR="/opt/homebrew/opt/qt"
# obtain nr of logical CPUs via `sysctl hw.logicalcpu`
- NPROC=14
script: *mac_script
artifacts: *mac_artifacts
# To test the GitLab process _locally_ on MS-Windows with powershell (pwsh),
# go to the root Git directory, and run:
......
......@@ -24,7 +24,7 @@ add_custom_command(
DEPENDS bornagain.pod
)
install(FILES ${MAN_DIR}/bornagain.1 DESTINATION ${CMAKE_INSTALL_PREFIX}/man/man1)
install(FILES ${MAN_DIR}/bornagain.1 DESTINATION "${destination_man}")
set(BUILD_MAN_DIR "${MAN_DIR}" CACHE INTERNAL "Man directory")
set(POD2MAN_EXECUTABLE "${POD2MAN}" CACHE INTERNAL "POD2MAN executable")
......@@ -137,6 +137,7 @@ file(APPEND "${log}"
" share (destination_share) = ${destination_share}\n"
" examples (destination_examples) = ${destination_examples}\n"
" images (destination_images) = ${destination_images}\n"
" man pages (destination_man) = ${destination_man}\n"
" installer name (CPACK_PACKAGE_FILE_NAME) = ${CPACK_PACKAGE_FILE_NAME}\n"
" source package name (CPACK_SOURCE_PACKAGE_FILE_NAME) = ${CPACK_SOURCE_PACKAGE_FILE_NAME}\n"
" package components (CPACK_COMPONENTS_ALL) = ${CPACK_COMPONENTS_ALL}\n"
......
......@@ -14,6 +14,10 @@ get_target_property(formfactor_LIBRARIES formfactor IMPORTED_LOCATION_RELEASE)
if(NOT formfactor_LIBRARIES)
get_target_property(formfactor_LIBRARIES formfactor IMPORTED_LOCATION_NOCONFIG)
endif()
if(NOT formfactor_LIBRARIES)
message(FATAL_ERROR "Formfactor libraries not found (path: '${formfactor_DIR}').")
endif()
set(FormFactor_LIBRARIES ${formfactor_LIBRARIES} CACHE INTERNAL "")
message(STATUS "formfactor: found=${formfactor_FOUND}, include_dirs=${formfactor_INCLUDE_DIR}, "
......
......@@ -89,6 +89,10 @@ set(destination_include ${destination_root}include/${destination_suffix}/)
set(destination_share ${destination_root}share/${destination_suffix}/)
set(destination_examples ${destination_share}Examples/)
set(destination_images ${destination_share}Images/)
set(destination_man ${destination_share}man/man1)
if(LINUX)
set(destination_man ${CMAKE_INSTALL_PREFIX}/man/man1)
endif(LINUX)
list(APPEND dstIds bin lib include share examples images)
......
......@@ -56,9 +56,8 @@ function(make_python_wheel)
else()
# MS-Windows
add_custom_target(BAPyWheel ALL
COMMAND ${__Py3_EXECUTABLE} -m build --wheel -n -o ${BA_PY_PACKAGE_WHEEL_DIR}
COMMAND ${__Py3_EXECUTABLE} -m pip wheel ${BA_PY_OUTPUT_DIR} --no-deps --wheel ${BA_PY_PACKAGE_WHEEL_DIR}
COMMENT "${header} Making the Python wheel..."
WORKING_DIRECTORY ${BA_PY_OUTPUT_DIR}
)
endif()
......
......@@ -21,7 +21,7 @@ message(STATUS "Python package destination directory: ${destination_pypackage}")
# check presence of some Python modules
message(STATUS "Searching required Python packages...")
foreach(pkg build numpy setuptools wheel matplotlib)
foreach(pkg pip numpy matplotlib)
message(STATUS "Python package ${pkg}")
execute_process(
COMMAND ${Python3_EXECUTABLE}
......
......@@ -127,9 +127,7 @@ done
# make the Python wheel
echo "$TITLE: Making the Python wheel..."
pushd "$pyoutdir"
$PYTHON -m build --wheel -n -o "$wheeldir"
popd
$PYTHON -m pip wheel "$pyoutdir" --no-deps --wheel "$wheeldir"
# final message
echo "$TITLE: Done."
......@@ -159,7 +159,7 @@ done
declare -a abs_refs rel_refs py_refs fw_refs
for ref in $refs_all; do
if [[ $ref = @* ]]; then
# relative reference; eg. '@rpath/foo.dylib'
# relative reference; eg. '@rpath/foo.dylib'
rel_refs+=( "$ref" )
elif [[ $ref = *[Pp]ython* ]] && [[ ! $ref = *boost* ]]; then
# Python dependencies must be considered separately (exclude 'libboost_python')
......@@ -179,11 +179,13 @@ done
dst="$pkg_root/$pkgbindir[exlib]"
mkdir -p "$dst"
echo "$TITLE: Copy external libraries to '$dst':"
# pkglib: map{ library reference => destination full-path }
# e.g., /usr/local/opt/libA.dylib => /pkg-root/Library/libA.dylib
declare -A pkglib
for ref in $abs_refs; do
pth="$dst/${ref##*/}" # destination full-path
pkglib[$ref]="$pth"
cp -fv "$ref" "$pth"
cp -fnv "$ref" "$pth"
done
unset dst
......@@ -198,11 +200,11 @@ framework_re='s;.+/([^/]+\.[Ff]ramework/[^[:blank:]]+).*;\1;'
for ref in $fw_refs; do
# only Qt framework is considered
if [[ ${ref##*/} = Qt* ]]; then
# eg., copy '/opt/qt@5/lib/QtGui.framework/Versions/5/QtGui'
# to '<Frameworks>/Qt/QtGui.framework/Versions/5/QtGui'
# eg., copy '/opt/qt@5/lib/QtGui.framework/Versions/5/QtGui'
# to '<Frameworks>/Qt/QtGui.framework/Versions/5/QtGui'
qtfwdir0=$(echo $ref | sed -E $framework_re)
pth="$qt_fwdir/$qtfwdir0"
mkdir -p "${pth%/*}"
pth="$qt_fwdir/$qtfwdir0"
mkdir -p "${pth%/*}"
pkglib[$ref]="$pth"
cp -fnv "$ref" "$pth"
else
......@@ -211,9 +213,9 @@ for ref in $fw_refs; do
done
# Add relatively-referenced Qt framework;
# e.g., QtDBus framework referenced as
# `@rpath/QtDBus.framework/Versions/A/QtDBus`
# e.g., QtDBus framework referenced as `@rpath/QtDBus.framework/Versions/A/QtDBus`
echo "$TITLE: Add relatively-referenced Qt framework libraries:"
qt_exlib_dir="$pkg_root/$pkgbindir[exlib]"
for ref in $rel_refs; do
# select only Qt relative references
if [[ ${ref##*/} = Qt* ]]; then
......@@ -221,8 +223,30 @@ for ref in $rel_refs; do
ref_qt=${ref/@rpath\//}
qt_src="$qt_framework_root/lib/$ref_qt"
qt_dst="$qt_fwdir/$ref_qt"
mkdir -p "${qt_dst%/*}"
qt_dst_dir="${qt_dst%/*}"
pkglib["REL-$qt_dst"]="$qt_dst"
mkdir -p "$qt_dst_dir"
cp -fnv "$qt_src" "$qt_dst"
# add the *1st-order optional* dependencies of the Qt library (if any)
# to the same folder as that of the Qt library
deps1=$(dylib_deps "$qt_dst" | sed -nE "s;[[:blank:]]*(/.+/opt/.+)[[:blank:]]\(.+;\1;p")
has_deps=0
for libpth_ in ${=deps1}; do
has_deps=1
# '/usr/local/opt/libA.1.2.dylib' => 'libA.1.2.dylib'
libname_="${libpth_##*/}"
# cp the library to the external library dir of the package
libdst="$qt_exlib_dir/$libname_"
pkglib[$libpth_]="$libdst"
cp -fnv "$libpth_" "$libdst"
# change the reference in the Qt library
# install_name_tool "$qt_dst" -change "$libpth_" "@rpath/$libname_"
done
# if the Qt library had any extra dependencies, add a proper RPATH
# if [[ $has_deps ]]; then
# install_name_tool "$qt_dst" -add_rpath "@loader_path"
# fi
fi
done
......@@ -230,6 +254,7 @@ done
declare -ar pkgbins=( $(rm_list_duplicates ${(v)pkglib} $libs_init "$main_exe") )
echo "$TITLE: All binaries:"
# a sorted list of binaries
for lib in ${(o)pkgbins}; do
echo " + '${lib#$pkg_root/}'"
done
......@@ -241,37 +266,37 @@ declare -A rpaths bin_deps
for bin in $pkgbins; do
declare -A rpaths_tmp=()
bin_deps[$bin]=$(dylib_deps "$bin")
bindir="${bin%/*}" # abs. dir of target binary
bindir="${bin%/*}" # abs. dir of target binary
# abspth0 = original abs. full-path of the library
# abspth_pkg = abs. full-path of the library in the package
for abspth0 abspth_pkg in ${(kv)pkglib}; do
# if the binary does not depend on the current library, do nothing
[[ "$bin_deps[$bin]" != *"$abspth0"* ]] && continue
# change the library reference in the binary
# eg. '/usr/local/opt/lib/libA.5.dylib' => '@rpath/libA.5.dylib'
libname="${abspth_pkg##*/}" # library filename
libdir="${abspth_pkg%/*}" # abs. dir of the referenced library
librelpth="" # rel. path of the library
# change the library reference in the binary
# eg. '/usr/local/opt/lib/libA.5.dylib' => '@rpath/libA.5.dylib'
libname="${abspth_pkg##*/}" # library filename
libdir="${abspth_pkg%/*}" # abs. dir of the referenced library
librelpth="" # rel. path of the library
# make a framework-relative path for the Qt framework libraries
# eg. '/opt/qt@5/lib/QtGui.framework/Versions/5/QtGui'
# => 'QtGui.framework/Versions/5'
if [[ $libname == Qt* ]]; then
if [[ $libname == Qt* ]]; then
# rm framework root dir from the beginning;
# eg. '/opt/qt@5/lib/QtGui.framework/Versions/5/QtGui'
# => 'QtGui.framework/Versions/5/QtGui'
librelpth="${abspth_pkg#$qt_fwdir/}"
librelpth="${abspth_pkg#$qt_fwdir/}"
# rm filename from the end
# eg. 'QtGui.framework/Versions/5/QtGui'
# => 'QtGui.framework/Versions/5'
librelpth="${librelpth%/*}"
fi
ref_new="$libname"
# prepend with library rel. path, if any
[[ ! -z $librelpth ]] && ref_new="$librelpth/$ref_new"
librelpth="${librelpth%/*}"
fi
ref_new="$libname"
# prepend with library rel. path, if any
[[ ! -z $librelpth ]] && ref_new="$librelpth/$ref_new"
install_name_tool "$bin" -change "$abspth0" "@rpath/$ref_new"
# make a proper RPATH to refer to the library within the package
# eg. '@loader_path/../Frameworks/Qt/'
rpath="@loader_path/"$(find_rpath "$bindir" "$libdir" "$librelpth")
# make a proper RPATH to refer to the library within the package
# eg. '@loader_path/../Frameworks/Qt/'
rpath="@loader_path/"$(find_rpath "$bindir" "$libdir" "$librelpth")
rpaths_tmp[$rpath]=1
done
# store a duplicateless list of rpaths needed for the binary,
......
......@@ -380,9 +380,7 @@ done
# make the Python wheel
echo "$TITLE: Making the Python wheel..."
pushd "$pyoutdir"
eval $PYTHON -m build --wheel -n -o "$wheeldir"
popd
eval $PYTHON -m pip wheel "$pyoutdir" --no-deps --wheel "$wheeldir"
#-- final message
echo "$TITLE: Done."
......@@ -16,7 +16,7 @@ Required software:
* `libtiff >=4.0.2`
* `libcerf >=1.14` (complex error function, maintained by us)
* `python3 python3-dev`
* `python3-build python3-setuptools python3-wheel python3-numpy python3-matplotlib`
* `python3-pip python3-numpy python3-matplotlib`
* `python3-lmfit` (optional, for some fit scripts)
* `boost >= 1.65` (see note below)
* `Qt5 >=5.5.1` (required modules are listed below)
......
......@@ -44,10 +44,10 @@ Once Python is set up correctly, install `numpy`. Therefore open a PowerShell an
py -m pip install numpy
```
Analogously install `matplotlib`, `setuptools`, `build` and `wheel` with
Analogously install `matplotlib` with
```
py -m pip install matplotlib setuptools build wheel
py -m pip install matplotlib
```
#### NSIS (for packaging only)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment