Skip to content

Commit 502538d

Browse files
committed
ci: add musl build step
1 parent d5022a1 commit 502538d

File tree

12 files changed

+204
-24
lines changed

12 files changed

+204
-24
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: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
ARG PHP_VERSION=8.4
2+
ARG TS=-zts
3+
4+
FROM php:${PHP_VERSION}${TS}-alpine
5+
6+
RUN apk add --no-cache \
7+
llvm17 \
8+
llvm17-dev \
9+
llvm17-libs \
10+
llvm17-static \
11+
clang17 \
12+
clang17-dev \
13+
clang17-static \
14+
curl
15+
16+
# WORKDIR /tmp
17+
# RUN FULL_VERSION=$(curl -fsSL "https://www.php.net/releases/index.php?json&version=${PHP_VERSION}" | jq -r '.version') && \
18+
# echo "Downloading PHP ${FULL_VERSION}..." && \
19+
# curl -fsSL "https://www.php.net/distributions/php-${FULL_VERSION}.tar.gz" -o php.tar.gz && \
20+
# tar -xzf php.tar.gz && \
21+
# rm php.tar.gz && \
22+
# mv "php-${FULL_VERSION}" php-src
23+
24+
# WORKDIR /tmp/php-src
25+
# RUN CONFIGURE_OPTS="--enable-debug --enable-embed=shared --disable-all --disable-cgi" && \
26+
# if [ "$TS" = "ts" ]; then CONFIGURE_OPTS="$CONFIGURE_OPTS --enable-zts"; fi && \
27+
# ./configure $CONFIGURE_OPTS --prefix=/usr/local && \
28+
# make -j$(nproc) && \
29+
# make install && \
30+
# rm -rf /tmp/php-src
31+
32+
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable
33+
ENV PATH="/root/.cargo/bin:${PATH}"
34+
35+
RUN rustup target add x86_64-unknown-linux-musl
36+
RUN cargo install cargo-expand --locked
37+
38+
ENV PHP=/usr/local/bin/php
39+
ENV PHP_CONFIG=/usr/local/bin/php-config
40+
41+
ENV LLVM_CONFIG_PATH=/usr/lib/llvm17/bin/llvm-config
42+
ENV LIBCLANG_PATH=/usr/lib/llvm17/lib
43+
ENV LD_LIBRARY_PATH=/usr/local/lib:/usr/lib
44+
ENV RUSTFLAGS="-C target-feature=-crt-static -C link-arg=-Wl,-rpath,/usr/local/lib -L /usr/local/lib"
45+
46+
WORKDIR /workspace
47+
48+
COPY . .
49+
50+
ENTRYPOINT ["cargo"]
51+
CMD ["build", "--release", "--no-default-features", "--features", "closure,anyhow,runtime,enum", "--workspace", "--target", "x86_64-unknown-linux-musl"]

.github/workflows/build.yml

Lines changed: 42 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,45 @@ 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 / ${{ matrix.php }} / ${{ matrix.phpts[1] }}
231+
runs-on: ubuntu-latest
232+
strategy:
233+
matrix:
234+
php: ["8.1", "8.2", "8.3", "8.4"]
235+
phpts: [["-zts", "TS"], ["", "NTS"]]
236+
env:
237+
CARGO_TERM_COLOR: always
238+
steps:
239+
- name: Checkout code
240+
uses: actions/checkout@v5
241+
- name: Setup DockerX
242+
uses: docker/setup-buildx-action@v3
243+
- name: Build
244+
uses: docker/build-push-action@v6
245+
with:
246+
context: .github/action/musl
247+
file: .github/action/musl/Dockerfile
248+
tags: |
249+
extphprs/ext-php-rs:musl-${{ matrix.php }}-${{ matrix.phpts[1] }}
250+
push: false
251+
load: true
252+
platforms: linux/amd64
253+
build-args: |
254+
PHP_VERSION=${{ matrix.php }}
255+
TS=${{ matrix.phpts[0] }}
256+
- name: Build
257+
run: |
258+
docker run \
259+
-v $(pwd):/workspace \
260+
-w /workspace \
261+
extphprs/ext-php-rs:musl-${{ matrix.php }}-${{ matrix.phpts[1] }} \
262+
build --release --features closure,anyhow,runtime --workspace
263+
- name: Run tests
264+
run: |
265+
docker run \
266+
-v $(pwd):/workspace \
267+
-w /workspace \
268+
extphprs/ext-php-rs:musl-${{ matrix.php }}-${{ matrix.phpts[1] }} \
269+
test --workspace --release --features closure,anyhow,runtime --no-fail-fast

Dockerfile

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,20 @@ apt update -y
88
apt install -y \
99
libclang-dev \
1010
bison \
11-
re2c
11+
re2c \
12+
curl \
13+
jq
14+
15+
# Download and extract PHP
16+
FULL_VERSION=$(curl -fsSL "https://www.php.net/releases/index.php?json&version=${PHP_VERSION}" | jq -r '.version')
17+
echo "Downloading PHP ${FULL_VERSION}..."
18+
curl -fsSL "https://www.php.net/distributions/php-${FULL_VERSION}.tar.gz" -o php.tar.gz
19+
tar -xzf php.tar.gz
20+
rm php.tar.gz
21+
mv "php-${FULL_VERSION}" php-src
1222

1323
# Build PHP
14-
git clone --depth 1 -b PHP-${PHP_VERSION} https://github.com/php/php-src.git
1524
cd php-src
16-
# by default you will be on the master branch, which is the current
17-
# development version. You can check out a stable branch instead:
18-
./buildconf
1925
./configure \
2026
--enable-debug \
2127
--disable-all --disable-cgi

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,16 @@ 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)
130+
131+
Building for Alpine Linux (musl libc) is supported on stable Rust with dynamic linking
132+
thanks to `runtime` feature flag from `bindgen`.
133+
134+
**Note**: Building for musl requires dynamic CRT linking (`-crt-static` flag) to produce
135+
the `cdylib` output required for PHP extensions.
136+
If you want to build statically, you'll need full LLVM + Clang toolchain.
137+
Please read: <https://github.com/KyleMayes/clang-sys#static>
138+
129139
### Windows Requirements
130140

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

src/builders/ini.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
//! This module is only available in PHP 8.2+, as the `php_ini_builder`
2+
//! API was introduced in PHP 8.2.0.
3+
#![cfg(php82)]
4+
15
use crate::embed::ext_php_rs_php_ini_builder_deinit;
26
use crate::ffi::{
37
php_ini_builder, php_ini_builder_define, php_ini_builder_prepend, php_ini_builder_quoted,
@@ -229,7 +233,7 @@ impl Drop for IniBuilder {
229233
}
230234
}
231235

232-
#[cfg(test)]
236+
#[cfg(all(test, php82))]
233237
mod tests {
234238
use super::*;
235239

src/builders/sapi.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,15 @@ pub type SapiRegisterServerVariablesFunc = extern "C" fn(vars: *mut Zval);
428428
pub type SapiLogMessageFunc = extern "C" fn(message: *const c_char, syslog_type_int: c_int);
429429

430430
/// A function to be called when PHP gets the request time
431-
pub type SapiRequestTimeFunc = extern "C" fn(time: *mut f64) -> c_int;
431+
///
432+
/// Note: Signature changed in PHP 8.2:
433+
/// - PHP 8.1 and earlier: `unsafe extern "C" fn() -> f64` (returns time directly)
434+
/// - PHP 8.2+: `unsafe extern "C" fn(time: *mut f64) -> c_int` (writes to pointer)
435+
#[cfg(not(php82))]
436+
pub type SapiRequestTimeFunc = unsafe extern "C" fn() -> f64;
437+
438+
#[cfg(php82)]
439+
pub type SapiRequestTimeFunc = unsafe extern "C" fn(time: *mut f64) -> c_int;
432440

433441
/// A function to be called when PHP terminates the process
434442
pub type SapiTerminateProcessFunc = extern "C" fn();
@@ -480,9 +488,17 @@ mod test {
480488
}
481489
extern "C" fn test_register_server_variables(_vars: *mut Zval) {}
482490
extern "C" fn test_log_message(_message: *const c_char, _syslog_type_int: c_int) {}
483-
extern "C" fn test_get_request_time(_time: *mut f64) -> c_int {
491+
492+
#[cfg(not(php82))]
493+
unsafe extern "C" fn test_get_request_time() -> f64 {
494+
0.0
495+
}
496+
497+
#[cfg(php82)]
498+
unsafe extern "C" fn test_get_request_time(_time: *mut f64) -> c_int {
484499
0
485500
}
501+
486502
extern "C" fn test_terminate_process() {}
487503
extern "C" fn test_get_target_uid(_uid: *mut uid_t) -> c_int {
488504
0

src/embed/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,15 @@ impl Embed {
105105
zend_stream_init_filename(&raw mut file_handle, path.as_ptr());
106106
}
107107

108+
// php_execute_script returns different types across PHP versions:
109+
// PHP 8.1 and earlier: returns i32 (ZEND_RESULT_CODE: 0 = success, -1 = failure)
110+
// PHP 8.2+: returns bool (true = success, false = failure)
111+
#[cfg(not(php82))]
112+
let exec_result = try_catch(|| unsafe {
113+
php_execute_script(&raw mut file_handle) == ZEND_RESULT_CODE_SUCCESS
114+
});
115+
116+
#[cfg(php82)]
108117
let exec_result = try_catch(|| unsafe { php_execute_script(&raw mut file_handle) });
109118

110119
unsafe { zend_destroy_file_handle(&raw mut file_handle) }

tests/Cargo.toml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
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 }
1010

1111
[features]
12-
default = ["enum"]
12+
default = ["enum", "runtime", "closure"]
1313
enum = ["ext-php-rs/enum"]
14+
anyhow = ["ext-php-rs/anyhow"]
15+
runtime = ["ext-php-rs/runtime"]
16+
closure = ["ext-php-rs/closure"]
17+
static = ["ext-php-rs/static"]
1418

1519
[lib]
1620
crate-type = ["cdylib"]

tests/sapi.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@ fn test_sapi() {
4949
sapi_startup(sapi);
5050
}
5151

52+
#[cfg(not(php82))]
53+
unsafe {
54+
php_module_startup(sapi, module, 1);
55+
}
56+
57+
#[cfg(php82)]
5258
unsafe {
5359
php_module_startup(sapi, module);
5460
}

0 commit comments

Comments
 (0)