Skip to content

Fix:GetCSX

Fix:GetCSX #303

Workflow file for this run

name: "CI"
on:
push:
branches:
- '**'
pull_request:
branches:
- "**"
jobs:
Dependencies:
runs-on: ubuntu-latest
name: "Resolve repo dependencies"
steps:
- name: Checkout repo
uses: actions/checkout@v4
- name: Resolve repo dependencies
id: resolve-dependencies
# writes to $GITHUB_OUTPUT file
run: |
python3 $GITHUB_WORKSPACE/.github/scripts/resolve_dependent_repos.py \
--project openEMS
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_FORK_OWNER: ${{ github.event.pull_request.head.repo.owner.login }}
# format a human-friendly string in the following format:
#
# * Checkout XXXX.git
# (keep the "master" branch case boring to avoid information overload)
#
# OR:
#
# * Checkout XXXX.git | PR: https://example.com/XXXX
#
# OR:
#
# * Checkout XXXX.git | branch: feature | http://example.com/XXXX
- name: Format title strings
id: format-title
shell: python
run: |
import os
def format_title_string(var, repo, pr_url, branch):
title = "Checkout %s.git" % repo
if pr_url != "None":
title += " | PR: %s" % pr_url
elif branch != "master":
title += " | branch: %s | %s/%s/tree/%s" % (
branch, ${{ toJSON(github.server_url) }}, repo, branch
)
with open(os.getenv("GITHUB_OUTPUT"), "a") as output:
output.write("%s=%s\n" % (var, title))
format_title_string(
"fparser_checkout_title",
# escape special characters (single and double quotes) in string
# using JSON representation
${{ toJSON(steps.resolve-dependencies.outputs.fparser_repo) }},
${{ toJSON(steps.resolve-dependencies.outputs.fparser_pr_url) }},
${{ toJSON(steps.resolve-dependencies.outputs.fparser_branch) }}
)
format_title_string(
"CSXCAD_checkout_title",
${{ toJSON(steps.resolve-dependencies.outputs.csxcad_repo) }},
${{ toJSON(steps.resolve-dependencies.outputs.csxcad_pr_url) }},
${{ toJSON(steps.resolve-dependencies.outputs.csxcad_branch) }}
)
# map a step output to a job output
outputs:
fparser_repo: ${{ steps.resolve-dependencies.outputs.fparser_repo }}
fparser_branch: ${{ steps.resolve-dependencies.outputs.fparser_branch }}
fparser_checkout_title: ${{ steps.format-title.outputs.fparser_checkout_title }}
csxcad_repo: ${{ steps.resolve-dependencies.outputs.CSXCAD_repo }}
csxcad_branch: ${{ steps.resolve-dependencies.outputs.CSXCAD_branch }}
csxcad_checkout_title: ${{ steps.format-title.outputs.CSXCAD_checkout_title }}
Linux:
runs-on: ubuntu-latest
needs: Dependencies
defaults:
run:
shell: bash
strategy:
# Use "false" means a single failed build won't terminate other combinations
# in the matrix. This wastes CPU time, but is an important debugging tool to
# prevent a single broken platform from stopping the whole matrix.
fail-fast: false
matrix:
os:
# name: OS name (only a name for humans to read).
# libc: userland libc, "GNU" or "musl"
# (only a name for humans to read)
# ancient: true or false.
# true: incompatible with GitHub's actions/checkout due to
# node.js compatibility problem. Manual git checkout
# required.
# false: use standard GitHub's actions/checkout.
# docker-image: string, image on DockerHub to use
- name: "CentOS 7"
libc: "GNU"
ancient: true
docker-image: "centos:7"
- name: "Ubuntu 14.04"
libc: "GNU"
ancient: true
docker-image: "ubuntu:14.04"
- name: "Debian oldoldstable"
libc: "GNU"
ancient: false
docker-image: "debian:oldoldstable"
- name: "Debian oldstable"
libc: "GNU"
ancient: false
docker-image: "debian:oldstable"
- name: "Debian"
libc: "GNU"
ancient: false
docker-image: "debian:latest"
- name: "Ubuntu"
libc: "GNU"
ancient: false
docker-image: "ubuntu:latest"
- name: "Fedora"
libc: "GNU"
ancient: false
docker-image: "fedora:latest"
- name: "AlmaLinux 8"
libc: "GNU"
ancient: false
docker-image: "almalinux:8"
- name: "AlmaLinux 9"
libc: "GNU"
ancient: false
docker-image: "almalinux:9"
# Waiting for upstream packages:
# https://bugzilla.redhat.com/show_bug.cgi?id=2374130
# https://bugzilla.redhat.com/show_bug.cgi?id=2419727
#
#- name: "AlmaLinux Latest"
# libc: "GNU"
# ancient: false
# docker-image: "almalinux:latest"
- name: "Alpine"
libc: "musl"
ancient: false
docker-image: "alpine:latest"
container:
image: ${{ matrix.os.docker-image }}
# allow mount/netns
options: "--cap-add CAP_SYS_ADMIN --cap-add NET_ADMIN --security-opt apparmor=unconfined"
name: "${{ matrix.os.libc }}/Linux (${{ matrix.os.name }})"
env:
# Wno-error is needed because any third-party dependencies
# like compiler version changes or even Python libraries
# installed by pip can block the pipeline, this is not what
# we want.
CXXFLAGS: "-Wall -Wextra -Wno-error"
steps:
- name: Check for dockerenv file
# bash is not installed on Alpine at this point
shell: sh
run: (ls /.dockerenv && echo Found dockerenv) || exit 1
- name: Show checkout sources
shell: sh
run: |
echo "$FPARSER_CHECKOUT_TITLE"
echo "$CSXCAD_CHECKOUT_TITLE"
env:
# convert template variables to shell variables to avoid arbitrary code injection
FPARSER_CHECKOUT_TITLE: ${{ needs.Dependencies.outputs.fparser_checkout_title }}
CSXCAD_CHECKOUT_TITLE: ${{ needs.Dependencies.outputs.csxcad_checkout_title }}
# When checking out repos, I recommend running actions/checkout
# as soon as possible before anything else, and in the reverse
# order, from the project repo to its dependencies. This reduces
# race conditions due to force pushes (they are harmless but
# annoying).
- if: ${{ ! matrix.os.ancient }}
name: Checkout openEMS.git
uses: actions/checkout@v4
with:
path: openEMS
# checkout must be deep, not shallow.
# We need tags for "git describe", otherwise build fails.
fetch-depth: 0
- if: ${{ ! matrix.os.ancient }}
name: ${{ needs.Dependencies.outputs.csxcad_checkout_title }}
uses: actions/checkout@v4
with:
repository: "${{ needs.Dependencies.outputs.csxcad_repo }}"
ref: "${{ needs.Dependencies.outputs.csxcad_branch }}"
path: CSXCAD
# checkout must be deep, not shallow.
# We need tags for "git describe", otherwise build fails.
fetch-depth: 0
- if: ${{ ! matrix.os.ancient }}
name: ${{ needs.Dependencies.outputs.fparser_checkout_title }}
uses: actions/checkout@v4
with:
repository: "${{ needs.Dependencies.outputs.fparser_repo }}"
ref: "${{ needs.Dependencies.outputs.fparser_branch }}"
path: fparser
- if: ${{ matrix.os.ancient }}
name: (legacy) Work around known problems
run: |
if [ -f /etc/centos-release ]; then
# IPv6 on GitHub Actions is broken, causing random network failures
# if a CDN rosolves to IPv6.
echo "ip_resolve=4" >> /etc/yum.conf
# CentOS repos are EOL and desupported
sed -i 's|^mirrorlist|#mirrorlist|g; s|^#baseurl|baseurl|g; s|mirror.centos.org|vault.centos.org|g' \
/etc/yum.repos.d/CentOS-Base.repo
yum install -y centos-release-scl || true
sed -i 's|^mirrorlist|#mirrorlist|g; s|^#baseurl|baseurl|g;
s|^# baseurl|baseurl|g; s|mirror.centos.org|vault.centos.org|g' \
/etc/yum.repos.d/CentOS-SCLo-scl.repo \
/etc/yum.repos.d/CentOS-SCLo-scl-rh.repo
fi
- if: ${{ matrix.os.ancient }}
name: (legacy) Install git
run: |
if [ -f /etc/centos-release ]; then
yum install -y git
elif grep -q "ID=ubuntu" /etc/os-release && \
grep -q 'VERSION_ID="14.04"' /etc/os-release; then
apt-get install -y git
fi
- if: ${{ matrix.os.ancient }}
name: (legacy) Checkout openEMS.git
run: |
git clone "$GITHUB_SERVER_URL/$GITHUB_REPOSITORY.git" openEMS
cd "$GITHUB_WORKSPACE/openEMS"
git fetch --force "$GITHUB_SERVER_URL/$GITHUB_REPOSITORY.git" "+refs/heads/*:refs/remotes/origin/*"
git fetch --force "$GITHUB_SERVER_URL/$GITHUB_REPOSITORY.git" "+refs/pull/*/merge:refs/remotes/origin/pr/*"
git checkout "$GITHUB_SHA"
- if: ${{ matrix.os.ancient }}
name: (legacy) ${{ needs.Dependencies.outputs.csxcad_checkout_title }}
run: |
echo "Clone $REPO.git (branch $BRANCH)"
git clone "$GITHUB_SERVER_URL/$REPO.git"
cd "$GITHUB_WORKSPACE/$CHECKOUT_PATH"
git fetch --force "$GITHUB_SERVER_URL/$REPO.git" "+refs/heads/*:refs/remotes/origin/*"
git fetch --force "$GITHUB_SERVER_URL/$REPO.git" "+refs/pull/*/merge:refs/remotes/origin/pr/*"
git checkout "$BRANCH"
env:
# convert template variables to shell variables to avoid arbitrary code injection
REPO: ${{ needs.Dependencies.outputs.csxcad_repo }}
BRANCH: ${{ needs.Dependencies.outputs.csxcad_branch }}
CHECKOUT_PATH: CSXCAD
- if: ${{ matrix.os.ancient }}
name: (legacy) ${{ needs.Dependencies.outputs.fparser_checkout_title }}
run: |
echo "Clone $REPO.git (branch $BRANCH)"
git clone "$GITHUB_SERVER_URL/$REPO.git"
cd "$GITHUB_WORKSPACE/$CHECKOUT_PATH"
git fetch --force "$GITHUB_SERVER_URL/$REPO.git" "+refs/heads/*:refs/remotes/origin/*"
git fetch --force "$GITHUB_SERVER_URL/$REPO.git" "+refs/pull/*/merge:refs/remotes/origin/pr/*"
git checkout "$BRANCH"
env:
# convert template variables to shell variables to avoid arbitrary code injection
REPO: ${{ needs.Dependencies.outputs.fparser_repo }}
BRANCH: ${{ needs.Dependencies.outputs.fparser_branch }}
CHECKOUT_PATH: fparser
- name: Install dependencies
shell: sh
run: |
cat /etc/os-release
if grep -q "ID=fedora" /etc/os-release; then
dnf install -y git
dnf install -y gcc gcc-c++ cmake git boost-devel tinyxml-devel vtk-devel hdf5-devel \
CGAL-devel octave python3-pip \
python3-setuptools python3-setuptools_scm \
python3-Cython python3-numpy python3-h5py python3-matplotlib
# only for CI/CD test builds without networks.
dnf install -y iproute
elif grep -q 'ID="almalinux"' /etc/os-release; then
dnf install -y epel-release
dnf config-manager --set-enabled powertools || dnf config-manager --set-enabled crb
dnf install -y git
dnf install -y gcc gcc-c++ cmake git boost-devel tinyxml-devel vtk-devel hdf5-devel \
CGAL-devel octave python3-pip \
python3-setuptools python3-wheel python3-setuptools_scm \
python3-Cython python3-numpy python3-h5py python3-matplotlib
# only for CI/CD test builds without networks.
dnf install -y iproute
elif grep -q "ID=debian" /etc/os-release || grep -q "ID=ubuntu" /etc/os-release; then
# retry failed downloads 3 times
echo 'Acquire::Retries "3";' > /etc/apt/apt.conf.d/80-retries
apt-get update
apt-get install -y build-essential git \
libhdf5-dev libtinyxml-dev \
octave \
python3-pip \
python3-setuptools python3-numpy python3-matplotlib python3-h5py
# VTK9 or VTK7, at least one must succeed (depending on Debian version)
# VTK9, VTK7, or VTK6, at least one must succeed (depending on Debian version)
apt-get install -y libvtk9-dev || \
apt-get install -y libvtk7-dev || \
apt-get install -y libvtk6-dev
# only for CI/CD test builds without networks.
apt-get install -y iproute2
if grep -q 'VERSION_ID="14.04"' /etc/os-release; then
# Ubuntu 14.04 has CMake 2 by default, but we require CMake 3
apt-get install -y cmake3
# Ubuntu 14.04 ships Boost 1.54 and is required by libcgal-dev,
# but we need Boost 1.55, so we install Boost 1.55 first, then
# install CGAL from source.
apt-get install -y boost1.55 boost1.55-dev
# CGAL v4.14.3 was old enough to be compatible with GCC 4.8. Otherwise,
# you get: The compiler feature "cxx_decltype_auto" is not known
# to CXX compiler "GNU" version 4.8.5.
apt-get install -y libgmp-dev libmpfr-dev
git clone $GITHUB_SERVER_URL/CGAL/cgal.git --depth=1 --branch=v4.14.3
cd cgal && mkdir build && cd build
cmake ../ -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$HOME/opt
make -j`nproc` && make install
# Must use Cython 3.0 or lower, since 3.1 uses f-string which is
# incompatible with Python 3.4.
pip3 install "cython<3.1"
# Ubuntu 14.04's matplotlib package is ancient, install the
# minimum version and its dependencies via pip. Note that the
# native build uses Python 3.4 while the venv build (tested
# later) uses Python 3.5 without these problems.
#
# pip's pyparsing is incompatible with Python 3.4
apt-get install -y python3-pyparsing
# same, newer cycler has incompatible type annotation
pip3 install "cycler==0.10.0"
pip3 install "matplotlib==2.1.0"
else
apt-get install -y libboost-all-dev
apt-get install -y libcgal-dev
apt-get install -y cmake
apt-get install -y python3-setuptools-scm cython3 python3-matplotlib
# testing Python packages in isolated venv
apt-get install -y python3-venv
fi
elif grep -q "ID=alpine" /etc/os-release; then
apk add bash \
build-base gmp-dev mpfr-dev git cmake \
boost-dev tinyxml-dev hdf5-dev cgal-dev vtk-dev \
octave \
python3-dev py3-pip \
py3-setuptools py3-setuptools_scm cython \
py3-numpy py3-h5py py3-matplotlib
# only for CI/CD test builds without networks.
apk add iproute2
elif [ -f /etc/centos-release ]; then
# "(legacy) Work around known problems" must run before this step
yum install -y epel-release
yum install -y git
yum install -y gcc gcc-c++ gmp-devel mpfr-devel \
cmake3 git tinyxml-devel vtk-devel hdf5-devel octave \
python3-devel python3-pip \
python3-setuptools python3-setuptools_scm python3-Cython
# only for CI/CD test builds without networks.
yum install -y iproute
# use cmake3 instead of default cmake2
alternatives --install /usr/local/bin/cmake cmake /usr/bin/cmake3 99
# To upgrade GCC, one can use GCC 7 from centos-release-scl, required by CGAL.
# Even GCC 10+ is provided.
# Not used for now, since openEMS is still compatible with GCC 4.8! But we may
# need it in the future.
# yum install -y devtoolset-7-gcc devtoolset-7-gcc-c++
# alternatives --install /usr/local/bin/gcc gcc /opt/rh/devtoolset-7/root/usr/bin/gcc 99
# alternatives --install /usr/local/bin/g++ g++ /opt/rh/devtoolset-7/root/usr/bin/g++ 99
# boost-predef is only available on Boost 1.55 and later.
# /usr/local/include/CGAL/config.h:210:10: fatal error: boost/predef.h:
# No such file or directory
# We borrow a copy of Boost 1.58 from rh repo's mariadb backport package.
yum install -y rh-mariadb101-boost-devel
# copy rh repo's Boost to /usr/local because CMake doesn't support CPATH
ln -s /opt/rh/rh-mariadb101/root/usr/include/boost /usr/local/include/boost
mkdir /usr/local/lib64 && cd /usr/local/lib64
for i in /opt/rh/rh-mariadb101/root/usr/lib64/libboost*; do
ln -s $i /usr/local/lib64/
done
# setup.py is broken on CentOS 7, installing openEMS shows:
# error: Couldn't find a setup script in /tmp/easy_install-8fl5smm_/numpy-2.2.0.tar.gz
# Error: Process completed with exit code 1.
pip3 install numpy h5py matplotlib --user
# not package on CentOS
# CGAL v4.14.3 was old enough to be compatible with GCC 4.8. Otherwise,
# you get: The compiler feature "cxx_decltype_auto" is not known
# to CXX compiler "GNU" version 4.8.5.
git clone $GITHUB_SERVER_URL/CGAL/cgal.git --depth=1 --branch=v4.14.3
cd cgal && mkdir build && cd build
cmake ../ -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$HOME/opt
make -j`nproc` && make install
else
echo "Unknown system!"
exit 1
fi
- name: Build and install fparser
run: |
cd $GITHUB_WORKSPACE/fparser
mkdir build && cd build
cmake ../ -DCMAKE_INSTALL_PREFIX=$HOME/opt
make -j`nproc` && make install
- name: Build and install CSXCAD
run: |
# cmake may fail with "fatal: No names found, cannot describe anything."
# if it happens, check if you're using a shallow clone, or if it's a GitHub
# fork created with "Copy the master branch only". If so, you need to FULL
# fork or clone.
#
# MPI may also fail, but this error is not fatal. The real error is often
# the error above! There's no need to install MPI.
cd $GITHUB_WORKSPACE/CSXCAD
mkdir build && cd build
cmake ../ -DCMAKE_INSTALL_PREFIX=$HOME/opt
make -j`nproc` && make install
- name: Build and install CSXCAD Python module with --no-build-isolation
run: |
cd $GITHUB_WORKSPACE/CSXCAD/python
export CSXCAD_INSTALL_PATH=$HOME/opt/
pip_opts=( "--user" "--verbose" )
# some systems don't have --no-build-isolation, some systems don't have
# --break-system-packages, the oldest systems don't have both.
if pip3 install --help | grep -q no-build-isolation; then
pip_opts+=( "--no-build-isolation" )
fi
if pip3 install --help | grep -q break-system-packages; then
pip_opts+=( "--break-system-packages" )
fi
# run in an isolated container without network, ensure
# pip install really works without auto-downloads.
ip netns add no-network
ip netns exec no-network pip3 install . "${pip_opts[@]}"
- name: Build and install openEMS
run: |
# Hack: openEMS requires Boost Predef (1.55+), but CSXCAD requires CGAL, on
# Ubuntu 14.04's libcgal-dev requires Boost 1.54. So we install Boost 1.55
# after CSXCAD but before openEMS - this uninstalls libcgal-dev (but libcgal
# itself is okay)
if grep -q 'VERSION_ID="14.04"' /etc/os-release; then
apt-get install -y boost1.55-dev
apt-get install -y boost1.55
fi
cd $GITHUB_WORKSPACE/openEMS
mkdir build && cd build
cmake ../ -DCMAKE_INSTALL_PREFIX=$HOME/opt -DFPARSER_ROOT_DIR=$HOME/opt
make -j`nproc` && make install
echo "addpath('~/opt/share/openEMS/matlab')" >> ~/.octaverc
echo "addpath('~/opt/share/CSXCAD/matlab')" >> ~/.octaverc
- name: Build and install openEMS Python module with --no-build-isolation
run: |
cd $GITHUB_WORKSPACE/openEMS/python
# Python "exit(False)" = bash "if true"
# Python "exit(True)" = bash "if false"
if python3 -c "import pip; exit(int(pip.__version__.split('.')[0]) > 20)"; then
# old pip < 21.3 (checking <= 21 here for simplicity),
# CSXCAD needs CSXCAD_PYSRC_PATH as auto-detection is
# not reliable.
export CSXCAD_PYSRC_PATH=$GITHUB_WORKSPACE/CSXCAD/python/
fi
pip_opts=( "--user" "--verbose" )
# some systems don't have --no-build-isolation, some systems don't have
# --break-system-packages, the oldest systems don't have both.
if pip3 install --help | grep -q no-build-isolation; then
pip_opts+=( "--no-build-isolation" )
fi
if pip3 install --help | grep -q break-system-packages; then
pip_opts+=( "--break-system-packages" )
fi
export CSXCAD_INSTALL_PATH=$HOME/opt/
export OPENEMS_INSTALL_PATH=$HOME/opt/
# run in an isolated container without network, ensure
# pip install really works without auto-downloads.
ip netns exec no-network pip3 install . "${pip_opts[@]}"
- name: Smoketest Octave execution
run: |
cd $GITHUB_WORKSPACE/openEMS/.github/smoketests/octave
octave MSL_NotchFilter.m
- name: Smoketest Python execution
run: |
cd $GITHUB_WORKSPACE/openEMS/.github/smoketests/python
python3 -c "import CSXCAD; print(CSXCAD.__version__)"
python3 -c "import openEMS; print(openEMS.__version__)"
python3 MSL_NotchFilter.py
- name: Create Python venv and install dependencies
run: |
cd ~/
if grep -q "ID=ubuntu" /etc/os-release && \
grep -q 'VERSION_ID="14.04"' /etc/os-release; then
# Use Python 3.5 instead of the default Python 3.4 because
# 3.5 is the latest available version on Ubuntu 14.04, and
# also because Python 3.5 is the first Python that supported
# type annotation, while Python 3.4 is locked out from most
# modern packages.
apt-get install -y curl python3.5-dev
# Ubuntu 14.04 is ancient, and the python3.5-venv package is
# broken. So the best approach is to install a bare Python 3.5
# interpreter from apt, and bootstrapping pip ourselves.
python3.5 -m venv ~/venv --without-pip
curl -O https://bootstrap.pypa.io/pip/3.5/get-pip.py
source ~/venv/bin/activate
python3.5 get-pip.py
else
python3 -m venv ~/venv
source ~/venv/bin/activate
fi
pip install --upgrade pip
if [ -f /etc/centos-release ]; then
pip3 install "cython<3.1"
fi
- name: Build and install CSXCAD Python module in venv
run: |
source ~/venv/bin/activate
cd $GITHUB_WORKSPACE/CSXCAD/python
export CSXCAD_INSTALL_PATH="$HOME/opt"
pip3 install . --verbose
- name: Build and install openEMS Python module in venv
run: |
source ~/venv/bin/activate
cd $GITHUB_WORKSPACE/openEMS/python
# Python "exit(False)" = bash "if true"
# Python "exit(True)" = bash "if false"
if python3 -c "import pip; exit(int(pip.__version__.split('.')[0]) > 20)"; then
# old pip < 21.3 (checking <= 21 here for simplicity),
# CSXCAD needs CSXCAD_PYSRC_PATH as auto-detection is
# not reliable.
export CSXCAD_PYSRC_PATH=$GITHUB_WORKSPACE/CSXCAD/python/
fi
export CSXCAD_INSTALL_PATH="$HOME/opt"
export OPENEMS_INSTALL_PATH="$HOME/opt"
pip3 install . --verbose
- name: Smoketest Python execution in venv
run: |
source ~/venv/bin/activate
cd $GITHUB_WORKSPACE/openEMS/.github/smoketests/python
python3 -c "import CSXCAD; print(CSXCAD.__version__)"
python3 -c "import openEMS; print(openEMS.__version__)"
python3 MSL_NotchFilter.py
macOS:
name: "macOS (ARM, latest)"
runs-on: macos-latest
needs: Dependencies
steps:
- name: Show checkout sources
run: |
echo "$FPARSER_CHECKOUT_TITLE"
echo "$CSXCAD_CHECKOUT_TITLE"
env:
# convert template variables to shell variables to avoid arbitrary code injection
FPARSER_CHECKOUT_TITLE: ${{ needs.Dependencies.outputs.fparser_checkout_title }}
CSXCAD_CHECKOUT_TITLE: ${{ needs.Dependencies.outputs.csxcad_checkout_title }}
# When checking out repos, I recommend running actions/checkout
# as soon as possible before anything else, and in the reverse
# order, from the project repo to its dependencies. This reduces
# race conditions due to force pushes (they are harmless but
# annoying).
- name: Checkout openEMS.git
uses: actions/checkout@v4
with:
path: openEMS
# checkout must be deep, not shallow.
# We need tags for "git describe", otherwise build fails.
fetch-depth: 0
- name: ${{ needs.Dependencies.outputs.csxcad_checkout_title }}
uses: actions/checkout@v4
with:
repository: "${{ needs.Dependencies.outputs.csxcad_repo }}"
ref: "${{ needs.Dependencies.outputs.csxcad_branch }}"
path: CSXCAD
# checkout must be deep, not shallow.
# We need tags for "git describe", otherwise build fails.
fetch-depth: 0
- name: ${{ needs.Dependencies.outputs.fparser_checkout_title }}
uses: actions/checkout@v4
with:
repository: "${{ needs.Dependencies.outputs.fparser_repo }}"
ref: "${{ needs.Dependencies.outputs.fparser_branch }}"
path: fparser
- name: Install dependencies
run: |
touch ~/.zprofile # set environment variables here
echo 'export CXXFLAGS="-Wall -Wextra -Wno-error"' >> ~/.zprofile
# already installed on the CI/CD system, disable to avoid warning fatigue
# brew install python3 cmake
brew install boost hdf5 cgal vtk octave \
python-setuptools cython numpy python-matplotlib
echo "export NCPUS=$(python3 -c 'import os; print(os.cpu_count())')" >> ~/.zprofile
source ~/.zprofile
# TinyXML has been disabled by Homebrew at it's unmaintained
# since 2011, TinyXML2 is not API-compatible. As a stop-gap,
# build from source.
#
# -L: follow redirect, REQUIRED!
curl -L https://sourceforge.net/projects/tinyxml/files/tinyxml/2.6.2/tinyxml_2_6_2.tar.gz -o tinyxml-2.6.2.tar.gz
tar -xf tinyxml-2.6.2.tar.gz
cd tinyxml
# The first patch enforces use of stl strings, rather than a custom string type.
# The second patch is a fix for incorrect encoding of elements with special characters
# The third and fourth patches are security fixes.
#
# -L: follow redirect, REQUIRED!
# -O: save to disk with an automatic file name.
curl -L -O "https://raw.githubusercontent.com/alpinelinux/aports/b1ff376e83eb49c0127b039b3684eccdf9a60694/community/tinyxml/tinyxml-2.6.2-defineSTL.patch"
curl -L -O "https://raw.githubusercontent.com/alpinelinux/aports/b1ff376e83eb49c0127b039b3684eccdf9a60694/community/tinyxml/tinyxml-2.6.1-entity.patch"
curl -L -O "https://raw.githubusercontent.com/alpinelinux/aports/b1ff376e83eb49c0127b039b3684eccdf9a60694/community/tinyxml/CVE-2021-42260.patch"
curl -L -O "https://raw.githubusercontent.com/alpinelinux/aports/b1ff376e83eb49c0127b039b3684eccdf9a60694/community/tinyxml/CVE-2023-34194.patch"
# The final patch adds a CMakeLists.txt file to build a shared library and provide an install target
# submitted upstream as https://sourceforge.net/p/tinyxml/patches/66/
curl -L -O "https://gist.githubusercontent.com/scpeters/6325123/raw/cfb079be67997cb19a1aee60449714a1dedefed5/tinyxml_CMakeLists.patch"
patch -p1 < tinyxml-2.6.2-defineSTL.patch
patch -p1 < tinyxml-2.6.1-entity.patch
patch -p1 < CVE-2021-42260.patch
patch -p1 < CVE-2023-34194.patch
# You know something is truly deprecated when the patch itself needs
# patching! In CMake 4, 3.10 is deprecated and 3.5 has been removed.
# use 3.0...3.10 so all of these versions are acceptable as min. version.
# (CMake 2 is dropped since openEMS already requires CMake 3, and also
# because CMake 2 is too old that it's not even documented anymore)
#
# https://cmake.org/cmake/help/latest/command/cmake_minimum_required.html
sed -i -e "s/cmake_minimum_required(VERSION 2.4.6)/cmake_minimum_required(VERSION 3.0...3.10)/" \
tinyxml_CMakeLists.patch # -e is not optional in BSD sed
patch -p1 < tinyxml_CMakeLists.patch
mkdir build && cd build
cmake ../ -DCMAKE_INSTALL_PREFIX=$HOME/opt
make -j$NCPUS && make install
- name: Build and install fparser
run: |
source ~/.zprofile
cd $GITHUB_WORKSPACE/fparser
mkdir build && cd build
cmake ../ -DCMAKE_INSTALL_PREFIX=$HOME/opt
make -j$NCPUS && make install
- name: Build and install CSXCAD
run: |
# cmake may fail with "fatal: No names found, cannot describe anything."
# if it happens, check if you're using a shallow clone, or if it's a GitHub
# fork created with "Copy the master branch only". If so, you need to FULL
# fork or clone.
#
# MPI may also fail, but this error is not fatal. The real error is often
# the error above! There's no need to install MPI.
source ~/.zprofile
cd $GITHUB_WORKSPACE/CSXCAD
mkdir build && cd build
cmake ../ -DCMAKE_INSTALL_PREFIX=$HOME/opt
make -j$NCPUS && make install
- name: Build and install CSXCAD Python module with --no-build-isolation
run: |
source ~/.zprofile
cd $GITHUB_WORKSPACE/CSXCAD/python
export CSXCAD_INSTALL_PATH=$HOME/opt/
pip3 install . --user --break-system-packages --no-build-isolation --verbose
- name: Build and install openEMS
run: |
source ~/.zprofile
cd $GITHUB_WORKSPACE/openEMS
mkdir build && cd build
cmake ../ -DCMAKE_INSTALL_PREFIX=$HOME/opt -DFPARSER_ROOT_DIR=$HOME/opt
make -j$NCPUS && make install
echo "addpath('~/opt/share/openEMS/matlab')" >> ~/.octaverc
echo "addpath('~/opt/share/CSXCAD/matlab')" >> ~/.octaverc
- name: Build and install openEMS Python module with --no-build-isolation
run: |
source ~/.zprofile
cd $GITHUB_WORKSPACE/openEMS/python
export CSXCAD_INSTALL_PATH=$HOME/opt/
export OPENEMS_INSTALL_PATH=$HOME/opt/
pip3 install . --user --break-system-packages --no-build-isolation --verbose
- name: Smoketest Octave execution
run: |
cd $GITHUB_WORKSPACE/openEMS/.github/smoketests/octave
octave MSL_NotchFilter.m
- name: Smoketest Python execution
run: |
cd $GITHUB_WORKSPACE/openEMS/.github/smoketests/python
python3 -c "import CSXCAD; print(CSXCAD.__version__)"
python3 -c "import openEMS; print(openEMS.__version__)"
python3 MSL_NotchFilter.py
- name: Create Python venv and install dependencies
run: |
# remove Python dependencies to see if venv really works
pip3 uninstall -y CSXCAD openEMS --break-system-packages
brew remove python-setuptools cython numpy python-matplotlib
python3 -m venv ~/venv
source ~/venv/bin/activate
pip3 install --upgrade pip
- name: Build and install CSXCAD Python module in venv
run: |
source ~/venv/bin/activate
cd $GITHUB_WORKSPACE/CSXCAD/python
export CSXCAD_INSTALL_PATH="$HOME/opt"
pip3 install . --verbose
- name: Build and install openEMS Python module in venv
run: |
source ~/venv/bin/activate
cd $GITHUB_WORKSPACE/openEMS/python
export CSXCAD_INSTALL_PATH="$HOME/opt"
export OPENEMS_INSTALL_PATH="$HOME/opt"
pip3 install . --verbose
- name: Smoketest Python execution in venv
run: |
source ~/venv/bin/activate
cd $GITHUB_WORKSPACE/openEMS/.github/smoketests/python
python3 -c "import CSXCAD; print(CSXCAD.__version__)"
python3 -c "import openEMS; print(openEMS.__version__)"
python3 MSL_NotchFilter.py
FreeBSD:
runs-on: ubuntu-latest
needs: Dependencies
strategy:
matrix:
machine:
- name: "FreeBSD 14.2"
os: freebsd
arch: x86-64
version: '14.2'
# macOS already tests ARM for us, so disable the slow ARM emulator
# for now
#- name: "FreeBSD 14.2 (ARM emulator)"
# os: freebsd
# arch: arm64
# version: '14.2'
name: "${{ matrix.machine.name }}"
steps:
- name: Show checkout sources
run: |
echo "$FPARSER_CHECKOUT_TITLE"
echo "$CSXCAD_CHECKOUT_TITLE"
env:
# convert template variables to shell variables to avoid arbitrary code injection
FPARSER_CHECKOUT_TITLE: ${{ needs.Dependencies.outputs.fparser_checkout_title }}
CSXCAD_CHECKOUT_TITLE: ${{ needs.Dependencies.outputs.csxcad_checkout_title }}
# When checking out repos, I recommend running actions/checkout
# as soon as possible before anything else, and in the reverse
# order, from the project repo to its dependencies. This reduces
# race conditions due to force pushes (they are harmless but
# annoying).
- name: Checkout openEMS.git
uses: actions/checkout@v4
with:
path: openEMS
# checkout must be deep, not shallow.
# We need tags for "git describe", otherwise build fails.
fetch-depth: 0
- name: ${{ needs.Dependencies.outputs.csxcad_checkout_title }}
uses: actions/checkout@v4
with:
repository: "${{ needs.Dependencies.outputs.csxcad_repo }}"
ref: "${{ needs.Dependencies.outputs.csxcad_branch }}"
path: CSXCAD
# checkout must be deep, not shallow.
# We need tags for "git describe", otherwise build fails.
fetch-depth: 0
- name: ${{ needs.Dependencies.outputs.fparser_checkout_title }}
uses: actions/checkout@v4
with:
repository: "${{ needs.Dependencies.outputs.fparser_repo }}"
ref: "${{ needs.Dependencies.outputs.fparser_branch }}"
path: fparser
- name: Test in FreeBSD ${{ matrix.machine.version }} ${{ matrix.machine.arch }}
uses: cross-platform-actions/action@v0.26.0
with:
cpu_count: 4
architecture: ${{ matrix.machine.arch }}
operating_system: ${{ matrix.machine.os }}
version: ${{ matrix.machine.version }}
run: |
echo "Install dependencies..."
sudo pkg install -y cmake git boost-libs tinyxml vtk9 hdf5 cgal octave python3 \
py311-pip \
py311-setuptools py311-wheel py311-setuptools-scm \
py311-cython3 py311-numpy py311-h5py py311-matplotlib
# prefix must match FreeBSD's default python
# version. FreeBSD 14.2 uses Python 3.11 so
# use "py311-"
export CXXFLAGS="-Wall -Wextra -Wno-error"
export NCPUS=$(python3 -c 'import os; print(os.cpu_count())')
echo "Build and install fparser..."
cd $GITHUB_WORKSPACE/fparser
mkdir build && cd build
cmake ../ -DCMAKE_INSTALL_PREFIX=$HOME/opt
make -j$NCPUS && make install
echo "Build and install CSXCAD..."
# cmake may fail with "fatal: No names found, cannot describe anything."
# if it happens, check if you're using a shallow clone, or if it's a GitHub
# fork created with "Copy the master branch only". If so, you need to FULL
# fork or clone.
#
# MPI may also fail, but this error is not fatal. The real error is often
# the error above! There's no need to install MPI.
cd $GITHUB_WORKSPACE/CSXCAD
mkdir build && cd build
cmake ../ -DCMAKE_INSTALL_PREFIX=$HOME/opt
make -j$NCPUS && make install
echo "Build and install CSXCAD Python module with --no-build-isolation..."
cd $GITHUB_WORKSPACE/CSXCAD/python
export CSXCAD_INSTALL_PATH=$HOME/opt/
pip install . --user --break-system-packages --no-build-isolation --verbose
echo "Build and install openEMS..."
cd $GITHUB_WORKSPACE/openEMS
mkdir build && cd build
cmake ../ -DCMAKE_INSTALL_PREFIX=$HOME/opt -DFPARSER_ROOT_DIR=$HOME/opt
make -j$NCPUS && make install
echo "addpath('~/opt/share/openEMS/matlab')" >> ~/.octaverc
echo "addpath('~/opt/share/CSXCAD/matlab')" >> ~/.octaverc
echo "Build and install openEMS Python module with --no-build-isolation..."
cd $GITHUB_WORKSPACE/openEMS/python
export CSXCAD_INSTALL_PATH=$HOME/opt/
export OPENEMS_INSTALL_PATH=$HOME/opt/
pip install . --user --break-system-packages --no-build-isolation --verbose
echo "Smoketest Octave execution..."
cd $GITHUB_WORKSPACE/openEMS/.github/smoketests/octave/
octave MSL_NotchFilter.m
echo "Smoketest Python execution..."
cd $GITHUB_WORKSPACE/openEMS/.github/smoketests/python
python3 -c "import CSXCAD; print(CSXCAD.__version__)"
python3 -c "import openEMS; print(openEMS.__version__)"
python3 MSL_NotchFilter.py
echo "Create Python venv and install dependencies..."
# remove Python dependencies to see if venv really works
pip uninstall -y CSXCAD openEMS --break-system-packages
sudo pkg remove -y py311-pip \
py311-setuptools py311-wheel py311-setuptools-scm \
py311-cython3 py311-numpy py311-h5py py311-matplotlib
python3 -m venv ~/venv
. ~/venv/bin/activate
pip install --upgrade pip
echo "Build and install CSXCAD Python module in venv..."
cd $GITHUB_WORKSPACE/CSXCAD/python
export CSXCAD_INSTALL_PATH="$HOME/opt"
pip install . --verbose
echo "Build and install openEMS Python module in venv..."
cd $GITHUB_WORKSPACE/openEMS/python
export CSXCAD_INSTALL_PATH="$HOME/opt"
export OPENEMS_INSTALL_PATH="$HOME/opt"
pip install . --verbose
echo "Smoketest Python execution in venv..."
cd $GITHUB_WORKSPACE/openEMS/.github/smoketests/python
python3 -c "import CSXCAD; print(CSXCAD.__version__)"
python3 -c "import openEMS; print(openEMS.__version__)"
python3 MSL_NotchFilter.py
Windows:
runs-on: windows-latest
needs: Dependencies
strategy:
# Use "false" means a single failed build won't terminate other combinations
# in the matrix. This wastes CPU time, but is an important debugging tool to
# prevent a single broken platform from stopping the whole matrix.
fail-fast: false
matrix:
toolchain:
# name: toonchain name (only a name for humans to read).
# CC, CXX: C/C++ compiler, environment variables
- name: "MSVC"
CC: "cl"
CXX: "cl"
- name: "clang-cl"
CC: "clang-cl"
CXX: "clang-cl"
env:
VS_ROOT_DIR: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/"
CC: "${{ matrix.toolchain.CC }}"
CXX: "${{ matrix.toolchain.CXX }}"
CFLAGS: "/D_WIN32_WINNT=0x0601"
CXXFLAGS: "/D_WIN32_WINNT=0x0601"
VCPKG_CACHE_PATH: "${{ github.workspace }}/vcpkg-cache/"
VCPKG_BINARY_CACHE_PATH: "${{ github.workspace }}/vcpkg-cache/binary"
VCPKG_BINARY_SOURCES: "clear;files,${{ github.workspace }}/vcpkg-cache/binary,readwrite"
VCPKG_ASSET_CACHE_PATH: "${{ github.workspace }}/vcpkg-cache/asset"
X_VCPKG_ASSET_SOURCES: "x-azurl,file://${{ github.workspace }}/vcpkg-cache/asset,readwrite"
name: "Windows (${{ matrix.toolchain.name }}, latest)"
steps:
- name: Show checkout sources
run: |
echo "$env:FPARSER_CHECKOUT_TITLE"
echo "$env:CSXCAD_CHECKOUT_TITLE"
env:
# convert template variables to shell variables to avoid arbitrary code injection
FPARSER_CHECKOUT_TITLE: ${{ needs.Dependencies.outputs.fparser_checkout_title }}
CSXCAD_CHECKOUT_TITLE: ${{ needs.Dependencies.outputs.csxcad_checkout_title }}
# When checking out repos, I recommend running actions/checkout
# as soon as possible before anything else, and in the reverse
# order, from the project repo to its dependencies. This reduces
# race conditions due to force pushes (they are harmless but
# annoying).
- name: Checkout openEMS.git
uses: actions/checkout@v4
with:
path: openEMS
# checkout must be deep, not shallow.
# We need tags for "git describe", otherwise build fails.
fetch-depth: 0
- name: ${{ needs.Dependencies.outputs.csxcad_checkout_title }}
uses: actions/checkout@v4
with:
repository: "${{ needs.Dependencies.outputs.csxcad_repo }}"
ref: "${{ needs.Dependencies.outputs.csxcad_branch }}"
path: CSXCAD
# checkout must be deep, not shallow.
# We need tags for "git describe", otherwise build fails.
fetch-depth: 0
- name: ${{ needs.Dependencies.outputs.fparser_checkout_title }}
uses: actions/checkout@v4
with:
repository: "${{ needs.Dependencies.outputs.fparser_repo }}"
ref: "${{ needs.Dependencies.outputs.fparser_branch }}"
path: fparser
# It doesn't really work, because MSVC itself doesn't support long path.
# But for future-proofing (it does work for clang).
- name: Enable long paths
run: |
New-ItemProperty -Path "HKLM:/SYSTEM/CurrentControlSet/Control/FileSystem" `
-Name "LongPathsEnabled" -Value 1 -PropertyType DWORD -Force
- name: Create vcpkg cache directories
run: |
mkdir -p "$env:VCPKG_CACHE_PATH"
mkdir -p "$env:VCPKG_BINARY_CACHE_PATH"
mkdir -p "$env:VCPKG_ASSET_CACHE_PATH"
- name: Restore vcpkg cache
uses: actions/cache/restore@v5
with:
path: ${{ env.VCPKG_CACHE_PATH }}
# almost always nonexistent
key: "Windows - ${{ matrix.toolchain.name }} - ${{ github.sha }}"
# use GitHub's fallback feature to pick the latest cache with this prefix
restore-keys: |
Windows - ${{ matrix.toolchain.name }}
- name: Build and install fparser
run: |
& "$env:VS_ROOT_DIR/Common7/Tools/Launch-VsDevShell.ps1" -Arch amd64 -HostArch amd64
cd "$env:GITHUB_WORKSPACE/fparser"
mkdir build && cd build
cmake ../ -GNinja -DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS=ON `
-DCMAKE_BUILD_TYPE=Release `
-DCMAKE_INSTALL_PREFIX="$HOME/opt"
cmake --build ./ --parallel
cmake --install ./ --parallel 8
- name: Build and install CSXCAD
run: |
& "$env:VS_ROOT_DIR/Common7/Tools/Launch-VsDevShell.ps1" -Arch amd64 -HostArch amd64
cd "$env:GITHUB_WORKSPACE/CSXCAD"
mkdir build && cd build
cmake ../ -GNinja `
-DCMAKE_BUILD_TYPE=Release `
-DCMAKE_INSTALL_PREFIX="$HOME/opt" `
-DFPARSER_ROOT_DIR="$HOME/opt" `
-DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake" `
-DVCPKG_HOST_TRIPLET="x64-windows-release" `
-DVCPKG_TARGET_TRIPLET="x64-windows-release"
cmake --build ./ --parallel
cmake --install ./ --parallel 8
- name: Build and install openEMS
run: |
& "$env:VS_ROOT_DIR/Common7/Tools/Launch-VsDevShell.ps1" -Arch amd64 -HostArch amd64
cd "$env:GITHUB_WORKSPACE/openEMS"
mkdir build && cd build
cmake ../ -GNinja `
-DCMAKE_BUILD_TYPE=Release `
-DCMAKE_INSTALL_PREFIX="$HOME/opt" `
-DFPARSER_ROOT_DIR="$HOME/opt" `
-DCSXCAD_ROOT_DIR="$HOME/opt" `
-DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake" `
-DVCPKG_HOST_TRIPLET="x64-windows-release" `
-DVCPKG_TARGET_TRIPLET="x64-windows-release"
cmake --build ./ --parallel
cmake --install ./ --parallel 8
- name: Save vcpkg cache
if: always() # save even after a build failure.
uses: actions/cache/save@v5
with:
path: ${{ env.VCPKG_CACHE_PATH }}
# GitHub cache is immutable and can't be overwritten
# save a new cache key every time
key: Windows - ${{ matrix.toolchain.name }} - ${{ github.sha }}