Skip to content

Commit d0caf3d

Browse files
committed
Added CI job to build binaries
1 parent 6049efb commit d0caf3d

File tree

5 files changed

+388
-5
lines changed

5 files changed

+388
-5
lines changed
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
name: Build Static Binaries
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
branches:
9+
- main
10+
workflow_dispatch:
11+
12+
jobs:
13+
build-static-binaries:
14+
runs-on: ubuntu-latest
15+
16+
steps:
17+
- name: Checkout repository
18+
uses: actions/checkout@v4
19+
20+
- name: Set up Docker Buildx
21+
uses: docker/setup-buildx-action@v3
22+
23+
- name: Build static binaries with Docker
24+
uses: docker/build-push-action@v5
25+
with:
26+
context: .
27+
file: ./docker/static-build.Dockerfile
28+
target: export
29+
outputs: type=local,dest=./binaries
30+
cache-from: type=gha
31+
cache-to: type=gha,mode=max
32+
33+
- name: Verify binaries
34+
run: |
35+
echo "=== Clang binary info ==="
36+
file binaries/clang || true
37+
ls -lh binaries/clang
38+
39+
echo "=== xcfa-mapper binary info ==="
40+
file binaries/xcfa-mapper || true
41+
ls -lh binaries/xcfa-mapper
42+
43+
- name: Get ClangIR commit hash
44+
id: clangir-commit
45+
run: |
46+
# Extract from docker image or use current date as fallback
47+
echo "hash=$(date +%Y%m%d-%H%M%S)" >> $GITHUB_OUTPUT
48+
49+
- name: Upload clang binary
50+
uses: actions/upload-artifact@v4
51+
with:
52+
name: clang-static-${{ steps.clangir-commit.outputs.hash }}
53+
path: binaries/clang
54+
retention-days: 90
55+
56+
- name: Upload xcfa-mapper binary
57+
uses: actions/upload-artifact@v4
58+
with:
59+
name: xcfa-mapper-static-${{ github.sha }}
60+
path: binaries/xcfa-mapper
61+
retention-days: 90
62+
63+
- name: Create release on tag
64+
if: startsWith(github.ref, 'refs/tags/')
65+
uses: softprops/action-gh-release@v1
66+
with:
67+
files: |
68+
binaries/clang
69+
binaries/xcfa-mapper
70+
env:
71+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

build-static-binaries.sh

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
# Build static binaries using Docker Buildx (BuildKit)
5+
# This script mirrors the GitHub Actions workflow using the Dockerfile in docker/static-build.Dockerfile
6+
7+
echo "Building static binaries with Docker Buildx…"
8+
echo "This may take a while (1-2 hours depending on your hardware)."
9+
echo
10+
11+
# Ensure docker is available
12+
if ! command -v docker >/dev/null 2>&1; then
13+
echo "Error: docker is not installed or not on PATH." >&2
14+
exit 1
15+
fi
16+
17+
# Ensure buildx is available
18+
if ! docker buildx version >/dev/null 2>&1; then
19+
echo "Docker Buildx is not installed/enabled."
20+
echo "Please install/enable Buildx: https://docs.docker.com/build/buildx/install/" >&2
21+
exit 1
22+
fi
23+
24+
# Create and use a local builder if none is active
25+
ACTIVE_BUILDER=$(docker buildx ls | awk '/\*/ {print $1}' || true)
26+
if [[ -z "${ACTIVE_BUILDER}" ]]; then
27+
echo "No active buildx builder found. Creating 'cir-static-builder'…"
28+
docker buildx create --use --name cir-static-builder >/dev/null
29+
fi
30+
31+
# Build and export only the final binaries using the `export` stage
32+
rm -rf ./output
33+
docker buildx build \
34+
-f docker/static-build.Dockerfile \
35+
--target=export \
36+
--output type=local,dest=./output \
37+
.
38+
39+
# The export stage places the stripped binaries at the root of ./output
40+
if [[ ! -f ./output/clang || ! -f ./output/xcfa-mapper ]]; then
41+
echo "Error: Expected binaries not found in ./output."
42+
echo "Contents of ./output:" >&2
43+
ls -lah ./output || true
44+
exit 1
45+
fi
46+
47+
echo
48+
echo "✓ Build complete!"
49+
echo
50+
echo "Binaries are available in ./output/"
51+
echo " - clang: ./output/clang"
52+
echo " - xcfa-mapper: ./output/xcfa-mapper"
53+
echo
54+
echo "Binary information:"
55+
file ./output/clang || true
56+
file ./output/xcfa-mapper || true
57+
echo
58+
ls -lh ./output/

docker/BUILD_STATIC.md

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# Building Static Binaries
2+
3+
This directory contains configuration for building static binaries of `clang` (with ClangIR support) and `xcfa-mapper`.
4+
5+
## Building Locally
6+
7+
To build the static binaries on your local machine:
8+
9+
```bash
10+
./build-static-binaries.sh
11+
```
12+
13+
This will:
14+
1. Build LLVM with ClangIR support statically
15+
2. Build xcfa-mapper statically
16+
3. Strip the binaries
17+
4. Output them to `./output/` directory
18+
19+
**Note:** The build process can take 1-2 hours depending on your hardware.
20+
21+
### Requirements
22+
23+
- Docker
24+
- At least 16GB RAM
25+
- At least 50GB free disk space
26+
27+
### Manual Build
28+
29+
If you want more control over the build process:
30+
31+
```bash
32+
# Build with Docker
33+
docker build -f docker/static-build.Dockerfile --target=builder -o type=local,dest=./output .
34+
35+
# The binaries will be in:
36+
# - ./output/build/llvm-install/bin/clang
37+
# - ./output/build/xcfa-mapper/build/xcfa-mapper
38+
```
39+
40+
## CI/CD
41+
42+
The GitHub Actions workflow (`.github/workflows/build-static-binaries.yml`) automatically builds and uploads static binaries on:
43+
- Push to `main` branch
44+
- Pull requests
45+
- Manual workflow dispatch
46+
- Git tags (will create a release)
47+
48+
Built binaries are uploaded as artifacts and retained for 90 days.
49+
50+
### Downloading from CI
51+
52+
1. Go to the [Actions tab](../../actions/workflows/build-static-binaries.yml)
53+
2. Click on a successful workflow run
54+
3. Download the artifacts:
55+
- `clang-static-*`
56+
- `xcfa-mapper-static-*`
57+
58+
## Dockerfile Details
59+
60+
The `docker/static-build.Dockerfile` uses a multi-stage build:
61+
62+
1. **builder**: Builds LLVM and xcfa-mapper with static linking
63+
2. **export**: Contains only the stripped binaries (for extraction)
64+
3. **runtime**: Optional runtime image for testing
65+
66+
### Static Build Flags
67+
68+
LLVM is built with the following key flags for static linking:
69+
- `BUILD_SHARED_LIBS=OFF` - Build only static libraries
70+
- `LLVM_ENABLE_PIC=OFF` - Disable position-independent code
71+
- `LIBCLANG_BUILD_STATIC=ON` - Build static libclang
72+
- `LLVM_BUILD_LLVM_DYLIB=OFF` - Disable dynamic LLVM library
73+
- `CMAKE_EXE_LINKER_FLAGS="-static-libgcc -static-libstdc++"` - Static C++ runtime
74+
75+
## Testing
76+
77+
To test the runtime image with both binaries installed:
78+
79+
```bash
80+
docker build -f docker/static-build.Dockerfile --target=runtime -t cir-static-test .
81+
docker run -it cir-static-test bash
82+
83+
# Inside the container:
84+
clang --version
85+
xcfa-mapper --help
86+
```
87+
88+
## Troubleshooting
89+
90+
### Out of Memory
91+
If the build fails with OOM errors, you can:
92+
- Reduce parallel jobs by modifying `-j$(nproc)` in the Dockerfile
93+
- Increase Docker's memory limit in Docker Desktop settings
94+
95+
### Build Cache
96+
Docker BuildKit cache is used in the GitHub Actions workflow to speed up builds. To clear local cache:
97+
98+
```bash
99+
docker builder prune
100+
```

docker/static-build.Dockerfile

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
FROM debian:trixie-slim AS builder
2+
3+
ARG DEBIAN_FRONTEND=noninteractive
4+
ENV LC_ALL=C.UTF-8
5+
6+
RUN apt-get update \
7+
&& apt-get install -y --no-install-recommends \
8+
ca-certificates \
9+
git \
10+
cmake \
11+
ninja-build \
12+
build-essential \
13+
pkg-config \
14+
python3 \
15+
clang \
16+
lld \
17+
wget \
18+
curl \
19+
zlib1g-dev \
20+
libstdc++-13-dev \
21+
&& rm -rf /var/lib/apt/lists/*
22+
23+
WORKDIR /build
24+
25+
# Clone ClangIR (shallow) for LLVM with CIR support
26+
RUN git clone --depth=1 https://github.com/llvm/clangir.git
27+
28+
# Find zlib for static linking
29+
RUN ZLIB_LIBRARY=$(find /usr/lib /lib -name libz.a | head -n 1) && \
30+
ZLIB_INCLUDE_DIR=$(find /usr/include -name zlib.h | head -n 1 | xargs dirname) && \
31+
echo "ZLIB_LIBRARY=$ZLIB_LIBRARY" > /build/zlib-config.env && \
32+
echo "ZLIB_INCLUDE_DIR=$ZLIB_INCLUDE_DIR" >> /build/zlib-config.env
33+
34+
# Configure LLVM with static build flags
35+
RUN . /build/zlib-config.env && \
36+
cmake -S clangir/llvm -B llvm-build -GNinja \
37+
-DCMAKE_BUILD_TYPE=Release \
38+
-DCMAKE_INSTALL_PREFIX=/build/llvm-install \
39+
-DCMAKE_C_COMPILER=clang \
40+
-DCMAKE_CXX_COMPILER=clang++ \
41+
-DLLVM_USE_LINKER=lld \
42+
-DCLANG_ENABLE_CIR=ON \
43+
-DLLVM_ENABLE_PROJECTS="clang;mlir" \
44+
-DLLVM_TARGETS_TO_BUILD=host \
45+
-DLIBCLANG_BUILD_STATIC=ON \
46+
-DLLVM_BUILD_LLVM_DYLIB=OFF \
47+
-DLLVM_LINK_LLVM_DYLIB=OFF \
48+
-DBUILD_SHARED_LIBS=OFF \
49+
-DLLVM_ENABLE_PIC=OFF \
50+
-DLLVM_ENABLE_TERMINFO=OFF \
51+
-DLLVM_ENABLE_ZLIB=FORCE_ON \
52+
-DLLVM_ENABLE_ZSTD=OFF \
53+
-DLLVM_ENABLE_LIBXML2=OFF \
54+
-DLLVM_ENABLE_BINDINGS=OFF \
55+
-DLLVM_ENABLE_OCAMLDOC=OFF \
56+
-DLLVM_ENABLE_Z3_SOLVER=OFF \
57+
-DLLVM_HAVE_LIBXAR=OFF \
58+
-DLLVM_INCLUDE_BENCHMARKS=OFF \
59+
-DLLVM_INCLUDE_TESTS=OFF \
60+
-DLLVM_TOOL_REMARKS_SHLIB_BUILD=OFF \
61+
-DZLIB_LIBRARY="$ZLIB_LIBRARY" \
62+
-DZLIB_INCLUDE_DIR="$ZLIB_INCLUDE_DIR"
63+
64+
# Build and install LLVM
65+
RUN cmake --build llvm-build -j$(nproc) && \
66+
cmake --install llvm-build
67+
68+
# Copy xcfa-mapper source
69+
COPY xcfa-mapper /build/xcfa-mapper
70+
71+
# Verify MLIRCIR was built and installed
72+
RUN echo "=== Checking for CIR dialect libraries ===" && \
73+
ls -lh /build/llvm-install/lib/libMLIRCIR* || \
74+
(echo "WARNING: libMLIRCIR not found in install directory" && \
75+
echo "Checking build directory:" && \
76+
find /build/llvm-build -name "libMLIRCIR*")
77+
78+
# Configure and build xcfa-mapper statically
79+
RUN cd /build/xcfa-mapper && \
80+
mkdir -p build && \
81+
cd build && \
82+
cmake .. \
83+
-DCMAKE_BUILD_TYPE=Release \
84+
-DCMAKE_C_COMPILER=clang \
85+
-DCMAKE_CXX_COMPILER=clang++ \
86+
-DCMAKE_EXE_LINKER_FLAGS="-static-libgcc -static-libstdc++" \
87+
-DLLVM_DIR=/build/llvm-install/lib/cmake/llvm \
88+
-DMLIR_DIR=/build/llvm-install/lib/cmake/mlir && \
89+
make -j$(nproc)
90+
91+
# Strip binaries
92+
RUN strip /build/llvm-install/bin/clang-22 && \
93+
strip /build/xcfa-mapper/build/xcfa-mapper
94+
95+
# Verify binaries
96+
RUN echo "=== Clang binary info ===" && \
97+
ls -lh /build/llvm-install/bin/clang-22 && \
98+
/build/llvm-install/bin/clang-22 --version && \
99+
echo "\n=== xcfa-mapper binary info ===" && \
100+
ls -lh /build/xcfa-mapper/build/xcfa-mapper
101+
102+
# Final stage - copy only the binaries
103+
FROM scratch AS export
104+
COPY --from=builder /build/llvm-install/bin/clang-22 /clang
105+
COPY --from=builder /build/xcfa-mapper/build/xcfa-mapper /xcfa-mapper
106+
107+
# Runtime stage for testing (optional)
108+
FROM debian:trixie-slim AS runtime
109+
COPY --from=builder /build/llvm-install/bin/clang /usr/local/bin/clang
110+
COPY --from=builder /build/xcfa-mapper/build/xcfa-mapper /usr/local/bin/xcfa-mapper
111+
RUN clang --version && xcfa-mapper --help || true
112+
CMD ["/bin/bash"]

0 commit comments

Comments
 (0)