Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
264 changes: 91 additions & 173 deletions .github/workflows/compile_madng.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ jobs:
name: mad-Linux
path: MAD/src/mad

build-macos-x86_64:
runs-on: macos-15-intel
build-macos-arm64:
runs-on: macos-15
defaults:
run:
shell: bash
Expand All @@ -93,203 +93,121 @@ jobs:

- name: Install build tools
run: |
brew update
brew install gcc@12 make cmake automake autoconf libtool pkg-config curl
brew install gcc cmake automake autoconf libtool pkg-config curl

- name: Prepare compiler shims
- name: Select native compiler toolchain
run: |
set -euo pipefail

gcc_prefix="$(brew --prefix gcc@12)"
toolshim="${RUNNER_TEMP}/gcc-shim"
mkdir -p "${toolshim}"

ln -sf "${gcc_prefix}/bin/gcc-12" "${toolshim}/gcc"
ln -sf "${gcc_prefix}/bin/g++-12" "${toolshim}/g++"
ln -sf "${gcc_prefix}/bin/gfortran-12" "${toolshim}/gfortran"
ln -sf "/usr/local/bin/make" "${toolshim}/make"
ln -sf "/usr/local/bin/cmake" "${toolshim}/cmake"
ln -sf "/usr/local/bin/pkg-config" "${toolshim}/pkg-config"
ln -sf "/usr/local/bin/libtool" "${toolshim}/libtool"
ln -sf "/usr/local/bin/ar" "${toolshim}/ar"
ln -sf "/usr/local/bin/ranlib" "${toolshim}/ranlib"
gcc_bin="$(ls /opt/homebrew/bin/gcc-[0-9]* | sort -V | tail -n1)"
ver="${gcc_bin##*-}"

{
echo "${toolshim}"
echo "/usr/local/bin"
echo "$(brew --prefix)/bin"
} >> "${GITHUB_PATH}"

- name: Select MAD-NG macOS Makefile
run: |
cp MAD/src/Makefile.macosx MAD/src/Makefile
python3 - <<'PY'
from pathlib import Path

path = Path("MAD/src/Makefile")
text = path.read_text()
replacements = [
("CC := gcc-11", "CC := gcc"),
("CXX := g++-11", "CXX := g++"),
("FC := gfortran-11", "FC := gfortran"),
("-fdiagnostics-all-candidates", ""),
("-flto", ""),
("-march=native", ""),
("-mtune=native", ""),
("-mfma", ""),
]
for old, new in replacements:
text = text.replace(old, new)
path.write_text(text)
PY

- name: Build MAD-NG dependencies (README order)
echo "CC=gcc-${ver}"
echo "CXX=g++-${ver}"
echo "FC=gfortran-${ver}"
echo "MACOSX_DEPLOYMENT_TARGET=14"
} >> "${GITHUB_ENV}"

- name: Build native MAD-NG dependencies (lib/README.md)
env:
MAD_ROOT: ${{ github.workspace }}/MAD
run: |
set -euo pipefail

echo "== Toolchain =="
which gcc
gcc --version
which g++
g++ --version
which gfortran
gfortran --version

export OS=macosx
export MACOSX_DEPLOYMENT_TARGET=11
export JOBS="$(sysctl -n hw.ncpu)"
export CC=gcc
export CXX=g++
export FC=gfortran
export AR=ar
export RANLIB=ranlib

mkdir -p MAD/bin/macosx

cd MAD/lib
echo "== MAD/lib contents (before download) =="
ls -la

echo "== LuaJIT (README.luajit) =="
rm -rf luajit
git clone https://github.com/MethodicalAcceleratorDesign/LuaJIT.git luajit
cd luajit
git checkout mad-patch
git pull
which "${CC}"; "${CC}" --version
which "${CXX}"; "${CXX}" --version
which "${FC}"; "${FC}" --version

export MAD_BIN="${MAD_ROOT}/bin/macosx"
export MAD_DEPS="${RUNNER_TEMP}/mad-deps"
mkdir -p "${MAD_BIN}" "${MAD_DEPS}"
JOBS="$(sysctl -n hw.ncpu)"

cd "${MAD_DEPS}"
git clone --depth 1 --branch mad-patch https://github.com/MethodicalAcceleratorDesign/LuaJIT.git luajit
git clone --depth 1 https://github.com/MethodicalAcceleratorDesign/luafilesystem.git lfs
git clone --depth 1 --branch v3.12.1 https://github.com/Reference-LAPACK/lapack.git lapack
git clone --depth 1 --branch v2.7.1 https://github.com/stevengj/nlopt.git nlopt
curl -fsSL -o fftw-3.3.10.tar.gz https://www.fftw.org/fftw-3.3.10.tar.gz
curl -fsSL -o nfft-3.5.3.tar.gz https://www-user.tu-chemnitz.de/~potts/nfft/download/nfft-3.5.3.tar.gz
curl -fsSL -o lpeg-1.1.0.tar.gz http://www.inf.puc-rio.br/~roberto/lpeg/lpeg-1.1.0.tar.gz
tar xzf fftw-3.3.10.tar.gz
tar xzf nfft-3.5.3.tar.gz
tar xzf lpeg-1.1.0.tar.gz

echo "== LuaJIT =="
cd "${MAD_DEPS}/luajit"
make clean
make -j"${JOBS}" amalg PREFIX="$(pwd)"
make -j"${JOBS}" amalg PREFIX="$(pwd)" CC="${CC}"
make install PREFIX="$(pwd)"
cp -f src/libluajit.a ../../bin/macosx/
cd ..
cp -f src/libluajit.a "${MAD_BIN}/"

echo "== LFS (README.lfs) =="
rm -rf lfs
git clone https://github.com/MethodicalAcceleratorDesign/luafilesystem.git lfs
cd lfs
make clean || true
make lfs.a
cp -f liblfs.a ../../bin/macosx/
cd ..
echo "== FFTW3 =="
cd "${MAD_DEPS}/fftw-3.3.10"
CC="${CC}" CFLAGS='-O3 -fPIC' ./configure --disable-shared --enable-static
make -j"${JOBS}"
cp -f .libs/libfftw3.a "${MAD_BIN}/"

echo "== LPEG (README.lpeg) =="
rm -rf lpeg lpeg-1.1.0 lpeg-1.1.0.tar.gz
curl -fsSL -o lpeg-1.1.0.tar.gz http://www.inf.puc-rio.br/~roberto/lpeg/lpeg-1.1.0.tar.gz
tar xvzf lpeg-1.1.0.tar.gz
ln -s lpeg-1.1.0 lpeg
cd lpeg
python3 - <<'PY'
from pathlib import Path
import re

path = Path("makefile")
text = path.read_text()
text = re.sub(r"^LUADIR[ \t]*=.*$", "LUADIR = ../luajit/include/luajit-2.1", text, flags=re.MULTILINE)
text = re.sub(r"^LUALIB[ \t]*=.*$", "LUALIB = ../luajit/lib/libluajit-5.1.a", text, flags=re.MULTILINE)
text = re.sub(r"^COPT[ \t]*=.*$", "COPT = -O3 -DNDEBUG", text, flags=re.MULTILINE)
path.write_text(text)
PY
make clean || true
make -j"${JOBS}" CC="${CC:-gcc}" LUADIR="../luajit/include/luajit-2.1" lpvm.o lpcap.o lptree.o lpcode.o lpprint.o lpcset.o
ar -r liblpeg.a lpvm.o lpcap.o lptree.o lpcode.o lpprint.o lpcset.o
ranlib liblpeg.a
cp -f liblpeg.a ../../bin/macosx/
cd ..

echo "== LAPACK (README.lapack) =="
rm -rf lapack
git clone https://github.com/Reference-LAPACK/lapack lapack
cd lapack
cp -f make.inc.example make.inc
python3 - <<'PY'
from pathlib import Path
import re

path = Path("make.inc")
text = path.read_text()
for key in ("CFLAGS", "FFLAGS", "FFLAGS_NOOPT"):
text = re.sub(rf"^({key}[ \t]*=[ \t]*)(?!-fPIC\b)", r"\1-fPIC ", text, flags=re.MULTILINE)
path.write_text(text)
PY
echo "== LuaFileSystem =="
cd "${MAD_DEPS}/lfs"
make clean || true
make -j"${JOBS}" blaslib
make -j"${JOBS}" lapacklib
cp -f librefblas.a ../../bin/macosx/
cp -f liblapack.a ../../bin/macosx/
cd ..

echo "== FFTW3 (README.fftw3) =="
rm -rf fftw3 fftw-3.3.10 fftw-3.3.10.tar.gz
curl -fsSL -o fftw-3.3.10.tar.gz ftp://ftp.fftw.org/pub/fftw/fftw-3.3.10.tar.gz
tar xvzf fftw-3.3.10.tar.gz
ln -s fftw-3.3.10 fftw3
cd fftw3
make clean || true
./configure --disable-shared
make -j"${JOBS}"
cp -f .libs/libfftw3.a ../../bin/macosx/
cd ..
make lfs.a CC="${CC}" AR=ar CFLAGS="-O3 -fPIC -I${MAD_DEPS}/luajit/src"
cp -f liblfs.a "${MAD_BIN}/"

echo "== NFFT3 (README.nfft3) =="
rm -rf nfft3 nfft-3.5.3 nfft-3.5.3.tar.gz
curl -fsSL -o nfft-3.5.3.tar.gz https://www-user.tu-chemnitz.de/~potts/nfft/download/nfft-3.5.3.tar.gz
tar xvzf nfft-3.5.3.tar.gz
ln -s nfft-3.5.3 nfft3
cd nfft3
echo "== LPeg =="
cd "${MAD_DEPS}/lpeg-1.1.0"
make clean || true
./configure --enable-all --disable-shared \
--with-fftw3="$(pwd)"/../fftw3 \
--with-fftw3-libdir="$(pwd)"/../fftw3/.libs \
--with-fftw3-includedir="$(pwd)"/../fftw3/api
make -j"${JOBS}"
cp -f .libs/libnfft3.a ../../bin/macosx/
cd ..

echo "== NLOPT (README.nlopt) =="
rm -rf nlopt
git clone https://github.com/stevengj/nlopt nlopt
cd nlopt
rm -rf build
mkdir -p build
cd build
cmake -DBUILD_SHARED_LIBS=OFF -DNLOPT_CXX=OFF ..
make -j"${JOBS}" CC="${CC}" LUADIR="${MAD_DEPS}/luajit/src" COPT='-O3 -DNDEBUG' \
lpvm.o lpcap.o lptree.o lpcode.o lpprint.o lpcset.o
ar -rcs liblpeg.a lpvm.o lpcap.o lptree.o lpcode.o lpprint.o lpcset.o
cp -f liblpeg.a "${MAD_BIN}/"

echo "== NLopt =="
cd "${MAD_DEPS}/nlopt"
cmake -S . -B build-arm64 -DBUILD_SHARED_LIBS=OFF -DNLOPT_CXX=OFF -DNLOPT_FORTRAN=OFF \
-DCMAKE_C_COMPILER="${CC}" -DCMAKE_OSX_ARCHITECTURES=arm64 -DCMAKE_POLICY_VERSION_MINIMUM=3.5
CMAKE_POLICY_VERSION_MINIMUM=3.5 cmake --build build-arm64 -j"${JOBS}"
cp -f build-arm64/libnlopt.a "${MAD_BIN}/"

echo "== LAPACK and reference BLAS =="
cd "${MAD_DEPS}/lapack"
cmake -S . -B build-arm64 -DBUILD_SHARED_LIBS=OFF -DBUILD_TESTING=OFF \
-DCMAKE_C_COMPILER="${CC}" -DCMAKE_Fortran_COMPILER="${FC}" -DCMAKE_OSX_ARCHITECTURES=arm64
cmake --build build-arm64 -j"${JOBS}" --target blas lapack
cp -f build-arm64/lib/libblas.a "${MAD_BIN}/librefblas.a"
cp -f build-arm64/lib/liblapack.a "${MAD_BIN}/"

echo "== NFFT3 =="
cd "${MAD_DEPS}/nfft-3.5.3"
CC="${CC}" CFLAGS='-O3 -fPIC' ./configure --enable-all --disable-shared \
--with-fftw3="${MAD_DEPS}/fftw-3.3.10" \
--with-fftw3-libdir="${MAD_DEPS}/fftw-3.3.10/.libs" \
--with-fftw3-includedir="${MAD_DEPS}/fftw-3.3.10/api"
make -j"${JOBS}"
cp -f libnlopt.a ../../../bin/macosx/
cp -f .libs/libnfft3.a "${MAD_BIN}/"

echo "== Verify native archives =="
lipo -info "${MAD_BIN}"/*.a

- name: Compile MAD-NG
working-directory: MAD/src
env:
MAD_DEPS: ${{ runner.temp }}/mad-deps
run: |
echo "== Toolchain =="
which gcc
gcc --version
which g++
g++ --version
which gfortran
gfortran --version
which "${CC}"; "${CC}" --version
which "${CXX}"; "${CXX}" --version
which "${FC}"; "${FC}" --version

make SHELL=/bin/bash CC=gcc CXX=g++ FC=gfortran
make -f Makefile.macosx clean
make -f Makefile.macosx SHELL=/bin/bash CC="${CC}" CXX="${CXX}" FC="${FC}" LIB="${MAD_DEPS}"
lipo -info mad
chmod 755 mad

- name: Upload binary
uses: actions/upload-artifact@v4
with:
name: mad-macOS-x86_64
name: mad-macOS-arm64
path: MAD/src/mad
6 changes: 3 additions & 3 deletions .github/workflows/python-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ jobs:
if: ${{ vars.PYMADNG_BUILD_MADNG_FROM_SOURCE != 'false' }}
uses: actions/download-artifact@v5
with:
name: mad-macOS-x86_64
name: mad-macOS-arm64
path: build/mad-Darwin
- name: Add compiled MAD-NG binaries to the package
if: ${{ vars.PYMADNG_BUILD_MADNG_FROM_SOURCE != 'false' }}
Expand All @@ -64,8 +64,8 @@ jobs:
if: ${{ vars.PYMADNG_BUILD_MADNG_FROM_SOURCE == 'false' }}
run: |
mkdir -p src/pymadng/bin
curl --fail --location https://madx.web.cern.ch/releases/madng/1.1/mad-linux-1.1.14 -o src/pymadng/bin/mad_Linux
curl --fail --location https://madx.web.cern.ch/releases/madng/1.1/mad-macos-1.1.14 -o src/pymadng/bin/mad_Darwin
curl --fail --location https://madx.web.cern.ch/releases/madng/1.1/mad-linux-1.1.15 -o src/pymadng/bin/mad_Linux
curl --fail --location https://madx.web.cern.ch/releases/madng/1.1/mad-macos-1.1.15 -o src/pymadng/bin/mad_Darwin
chmod +x src/pymadng/bin/mad_Linux src/pymadng/bin/mad_Darwin
- name: Build package
run: python -m build
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/test-pymadng.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@ jobs:
- name: Get MAD Binaries
run: |
mkdir ./src/pymadng/bin
curl https://madx.web.cern.ch/releases/madng/1.1/mad-linux-1.1.14 -o ./src/pymadng/bin/mad_Linux
curl https://madx.web.cern.ch/releases/madng/1.1/mad-macos-1.1.14 -o ./src/pymadng/bin/mad_Darwin
curl https://madx.web.cern.ch/releases/madng/1.1/mad-linux-1.1.15 -o ./src/pymadng/bin/mad_Linux
curl https://madx.web.cern.ch/releases/madng/1.1/mad-macos-1.1.15 -o ./src/pymadng/bin/mad_Darwin
chmod +x ./src/pymadng/bin/mad_Linux ./src/pymadng/bin/mad_Darwin
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install -e .[tfs]
python -m pip install -e .[tfs,jupyter]
- name: Test with python
run: |
python -m unittest tests/*.py
15 changes: 14 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
0.10.0 (2026/09/06) \
Major behaviour change: MAD-NG's stdout/stderr are now always piped back through Python.
This means the output has to be captured and manually handled on each send and receive
command. Due to the deliberate asynchronous design of the PyMAD-NG interface, this
means that the output may be delayed and not appear immediately after MAD-NG sends it.
The reason for this change was to support environments where stdout/stderr are not real
OS file descriptors, such as Jupyter notebooks. \
Bump MAD-NG to 1.1.15. \
Fixed a stack overflow in the `ex-recv-lhc` deferred-expressions example (hit a
recursive call). \
Fixed an incorrect range-construction snippet in the `ex-LowLevel` example. \
Added `examples/ex-jupyter` and automated notebook execution tests.

0.9.6 (2026/07/11) \
Added way to compile on pull request and new release.
Added way to compile on pull request and new release.

0.9.5 (2026/07/11) \
Update pymadng version
Expand Down
2 changes: 1 addition & 1 deletion examples/ex-LowLevel/ex-send-multypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@

# Receive ranges from MAD
mad.send("""
py:send(3..11..2)
py:send(MAD.range(3, 11, 2))
py:send(MAD.nrange(3.5, 21.4, 12))
py:send(MAD.nlogrange(1, 20, 20))
""")
Expand Down
Loading
Loading