Skip to content

Commit f4c4a6e

Browse files
committed
ci: add musl build step
1 parent 3f6595d commit f4c4a6e

File tree

6 files changed

+287
-3
lines changed

6 files changed

+287
-3
lines changed

.cargo/config.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,6 @@ linker = "rust-lld"
66

77
[target.i686-pc-windows-msvc]
88
linker = "rust-lld"
9+
10+
[target.'cfg(target_env = "musl")']
11+
rustflags = ["-C", "target-feature=-crt-static"]

.github/action/musl/Dockerfile

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# Multi-stage Dockerfile for building ext-php-rs with musl libc
2+
# This ensures PHP and the Rust extension are both compiled against musl
3+
FROM alpine:3.20 AS php-builder
4+
5+
ARG PHP_VERSION=8.4.1
6+
ARG PHP_BRANCH=PHP-${PHP_VERSION}
7+
8+
RUN apk add --no-cache \
9+
autoconf \
10+
automake \
11+
bison \
12+
re2c \
13+
gcc \
14+
g++ \
15+
make \
16+
musl-dev \
17+
linux-headers \
18+
pkgconfig \
19+
git \
20+
libxml2-dev \
21+
sqlite-dev \
22+
openssl-dev \
23+
curl-dev
24+
25+
# Clone and build PHP with musl
26+
WORKDIR /tmp/php-src
27+
RUN git clone --depth 1 -b ${PHP_BRANCH} https://github.com/php/php-src.git . || \
28+
git clone --depth 1 https://github.com/php/php-src.git .
29+
30+
RUN ./buildconf --force && \
31+
./configure \
32+
--enable-debug \
33+
--enable-embed=shared \
34+
--with-openssl \
35+
--with-curl \
36+
--with-sqlite3 \
37+
--disable-cgi \
38+
--prefix=/usr/local && \
39+
make -j$(nproc) && \
40+
make install
41+
42+
# Stage 2: Build ext-php-rs
43+
FROM alpine:3.20 AS rust-builder
44+
45+
# Copy PHP installation from previous stage
46+
COPY --from=php-builder /usr/local /usr/local
47+
48+
# Install Rust and build dependencies
49+
RUN apk add --no-cache \
50+
curl \
51+
gcc \
52+
g++ \
53+
musl-dev \
54+
clang17-dev \
55+
clang17-static \
56+
llvm17-dev \
57+
make \
58+
git
59+
60+
# Install Rust
61+
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable
62+
ENV PATH="/root/.cargo/bin:${PATH}"
63+
64+
# Add musl target
65+
RUN rustup target add x86_64-unknown-linux-musl
66+
67+
# Set up environment for musl build
68+
ENV CC=gcc
69+
ENV LIBCLANG_PATH=/usr/lib/llvm17/lib
70+
ENV LLVM_CONFIG_PATH=/usr/bin/llvm-config
71+
ENV PHP=/usr/local/bin/php
72+
ENV PHP_CONFIG=/usr/local/bin/php-config
73+
74+
WORKDIR /workspace
75+
76+
COPY . .
77+
78+
RUN cargo build --release \
79+
--features closure,anyhow,runtime \
80+
--workspace \
81+
--target x86_64-unknown-linux-musl
82+
83+
FROM alpine:3.20 AS runtime
84+
COPY --from=php-builder /usr/local /usr/local
85+
COPY --from=rust-builder /workspace/target/x86_64-unknown-linux-musl/release/cargo-php /usr/local/bin/
86+
87+
RUN apk add --no-cache \
88+
libxml2 \
89+
sqlite-libs \
90+
openssl \
91+
curl
92+
93+
WORKDIR /app
94+
95+
ENTRYPOINT ["/usr/local/bin/cargo-php"]
96+
97+
FROM rust-builder AS ci-builder
98+
99+
ENTRYPOINT ["cargo"]
100+
CMD ["build", "--release", "--features", "closure,anyhow,runtime", "--workspace", "--target", "x86_64-unknown-linux-musl"]

.github/workflows/build.yml

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ jobs:
9191
rust: [stable, nightly]
9292
clang: ["15", "17"]
9393
phpts: [ts, nts]
94+
target: [gnu]
9495
exclude:
9596
# ext-php-rs requires nightly Rust when on Windows.
9697
- os: windows-latest
@@ -168,7 +169,6 @@ jobs:
168169
# Macos fails on unstable rust. We skip the inline examples test for now.
169170
if: "!(contains(matrix.os, 'macos') && matrix.rust == 'nightly')"
170171
run: cargo test --release --workspace --features closure,anyhow,runtime --no-fail-fast
171-
172172
test-embed:
173173
name: Test with embed
174174
runs-on: ubuntu-latest
@@ -226,3 +226,49 @@ jobs:
226226
227227
- name: Test with embed feature
228228
run: cargo test --workspace --release --features closure,embed,anyhow --no-fail-fast
229+
230+
build-musl:
231+
name: Build with musl (Docker)
232+
runs-on: ubuntu-latest
233+
strategy:
234+
matrix:
235+
php: ["8.1", "8.2", "8.3", "8.4"]
236+
phpts: [ts, nts]
237+
env:
238+
CARGO_TERM_COLOR: always
239+
steps:
240+
- name: Checkout code
241+
uses: actions/checkout@v5
242+
243+
- name: Set up Docker Buildx
244+
uses: docker/setup-buildx-action@v3
245+
246+
- name: Build Docker image with PHP ${{ matrix.php }}
247+
uses: docker/build-push-action@v6
248+
with:
249+
context: .
250+
file: .github/action/musl/Dockerfile
251+
target: ci-builder
252+
tags: ext-php-rs-musl:${{ matrix.php }}-${{ matrix.phpts }}
253+
cache-from: type=gha,scope=musl-${{ matrix.php }}-${{ matrix.phpts }}
254+
cache-to: type=gha,mode=max,scope=musl-${{ matrix.php }}-${{ matrix.phpts }}
255+
build-args: |
256+
PHP_VERSION=${{ matrix.php }}
257+
load: true
258+
259+
- name: Build ext-php-rs with musl
260+
run: |
261+
docker run --rm \
262+
-e EXT_PHP_RS_TEST="" \
263+
-v ${{ github.workspace }}:/workspace \
264+
-w /workspace \
265+
ext-php-rs-musl:${{ matrix.php }}-${{ matrix.phpts }} \
266+
build --release --features closure,anyhow,runtime --workspace --target x86_64-unknown-linux-musl
267+
268+
- name: Test ext-php-rs with musl
269+
run: |
270+
docker run --rm \
271+
-v ${{ github.workspace }}:/workspace \
272+
-w /workspace \
273+
ext-php-rs-musl:${{ matrix.php }}-${{ matrix.phpts }} \
274+
test --release --workspace --features closure,anyhow,runtime --target x86_64-unknown-linux-musl --no-fail-fast

Dockerfile.musl

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
# Multi-stage Dockerfile for building ext-php-rs with musl libc
2+
# This ensures PHP and the Rust extension are both compiled against musl
3+
4+
# Stage 1: Build PHP from source with musl
5+
FROM alpine:3.20 AS php-builder
6+
7+
ARG PHP_VERSION=8.4.3
8+
ARG PHP_BRANCH=PHP-${PHP_VERSION}
9+
10+
# Install build dependencies
11+
RUN apk add --no-cache \
12+
autoconf \
13+
automake \
14+
bison \
15+
re2c \
16+
gcc \
17+
g++ \
18+
make \
19+
musl-dev \
20+
linux-headers \
21+
pkgconfig \
22+
git \
23+
libxml2-dev \
24+
sqlite-dev \
25+
openssl-dev \
26+
curl-dev
27+
28+
# Clone and build PHP with musl
29+
WORKDIR /tmp/php-src
30+
RUN git clone --depth 1 -b ${PHP_BRANCH} https://github.com/php/php-src.git . || \
31+
git clone --depth 1 https://github.com/php/php-src.git .
32+
33+
RUN ./buildconf --force && \
34+
./configure \
35+
--enable-debug \
36+
--enable-embed=shared \
37+
--with-openssl \
38+
--with-curl \
39+
--with-sqlite3 \
40+
--disable-cgi \
41+
--prefix=/usr/local && \
42+
make -j$(nproc) && \
43+
make install
44+
45+
# Stage 2: Build ext-php-rs
46+
FROM alpine:3.20 AS rust-builder
47+
48+
# Copy PHP installation from previous stage
49+
COPY --from=php-builder /usr/local /usr/local
50+
51+
# Install Rust and build dependencies
52+
RUN apk add --no-cache \
53+
curl \
54+
gcc \
55+
g++ \
56+
musl-dev \
57+
clang17-dev \
58+
clang17-static \
59+
llvm17-dev \
60+
make \
61+
git
62+
63+
# Install Rust
64+
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable
65+
ENV PATH="/root/.cargo/bin:${PATH}"
66+
67+
# Add musl target
68+
RUN rustup target add x86_64-unknown-linux-musl
69+
70+
# Set up environment for musl build
71+
ENV CC=gcc
72+
ENV LIBCLANG_PATH=/usr/lib/llvm17/lib
73+
ENV LLVM_CONFIG_PATH=/usr/bin/llvm-config
74+
ENV PHP=/usr/local/bin/php
75+
ENV PHP_CONFIG=/usr/local/bin/php-config
76+
ENV RUSTFLAGS="-C target-feature=-crt-static"
77+
78+
# Create working directory
79+
WORKDIR /workspace
80+
81+
# Copy source code
82+
COPY . .
83+
84+
# Build the project
85+
RUN cargo build --release \
86+
--features closure,anyhow,runtime \
87+
--workspace \
88+
--target x86_64-unknown-linux-musl
89+
90+
# Stage 3: Runtime image with built artifacts
91+
FROM alpine:3.20 AS runtime
92+
93+
# Copy PHP runtime
94+
COPY --from=php-builder /usr/local /usr/local
95+
96+
# Copy built artifacts
97+
COPY --from=rust-builder /workspace/target/x86_64-unknown-linux-musl/release/cargo-php /usr/local/bin/
98+
99+
# Install runtime dependencies
100+
RUN apk add --no-cache \
101+
libxml2 \
102+
sqlite-libs \
103+
openssl \
104+
curl
105+
106+
WORKDIR /app
107+
108+
ENTRYPOINT ["/usr/local/bin/cargo-php"]
109+
110+
# Stage 4: Builder image for CI usage
111+
FROM rust-builder AS ci-builder
112+
113+
# This stage is used in CI to build and test
114+
# Usage: docker build --target ci-builder -t ext-php-rs-musl-ci .
115+
ENTRYPOINT ["cargo"]
116+
CMD ["build", "--release", "--features", "closure,anyhow,runtime", "--workspace", "--target", "x86_64-unknown-linux-musl"]

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,22 @@ best resource at the moment. This can be viewed at [docs.rs].
126126
1.57 at the time of writing.
127127
- Clang 5.0 or later.
128128

129+
### Alpine Linux (musl) Requirements
130+
131+
Building for Alpine Linux (musl libc) is supported on stable Rust with the following
132+
requirements:
133+
134+
- Install musl toolchain: `sudo apt-get install musl-tools musl-dev`
135+
- Add musl target: `rustup target add x86_64-unknown-linux-musl`
136+
- Build with dynamic linking flag:
137+
```bash
138+
RUSTFLAGS="-C target-feature=-crt-static" \
139+
cargo build --target x86_64-unknown-linux-musl
140+
```
141+
142+
**Note**: Building for musl requires dynamic CRT linking (`-crt-static` flag) to produce
143+
the `cdylib` output required for PHP extensions.
144+
129145
### Windows Requirements
130146

131147
- Extensions can only be compiled for PHP installations sourced from

tests/Cargo.toml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
[package]
22
name = "tests"
33
version = "0.0.0"
4-
edition = "2021"
4+
edition = "2024"
55
publish = false
66
license = "MIT OR Apache-2.0"
77

88
[dependencies]
9-
ext-php-rs = { path = "../", default-features = false, features = ["closure", "runtime"] }
9+
ext-php-rs = { path = "../", default-features = false, features = [
10+
"closure",
11+
"runtime",
12+
] }
1013

1114
[features]
1215
default = ["enum"]

0 commit comments

Comments
 (0)