Skip to content

Add inko recipe#32967

Merged
pavelzw merged 8 commits intoconda-forge:mainfrom
tdejager:inko
Apr 20, 2026
Merged

Add inko recipe#32967
pavelzw merged 8 commits intoconda-forge:mainfrom
tdejager:inko

Conversation

@tdejager
Copy link
Copy Markdown
Contributor

@tdejager tdejager commented Apr 14, 2026

Adds a recipe for inko, a language for building concurrent software with confidence. Inko compiles to machine code via LLVM 18 and ships a standard library and a static runtime.

Patch: 0001-locate-std-and-runtime-relative-to-executable.patch

Inko's Config::new() upstream bakes the absolute install paths of the standard library and runtime into the compiler binary via env!("INKO_STD") / env!("INKO_RT"). That breaks under rattlers binary prefix relocation: rattler's copy_and_replace_cstring_placeholder rewrites the C-string region in place, the tail content shifts left, and the trailing NUL padding both clobbers adjacent linker-merged short string literals (e.g. `pub const DEP: &str = "dep"` ends up reading three NULs) and leaves INKO_RT itself with embedded NULs that fail any subsequent CString::new.

The patch adds a small locate_sibling() helper to compiler/src/config.rs that resolves both paths at runtime with the following precedence:

  1. $INKO_STD / $INKO_RT environment variables (explicit override)
  2. <exe_dir>/../lib/inko/{std,runtime} if it exists, derived from std::env::current_exe()
  3. The compile-time env!() value, as a last resort for cargo run from a source checkout

Test plan

  • pixi run lintrecipes/inko is in fine form
  • Local osx-arm64 build via pixi run build-osx osx_arm64
  • Test phase passes including inko check hello.inko (the test that originally surfaced the prefix-relocation bug)
  • Inspected the rebuilt binary with a Python script: 0 placehold_placehold occurrences, 0 /lib/inko/runtime baked literals, 2 /nonexistent/inko fallback literals
  • CI green on linux-64 and linux-aarch64 (have not been able to test locally)

Checklist

  • Title of this PR is meaningful
  • License file is packaged (LICENSE + THIRDPARTY.yml from cargo-bundle-licenses)
  • Source is from official source (GitHub release tarball)
  • Package does not vendor other packages
  • Static library license is packaged (the static runtime is built from the same MPL-2.0 source as inko itself; third-party Rust crate licenses are aggregated into THIRDPARTY.yml)
  • Package ships static libraries (libinko.a) — this is a language runtime that the inko compiler links into every program it produces, so the static-only distribution is intentional and not subject to CFEP-18's "use shared libs where possible" guidance
  • Build number is 0
  • A tarball (url) is used
  • Maintainer (myself) is willing to be listed

Inko is a language for building concurrent software with confidence,
compiled to machine code via LLVM 18. The recipe builds the compiler
with the conda-forge Rust toolchain, links against conda-forge's
llvmdev, and installs the standard library and static runtime to
$PREFIX/lib/inko/{std,runtime}.

Includes a patch to compiler/src/config.rs that resolves INKO_STD and
INKO_RT at runtime via env var override / current_exe()-relative
discovery / baked fallback, matching how rustc, zig, clang, ruby (with
LOAD_RELATIVE) and python locate their own bundled files. Without this
the absolute install paths baked by env\!() get corrupted by binary
prefix relocation, leaving trailing NUL bytes that break syscalls and
clobbering adjacent string literals via linker suffix-merging.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@conda-forge-admin
Copy link
Copy Markdown
Contributor

Hi! This is the friendly automated conda-forge-linting service.

I just wanted to let you know that I linted all conda-recipes in your PR (recipes/inko/recipe.yaml) and found it was in an excellent condition.

Tim de Jager and others added 3 commits April 14, 2026 13:38
Local osx-arm64 builds passed because Apple's ld64 implicitly searches
/usr/lib, where macOS ships libxml2 and zlib system libraries. Linux
rust-lld only searches -L paths, so it can't find the unversioned
linker symlinks and fails with:

  rust-lld: error: unable to find library -lz
  rust-lld: error: unable to find library -lxml2

`libzlib` is runtime-only on conda-forge; `zlib` is the package that
provides the `libz.so` symlink and headers for linking. And libxml2
was split in 2.15: the new `libxml2` is a metapackage of tools plus
`libxml2-16` runtime with no `libxml2.so` symlink. Pin to `<2.15` to
pick up the last combined release until llvm-sys stops forwarding
`-lxml2` or a conda-forge devel split appears.

Tested locally on osx-arm64: build and rattler-build test both pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The top-level libxml2 package is just tools + libxml2-16 post-2.15;
depending on libxml2-16 directly skips the tools we don't need.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Move build logic from build.sh into the recipe via interpreter: nu.
  No behaviour change — same cargo auditable build, same install
  layout — but the recipe is now self-contained and cross-platform
  friendly via $nu.os-info.name.

- Fix Linux link failure by creating a libxml2.so/libxml2.dylib
  shim in a temp directory pointing at libxml2.16.dylib /
  libxml2.so.16 and adding it to RUSTFLAGS. llvm-sys forwards
  `-lxml2` to the final link because llvmdev was built with XML
  remark support, but libxml2-16 on conda-forge ships only the
  versioned runtime with no unversioned linker symlink.

- Add libxml2-16 to requirements.run. It does not set a
  run_exports, so without an explicit entry the test env does not
  get the runtime dylib and `inko --help` aborts with "Library not
  loaded: libxml2.16.dylib".

- Add nushell to requirements.build (needed by interpreter: nu).

- Delete build.sh; everything lives inline in recipe.yaml now.

Tested locally on osx-arm64: rattler-build build + test both pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@tdejager tdejager marked this pull request as ready for review April 14, 2026 12:11
Comment thread recipes/inko/recipe.yaml Outdated
Tim de Jager and others added 4 commits April 14, 2026 14:22
libxml2-devel is the conda-forge split that actually ships the
unversioned libxml2.so / libxml2.dylib symlink plus headers, with
libxml2-16 (the versioned runtime) as a hard dep. Adding it to host
lets `-lxml2` resolve against $PREFIX/lib directly and drops the
custom shim-symlink + RUSTFLAGS manipulation from the build script.

libxml2-devel has no run_exports either, so keep libxml2-16 in run
explicitly so the runtime dylib lands in the test env.

Tested locally on osx-arm64: build + test both pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
libxml2-devel sets a run_exports that pulls in libxml2-16 >=2.15.2
automatically — the entry I added earlier on the assumption that
neither package had run_exports was wrong (pixi search said
"run exports not available in repodata", which turns out to mean
"can't be surfaced by pixi search", not "does not exist").

Verified locally: build and tests pass with just libxml2-devel in
host and nothing explicit in run — rattler-build's finalized run
deps show libxml2-16 >=2.15.2 getting pulled in from the
libxml2-devel run_exports.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
inkwell's version-specific feature flags (llvm18-0 here) generate
bindings against a single LLVM major version that aren't forward-
compatible. Document the lockstep dependency so the next maintainer
doesn't wonder.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@tdejager
Copy link
Copy Markdown
Contributor Author

@conda-forge/help-rust, ready for review!

@pavelzw pavelzw merged commit 43e291d into conda-forge:main Apr 20, 2026
9 of 11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants