Skip to content

Conversation

ZZBaron
Copy link
Contributor

@ZZBaron ZZBaron commented Sep 11, 2025

This PR introduces comprehensive support for the Nix package manager in XMake, enabling users to find, install, and use packages from the Nixpkgs ecosystem.

Note: This is a re-submission of #6790 with a clean commit history. The previous PR accidentally included upstream commits during sync attempts, making the git history messy. Rather than continuing to troubleshoot the rebase issues, I've created a fresh branch with only the Nix package manager implementation to make review easier.
This PR contains the same Nix integration functionality as before, with the adjustments requested during the initial review.

Core Functionality

Package Detection: Automatically detects Nix installations in common locations
Package Finding: Searches through available Nix store paths and can build packages on-demand
Package Installation: Supports both modern Nix (with flakes) and legacy nix-env workflows
Package Search: Comprehensive search functionality with JSON parsing for modern Nix

used like:

add_requires("nix::zlib.dev", {alias = "zlib"})
add_requires("nix::openssl")
add_requires("nix::boost.dev")

Key Components

find_nix.lua: Tool detection module that handles various Nix installation scenarios
nix/find_package.lua: Main package resolution logic with intelligent path scanning
nix/install_package.lua: Package installation using both modern and legacy Nix commands
nix/search_package.lua: Package search functionality with fallback support

Smart Package Resolution

Scans existing Nix store paths from environment ($PATH, $NIX_PROFILES, etc.)
Falls back to building packages on-demand if not found in available paths
Supports both modern Nix flakes (nix build nixpkgs#package) and legacy (nix-build -A package)
Integrates with pkg-config when available for better metadata extraction

if not opt.program then
opt.paths = opt.paths or {}
local nix_paths = {
"/nix/var/nix/profiles/default/bin", -- multi-user installation
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

only for nixos?

"/nix/var/nix/profiles/default/bin", -- multi-user installation
"/home/" .. (os.getenv("USER") or "user") .. "/.nix-profile/bin", -- single user installation
"/run/current-system/sw/bin", -- only on nixos, maybe separate nix logic from nixos logic?
"/usr/local/bin", -- default path of nix when compiling nix from source
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can improve linuxos.name() to check nixos.

function linuxos.name()

then add paths for nixos

if linuxos.name() == "nixos" then
    table.insert(nix_paths, "xxx")
end


-- add common nix installation paths if no specific program is given
if not opt.program then
opt.paths = opt.paths or {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

opt.paths = table.wrap(paths)

-- Also check for manifest (generation info)
local manifest = path.join(location, "manifest.nix")
if os.isfile(manifest) then
local manifest_content = try {function()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove try block

if #pcfiles > 0 then
-- Use pkg-config to get proper info
local old_path = os.getenv("PKG_CONFIG_PATH")
os.setenv("PKG_CONFIG_PATH", pcdir .. (old_path and (":" .. old_path) or ""))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please do not set envs globals, you can pass configdirs arguments to find_package_from_pkgconfig

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

local configdirs = table.wrap(opt.configdirs)

if old_path then
os.setenv("PKG_CONFIG_PATH", old_path)
else
os.setenv("PKG_CONFIG_PATH", nil)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and here

raise("nix not found!")
end

-- check architecture (nix supports cross compilation but for simplicity...)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but you used is_cross in find_package.

@waruqi waruqi added this to the v3.0.3 milestone Sep 11, 2025
}

-- NixOS-specific paths
if linuxos.name() == "nixos" then
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you need to improve linuxos.name() to check nixos, it is not implemented now.

@waruqi waruqi merged commit e6c0922 into xmake-io:dev Sep 12, 2025
22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants