#!/bin/sh # SPDX-FileCopyrightText: 2026 GPForum Contributors # SPDX-License-Identifier: BSD-3-Clause set -eu # Locate Carton for lock updates, checks and bundles, or run from local/. # Locked installation uses script/gpforum-cpm. The runtime selector accepts # any supported Perl; native dependencies must match that interpreter's ABI. root=$(CDPATH= cd -- "$(dirname "$0")/.." && pwd) # libev reads LIBEV_FLAGS once, when EV loads, and morbo, Test::Mojo, yath or # a profiler load it before any GPForum code can choose: on macOS and FreeBSD # libev's own default is then select or poll. Choosing here, before any Perl # starts, gives every tool run through this script the native backend that # GPForum::OS::Reactor requires (keep the two tables equal; t/698 checks). # Another system keeps whatever it inherited. case $(uname -s) in Linux) native_backend=4 ;; Darwin | FreeBSD) native_backend=8 ;; *) native_backend= ;; esac if [ -n "$native_backend" ]; then LIBEV_FLAGS=$native_backend MOJO_REACTOR=Mojo::Reactor::EV export LIBEV_FLAGS MOJO_REACTOR fi if [ -n "${GPFORUM_CARTON:-}" ]; then if [ ! -x "${GPFORUM_CARTON}" ]; then echo "gpforum-carton: GPFORUM_CARTON is not executable: ${GPFORUM_CARTON}" >&2 exit 1 fi exec "${GPFORUM_CARTON}" "$@" fi perl_bin=$("$root/script/gpforum-system-perl" --require) GPFORUM_PERL=$perl_bin perl_dir=$(dirname "$perl_bin") # Keep PATH lookups on the same interpreter for `perl -S carton`. PATH="$perl_dir:$PATH" export PATH GPFORUM_PERL # Probe before adding local/ to @INC, so a mismatched XS module produces a # rebuild instruction instead of a loader crash. Do not inherit Perl library # overrides into the core-only compatibility check. PERL5LIB= PERL5OPT= "$perl_bin" -I"$root/lib" -MGPForum::Infrastructure::PerlRuntime \ -e 'GPForum::Infrastructure::PerlRuntime->check(shift)' "$root" # `exec` only needs the locked tree on @INC, which local/ already provides, so # it is reproduced here whether or not Carton is installed. Real `carton exec` # parses the options that follow the command as its own: `exec prove -v` # printed Carton's version instead of running the tests. Reproducing it also # pins every Perl tool to the validated interpreter. Lock updates and checks # still need Carton itself (below). if [ "${1:-}" = "exec" ] && [ -d "$root/local/lib/perl5" ]; then shift PERL5LIB="$root/local/lib/perl5${PERL5LIB:+:$PERL5LIB}" export PERL5LIB # Anything launched from here — including a program whose shebang says # `#!/usr/bin/env perl` — must find the validated interpreter first, or it # loads XS built for a different Perl. A shim directory makes `perl` on # PATH mean exactly $perl_bin for the whole process tree. shim="$root/local/.perl-shim" if [ ! -x "$shim/perl" ] || [ "$(readlink "$shim/perl" 2>/dev/null)" != "$perl_bin" ]; then mkdir -p "$shim" && ln -sf "$perl_bin" "$shim/perl" fi PATH="$shim:$root/local/bin:$PATH" export PATH # `carton exec -- cmd` is valid; drop the separator before dispatching. if [ "${1:-}" = "--" ]; then shift fi # A bare `perl`, `prove` or other Perl tool found on PATH can belong to # an older interpreter than the one that validated above (macOS keeps # its own /usr/bin/perl next to Homebrew's). Pin every Perl tool to # $perl_bin. command_name=${1:-} case "$command_name" in */*) # An explicit path. A Perl entrypoint must run under the # interpreter that validated above, not under whatever its # shebang resolves to on this host, or it loads XS built for a # different Perl and dies with a handshake mismatch. if [ -r "$command_name" ] \ && head -n 1 "$command_name" 2>/dev/null | grep -q 'perl'; then shift exec "$perl_bin" "$command_name" "$@" fi exec "$@" ;; perl) shift exec "$perl_bin" "$@" ;; esac if [ -n "$command_name" ] && [ ! -x "$perl_dir/$command_name" ] \ && "$perl_bin" -e 'exit 0' >/dev/null 2>&1 \ && "$perl_bin" -S "$command_name" --version >/dev/null 2>&1; then shift exec "$perl_bin" -S "$command_name" "$@" fi exec "$@" fi if [ -x "$perl_dir/carton" ]; then exec "$perl_bin" -I"$root/script/lib" -MGPForum::Tool::CartonHTTPS "$perl_dir/carton" "$@" fi if "$perl_bin" -S carton version >/dev/null 2>&1; then exec "$perl_bin" -I"$root/script/lib" -MGPForum::Tool::CartonHTTPS -S carton "$@" fi echo "gpforum-carton: Carton was not found for selected Perl $perl_bin." >&2 echo "Install it for this Perl with: $perl_bin -S cpanm -M https://cpan.metacpan.org/ Carton" >&2 exit 1