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
3 changes: 3 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@ linker = "rust-lld"

[target.i686-pc-windows-msvc]
linker = "rust-lld"

[target.'cfg(target_env = "musl")']
rustflags = ["-C", "target-feature=-crt-static"]
35 changes: 35 additions & 0 deletions .github/action/musl/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
ARG PHP_VERSION=8.4
ARG TS=-zts

FROM php:${PHP_VERSION}${TS}-alpine

RUN apk add --no-cache \
llvm17 \
llvm17-dev \
llvm17-libs \
llvm17-static \
clang17 \
clang17-dev \
clang17-static \
curl

RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable
ENV PATH="/root/.cargo/bin:${PATH}"

RUN rustup target add x86_64-unknown-linux-musl
RUN cargo install cargo-expand --locked

ENV PHP=/usr/local/bin/php
ENV PHP_CONFIG=/usr/local/bin/php-config

ENV LLVM_CONFIG_PATH=/usr/lib/llvm17/bin/llvm-config
ENV LIBCLANG_PATH=/usr/lib/llvm17/lib
ENV LD_LIBRARY_PATH=/usr/local/lib:/usr/lib
ENV RUSTFLAGS="-C target-feature=-crt-static -C link-arg=-Wl,-rpath,/usr/local/lib -L /usr/local/lib"

WORKDIR /workspace

COPY . .

ENTRYPOINT ["cargo"]
CMD ["build", "--release", "--no-default-features", "--features", "closure,anyhow,runtime,enum", "--workspace", "--target", "x86_64-unknown-linux-musl"]
43 changes: 42 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,6 @@ jobs:
# Macos fails on unstable rust. We skip the inline examples test for now.
if: "!(contains(matrix.os, 'macos') && matrix.rust == 'nightly')"
run: cargo test --release --workspace --features closure,anyhow,runtime --no-fail-fast

test-embed:
name: Test with embed
runs-on: ubuntu-latest
Expand Down Expand Up @@ -226,3 +225,45 @@ jobs:

- name: Test with embed feature
run: cargo test --workspace --release --features closure,embed,anyhow --no-fail-fast

build-musl:
name: musl / ${{ matrix.php }} / ${{ matrix.phpts[1] }}
runs-on: ubuntu-latest
strategy:
matrix:
php: ["8.1", "8.2", "8.3", "8.4"]
phpts: [["-zts", "TS"], ["", "NTS"]]
env:
CARGO_TERM_COLOR: always
steps:
- name: Checkout code
uses: actions/checkout@v5
- name: Setup DockerX
uses: docker/setup-buildx-action@v3
- name: Build
uses: docker/build-push-action@v6
with:
context: .github/action/musl
file: .github/action/musl/Dockerfile
tags: |
extphprs/ext-php-rs:musl-${{ matrix.php }}-${{ matrix.phpts[1] }}
push: false
load: true
platforms: linux/amd64
build-args: |
PHP_VERSION=${{ matrix.php }}
TS=${{ matrix.phpts[0] }}
- name: Build
run: |
docker run \
-v $(pwd):/workspace \
-w /workspace \
extphprs/ext-php-rs:musl-${{ matrix.php }}-${{ matrix.phpts[1] }} \
build --release --features closure,anyhow,runtime --workspace
- name: Run tests
run: |
docker run \
-v $(pwd):/workspace \
-w /workspace \
extphprs/ext-php-rs:musl-${{ matrix.php }}-${{ matrix.phpts[1] }} \
test --workspace --release --features closure,anyhow,runtime --no-fail-fast
16 changes: 11 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,20 @@ apt update -y
apt install -y \
libclang-dev \
bison \
re2c
re2c \
curl \
jq

# Download and extract PHP
FULL_VERSION=$(curl -fsSL "https://www.php.net/releases/index.php?json&version=${PHP_VERSION}" | jq -r '.version')
echo "Downloading PHP ${FULL_VERSION}..."
curl -fsSL "https://www.php.net/distributions/php-${FULL_VERSION}.tar.gz" -o php.tar.gz
tar -xzf php.tar.gz
rm php.tar.gz
mv "php-${FULL_VERSION}" php-src

# Build PHP
git clone --depth 1 -b PHP-${PHP_VERSION} https://github.com/php/php-src.git
cd php-src
# by default you will be on the master branch, which is the current
# development version. You can check out a stable branch instead:
./buildconf
./configure \
--enable-debug \
--disable-all --disable-cgi
Expand Down
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,16 @@ best resource at the moment. This can be viewed at [docs.rs].
1.57 at the time of writing.
- Clang 5.0 or later.

### Alpine Linux (musl)

Building for Alpine Linux (musl libc) is supported on stable Rust with dynamic linking
thanks to `runtime` feature flag from `bindgen`.

**Note**: Building for musl requires dynamic CRT linking (`-crt-static` flag) to produce
the `cdylib` output required for PHP extensions.
If you want to build statically, you'll need full LLVM + Clang toolchain.
Please read: <https://github.com/KyleMayes/clang-sys#static>

### Windows Requirements

- Extensions can only be compiled for PHP installations sourced from
Expand Down
10 changes: 7 additions & 3 deletions tests/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
[package]
name = "tests"
version = "0.0.0"
edition = "2021"
edition = "2024"
publish = false
license = "MIT OR Apache-2.0"

[dependencies]
ext-php-rs = { path = "../", default-features = false, features = ["closure", "runtime"] }
ext-php-rs = { path = "../", default-features = false }

[features]
default = ["enum"]
default = ["enum", "runtime", "closure"]
enum = ["ext-php-rs/enum"]
anyhow = ["ext-php-rs/anyhow"]
runtime = ["ext-php-rs/runtime"]
closure = ["ext-php-rs/closure"]
static = ["ext-php-rs/static"]

[lib]
crate-type = ["cdylib"]
46 changes: 38 additions & 8 deletions tests/src/integration/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,41 @@ mod test {
fn setup() {
BUILD.call_once(|| {
let mut command = Command::new("cargo");
command.arg("build").arg("--no-default-features");
#[cfg(feature = "enum")]
command.arg("build");

#[cfg(not(debug_assertions))]
command.arg("--release");

// Build features list dynamically based on compiled features
// Note: Using vec_init_then_push pattern here is intentional due to conditional compilation
#[allow(clippy::vec_init_then_push)]
{
command.arg("--features=enum");
let mut features = vec![];
#[cfg(feature = "enum")]
features.push("enum");
#[cfg(feature = "closure")]
features.push("closure");
#[cfg(feature = "anyhow")]
features.push("anyhow");
#[cfg(feature = "runtime")]
features.push("runtime");
#[cfg(feature = "static")]
features.push("static");

if !features.is_empty() {
command.arg("--no-default-features");
command.arg("--features").arg(features.join(","));
}
}
assert!(command
.output()
.expect("failed to build extension")
.status
.success());

let result = command.output().expect("failed to execute cargo build");

assert!(
result.status.success(),
"Extension build failed:\nstdout: {}\nstderr: {}",
String::from_utf8_lossy(&result.stdout),
String::from_utf8_lossy(&result.stderr)
);
});
}

Expand Down Expand Up @@ -99,7 +124,12 @@ mod test {
let mut path = env::current_dir().expect("Could not get cwd");
path.pop();
path.push("target");

#[cfg(not(debug_assertions))]
path.push("release");
#[cfg(debug_assertions)]
path.push("debug");

path.push(if std::env::consts::DLL_EXTENSION == "dll" {
"tests"
} else {
Expand Down
8 changes: 4 additions & 4 deletions tests/src/integration/variadic_args/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,10 @@ pub fn test_variadic_first_last(items: &[&Zval]) -> Vec<Zval> {
if let Some(first) = items.first() {
result.push(first.shallow_clone());
}
if let Some(last) = items.last() {
if items.len() > 1 {
result.push(last.shallow_clone());
}
if let Some(last) = items.last()
&& items.len() > 1
{
result.push(last.shallow_clone());
}
result
}
Expand Down
Loading