# Copyright 2025-2026 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 EAPI=8 # NOTE: This package uses a pre-built crate tarball instead of listing individual # crates in CRATES="". This approach is required because: # 1. Codex has 800+ crate dependencies, which triggers Portage QA warnings: # "QA Notice: This package uses a very large number of CRATES. Please provide # a crate tarball instead and fetch it via SRC_URI." # 2. Stricter ebuild QA checks (e.g., in CI pipelines) fail with too many crates. # # The crate tarball is auto-generated by GitHub Actions at: # https://github.com/gentoo-zh-drafts/codex/ # Workflow source code for auditing: # https://github.com/gentoo-zh-drafts/codex/blob/crate-dist/.github/workflows/crates.yml # This allows anyone to review and verify the crate packaging process. # The prebuilt crate tarball contains every crates.io dependency, # including libz-sys 1.1.29. CRATES="" declare -A GIT_CRATES=( [crossterm]='https://github.com/openai-oss-forks/crossterm;ed1cdab335221515706178d68495bba2aed1924f;crossterm-%commit%' [h3]='https://github.com/hyperium/h3;e07e69412876f7e26f026bd75a48b2704d8c8283;h3-%commit%/h3' [h3-quinn]='https://github.com/hyperium/h3;e07e69412876f7e26f026bd75a48b2704d8c8283;h3-%commit%/h3-quinn' [mxc-sdk]='https://github.com/microsoft/mxc;b21120168d70befe12356411423266bfef168446;mxc-%commit%/src/mxc-sdk' [nucleo-matcher]='https://github.com/helix-editor/nucleo;4253de9faabb4e5c6d81d946a5e35a90f87347ee;nucleo-%commit%/matcher' [nucleo]='https://github.com/helix-editor/nucleo;4253de9faabb4e5c6d81d946a5e35a90f87347ee;nucleo-%commit%' [rmcp]='https://github.com/modelcontextprotocol/rust-sdk;98a54789b80110ad210495c4ad845c89e1980471;rust-sdk-%commit%/crates/rmcp' [rmcp-macros]='https://github.com/modelcontextprotocol/rust-sdk;98a54789b80110ad210495c4ad845c89e1980471;rust-sdk-%commit%/crates/rmcp-macros' [runfiles]='https://github.com/dzbarsky/rules_rust;b56cbaa8465e74127f1ea216f813cd377295ad81;rules_rust-%commit%/rust/runfiles' [tokio-tungstenite]='https://github.com/openai-oss-forks/tokio-tungstenite;0e5b2d73aa18dd9f0a50ee9ff199d5aef7594186;tokio-tungstenite-%commit%' [tungstenite]='https://github.com/openai-oss-forks/tungstenite-rs;4fffad30fe373adbdcffab9545e9e9bf4f2fc19f;tungstenite-rs-%commit%' ) # Upstream rust-toolchain.toml pins 1.99.1. The newest packaged slot is # 1.99.0; rust.eclass would round 1.99.1 up to the 9999 live slot. RUST_MIN_VER="1.99.0" # python3 .github/scripts/rusty_v8_bazel.py resolved-v8-crate-version RUSTY_V8_TAG="152.2.0" inherit cargo check-reqs toolchain-funcs CHECKREQS_MEMORY="15G" CHECKREQS_DISK_BUILD="20G" DESCRIPTION="Codex CLI - OpenAI's AI-powered coding agent" HOMEPAGE="https://github.com/openai/codex" # The crate tarball URL uses ${PV} so it auto-updates when bumping versions. # This tarball is generated by: https://github.com/gentoo-zh-drafts/codex/ # See .github/workflows/crates.yml for the generation process. SRC_URI=" https://github.com/openai/${PN}/archive/rust-v${PV}.tar.gz -> ${P}.tar.gz https://github.com/gentoo-zh-drafts/codex/releases/download/rust-v${PV}/codex-rust-v${PV}-crates.tar.xz amd64? ( https://github.com/openai/codex/releases/download/rusty-v8-v${RUSTY_V8_TAG}/librusty_v8_ptrcomp_sandbox_release_x86_64-unknown-linux-musl.a.gz -> rusty_v8_${RUSTY_V8_TAG}_librusty_v8_ptrcomp_sandbox_release_x86_64-unknown-linux-musl.a.gz https://github.com/openai/codex/releases/download/rusty-v8-v${RUSTY_V8_TAG}/src_binding_ptrcomp_sandbox_release_x86_64-unknown-linux-musl.rs -> rusty_v8_${RUSTY_V8_TAG}_src_binding_ptrcomp_sandbox_release_x86_64-unknown-linux-musl.rs ) arm64? ( https://github.com/openai/codex/releases/download/rusty-v8-v${RUSTY_V8_TAG}/librusty_v8_ptrcomp_sandbox_release_aarch64-unknown-linux-musl.a.gz -> rusty_v8_${RUSTY_V8_TAG}_librusty_v8_ptrcomp_sandbox_release_aarch64-unknown-linux-musl.a.gz https://github.com/openai/codex/releases/download/rusty-v8-v${RUSTY_V8_TAG}/src_binding_ptrcomp_sandbox_release_aarch64-unknown-linux-musl.rs -> rusty_v8_${RUSTY_V8_TAG}_src_binding_ptrcomp_sandbox_release_aarch64-unknown-linux-musl.rs ) ${CARGO_CRATE_URIS} " S="${WORKDIR}/${PN}-rust-v${PV}/codex-rs" LICENSE="Apache-2.0" # Dependent crate licenses LICENSE+=" Apache-2.0 Apache-2.0-with-LLVM-exceptions BSD-2 BSD Boost-1.0 CC0-1.0 CDLA-Permissive-2.0 ISC MIT MPL-2.0 Unicode-3.0 ZLIB " SLOT="0" KEYWORDS="-* ~amd64 ~arm64" # Tests fail due to ring crate conflicts with system OpenSSL RESTRICT="test" DEPEND=" dev-libs/openssl:= sys-apps/dbus " RDEPEND="${DEPEND}" BDEPEND="virtual/pkgconfig" # rust does not use *FLAGS from make.conf, silence portage warning QA_FLAGS_IGNORED="usr/bin/${PN} usr/bin/codex-code-mode-host" pkg_pretend() { check-reqs_pkg_pretend } pkg_setup() { check-reqs_pkg_setup rust_pkg_setup if tc-is-lto; then export CARGO_PROFILE_RELEASE_LTO=thin else export CARGO_PROFILE_RELEASE_LTO=false fi } gen_git_crate_dir() { # https://github.com/gentoo/gentoo/blob/b09dd88412fe2d5eee5a8891e08bfa2d67848da3/eclass/cargo.eclass#L442 IFS=';' read -r crate_uri commit crate_dir <<<"${GIT_CRATES[$1]}" echo "${WORKDIR}/${crate_dir//%commit%/${commit}}" } src_prepare() { default # Fix tokio-tungstenite's git dependency on tungstenite sed -i '/^\[dependencies\.tungstenite\]/,/^$/{ s|git = "[^"]*"|path = "'"$(gen_git_crate_dir tungstenite)"'"| /^rev = /d }' "$(gen_git_crate_dir tokio-tungstenite)/Cargo.toml" || die # Remove the [patch.crates-io] section and add path-based patches sed -i '/^\[patch\.crates-io\]/,/^$/d' "${S}/Cargo.toml" || die sed -i '/^\[patch\."ssh:\/\/git@github\.com/,/^$/d' "${S}/Cargo.toml" || die # Add new patch section with local paths cat >> "${S}/Cargo.toml" <<-EOF || die [patch.crates-io] crossterm = { path = "$(gen_git_crate_dir crossterm)" } tokio-tungstenite = { path = "$(gen_git_crate_dir tokio-tungstenite)" } tungstenite = { path = "$(gen_git_crate_dir tungstenite)" } EOF } src_compile() { local rusty_v8_triple use amd64 && rusty_v8_triple=x86_64-unknown-linux-musl use arm64 && rusty_v8_triple=aarch64-unknown-linux-musl # codex-core trait resolution overflows rustc's default 8MiB stack export RUST_MIN_STACK=16777216 # codex-code-mode-runtime enables V8's sandbox and pointer compression. RUSTY_V8_ARCHIVE="${DISTDIR}/rusty_v8_${RUSTY_V8_TAG}_librusty_v8_ptrcomp_sandbox_release_${rusty_v8_triple}.a.gz" \ RUSTY_V8_SRC_BINDING_PATH="${DISTDIR}/rusty_v8_${RUSTY_V8_TAG}_src_binding_ptrcomp_sandbox_release_${rusty_v8_triple}.rs" \ cargo_src_compile --package codex-cli --package codex-code-mode-host } src_install() { # The CLI starts Code Mode through a sibling executable. dobin "$(cargo_target_dir)/codex" \ "$(cargo_target_dir)/codex-code-mode-host" einstalldocs } pkg_postinst() { # Only update an existing daemon after a merge on the running system. [[ ${ROOT} == / && -z ${EPREFIX} && -n ${REPLACING_VERSIONS} ]] || return 0 [[ ${CODEX_DAEMON_AUTO_UPDATE:-yes} == yes ]] || return 0 # Portage does not inherit the interactive shell's CODEX_HOME reliably. # This distribution uses a shared home; other installations can override it # with CODEX_DAEMON_HOME in make.conf. local codex_home=${CODEX_DAEMON_HOME:-/var/lib/ai/codex/.codex} [[ -d ${codex_home}/app-server-daemon ]] || return 0 [[ -L ${codex_home}/packages/app-server-daemon/current || -L ${codex_home}/packages/standalone/current ]] || return 0 # Do not run a user's daemon as root or change its ownership during a merge. if [[ ! -O ${codex_home}/app-server-daemon/settings.json ]]; then ewarn "Skipping Codex daemon update: settings are not owned by the merge user." ewarn "Run 'codex app-server daemon update' as the daemon owner." return 0 fi # A restarted daemon must not inherit Portage's temporary HOME or build env. local passwd_entry daemon_user daemon_home daemon_shell unused if ! passwd_entry=$(getent passwd "${EUID}"); then ewarn "Cannot resolve the merge user's home; update the Codex daemon manually." return 0 fi IFS=: read -r daemon_user unused unused unused unused daemon_home daemon_shell \ <<< "${passwd_entry}" if [[ ${daemon_home} != /* || ! -d ${daemon_home} ]]; then ewarn "The merge user's home is unavailable; update the Codex daemon manually." return 0 fi einfo "Updating the Codex background server in ${codex_home} (may restart it)..." # The system build has no standalone package manifest, so --from-cli is # unavailable. Use the upstream daemon updater with a bounded wait. if ! ( cd "${daemon_home}" && env -i HOME="${daemon_home}" \ USER="${daemon_user}" LOGNAME="${daemon_user}" SHELL="${daemon_shell}" \ PATH=/usr/sbin:/usr/bin:/sbin:/bin CODEX_HOME="${codex_home}" \ /usr/bin/timeout --kill-after=10s 300s \ "${EROOT}usr/bin/codex" app-server daemon update ); then ewarn "Codex CLI was installed, but the background server update did not complete." ewarn "Retry: CODEX_HOME='${codex_home}' codex app-server daemon update" ewarn "If migration completed but startup failed, fix the reported error and run:" ewarn "CODEX_HOME='${codex_home}' codex app-server daemon start" fi }