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
83 changes: 83 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Use the prebuilt SHARED liblbug from ./liblbug (see scripts/download-liblbug.sh).
#
# Shared (not static) is required: the dlopen'd algo extension resolves
# ladybug symbols (e.g. GDSFunction::getLogicalPlan) from the host process at
# LOAD EXTENSION time. With a static liblbug.a, dead-code stripping drops
# unreferenced symbols and the extension fails to load. Mirrors
# ../bugscope/src-tauri/.cargo/config.toml.
#
# The icebug Rust crate's build script links libnetworkit from ./icebug
# (see scripts/download_icebug.sh).
[env]
LBUG_LIBRARY_DIR = { value = "liblbug", relative = true }
LBUG_INCLUDE_DIR = { value = "liblbug", relative = true }
LBUG_SHARED = "1"
ICEBUG_DIR = { value = "icebug", relative = true }

# Embed rpath so the binary finds the bundled shared libs at runtime:
# - dist archives ship `liblbug/` + `icebug/lib/` next to the binary
# ($ORIGIN / @executable_path entries)
# - macOS .app bundles stage them under Contents/Frameworks
# - cargo dev/test binaries resolve ../../../ entries
# (target/{debug,release}/deps/ -> repo root)
[target.aarch64-apple-darwin]
rustflags = [
"-C", "link-arg=-Wl,-rpath,@executable_path",
"-C", "link-arg=-Wl,-rpath,@executable_path/icebug/lib",
"-C", "link-arg=-Wl,-rpath,@executable_path/liblbug",
"-C", "link-arg=-Wl,-rpath,@executable_path/../Frameworks",
"-C", "link-arg=-Wl,-rpath,@executable_path/../icebug/lib",
"-C", "link-arg=-Wl,-rpath,@executable_path/../../liblbug",
"-C", "link-arg=-Wl,-rpath,@executable_path/../../icebug/lib",
"-C", "link-arg=-Wl,-rpath,@executable_path/../../../liblbug",
"-C", "link-arg=-Wl,-rpath,@executable_path/../../../../liblbug",
"-C", "link-arg=-Wl,-rpath,@executable_path/../../../icebug/lib",
"-C", "link-arg=-Wl,-rpath,@executable_path/../../../../icebug/lib",
]

[target.x86_64-apple-darwin]
rustflags = [
"-C", "link-arg=-Wl,-rpath,@executable_path",
"-C", "link-arg=-Wl,-rpath,@executable_path/icebug/lib",
"-C", "link-arg=-Wl,-rpath,@executable_path/liblbug",
"-C", "link-arg=-Wl,-rpath,@executable_path/../Frameworks",
"-C", "link-arg=-Wl,-rpath,@executable_path/../icebug/lib",
"-C", "link-arg=-Wl,-rpath,@executable_path/../../liblbug",
"-C", "link-arg=-Wl,-rpath,@executable_path/../../icebug/lib",
"-C", "link-arg=-Wl,-rpath,@executable_path/../../../liblbug",
"-C", "link-arg=-Wl,-rpath,@executable_path/../../../../liblbug",
"-C", "link-arg=-Wl,-rpath,@executable_path/../../../icebug/lib",
"-C", "link-arg=-Wl,-rpath,@executable_path/../../../../icebug/lib",
]

[target.aarch64-unknown-linux-gnu]
rustflags = [
"-C", "link-arg=-Wl,-rpath,$ORIGIN",
"-C", "link-arg=-Wl,-rpath,$ORIGIN/icebug/lib",
"-C", "link-arg=-Wl,-rpath,$ORIGIN/liblbug",
"-C", "link-arg=-Wl,-rpath,$ORIGIN/../icebug/lib",
"-C", "link-arg=-Wl,-rpath,$ORIGIN/../../liblbug",
"-C", "link-arg=-Wl,-rpath,$ORIGIN/../../icebug/lib",
"-C", "link-arg=-Wl,-rpath,$ORIGIN/../../../liblbug",
"-C", "link-arg=-Wl,-rpath,$ORIGIN/../../../../liblbug",
"-C", "link-arg=-Wl,-rpath,$ORIGIN/../../../icebug/lib",
"-C", "link-arg=-Wl,-rpath,$ORIGIN/../../../../icebug/lib",
# RPATH (not RUNPATH) so transitive deps like libarrow (needed by
# libnetworkit.so) also resolve from these dirs.
"-C", "link-arg=-Wl,--disable-new-dtags",
]

[target.x86_64-unknown-linux-gnu]
rustflags = [
"-C", "link-arg=-Wl,-rpath,$ORIGIN",
"-C", "link-arg=-Wl,-rpath,$ORIGIN/icebug/lib",
"-C", "link-arg=-Wl,-rpath,$ORIGIN/liblbug",
"-C", "link-arg=-Wl,-rpath,$ORIGIN/../icebug/lib",
"-C", "link-arg=-Wl,-rpath,$ORIGIN/../../liblbug",
"-C", "link-arg=-Wl,-rpath,$ORIGIN/../../icebug/lib",
"-C", "link-arg=-Wl,-rpath,$ORIGIN/../../../liblbug",
"-C", "link-arg=-Wl,-rpath,$ORIGIN/../../../../liblbug",
"-C", "link-arg=-Wl,-rpath,$ORIGIN/../../../icebug/lib",
"-C", "link-arg=-Wl,-rpath,$ORIGIN/../../../../icebug/lib",
"-C", "link-arg=-Wl,--disable-new-dtags",
]
155 changes: 150 additions & 5 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ on:

permissions:
contents: read
packages: write

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
Expand All @@ -27,11 +28,19 @@ jobs:
- uses: actions/checkout@v4

- name: Install system dependencies (Linux)
timeout-minutes: 25
run: |
# lbug's C++ bridge needs <format> (C++20): jammy's gcc-11 is too old.
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
sudo apt-get update
sudo apt-get install -y --no-install-recommends gcc-13 g++-13 pkg-config libssl-dev libxkbcommon-dev libxkbcommon-x11-dev libwayland-dev
# LLVM repo for libomp matching the icebug prebuilt binaries.
wget -qO- --timeout=60 --tries=3 https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/llvm-snapshot.asc
echo "deb http://apt.llvm.org/jammy llvm-toolchain-jammy-20 main" | sudo tee /etc/apt/sources.list.d/llvm20.list
# Apache Arrow repo (icebug's cxx bridge needs arrow headers).
wget --timeout=60 --tries=3 https://apache.jfrog.io/artifactory/arrow/ubuntu/apache-arrow-apt-source-latest-jammy.deb
sudo apt-get install -y ./apache-arrow-apt-source-latest-jammy.deb
# Bound mirror stalls: fail fast instead of hanging the run for hours.
sudo apt-get -o Acquire::Retries=3 -o Acquire::http::Timeout=60 -o Acquire::https::Timeout=60 update
sudo apt-get -o Acquire::Retries=3 -o Acquire::http::Timeout=60 -o Acquire::https::Timeout=60 install -y --no-install-recommends gcc-13 g++-13 cmake pkg-config libssl-dev libxkbcommon-dev libxkbcommon-x11-dev libwayland-dev libarrow-dev libomp-20-dev
echo "CC=gcc-13" >> "$GITHUB_ENV"
echo "CXX=g++-13" >> "$GITHUB_ENV"

Expand Down Expand Up @@ -66,6 +75,12 @@ jobs:
key: lbug-prebuilt-${{ env.LBUG_VERSION }}-${{ runner.os }}
restore-keys: lbug-prebuilt-

- name: Download icebug prebuilt
run: bash scripts/download_icebug.sh

- name: Download shared liblbug
run: bash scripts/download-liblbug.sh

- name: Rust cache
uses: Swatinem/rust-cache@v2
with:
Expand Down Expand Up @@ -118,15 +133,23 @@ jobs:

- name: Install dependencies (macOS)
if: matrix.platform == 'macos-latest'
run: brew install libomp openssl
run: brew install libomp apache-arrow cmake openssl

- name: Install dependencies (Linux)
timeout-minutes: 25
if: matrix.platform == 'ubuntu-22.04'
run: |
# lbug's C++ bridge needs <format> (C++20): jammy's gcc-11 is too old.
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
sudo apt-get update
sudo apt-get install -y --no-install-recommends gcc-13 g++-13 pkg-config libssl-dev libxkbcommon-dev libxkbcommon-x11-dev libwayland-dev
# LLVM repo for libomp matching the icebug prebuilt binaries.
wget -qO- --timeout=60 --tries=3 https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/llvm-snapshot.asc
echo "deb http://apt.llvm.org/jammy llvm-toolchain-jammy-20 main" | sudo tee /etc/apt/sources.list.d/llvm20.list
# Apache Arrow repo (icebug's cxx bridge needs arrow headers).
wget --timeout=60 --tries=3 https://apache.jfrog.io/artifactory/arrow/ubuntu/apache-arrow-apt-source-latest-jammy.deb
sudo apt-get install -y ./apache-arrow-apt-source-latest-jammy.deb
# Bound mirror stalls: fail fast instead of hanging the run for hours.
sudo apt-get -o Acquire::Retries=3 -o Acquire::http::Timeout=60 -o Acquire::https::Timeout=60 update
sudo apt-get -o Acquire::Retries=3 -o Acquire::http::Timeout=60 -o Acquire::https::Timeout=60 install -y --no-install-recommends gcc-13 g++-13 cmake pkg-config libssl-dev libxkbcommon-dev libxkbcommon-x11-dev libwayland-dev libarrow-dev libomp-20-dev
echo "CC=gcc-13" >> "$GITHUB_ENV"
echo "CXX=g++-13" >> "$GITHUB_ENV"

Expand Down Expand Up @@ -154,6 +177,49 @@ jobs:
Get-ChildItem $stage | Select-Object Name, Length
echo "LIB=$stage" >> "$env:GITHUB_ENV"

- name: Create vcpkg manifest (Windows)
if: matrix.platform == 'windows-2022'
shell: bash
run: |
cat > vcpkg.json << 'EOF'
{
"name": "bugscope-deps",
"version": "1.0.0",
"dependencies": [
"arrow",
"pkgconf"
]
}
EOF

- name: Setup vcpkg (Windows)
if: matrix.platform == 'windows-2022'
uses: lukka/run-vcpkg@v11
with:
vcpkgGitCommitId: '14d83b1c34655a6af6f044aa1679f668c0b0b70e'

- name: Authenticate vcpkg NuGet (Windows)
if: matrix.platform == 'windows-2022'
shell: pwsh
run: |
# NOTE: must be a classic PAT with write:packages (repo secret
# VCPKG_NUGET_PAT), SSO-authorized if the org enforces SAML.
# GITHUB_TOKEN 403s on push: repo-scoped tokens cannot publish
# new, unlinked packages to the org-level feed, so the cache
# could never populate and every build rebuilt from source.
$nuget = & $env:VCPKG_ROOT/vcpkg fetch nuget | Out-String
$nuget = $nuget.Trim()
& $nuget sources add -Source "https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json" -Name "GitHubPackages" -Username "${{ github.repository_owner }}" -Password "${{ secrets.VCPKG_NUGET_PAT }}" -StorePasswordInClearText -Verbosity detailed
& $nuget setapikey "${{ secrets.VCPKG_NUGET_PAT }}" -Source "https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json"

- name: Install vcpkg packages (Windows)
if: matrix.platform == 'windows-2022'
shell: pwsh
run: |
& $env:VCPKG_ROOT/vcpkg install --recurse --clean-after-build --triplet x64-windows
env:
VCPKG_BINARY_SOURCES: 'clear;nuget,https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json,readwrite'

- name: Install Rust stable
uses: dtolnay/rust-toolchain@stable
with:
Expand All @@ -172,6 +238,64 @@ jobs:
- name: Rust cache
uses: Swatinem/rust-cache@v2

- name: Download icebug prebuilt
shell: bash
run: bash scripts/download_icebug.sh

- name: Download shared liblbug
shell: bash
run: bash scripts/download-liblbug.sh

- name: Vendor arrow/openmp runtimes (macOS/Linux)
if: matrix.platform != 'windows-2022'
shell: bash
# The INSTALL'd algo extension references @rpath/libarrow, resolved
# against our rpaths: vendor the system libs next to libnetworkit.
run: bash scripts/vendor_arrow.sh

- name: Configure macOS build env
if: matrix.platform == 'macos-latest'
shell: bash
run: |
# Apple clang doesn't search Homebrew libomp without this (icebug's
# cxx bridge includes networkit headers needing omp.h). Mirrors
# ../bugscope's CXXFLAGS on its macOS build step.
echo "CXXFLAGS=-I/opt/homebrew/opt/libomp/include" >> "$GITHUB_ENV"

- name: Configure Windows build env
if: matrix.platform == 'windows-2022'
shell: bash
run: |
echo "PKG_CONFIG_PATH=$GITHUB_WORKSPACE/vcpkg_installed/x64-windows/lib/pkgconfig" >> "$GITHUB_ENV"
echo "CMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/vcpkg_installed/x64-windows" >> "$GITHUB_ENV"
echo "CXXFLAGS=/std:c++20" >> "$GITHUB_ENV"
# pkgconf itself must be on PATH: the icebug crate probes arrow via
# pkg-config (mirrors ../bugscope's PATH setup on its build step).
# Convert the whole list with cygpath -p: appending a Windows entry
# to bash's Unix-form PATH would leave later pwsh steps with an
# unresolvable PATH (cargo not found).
echo "PATH=$(cygpath -w "$GITHUB_WORKSPACE/vcpkg_installed/x64-windows/tools/pkgconf");$(cygpath -wp "$PATH")" >> "$GITHUB_ENV"

- name: Test GDS_PAGE_RANK
shell: bash
run: |
# The test INSTALLs the algo extension from the official repo and
# LOADs it at runtime: its libarrow dep resolves via our rpaths
# (vendored above) on Unix, via PATH (vcpkg) on Windows.
if [ "$RUNNER_OS" = "Windows" ]; then
# NB: networkit_state.dll lives in the icebug/lib/networkit
# subdir (the win prebuilt splits GlobalState out of the static
# networkit.lib); the loader needs that dir on PATH too.
export PATH="$(cygpath -w "$GITHUB_WORKSPACE/icebug/lib");$(cygpath -w "$GITHUB_WORKSPACE/icebug/lib/networkit");$(cygpath -w "$GITHUB_WORKSPACE/liblbug");$(cygpath -w "$GITHUB_WORKSPACE/vcpkg_installed/x64-windows/bin");$PATH"
export PKG_CONFIG_PATH="$GITHUB_WORKSPACE/vcpkg_installed/x64-windows/lib/pkgconfig"
export CXXFLAGS="/std:c++20"
else
export LD_LIBRARY_PATH="$GITHUB_WORKSPACE/icebug/lib:$GITHUB_WORKSPACE/liblbug${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
fi
# --lib --test selects only these targets so the GUI binary
# itself is not linked here (it gets built in the next step).
cargo test --release --target ${{ matrix.target }} --lib --test gds_page_rank

- name: Build release binary
run: cargo build --release --target ${{ matrix.target }}

Expand All @@ -191,6 +315,8 @@ jobs:
mkdir -p dist/Bugscope.app/Contents/MacOS dist/Bugscope.app/Contents/Resources
cp "target/${{ matrix.target }}/release/${{ matrix.binary }}" dist/Bugscope.app/Contents/MacOS/bugscope
sed "s|@VERSION@|${version}|g" packaging/macos/Info.plist > dist/Bugscope.app/Contents/Info.plist
# Bundle icebug shared libs + algo extension (GDS_* via Cypher).
bash scripts/stage_macos_bundle.sh dist/Bugscope.app
codesign --deep --force -s - dist/Bugscope.app
archive="dist/bugscope-${version}-${{ matrix.target }}-macos.zip"
ditto -c -k --keepParent dist/Bugscope.app "$archive"
Expand All @@ -209,6 +335,17 @@ jobs:
rm -rf dist && mkdir -p "dist/$name"
cp "target/${{ matrix.target }}/release/${{ matrix.binary }}" "dist/$name/"
strip "dist/$name/${{ matrix.binary }}"
# Bundle icebug shared libs + algo extension (GDS_* via Cypher).
# $ORIGIN/icebug/lib and $ORIGIN are baked rpaths (see .cargo/config.toml).
mkdir -p "dist/$name/icebug" "dist/$name/liblbug"
cp -r icebug/lib "dist/$name/icebug/"
cp liblbug/liblbug.so* "dist/$name/liblbug/"
# Best-effort: vendor libomp/libarrow so the tarball runs without
# system installs (the exe uses RPATH, not RUNPATH, so transitive
# deps resolve from these dirs too).
for dep in $(ldd "dist/$name/${{ matrix.binary }}" | grep -oE '/[^ ]*lib(arrow|omp)[^ ]*\.so[^ ]*' | sort -u); do
cp -f -n "$dep" "dist/$name/icebug/lib/" 2>/dev/null || true
done
cp README.md "dist/$name/"
echo "$version" > "dist/$name/VERSION"
tar -C dist -czf "dist/$name.tar.gz" "$name"
Expand All @@ -227,6 +364,14 @@ jobs:
if (Test-Path dist) { Remove-Item -Recurse -Force dist }
New-Item -ItemType Directory -Force "dist/$name" | Out-Null
Copy-Item "target/${{ matrix.target }}/release/${{ matrix.binary }}", README.md "dist/$name/"
# Bundle icebug DLLs + algo extension (GDS_* via Cypher) next to the exe.
New-Item -ItemType Directory -Force "dist/$name/icebug/lib" | Out-Null
New-Item -ItemType Directory -Force "dist/$name/liblbug" | Out-Null
Get-ChildItem "icebug/lib" -Filter *.dll -Recurse | ForEach-Object { Copy-Item $_.FullName "dist/$name/icebug/lib/" }
Get-ChildItem "liblbug" -Filter *.dll | ForEach-Object { Copy-Item $_.FullName "dist/$name/liblbug/" }
# The INSTALL'd algo extension loads arrow dynamically: ship the
# vcpkg arrow DLLs next to the binary (on PATH at runtime).
Get-ChildItem "vcpkg_installed/x64-windows/bin" -Filter arrow*.dll | ForEach-Object { Copy-Item $_.FullName "dist/$name/icebug/lib/" }
Compress-Archive -Path "dist/$name" -DestinationPath "dist/$name.zip"
$hash = (Get-FileHash "dist/$name.zip" -Algorithm SHA256).Hash.ToLower()
[IO.File]::WriteAllText("dist/$name.zip.sha256", "$hash $name.zip`n")
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
/target/
*.lbdb
/icebug/
/liblbug/
# Locally built algo extension (dev only; CI/app use INSTALL from the official repo).
/extensions/
Loading
Loading