Skip to content

Script to provide pre-compiled binaries, built by GitHub actions, for linux/mac/windows #218

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

Merged
merged 2 commits into from
Aug 16, 2024
Merged
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
262 changes: 262 additions & 0 deletions .github/workflows/build_binaries.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
name: Build binaries

on:
push:
pull_request:
release:
types: [created]

jobs:

ubuntu:
strategy:
matrix:
projects: [
{short_name: "physiboss-tutorial", project: "physiboss-tutorial", name: "PhysiBoSS tutorial", binary: "project", extra_run: "make Compile_MaBoSS PHYSICELL_CPP=g++-11"},
{short_name: "physiboss-tutorial-invasion", project: "physiboss-tutorial-invasion", name: "PhysiBoSS Cancer Invasion", binary: "invasion_model", extra_run: "make Compile_MaBoSS PHYSICELL_CPP=g++-11"},
{short_name: "physiboss-cell-lines", project: "physiboss-cell-lines-sample", name: "PhysiBoSS Cell Lines", binary: "PhysiBoSS_Cell_Lines", extra_run: "make Compile_MaBoSS PHYSICELL_CPP=g++-11"},
{short_name: "template_BM", project: "template_BM", name: "PhysiBoSS Template", binary: "project", extra_run: "make Compile_MaBoSS PHYSICELL_CPP=g++-11"},
{short_name: "template", project: "template", name: "PhysiCell Template", binary: "project", extra_run: ""},
{short_name: "rules", project: "rules-sample", name: "PhysiCell Rules", binary: "project", extra_run: ""},
{short_name: "physimess", project: "physimess-sample", name: "PhysiMeSS", binary: "project", extra_run: ""},
{short_name: "interaction", project: "interaction-sample", name: "PhysiCell Interaction", binary: "interaction_demo", extra_run: ""},
]

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Build ${{ matrix.projects.name }}
run: |
make ${{ matrix.projects.project }}
make clean
${{ matrix.projects.extra_run }}
make static STATIC_OPENMP=/usr/lib/gcc/x86_64-linux-gnu/11/libgomp.a

- name: Checking binary for ${{ matrix.projects.name }}
run: |
ldd ${{ matrix.projects.binary }}

- name: Build ${{ matrix.projects.name }} project archive
run: |
rm -fr config/PhysiCell_settings-backup.xml
tar -zcvf ${{ matrix.projects.short_name }}-linux.tar.gz ${{ matrix.projects.binary }} Makefile main.cpp config/ custom_modules/

- uses: actions/upload-release-asset@v1
if: github.event_name == 'release'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ github.event.release.upload_url }}
asset_name: ${{ matrix.projects.short_name }}-linux.tar.gz
asset_path: ${{ github.workspace }}/${{ matrix.projects.short_name }}-linux.tar.gz
asset_content_type: application/gzip


windows:
strategy:
matrix:
projects: [
{short_name: "physiboss-tutorial", project: "physiboss-tutorial", name: "PhysiBoSS tutorial", binary: "project", extra_run: "make Compile_MaBoSS PHYSICELL_CPP=g++-11"},
{short_name: "physiboss-tutorial-invasion", project: "physiboss-tutorial-invasion", name: "PhysiBoSS Cancer Invasion", binary: "invasion_model", extra_run: "make Compile_MaBoSS PHYSICELL_CPP=g++-11"},
{short_name: "physiboss-cell-lines", project: "physiboss-cell-lines-sample", name: "PhysiBoSS Cell Lines", binary: "PhysiBoSS_Cell_Lines", extra_run: "make Compile_MaBoSS PHYSICELL_CPP=g++-11"},
{short_name: "template_BM", project: "template_BM", name: "PhysiBoSS Template", binary: "project", extra_run: "make Compile_MaBoSS PHYSICELL_CPP=g++-11"},
{short_name: "template", project: "template", name: "PhysiCell Template", binary: "project", extra_run: ""},
{short_name: "rules", project: "rules-sample", name: "PhysiCell Rules", binary: "project", extra_run: ""},
{short_name: "physimess", project: "physimess-sample", name: "PhysiMeSS", binary: "project", extra_run: ""},
{short_name: "interaction", project: "interaction-sample", name: "PhysiCell Interaction", binary: "interaction_demo", extra_run: ""},
]

runs-on: windows-latest

defaults:
run:
shell: msys2 {0}

steps:
- uses: actions/checkout@v4

- uses: msys2/setup-msys2@v2
with:
update: true
install: mingw-w64-x86_64-binutils mingw-w64-x86_64-gcc mingw-w64-x86_64-headers-git mingw-w64-x86_64-gcc-libs mingw-w64-x86_64-libwinpthread-git mingw-w64-x86_64-lapack mingw-w64-x86_64-openblas mingw-w64-x86_64-libxml2 mingw-w64-x86_64-bzip2 mingw-w64-x86_64-python mingw-w64-x86_64-python-zstandard mingw-w64-x86_64-python-cffi make bison flex mingw-w64-x86_64-ca-certificates

- name: Build ${{ matrix.projects.name }} project
run: |
make ${{ matrix.projects.project }}
make clean
python beta/setup_windows_dep.py
${{ matrix.projects.extra_run }}
make static

- name: Checking binary for ${{ matrix.projects.name }}
run: |
ldd .\\${{ matrix.projects.binary }}.exe

- name: Build ${{ matrix.projects.name }} project archive
run: |
rm -fr config/PhysiCell_settings-backup.xml
tar -zcvf ${{ matrix.projects.short_name }}-win.tar.gz ${{ matrix.projects.binary }}.exe *.dll Makefile main.cpp config/ custom_modules/

- uses: actions/upload-release-asset@v1
if: github.event_name == 'release'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ github.event.release.upload_url }}
asset_name: ${{ matrix.projects.short_name }}-win.tar.gz
asset_path: ${{ github.workspace }}\${{ matrix.projects.short_name }}-win.tar.gz
asset_content_type: application/gzip


macos_step0a:
strategy:
matrix:
projects: [
{short_name: "physiboss-tutorial", project: "physiboss-tutorial", name: "PhysiBoSS tutorial", binary: "project", extra_run: "make Compile_MaBoSS PHYSICELL_CPP=g++-11"},
{short_name: "physiboss-tutorial-invasion", project: "physiboss-tutorial-invasion", name: "PhysiBoSS Cancer Invasion", binary: "invasion_model", extra_run: "make Compile_MaBoSS PHYSICELL_CPP=g++-11"},
{short_name: "physiboss-cell-lines", project: "physiboss-cell-lines-sample", name: "PhysiBoSS Cell Lines", binary: "PhysiBoSS_Cell_Lines", extra_run: "make Compile_MaBoSS PHYSICELL_CPP=g++-11"},
{short_name: "template_BM", project: "template_BM", name: "PhysiBoSS Template", binary: "project", extra_run: "make Compile_MaBoSS PHYSICELL_CPP=g++-11"},
{short_name: "template", project: "template", name: "PhysiCell Template", binary: "project", extra_run: ""},
{short_name: "rules", project: "rules-sample", name: "PhysiCell Rules", binary: "project", extra_run: ""},
{short_name: "physimess", project: "physimess-sample", name: "PhysiMeSS", binary: "project", extra_run: ""},
{short_name: "interaction", project: "interaction-sample", name: "PhysiCell Interaction", binary: "interaction_demo", extra_run: ""},
]

runs-on: macos-12

steps:
- uses: actions/checkout@v4

- name: Install dependencies
run : brew install gcc@11

- name: Build ${{ matrix.projects.name }} project
run: |
export MACOSX_DEPLOYMENT_TARGET=12
make ${{ matrix.projects.project }}
make clean
${{ matrix.projects.extra_run }}
make PHYSICELL_CPP=g++-11 static
cp ${{ matrix.projects.binary }} ${{ matrix.projects.binary }}_macos12

- name: Caching produced project binary
uses: actions/cache@v4
with:
path: |
${{ github.workspace }}/${{ matrix.projects.binary }}_macos12
key: ${{ runner.os }}-macos12-${{ github.run_id }}

- name: Look at the generated binary
run: |
otool -L ${{ matrix.projects.binary }}
otool -l ${{ matrix.projects.binary }}
lipo -archs ${{ matrix.projects.binary }}

macos_step0b:
strategy:
matrix:
projects: [
{short_name: "physiboss-tutorial", project: "physiboss-tutorial", name: "PhysiBoSS tutorial", binary: "project", extra_run: "make Compile_MaBoSS PHYSICELL_CPP=g++-11"},
{short_name: "physiboss-tutorial-invasion", project: "physiboss-tutorial-invasion", name: "PhysiBoSS Cancer Invasion", binary: "invasion_model", extra_run: "make Compile_MaBoSS PHYSICELL_CPP=g++-11"},
{short_name: "physiboss-cell-lines", project: "physiboss-cell-lines-sample", name: "PhysiBoSS Cell Lines", binary: "PhysiBoSS_Cell_Lines", extra_run: "make Compile_MaBoSS PHYSICELL_CPP=g++-11"},
{short_name: "template_BM", project: "template_BM", name: "PhysiBoSS Template", binary: "project", extra_run: "make Compile_MaBoSS PHYSICELL_CPP=g++-11"},
{short_name: "template", project: "template", name: "PhysiCell Template", binary: "project", extra_run: ""},
{short_name: "rules", project: "rules-sample", name: "PhysiCell Rules", binary: "project", extra_run: ""},
{short_name: "physimess", project: "physimess-sample", name: "PhysiMeSS", binary: "project", extra_run: ""},
{short_name: "interaction", project: "interaction-sample", name: "PhysiCell Interaction", binary: "interaction_demo", extra_run: ""},
]

runs-on: macos-14

steps:
- uses: actions/checkout@v4

- name: Downgrade XCODE to 14.3.1
run: sudo xcode-select -switch /Applications/Xcode_14.3.1.app

- name: Install dependencies
run : brew install gcc@11

- name: Build ${{ matrix.projects.name }} project
run: |
export MACOSX_DEPLOYMENT_TARGET=12
make ${{ matrix.projects.project }}
make clean
${{ matrix.projects.extra_run }}
make PHYSICELL_CPP=g++-11 static
cp ${{ matrix.projects.binary }} ${{ matrix.projects.binary }}_macosm1

- name: Caching produced project binary
uses: actions/cache@v4
with:
path: |
${{ github.workspace }}/${{ matrix.projects.binary }}_macosm1
key: ${{ runner.os }}-macosm1-${{ github.run_id }}

- name: Look at the generated binary
run: |
otool -L ${{ matrix.projects.binary }}
otool -l ${{ matrix.projects.binary }}
lipo -archs ${{ matrix.projects.binary }}

macos_step1:
strategy:
matrix:
projects: [
{short_name: "physiboss-tutorial", project: "physiboss-tutorial", name: "PhysiBoSS tutorial", binary: "project", extra_run: "make Compile_MaBoSS PHYSICELL_CPP=g++-11"},
{short_name: "physiboss-tutorial-invasion", project: "physiboss-tutorial-invasion", name: "PhysiBoSS Cancer Invasion", binary: "invasion_model", extra_run: "make Compile_MaBoSS PHYSICELL_CPP=g++-11"},
{short_name: "physiboss-cell-lines", project: "physiboss-cell-lines-sample", name: "PhysiBoSS Cell Lines", binary: "PhysiBoSS_Cell_Lines", extra_run: "make Compile_MaBoSS PHYSICELL_CPP=g++-11"},
{short_name: "template_BM", project: "template_BM", name: "PhysiBoSS Template", binary: "project", extra_run: "make Compile_MaBoSS PHYSICELL_CPP=g++-11"},
{short_name: "template", project: "template", name: "PhysiCell Template", binary: "project", extra_run: ""},
{short_name: "rules", project: "rules-sample", name: "PhysiCell Rules", binary: "project", extra_run: ""},
{short_name: "physimess", project: "physimess-sample", name: "PhysiMeSS", binary: "project", extra_run: ""},
{short_name: "interaction", project: "interaction-sample", name: "PhysiCell Interaction", binary: "interaction_demo", extra_run: ""},
]

runs-on: macos-12
needs: [macos_step0a, macos_step0b]

steps:
- uses: actions/checkout@v4

- name: Caching produced project binary
uses: actions/cache@v4
with:
path: |
${{ github.workspace }}/${{ matrix.projects.binary }}_macosm1
key: ${{ runner.os }}-macosm1-${{ github.run_id }}

- name: Caching produced project binary
uses: actions/cache@v4
with:
path: |
${{ github.workspace }}/${{ matrix.projects.binary }}_macos12
key: ${{ runner.os }}-macos12-${{ github.run_id }}

- name: Creating universal binary
run: |
lipo -create -output ${{ matrix.projects.binary }} ${{ matrix.projects.binary }}_macos12 ${{ matrix.projects.binary }}_macosm1

- name: Checking universal binary
run: |
lipo -archs ${{ matrix.projects.binary }}
otool -l ${{ matrix.projects.binary }}
otool -L ${{ matrix.projects.binary }}

- name: Build project archive
run: |
make ${{ matrix.projects.project }}
rm -fr config/PhysiCell_settings-backup.xml
tar -zcvf ${{ matrix.projects.short_name }}-macos.tar.gz ${{ matrix.projects.binary }} Makefile main.cpp config/ custom_modules/

- uses: actions/upload-release-asset@v1
if: github.event_name == 'release'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ github.event.release.upload_url }}
asset_name: ${{ matrix.projects.short_name }}-macos.tar.gz
asset_path: ${{ github.workspace }}/${{ matrix.projects.short_name }}-macos.tar.gz
asset_content_type: application/gzip
111 changes: 111 additions & 0 deletions beta/download_binary.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# This script attempts to download the MaBoSS (binary) library(s) and
# headers for your particular operating system. It installs them in a standard
# location (relative to a PhysiCell installation) which will be used by a PhysiCell Makefile.
#
# Authors: Randy Heiland, Vincent Noel

import platform
import urllib.request
import os
import sys
import tarfile
import stat
import shutil

physicell_version = "1.14.0"
repo_physicell = "MathCancer/PhysiCell"
physiboss_version = "v2.2.3"
repo_physiboss = "sysbio-curie/PhysiBoSS"
list_models = {
"physiboss-tutorial": "https://github.com/" + repo_physiboss + "/releases/download/" + physiboss_version + "/",
"physiboss-tutorial-invasion": "https://github.com/" + repo_physiboss + "/releases/download/" + physiboss_version + "/",
"physiboss-cell-lines": "https://github.com/" + repo_physiboss + "/releases/download/" + physiboss_version + "/",
"template_BM": "https://github.com/" + repo_physiboss + "/releases/download/" + physiboss_version + "/",
"template": "https://github.com/" + repo_physicell + "/releases/download/" + physicell_version + "/",
"rules": "https://github.com/" + repo_physicell + "/releases/download/" + physicell_version + "/",
"physimess": "https://github.com/" + repo_physicell + "/releases/download/" + physicell_version + "/",
"interaction": "https://github.com/" + repo_physicell + "/releases/download/" + physicell_version + "/",
}

def print_usage():
print("Usage : python download_binary.py <model>")
print("")
print("Models available : %s" % (",".join(list_models.keys())))

if len(sys.argv) < 2:
print_usage()
exit(1)

model = sys.argv[1]

if model in ["-h", "--help"] or model not in list_models.keys():
print_usage()
exit(1)

print('> Chosen model: ', model)

os_type = platform.system()
print('> Operating system: ', os_type)

mb_file = ""
if os_type.lower() == 'darwin':
mb_file = model + "-macos.tar.gz"
elif os_type.lower().startswith("win") or os_type.lower().startswith("msys_nt") or os_type.lower().startswith("mingw64_nt"):
mb_file = model + "-win.tar.gz"
elif os_type.lower().startswith("linux"):
mb_file = model + "-linux.tar.gz"
else:
print("Your operating system seems to be unsupported. Please create an new issue at https://github.com/PhysiBoSS/PhysiBoSS/issues/ ")
sys.exit(1)

url = list_models[model] + mb_file
print('> Downloading from: ', url)

dir_name = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
print('> Loading into directory: ', dir_name)

my_file = os.path.join(dir_name, mb_file)
print('> File: ',my_file)

def download_cb(blocknum, blocksize, totalsize):
readsofar = blocknum * blocksize
if totalsize > 0:
percent = readsofar * 1e2 / totalsize
s = "\r%5.1f%% %*d / %d" % (
percent, len(str(totalsize)), readsofar, totalsize)
sys.stderr.write(s)
if readsofar >= totalsize: # near the end
sys.stderr.write("\n")
else: # total size is unknown
sys.stderr.write("read %d\n" % (readsofar,))

urllib.request.urlretrieve(url, my_file, download_cb)

print('> Creating backup of XML settings, Makefile, main.cpp')
if os.path.exists("Makefile"):
shutil.copyfile("Makefile", "Makefile-backup")
if os.path.exists("main.cpp"):
shutil.copyfile("main.cpp", "main-backup.cpp")
if os.path.exists(os.path.join("config", "PhysiCell_settings.xml")):
shutil.copyfile(os.path.join("config", "PhysiCell_settings.xml"), os.path.join("PhysiCell_settings-backup.xml"))

os.chdir(dir_name)
print('> Uncompressing the model')

try:
tar = tarfile.open(mb_file)
tar.extractall()
binary_name = [names for names in tar.getnames() if not names.endswith(".dll")][0]
tar.close()
os.remove(mb_file)

except:
print('! Error untarring the file')
exit(1)

new_name = "project" if not mb_file.endswith("win.tar.gz") else "project.exe"
os.rename(binary_name, new_name)
st = os.stat(new_name)
os.chmod(new_name, st.st_mode | stat.S_IEXEC)

print('> Done. You can now run %s\n' % new_name)
Loading