Skip to content

Commit c1dd952

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

File tree

7 files changed

+173
-12
lines changed

7 files changed

+173
-12
lines changed

.cargo/config.toml

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

77
[target.i686-pc-windows-msvc]
88
linker = "rust-lld"
9+
10+
[target.'cfg(target_env = "musl")']
11+
rustflags = [
12+
"-C",
13+
"target-feature=-crt-static",
14+
"-C",
15+
"link-arg=-Wl,-undefined,dynamic_lookup",
16+
]

.github/action/musl/Dockerfile

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
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+
ARG TS=ts
8+
9+
RUN apk add --no-cache \
10+
autoconf \
11+
automake \
12+
bison \
13+
re2c \
14+
gcc \
15+
g++ \
16+
make \
17+
musl-dev \
18+
linux-headers \
19+
pkgconfig \
20+
git \
21+
libxml2-dev \
22+
sqlite-dev \
23+
openssl-dev \
24+
curl-dev
25+
26+
WORKDIR /tmp/php-src
27+
RUN git clone --depth 1 -b ${PHP_BRANCH} https://github.com/php/php-src.git .
28+
29+
RUN ./buildconf --force && \
30+
CONFIGURE_OPTS="--enable-debug --enable-embed=shared --with-openssl --with-curl --with-sqlite3 --disable-cgi" && \
31+
if [ "$TS" = "ts" ]; then CONFIGURE_OPTS="$CONFIGURE_OPTS --enable-zts"; fi && \
32+
./configure $CONFIGURE_OPTS --prefix=/usr/local && \
33+
make -j$(nproc) && \
34+
make install
35+
36+
FROM alpine:3.20 AS rust-builder
37+
38+
COPY --from=php-builder /usr/local /usr/local
39+
40+
RUN apk add --no-cache \
41+
curl \
42+
gcc \
43+
g++ \
44+
musl-dev \
45+
clang17 \
46+
clang17-libclang \
47+
clang17-dev \
48+
clang17-static \
49+
make \
50+
git
51+
52+
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable
53+
ENV PATH="/root/.cargo/bin:${PATH}"
54+
55+
RUN rustup target add x86_64-unknown-linux-musl
56+
57+
ENV PHP=/usr/local/bin/php
58+
ENV PHP_CONFIG=/usr/local/bin/php-config
59+
60+
WORKDIR /workspace
61+
62+
COPY . .
63+
64+
RUN cargo build --release \
65+
--features closure,anyhow,runtime \
66+
--workspace \
67+
--target x86_64-unknown-linux-musl
68+
69+
FROM alpine:3.20 AS runtime
70+
COPY --from=php-builder /usr/local /usr/local
71+
COPY --from=rust-builder /workspace/target/x86_64-unknown-linux-musl/release/cargo-php /usr/local/bin/
72+
73+
RUN apk add --no-cache \
74+
libxml2 \
75+
sqlite-libs \
76+
openssl \
77+
curl
78+
79+
WORKDIR /app
80+
81+
ENTRYPOINT ["/usr/local/bin/cargo-php"]
82+
83+
FROM rust-builder AS ci-builder
84+
85+
ENTRYPOINT ["cargo"]
86+
CMD ["build", "--release", "--features", "closure,anyhow,static", "--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
@@ -168,7 +168,6 @@ jobs:
168168
# Macos fails on unstable rust. We skip the inline examples test for now.
169169
if: "!(contains(matrix.os, 'macos') && matrix.rust == 'nightly')"
170170
run: cargo test --release --workspace --features closure,anyhow,runtime --no-fail-fast
171-
172171
test-embed:
173172
name: Test with embed
174173
runs-on: ubuntu-latest
@@ -226,3 +225,50 @@ jobs:
226225
227226
- name: Test with embed feature
228227
run: cargo test --workspace --release --features closure,embed,anyhow --no-fail-fast
228+
229+
build-musl:
230+
name: Musl
231+
runs-on: ubuntu-latest
232+
strategy:
233+
matrix:
234+
php: ["8.1", "8.2", "8.3", "8.4"]
235+
phpts: [ts, nts]
236+
env:
237+
CARGO_TERM_COLOR: always
238+
steps:
239+
- name: Checkout code
240+
uses: actions/checkout@v5
241+
242+
- name: Set up Docker Buildx
243+
uses: docker/setup-buildx-action@v3
244+
245+
- name: Build Docker image with PHP ${{ matrix.php }}
246+
uses: docker/build-push-action@v6
247+
with:
248+
context: .
249+
file: .github/action/musl/Dockerfile
250+
target: ci-builder
251+
tags: ext-php-rs-musl:${{ matrix.php }}-${{ matrix.phpts }}
252+
cache-from: type=gha,scope=musl-${{ matrix.php }}-${{ matrix.phpts }}
253+
cache-to: type=gha,mode=max,scope=musl-${{ matrix.php }}-${{ matrix.phpts }}
254+
build-args: |
255+
PHP_VERSION=${{ matrix.php }}
256+
TS=${{ matrix.phpts }}
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,static --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,static --target x86_64-unknown-linux-musl --no-fail-fast

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"]

tests/src/integration/mod.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,13 @@ mod test {
3636
{
3737
command.arg("--features=enum");
3838
}
39-
assert!(command
40-
.output()
41-
.expect("failed to build extension")
42-
.status
43-
.success());
39+
assert!(
40+
command
41+
.output()
42+
.expect("failed to build extension")
43+
.status
44+
.success()
45+
);
4446
});
4547
}
4648

tests/src/integration/variadic_args/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,10 @@ pub fn test_variadic_first_last(items: &[&Zval]) -> Vec<Zval> {
7979
if let Some(first) = items.first() {
8080
result.push(first.shallow_clone());
8181
}
82-
if let Some(last) = items.last() {
83-
if items.len() > 1 {
84-
result.push(last.shallow_clone());
85-
}
82+
if let Some(last) = items.last()
83+
&& items.len() > 1
84+
{
85+
result.push(last.shallow_clone());
8686
}
8787
result
8888
}

0 commit comments

Comments
 (0)