# Copyright 2026 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 EAPI=8 CRATES="" declare -A GIT_CRATES=( [crossterm]='https://github.com/openai-oss-forks/crossterm;ed1cdab335221515706178d68495bba2aed1924f;crossterm-%commit%' [h3-quinn]='https://github.com/hyperium/h3;e07e69412876f7e26f026bd75a48b2704d8c8283;h3-%commit%/h3-quinn' [h3]='https://github.com/hyperium/h3;e07e69412876f7e26f026bd75a48b2704d8c8283;h3-%commit%/h3' [learning_mode_core]='https://github.com/microsoft/mxc;6cd3d58f05d3447e67109cfb75e042803b843ca4;mxc-%commit%/src/core/learning_mode_core' [mxc_config_contract]='https://github.com/microsoft/mxc;6cd3d58f05d3447e67109cfb75e042803b843ca4;mxc-%commit%/src/core/mxc_config_contract' [mxc_telemetry]='https://github.com/microsoft/mxc;6cd3d58f05d3447e67109cfb75e042803b843ca4;mxc-%commit%/src/mxc_telemetry' [nucleo-matcher]='https://github.com/helix-editor/nucleo;4253de9faabb4e5c6d81d946a5e35a90f87347ee;nucleo-%commit%/matcher' [nucleo]='https://github.com/helix-editor/nucleo;4253de9faabb4e5c6d81d946a5e35a90f87347ee;nucleo-%commit%' [process_security_environment_spec]='https://github.com/microsoft/mxc;6cd3d58f05d3447e67109cfb75e042803b843ca4;mxc-%commit%/src/core/generated/process_security_environment_specification' [rmcp-macros]='https://github.com/modelcontextprotocol/rust-sdk;3e636cab26c013eca5131103c03d20237f12c4df;rust-sdk-%commit%/crates/rmcp-macros' [rmcp]='https://github.com/modelcontextprotocol/rust-sdk;3e636cab26c013eca5131103c03d20237f12c4df;rust-sdk-%commit%/crates/rmcp' [runfiles]='https://github.com/dzbarsky/rules_rust;b56cbaa8465e74127f1ea216f813cd377295ad81;rules_rust-%commit%/rust/runfiles' [sandbox_spec]='https://github.com/microsoft/mxc;6cd3d58f05d3447e67109cfb75e042803b843ca4;mxc-%commit%/src/core/generated/base_container_specification' [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%' [wxc_common]='https://github.com/microsoft/mxc;6cd3d58f05d3447e67109cfb75e042803b843ca4;mxc-%commit%/src/core/wxc_common' ) RUST_MIN_VER="1.95.0" RUSTY_V8_VER="150.4.0" # Chromium host clang 23 + rust-toolchain (Linux_x64) from rusty_v8 ${RUSTY_V8_VER} DEPS. CLANG_DIST="clang-llvmorg-23-init-10931-g20b6ec66-11.tar.xz" RUST_TC_DIST="rust-toolchain-4c4205163abcbd08948b3efab796c543ba1ea687-4-llvmorg-23-init-10931-g20b6ec66.tar.xz" inherit cargo check-reqs shell-completion toolchain-funcs CHECKREQS_MEMORY="15G" CHECKREQS_DISK_BUILD="20G" DESCRIPTION="OpenAI Codex CLI (from-source rusty_v8)" HOMEPAGE="https://github.com/openai/codex" SRC_URI=" https://github.com/openai/${PN}/archive/refs/tags/rust-v${PV}.tar.gz -> ${P}.tar.gz https://github.com/0x6d6e647a/mndz-overlay-assets/releases/download/codex-${PV}/${PN}-${PV}-crates.tar.xz https://github.com/0x6d6e647a/mndz-overlay-assets/releases/download/rusty-v8-${RUSTY_V8_VER}/rusty-v8-${RUSTY_V8_VER}-with-submodules.tar.xz https://commondatastorage.googleapis.com/chromium-browser-clang/Linux_x64/${CLANG_DIST} https://commondatastorage.googleapis.com/chromium-browser-clang/Linux_x64/${RUST_TC_DIST} ${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 Unicode-DFS-2016 WTFPL-2 ZLIB " SLOT="0" KEYWORDS="-* ~amd64" IUSE="bash-completion fish-completion test zsh-completion" RESTRICT="!test? ( test )" RDEPEND=" dev-libs/openssl:= sys-apps/bubblewrap " BDEPEND=" dev-build/gn dev-build/ninja dev-lang/python dev-libs/protobuf llvm-core/clang:22 virtual/pkgconfig " QA_FLAGS_IGNORED=" usr/bin/codex usr/bin/codex-code-mode-host " pkg_pretend() { check-reqs_pkg_pretend } pkg_setup() { check-reqs_pkg_setup rust_pkg_setup } src_unpack() { cargo_src_unpack mkdir -p "${WORKDIR}/rusty_v8" || die tar -C "${WORKDIR}/rusty_v8" --strip-components=1 \ -xf "${DISTDIR}/rusty-v8-${RUSTY_V8_VER}-with-submodules.tar.xz" || die mkdir -p "${WORKDIR}/chromium-clang" || die tar -C "${WORKDIR}/chromium-clang" \ -xf "${DISTDIR}/${CLANG_DIST}" || die # Archive root is VERSION + bin/ + lib/ (Chromium layout). Do not # --strip-components=1: that drops VERSION (gn rust.gni reads it) and # flattens bin/lib so rustc cannot find librustc_driver. mkdir -p "${WORKDIR}/rusty_v8/third_party/rust-toolchain" || die tar -C "${WORKDIR}/rusty_v8/third_party/rust-toolchain" \ -xf "${DISTDIR}/${RUST_TC_DIST}" || die [[ -f ${WORKDIR}/rusty_v8/third_party/rust-toolchain/VERSION ]] || die "Chromium rust-toolchain VERSION missing after unpack" [[ -x ${WORKDIR}/rusty_v8/third_party/rust-toolchain/bin/rustc ]] || die "Chromium rust-toolchain bin/rustc missing after unpack" # rusty_v8 tools/rust_toolchain.py skips GCS if this sentinel equals the # exact object URL (no trailing newline). printf '%s' \ "https://storage.googleapis.com/chromium-browser-clang/Linux_x64/${RUST_TC_DIST}" \ >"${WORKDIR}/rusty_v8/third_party/rust-toolchain/.rusty_v8_version" || die } src_prepare() { default local marker='protoc_bin_vendored::protoc_bin_path' local build_rs="${S}/code-mode-protocol/build.rs" grep -q "${marker}" "${build_rs}" || die "vendored protoc marker missing from ${build_rs}; update src_prepare" # Point tonic at system protoc ($PROTOC or /usr/bin/protoc). Keep the # protoc-bin-vendored crates in the lock/tarball so --offline --locked resolves. # '#' delimiter: the replacement contains '|_|', which breaks s||| . # Match the trailing '?' so a String is not used as Result. sed -i \ -e "s#${marker}()?#std::env::var(\"PROTOC\").unwrap_or_else(|_| \"/usr/bin/protoc\".into())#" \ "${build_rs}" || die # Windows-only microsoft/mxc crates are omitted from GIT_CRATES, but Cargo # still resolves their workspace git pins --offline. Point them at empty stubs. mkdir -p "${WORKDIR}/appcontainer_common_stub/src" || die cat > "${WORKDIR}/appcontainer_common_stub/Cargo.toml" <<-EOF || die [package] name = "appcontainer_common" version = "0.8.0" edition = "2021" EOF : > "${WORKDIR}/appcontainer_common_stub/src/lib.rs" || die mkdir -p "${WORKDIR}/learning_mode_windows_stub/src" || die cat > "${WORKDIR}/learning_mode_windows_stub/Cargo.toml" <<-EOF || die [package] name = "learning_mode_windows" version = "0.8.0" edition = "2021" EOF : > "${WORKDIR}/learning_mode_windows_stub/src/lib.rs" || die # crates.io v8 is not a from-source tree; path-patch onto the rusty_v8 snapshot. # cargo.eclass writes [patch] into CARGO_HOME/config.toml. On Cargo 1.97 that # does not satisfy a git dependency listed in the workspace [patch.crates-io] # table. Rewrite crossterm, tokio-tungstenite, and tungstenite from this # ebuild's GIT_CRATES entry so the commit and checkout path stay together. local crate_commit crate_dir local crossterm_commit crossterm_dir local tokio_tungstenite_commit tokio_tungstenite_dir local tungstenite_commit tungstenite_dir codex_git_crate() { local name=$1 spec [[ -v GIT_CRATES["${name}"] ]] || die "GIT_CRATES missing ${name}" spec="${GIT_CRATES["${name}"]}" IFS=';' read -r _ crate_commit crate_dir _ <<< "${spec}" [[ -n ${crate_commit} && -n ${crate_dir} ]] || die "GIT_CRATES ${name} has no commit and directory" crate_dir=${crate_dir//%commit%/${crate_commit}} } codex_git_crate crossterm crossterm_commit="${crate_commit}" crossterm_dir="${crate_dir}" codex_git_crate tokio-tungstenite tokio_tungstenite_commit="${crate_commit}" tokio_tungstenite_dir="${crate_dir}" codex_git_crate tungstenite tungstenite_commit="${crate_commit}" tungstenite_dir="${crate_dir}" python3 - "${WORKDIR}" "${S}/Cargo.toml" \ crossterm "${crossterm_commit}" "${WORKDIR}/${crossterm_dir}" \ tokio-tungstenite "${tokio_tungstenite_commit}" "${WORKDIR}/${tokio_tungstenite_dir}" \ tungstenite "${tungstenite_commit}" "${WORKDIR}/${tungstenite_dir}" \ <<'PY' || die "rewrite Cargo.toml git crates to paths" import re import sys from pathlib import Path workdir, toml_path = sys.argv[1], Path(sys.argv[2]) pin_args = sys.argv[3:] if len(pin_args) % 3 != 0: sys.exit("git pin arguments are not name, commit, path triples") text = toml_path.read_text() def rewrite_pin(text, name, commit, path): pattern = re.compile( rf'^(?P[ \t]*){re.escape(name)}[ \t]*=[ \t]*\{{(?=[^\n]*\bgit[ \t]*=)[^\n]*\brev[ \t]*=[ \t]*"{re.escape(commit)}"[^\n]*\}}$', re.MULTILINE, ) def repl(match): indent = match.group("indent") return f'{indent}{name} = {{ path = "{path}" }}' new, count = pattern.subn(repl, text) if count == 0: sys.exit( "expected git crate snippet missing from Cargo.toml: " f"{name} rev {commit}" ) return new for index in range(0, len(pin_args), 3): pin_name, pin_commit, pin_path = pin_args[index : index + 3] text = rewrite_pin(text, pin_name, pin_commit, pin_path) subs = [ ( 'nucleo = { git = "https://github.com/helix-editor/nucleo.git", rev = "4253de9faabb4e5c6d81d946a5e35a90f87347ee" }', f'nucleo = {{ path = "{workdir}/nucleo-4253de9faabb4e5c6d81d946a5e35a90f87347ee" }}', ), ( 'runfiles = { git = "https://github.com/dzbarsky/rules_rust", rev = "b56cbaa8465e74127f1ea216f813cd377295ad81" }', f'runfiles = {{ path = "{workdir}/rules_rust-b56cbaa8465e74127f1ea216f813cd377295ad81/rust/runfiles" }}', ), ( 'appcontainer_common = { git = "https://github.com/microsoft/mxc", rev = "6cd3d58f05d3447e67109cfb75e042803b843ca4" }', f'appcontainer_common = {{ path = "{workdir}/appcontainer_common_stub" }}', ), ( 'learning_mode_windows = { git = "https://github.com/microsoft/mxc", rev = "6cd3d58f05d3447e67109cfb75e042803b843ca4" }', f'learning_mode_windows = {{ path = "{workdir}/learning_mode_windows_stub" }}', ), ] for old, new in subs: if old not in text: sys.exit(f"expected git crate snippet missing from Cargo.toml: {old}") text = text.replace(old, new) needle = "[patch.crates-io]\n" if needle not in text: sys.exit("Cargo.toml missing [patch.crates-io]") text = text.replace( needle, needle + f'v8 = {{ path = "{workdir}/rusty_v8" }}\n', 1, ) toml_path.write_text(text) PY local git_toml for git_toml in \ "${WORKDIR}/${crossterm_dir}/Cargo.toml" \ "${WORKDIR}/${tokio_tungstenite_dir}/Cargo.toml" \ "${WORKDIR}/${tungstenite_dir}/Cargo.toml" \ "${WORKDIR}/nucleo-4253de9faabb4e5c6d81d946a5e35a90f87347ee/Cargo.toml" \ "${WORKDIR}/nucleo-4253de9faabb4e5c6d81d946a5e35a90f87347ee/matcher/Cargo.toml" \ "${WORKDIR}/rules_rust-b56cbaa8465e74127f1ea216f813cd377295ad81/rust/runfiles/Cargo.toml" \ "${WORKDIR}/rusty_v8/Cargo.toml" do [[ -f ${git_toml} ]] || die "unpacked git crate missing ${git_toml}" done } src_compile() { export V8_FROM_SOURCE=1 # rusty_v8 gn uses this tree; do not export it as CC/CXX — cc-rs (ring) # would then compile with Chromium clang, which rejects Portage CFLAGS # such as -mabm. export CLANG_BASE_PATH="${WORKDIR}/chromium-clang" # Chromium clang has no 64-bit libclang.so; Gentoo clang:22 lib64 does. export LIBCLANG_PATH="/usr/lib/llvm/22/$(get_libdir)" export RUST_MIN_STACK=16777216 cargo_src_compile --bin codex --bin codex-code-mode-host } src_test() { export V8_FROM_SOURCE=1 export RUST_MIN_STACK=16777216 # Skip network, sandbox, and known-failing crates under Portage FEATURES=test. # Remaining workspace members run via cargo.eclass. local CARGO_SKIP_TESTS=( # network codex-login # sandbox / bubblewrap host assumptions codex-linux-sandbox ) export CARGO_SKIP_TESTS cargo_src_test } src_install() { dobin "$(cargo_target_dir)/codex" dobin "$(cargo_target_dir)/codex-code-mode-host" local cdir cdir="$(cargo_target_dir)" if use bash-completion; then "${cdir}/codex" completion bash > codex.bash || die newbashcomp codex.bash codex fi if use zsh-completion; then "${cdir}/codex" completion zsh > codex.zsh || die newzshcomp codex.zsh _codex fi if use fish-completion; then "${cdir}/codex" completion fish > codex.fish || die newfishcomp codex.fish codex.fish fi }