From 7c30362ef0ba881c0c5dc241bef7cedbc5d45692 Mon Sep 17 00:00:00 2001 From: Luca Ruperto Date: Mon, 24 Aug 2026 13:48:48 +0200 Subject: [PATCH] add support for buildNimPackage --- CHANGELOG.md | 1 + README.md | 1 + src/cli.rs | 1 + src/codegen/mod.rs | 11 +++++-- src/codegen/nim.rs | 59 +++++++++++++++++++++++++++++++++++ src/main.rs | 9 +++++- tests/cmd/nim.out/default.nix | 38 ++++++++++++++++++++++ tests/cmd/nim.toml | 5 +++ 8 files changed, 122 insertions(+), 3 deletions(-) create mode 100644 src/codegen/nim.rs create mode 100644 tests/cmd/nim.out/default.nix create mode 100644 tests/cmd/nim.toml diff --git a/CHANGELOG.md b/CHANGELOG.md index 337f854c..f204ca5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Features - Add support for `buildNpmPackage` +- Add support for `buildNimPackage` ## v0.3.6 - 2026-05-15 diff --git a/README.md b/README.md index ae5f67f5..5c5b47e3 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,7 @@ Options: - `buildPythonApplication` and `buildPythonPackage` - `buildGoModule` - `buildNpmPackage` +- `buildNimPackage` ### Supported fetchers diff --git a/src/cli.rs b/src/cli.rs index dc63d2f8..829ce6ea 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -75,6 +75,7 @@ pub struct Opts { pub enum BuilderFunction { BuildGoModule, BuildNpmPackage, + BuildNimPackage, BuildPythonApplication, BuildPythonPackage, BuildRustPackage, diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index ccc11130..92539567 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -1,5 +1,6 @@ pub mod drv; pub mod go; +pub mod nim; pub mod npm; pub mod python; pub mod rust; @@ -26,8 +27,8 @@ use tracing::warn; use crate::{ cli::CargoVendor, codegen::{ - drv::MkDerivation, go::BuildGoModule, npm::BuildNpmPackage, python::BuildPythonPackage, - rust::BuildRustPackage, + drv::MkDerivation, go::BuildGoModule, nim::BuildNimPackage, npm::BuildNpmPackage, + python::BuildPythonPackage, rust::BuildRustPackage, }, frontend::FrontendDispatch, inputs::{AllInputs, write_all_lambda_inputs, write_inputs, write_lambda_input}, @@ -44,6 +45,7 @@ use crate::{ #[display("{0}")] pub enum BuilderDispatch { BuildGoModule(BuildGoModule), + BuildNimPackage(BuildNimPackage), BuildNpmPackage(BuildNpmPackage), BuildPythonPackage(BuildPythonPackage), BuildRustPackage(BuildRustPackage), @@ -80,6 +82,7 @@ pub struct SourceLayout { pub has_cmake: bool, pub has_go: bool, pub has_meson: bool, + pub has_nim: bool, pub has_npm: bool, pub has_npm_lock: bool, pub has_python: bool, @@ -474,6 +477,10 @@ impl SourceLayout { has_cmake: src_dir.join("CMakeLists.txt").is_file(), has_go: src_dir.join("go.mod").is_file(), has_meson: src_dir.join("meson.build").is_file(), + has_nim: std::fs::read_dir(src_dir).is_ok_and(|dir| { + dir.filter_map(Result::ok) + .any(|entry| entry.path().extension().is_some_and(|ext| ext == "nimble")) + }), has_npm: src_dir.join("package.json").is_file(), has_npm_lock: src_dir.join("package-lock.json").is_file() || src_dir.join("npm-shrinkwrap.json").is_file(), diff --git a/src/codegen/nim.rs b/src/codegen/nim.rs new file mode 100644 index 00000000..c548b00d --- /dev/null +++ b/src/codegen/nim.rs @@ -0,0 +1,59 @@ +use std::{ + fmt::Write as _, + path::{Path, PathBuf}, +}; + +use anyhow::Result; +use parse_display::Display; + +use crate::codegen::{Builder, Codegen}; + +#[derive(Clone, Copy, Display)] +#[display("buildNimPackage")] +pub struct BuildNimPackage; + +impl Builder for BuildNimPackage { + fn function(&self) -> &'static str { + "buildNimPackage" + } + + fn explicit_strict_deps(&self) -> bool { + true + } + + async fn after_src(&self, cg: &mut Codegen<'_>) -> Result { + let mut out = String::new(); + + let lock_path = get_lock_path(cg.out_dir); + + writeln!( + out, + " # Generate lockfile with: nix run -f . nim_lk ./result | jq --sort-keys > {lock_path}" + )?; + writeln!(out, " lockFile = ./lock.json;\n")?; + + if let Some(file) = find_nimble_file(cg.src_dir) { + writeln!(out, " nimbleFile = \"{file}\";\n")?; + } + + writeln!(out, " nimFlags = [ ];\n")?; + + Ok(out) + } +} + +fn get_lock_path(out_dir: Option<&Path>) -> String { + out_dir + .map(|d| d.join("lock.json")) + .unwrap_or_else(|| PathBuf::from("lock.json")) + .display() + .to_string() +} + +fn find_nimble_file(src_dir: &Path) -> Option { + std::fs::read_dir(src_dir) + .ok()? + .filter_map(Result::ok) + .find(|entry| entry.path().extension().is_some_and(|ext| ext == "nimble")) + .map(|entry| entry.file_name().to_string_lossy().into_owned()) +} diff --git a/src/main.rs b/src/main.rs index 9dbbee78..ff85e749 100644 --- a/src/main.rs +++ b/src/main.rs @@ -40,7 +40,8 @@ use crate::{ cmd::{NIX, NURL}, codegen::{ BuilderDispatch, Codegen, SourceLayout, drv::MkDerivation, go::BuildGoModule, - npm::BuildNpmPackage, python::BuildPythonPackage, rust::BuildRustPackage, + nim::BuildNimPackage, npm::BuildNpmPackage, python::BuildPythonPackage, + rust::BuildRustPackage, }, fetcher::{Fetcher, FetcherDispatch, PackageInfo, PypiFormat, Revisions, Version}, frontend::{Frontend, headless, readline}, @@ -385,6 +386,7 @@ async fn run() -> Result<()> { let builder = match (opts.builder, opts.cargo_vendor) { (Some(builder), rust @ Some(vendor)) if layout.has_cargo => match builder { BuilderFunction::BuildGoModule => BuildGoModule.into(), + BuilderFunction::BuildNimPackage => BuildNimPackage.into(), BuilderFunction::BuildNpmPackage => BuildNpmPackage.into(), BuilderFunction::BuildPythonApplication => BuildPythonPackage::new(true, rust).into(), BuilderFunction::BuildPythonPackage => BuildPythonPackage::new(false, rust).into(), @@ -396,6 +398,7 @@ async fn run() -> Result<()> { let rust = layout.has_cargo.then_some(CargoVendor::FetchCargoVendor); match builder { BuilderFunction::BuildGoModule => BuildGoModule.into(), + BuilderFunction::BuildNimPackage => BuildNimPackage.into(), BuilderFunction::BuildNpmPackage => BuildNpmPackage.into(), BuilderFunction::BuildPythonApplication => { BuildPythonPackage::new(true, rust).into() @@ -414,6 +417,10 @@ async fn run() -> Result<()> { builders.push(BuildGoModule.into()); } + if layout.has_nim { + builders.push(BuildNimPackage.into()); + } + if layout.has_cargo { let cargo_deps_options: &[_] = match rust { Some(vendor) => &[vendor], diff --git a/tests/cmd/nim.out/default.nix b/tests/cmd/nim.out/default.nix new file mode 100644 index 00000000..6c37831f --- /dev/null +++ b/tests/cmd/nim.out/default.nix @@ -0,0 +1,38 @@ +{ + lib, + buildNimPackage, + fetchFromGitHub, + nix-update-script, +}: + +buildNimPackage (finalAttrs: { + pname = "choosenim"; + version = "0.8.16"; + __structuredAttrs = true; + strictDeps = true; + + src = fetchFromGitHub { + owner = "nim-lang"; + repo = "choosenim"; + tag = "v${finalAttrs.version}"; + hash = "sha256-Sa1T7uZDIZHsakyI7QeJEWrHW7rSarFDniY9FaTBL7Q="; + }; + + # Generate lockfile with: nix run -f . nim_lk ./result | jq --sort-keys > ./lock.json + lockFile = ./lock.json; + + nimbleFile = "choosenim.nimble"; + + nimFlags = [ ]; + + passthru.updateScript = nix-update-script { }; + + meta = { + description = "Official tool for easily installing and managing multiple versions of the Nim programming language"; + homepage = "https://github.com/nim-lang/choosenim"; + changelog = "https://github.com/nim-lang/choosenim/blob/${finalAttrs.src.rev}/changelog.markdown"; + license = lib.licenses.bsd3; + maintainers = with lib.maintainers; [ alice ]; + mainProgram = "choosenim"; + }; +}) diff --git a/tests/cmd/nim.toml b/tests/cmd/nim.toml new file mode 100644 index 00000000..27624276 --- /dev/null +++ b/tests/cmd/nim.toml @@ -0,0 +1,5 @@ +args = [ + "--headless", + "--url=https://github.com/nim-lang/choosenim", + "--rev=v0.8.16", +]