Skip to content
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
208 changes: 208 additions & 0 deletions .github/workflows/release-binaries.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
name: Release binaries

# Builds release ZIPs on GitHub-hosted runners. MATLAB comes from
# matlab-actions/setup-matlab; CUDA comes from Jimver/cuda-toolkit. These builds
# compile CUDA but do not run GPU tests because hosted runners have no NVIDIA GPU.

on:
release:
types: [published]
workflow_dispatch:
inputs:
tag:
description: Release tag to upload assets to
required: true
overwrite:
description: Replace assets with the same name
type: boolean
default: false

permissions:
contents: write

concurrency:
group: release-binaries-${{ github.event.release.tag_name || inputs.tag }}
cancel-in-progress: false

env:
VCPKG_ROOT: "C:\\vcpkg"

jobs:
windows:
runs-on: windows-2022
timeout-minutes: 180
strategy:
fail-fast: false
matrix:
cuda:
- { label: "12.8", version: "12.8.1", arch: "61;75;86;89;90" }
- { label: "12.9", version: "12.9.1", arch: "61;75;86;89;90" }
- { label: "13.1", version: "13.1.0", arch: "75;80;86;89;90;100;103;121" }
matlab:
- { label: "2022a", release: "R2022a", cmake: "9.12" }
- { label: "2024a", release: "R2024a", cmake: "24.1" }
steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Set up CUDA
uses: Jimver/cuda-toolkit@v0.2.36
with:
cuda: ${{ matrix.cuda.version }}
log-file-suffix: windows-${{ matrix.cuda.label }}-${{ matrix.matlab.label }}

- name: Set up MATLAB
uses: matlab-actions/setup-matlab@v3
with:
release: ${{ matrix.matlab.release }}

- name: Set MATLAB root
shell: pwsh
run: |
$matlabExe = (Get-Command matlab).Source
$matlabRoot = Split-Path (Split-Path $matlabExe -Parent) -Parent
"Matlab_ROOT_DIR=$matlabRoot" >> $env:GITHUB_ENV

- name: Set up vcpkg
shell: pwsh
run: .\build_scripts\setup_vcpkg.ps1

- name: Configure
shell: pwsh
run: |
$args = @(
"-S", "echoframe/cpp/src",
"-B", "build",
"-G", "Visual Studio 17 2022",
"-A", "x64",
"-T", "cuda=$env:CUDA_PATH",
"-DCMAKE_BUILD_TYPE=Release",
"-DCMAKE_TOOLCHAIN_FILE=$env:VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake",
"-DVCPKG_TARGET_TRIPLET=x64-windows-static-md",
"-DCMAKE_PREFIX_PATH=$env:VCPKG_ROOT/installed/x64-windows-static-md",
"-DCMAKE_CUDA_ARCHITECTURES=${{ matrix.cuda.arch }}",
"-DCUDAToolkit_ROOT=$env:CUDA_PATH",
"-DMatlab_ROOT_DIR=$env:Matlab_ROOT_DIR",
"-DMATLAB_VERSION=${{ matrix.matlab.cmake }}",
"-DEF_BUILD_CLI=ON",
"-DEF_BUILD_MEX=ON",
"-DEF_BUILD_PYTHON=ON",
"-DPython_ROOT_DIR=$env:pythonLocation",
"-DPython_EXECUTABLE=$env:pythonLocation/python.exe",
"-DPython_FIND_STRATEGY=LOCATION"
)
cmake @args

- name: Build
shell: pwsh
run: cmake --build build --config Release -j $env:NUMBER_OF_PROCESSORS

- name: Package
shell: pwsh
run: |
New-Item -ItemType Directory -Force release-assets | Out-Null
$name = "build_CUDA_${{ matrix.cuda.label }}_MATLAB_${{ matrix.matlab.label }}"
pwsh -NoProfile -ExecutionPolicy Bypass -File build_scripts/pack_build.ps1 `
-ReleaseDir build/Release -Out "release-assets/$name.zip"

- name: Upload release asset
shell: pwsh
env:
GITHUB_TOKEN: ${{ github.token }}
TAG_NAME: ${{ github.event.release.tag_name || inputs.tag }}
OVERWRITE: ${{ inputs.overwrite || false }}
run: .github/workflows/scripts/upload-release-assets.ps1 release-assets

linux:
runs-on: ubuntu-22.04
timeout-minutes: 180
env:
VCPKG_ROOT: ${{ github.workspace }}/vcpkg
strategy:
fail-fast: false
matrix:
cuda:
- { label: "12.8", version: "12.8.1", arch: "61;75;86;89;90" }
- { label: "12.9", version: "12.9.1", arch: "61;75;86;89;90" }
- { label: "13.1", version: "13.1.0", arch: "75;80;86;89;90;100;103;121" }
matlab:
- { label: "2022a", release: "R2022a" }
- { label: "2024a", release: "R2024a" }
steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Install build tools
run: |
sudo apt-get update
sudo apt-get install --no-install-recommends -y build-essential cmake ninja-build zip curl unzip tar pkg-config

- name: Set up CUDA
uses: Jimver/cuda-toolkit@v0.2.36
with:
cuda: ${{ matrix.cuda.version }}
log-file-suffix: linux-${{ matrix.cuda.label }}-${{ matrix.matlab.label }}

- name: Set up MATLAB
uses: matlab-actions/setup-matlab@v3
with:
release: ${{ matrix.matlab.release }}

- name: Set MATLAB root
run: |
matlab_bin="$(command -v matlab)"
echo "Matlab_ROOT_DIR=$(dirname "$(dirname "$matlab_bin")")" >> "$GITHUB_ENV"

- name: Set up vcpkg
run: |
git clone https://github.com/microsoft/vcpkg "$VCPKG_ROOT"
"$VCPKG_ROOT/bootstrap-vcpkg.sh" -disableMetrics

- name: Configure
run: |
cmake -S echoframe/cpp/src -B build -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_TOOLCHAIN_FILE="$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake" \
-DCMAKE_CUDA_ARCHITECTURES="${{ matrix.cuda.arch }}" \
-DCUDAToolkit_ROOT="$CUDA_PATH" \
-DMatlab_ROOT_DIR="$Matlab_ROOT_DIR" \
-DEF_BUILD_CLI=ON \
-DEF_BUILD_MEX=ON \
-DEF_BUILD_PYTHON=ON \
-DPython_EXECUTABLE="$pythonLocation/bin/python" \
-DPython_FIND_STRATEGY=LOCATION \
-DCMAKE_CUDA_HOST_COMPILER=/usr/bin/g++

- name: Build
run: cmake --build build -j "$(nproc)"

- name: Package
run: |
name="build_linux_CUDA_${{ matrix.cuda.label }}_MATLAB_${{ matrix.matlab.label }}"
mkdir -p "stage/build/Release" release-assets
find build -maxdepth 2 -type f \( \
-name 'echoframe_mex.mexa64' -o \
-name 'storage.mexa64' -o \
-name 'echoframe*.so' -o \
-name 'echoframe_cli' \
\) -exec cp {} stage/build/Release/ \;
test "$(find stage/build/Release -type f | wc -l)" -gt 0
(cd stage && zip -r "../release-assets/$name.zip" build)

- name: Upload release asset
shell: pwsh
env:
GITHUB_TOKEN: ${{ github.token }}
TAG_NAME: ${{ github.event.release.tag_name || inputs.tag }}
OVERWRITE: ${{ inputs.overwrite || false }}
run: .github/workflows/scripts/upload-release-assets.ps1 release-assets
39 changes: 39 additions & 0 deletions .github/workflows/scripts/upload-release-assets.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
param(
[Parameter(Mandatory = $true)]
[string] $AssetDir
)

$ErrorActionPreference = "Stop"

$assets = Get-ChildItem $AssetDir -Filter *.zip
if (-not $assets) { throw "No release assets found in $AssetDir." }

$headers = @{
Authorization = "Bearer $env:GITHUB_TOKEN"
Accept = "application/vnd.github+json"
"X-GitHub-Api-Version" = "2022-11-28"
}

$release = Invoke-RestMethod `
-Headers $headers `
-Uri "https://api.github.com/repos/$env:GITHUB_REPOSITORY/releases/tags/$env:TAG_NAME"
$uploadUrl = $release.upload_url.Split("{")[0]

foreach ($asset in $assets) {
$existing = $release.assets | Where-Object { $_.name -eq $asset.Name }
if ($existing) {
if ($env:OVERWRITE -ne "true") {
throw "Release asset already exists: $($asset.Name). Re-run with overwrite=true."
}
Invoke-RestMethod -Method Delete -Headers $headers -Uri $existing.url | Out-Null
}

$name = [uri]::EscapeDataString($asset.Name)
Invoke-RestMethod `
-Method Post `
-Headers $headers `
-ContentType "application/zip" `
-InFile $asset.FullName `
-Uri "$uploadUrl?name=$name" | Out-Null
Write-Host "Uploaded $($asset.Name)"
}
7 changes: 4 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,10 @@ echoframe/cpp/src/py3.10_wheel_build
echoframe/cpp/src/py3.11_wheel_build
echoframe/cpp/src/py3.12_wheel_build
echoframe/cpp/src/tempbuild
# Build trees from build_scripts/build_echoframe.bat. Unanchored: the script
# writes them at the repository root by default, and EF_BUILD_ROOT can move
# them anywhere.
# Build trees and packaged zips from build_scripts/build_echoframe.bat.
# Unanchored build_CUDA_*: the script writes them at the repository root by
# default, and EF_BUILD_ROOT can move them anywhere.
/binaries/
build_CUDA_*/
echoframe/cpp/src/testing
documentation/_build/
Expand Down
8 changes: 3 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ EchoFrame delivers high‑throughput **Fourier‑domain beamforming** and **Powe
* Real‑time performance (> 10 kFPS on RTX 40‑series)
* Self‑contained build: CMake ≥ 3.21 (used to build the project) + a recent CUDA toolkit are all you need

**Prebuilt binaries**:
**Prebuilt binaries**: available from [GitHub Releases](https://github.com/BrainEchoLab/EchoFrame/releases/latest).

| Versions | CUDA 12.8 | CUDA 12.9 | CUDA 13.1 |
|----------|-----------|-----------|-----------|
Expand Down Expand Up @@ -59,9 +59,9 @@ We offer a range of pre-built binaries for EchoFrame. This means you can simply

**⚠️ IMPORTANT:** If you do not have one of the CUDA and Matlab combinations mentioned in the **Prebuilt binaries** table in [Overview](#overview), then you may run into issues using EchoFrame with them!

You can find these binaries in the `binaries` directory. There you can pick from the available builds whichever matches your CUDA and Matlab setup. Each folder in `binaries` contains a compressed `build` folder.
Download the matching `build_CUDA_<version>_MATLAB_<version>.zip` from [GitHub Releases](https://github.com/BrainEchoLab/EchoFrame/releases/latest). Each asset contains a compressed `build` folder.

Once you have the EchoFrame repository in your local machine, you can navigate to `EchoFrame\echoframe\cpp\src` and paste the **uncompressed** `build` folder inside `src`. After that, you should be good to go.
Once you have the EchoFrame repository on your local machine, unzip the asset, navigate to `EchoFrame\echoframe\cpp\src`, and paste the **uncompressed** `build` folder inside `src`. After that, you should be good to go.

You can then explore [how to use EchoFrame](#using-echoframe).

Expand Down Expand Up @@ -483,8 +483,6 @@ Each folder has its own README with the details.

- **build_scripts/**: developer helper scripts — the Windows build, vcpkg setup, and the build-verification harness. See [build_scripts/README.md](./build_scripts/README.md).

- **binaries/**: prebuilt builds, one zip per CUDA/MATLAB combination. See [Plug and Play](#plug-play).

- **docker/**: the Ubuntu/CUDA development image.

- **justfile**: task runner recipes. Stays at the repository root so `just` can find it.
Expand Down
Binary file removed binaries/build_CUDA_12.8_MATLAB_2022a/build.zip
Binary file not shown.
Binary file removed binaries/build_CUDA_12.8_MATLAB_2024a/build.zip
Binary file not shown.
Binary file removed binaries/build_CUDA_12.9_MATLAB_2022a/build.zip
Binary file not shown.
Binary file removed binaries/build_CUDA_12.9_MATLAB_2024a/build.zip
Binary file not shown.
Binary file removed binaries/build_CUDA_13.1_MATLAB_2022a/build.zip
Binary file not shown.
Binary file removed binaries/build_CUDA_13.1_MATLAB_2024a/build.zip
Binary file not shown.
3 changes: 2 additions & 1 deletion build_scripts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ set EF_BUILD_ROOT=C:\efb
```

The packaged `binaries\build_<CONFIG>\build.zip` is written to the repository
either way. Enabling long paths (`LongPathsEnabled` under
either way. These generated zips are ignored by git; attach them to the matching
GitHub Release instead. Enabling long paths (`LongPathsEnabled` under
`HKLM\SYSTEM\CurrentControlSet\Control\FileSystem`, needs a reboot) or using the
Ninja generator also works -- see the main README.

Expand Down
3 changes: 2 additions & 1 deletion justfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ jobs := if os() == "windows" { env_var_or_default("NUMBER_OF_PROCESSORS", "4") }
make_program := if os() == "windows" { "" } else { `command -v make` }
matlab_root := if os() == "windows" { env_var_or_default("Matlab_ROOT_DIR", "C:/Program Files/MATLAB/R2024a") } else { `printf '%s' "${Matlab_ROOT_DIR:-$HOME/MATLAB/R2024a}"` }
cuda_host_compiler := if os() == "windows" { "" } else { env_var_or_default("CMAKE_CUDA_HOST_COMPILER", "/usr/bin/g++") }
cuda_architectures := env_var_or_default("CMAKE_CUDA_ARCHITECTURES", "61;75;86;89;90")
default_cuda_architectures := if os() == "windows" { "" } else { `if nvcc --version 2>/dev/null | grep -Eq 'release 1[3-9]\.'; then printf '75;80;86;89;90;100;103;121'; else printf '61;75;86;89;90'; fi` }
cuda_architectures := env_var_or_default("CMAKE_CUDA_ARCHITECTURES", default_cuda_architectures)
vcpkg_root := env_var_or_default("VCPKG_ROOT", "C:/vcpkg")
vcpkg_triplet := "x64-windows-static"
test_img := env_var_or_default("HOME", "") / "ef_test.img"
Expand Down
Loading