-
Notifications
You must be signed in to change notification settings - Fork 0
Expose runtime dependencies of Nix package properly #22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
ofalvai
wants to merge
6
commits into
main
Choose a base branch
from
push-ywnvpnmmuqot
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
02423dd
Fix formatting task
ofalvai 289e8e8
Expose runtime dependencies of Nix package properly
ofalvai 92851b4
Don't expose nixpkgs' glibc
ofalvai fac733f
wip: clang
ofalvai 8516ce4
Add more Ruby gem tests
ofalvai 231c536
Merge branch 'main' into push-ywnvpnmmuqot
ofalvai File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,108 @@ | ||
| local M = {} | ||
|
|
||
| -- The main Nix package has runtime deps (other Nix store objects), which provide the usual | ||
| -- C headers, shared libraries and pkgconfig files. This function queries those runtime deps | ||
| -- and constructs the necessary env vars to make those dependencies available at runtime. | ||
| -- In practice, this is important when running package manager binaries that try to build native code | ||
| -- (e.g. Ruby gems that compile C extensions). | ||
| function M.get_env_vars(install_path, tool, version, os_type) | ||
| local file = require("file") | ||
| local cmd = require("cmd") | ||
|
|
||
| local result_path = file.join_path(install_path, "result") | ||
| local requisites = cmd.exec("nix-store --query --requisites " .. result_path) | ||
|
|
||
| if requisites:match("error") or requisites:match("failed") then | ||
| error("Failed to query runtime deps for " .. tool .. "@" .. version .. ": " .. requisites) | ||
| end | ||
|
|
||
| local store_paths = {} | ||
| for store_path in string.gmatch(requisites, "[^%s]+") do -- poor man's strings.Split(requisites, "\n") | ||
| table.insert(store_paths, store_path) | ||
| end | ||
|
|
||
| local lib_paths = M.find_lib_paths(store_paths, file, cmd) | ||
| local pkgconfig_paths = M.find_pkgconfig_paths(store_paths, file, cmd) | ||
|
|
||
| local env_vars = {} | ||
| local lib_env_vars = M.create_library_env_vars(lib_paths, os_type) | ||
| local pkgconfig_env_vars = M.create_pkgconfig_env_vars(pkgconfig_paths) | ||
|
|
||
| for _, var in ipairs(lib_env_vars) do | ||
| table.insert(env_vars, var) | ||
| end | ||
| for _, var in ipairs(pkgconfig_env_vars) do | ||
| table.insert(env_vars, var) | ||
| end | ||
|
|
||
| return env_vars | ||
| end | ||
|
|
||
| -- TODO: file.exists() doesn't exist 🤷 | ||
| -- https://github.com/jdx/mise/pull/6754 | ||
| -- Can be replaced once our pinned mise version is bumped again | ||
| function M.dir_exists(path, cmd_module) | ||
| local check_cmd = "if [ -d " .. path .. " ]; then echo 'exists'; fi" | ||
| local check_output = cmd_module.exec(check_cmd) | ||
| return check_output:match("exists") ~= nil | ||
| end | ||
|
|
||
| -- Finds all lib directories in the given store paths | ||
| function M.find_lib_paths(store_paths, file_module, cmd_module) | ||
| local lib_paths = {} | ||
| for _, store_path in ipairs(store_paths) do | ||
| local lib_path = file_module.join_path(store_path, "lib") | ||
| if M.dir_exists(lib_path, cmd_module) then | ||
| table.insert(lib_paths, lib_path) | ||
| end | ||
| end | ||
| return lib_paths | ||
| end | ||
|
|
||
| -- Finds all lib/pkgconfig directories in the given store paths | ||
| function M.find_pkgconfig_paths(store_paths, file_module, cmd_module) | ||
| local pkgconfig_paths = {} | ||
| for _, store_path in ipairs(store_paths) do | ||
| local pkgconfig_path = file_module.join_path(store_path, "lib/pkgconfig") | ||
| if M.dir_exists(pkgconfig_path, cmd_module) then | ||
| table.insert(pkgconfig_paths, pkgconfig_path) | ||
| end | ||
| end | ||
| return pkgconfig_paths | ||
| end | ||
|
|
||
| -- Exposes shared library paths for the (platform-specific) dynamic linker | ||
| function M.create_library_env_vars(lib_paths, os_type) | ||
| local env_vars = {} | ||
| local key = nil | ||
|
|
||
| if os_type == "linux" then | ||
| key = "LD_LIBRARY_PATH" | ||
| elseif os_type == "darwin" then | ||
| key = "DYLD_LIBRARY_PATH" | ||
| else | ||
| error("Unsupported architecture: " .. os_type) | ||
| end | ||
|
|
||
| for _, lib_path in ipairs(lib_paths) do | ||
| local is_linux_glibc = os_type == "linux" and lib_path:match("glibc") | ||
| local is_darwin_llvm = os_type == "darwin" and (lib_path:match("llvm") or lib_path:match("clang")) | ||
| local is_linux_libyaml = os_type == "linux" and lib_path:match("libyaml") | ||
| -- if not is_linux_glibc and not is_darwin_llvm then | ||
| if is_linux_libyaml then | ||
| table.insert(env_vars, { key = key, value = lib_path }) | ||
| end | ||
| end | ||
|
|
||
| return env_vars | ||
| end | ||
|
|
||
| function M.create_pkgconfig_env_vars(pkgconfig_paths) | ||
| local env_vars = {} | ||
| for _, pkgconfig_path in ipairs(pkgconfig_paths) do | ||
| table.insert(env_vars, { key = "PKG_CONFIG_PATH", value = pkgconfig_path }) | ||
| end | ||
| return env_vars | ||
| end | ||
|
|
||
| return M |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,41 +1,41 @@ | ||
| local M = {} | ||
|
|
||
| M.sample_index = { | ||
| pkgs = { | ||
| ruby = { | ||
| ["3.3.9"] = { | ||
| nixpkgs_commit = "abc123def456", | ||
| commit_timestamp = "2025-01-15T12:00:00+00:00", | ||
| store_paths = { | ||
| ["x86_64-linux"] = "/nix/store/hash1-ruby-3.3.9", | ||
| ["aarch64-darwin"] = "/nix/store/hash2-ruby-3.3.9", | ||
| }, | ||
| }, | ||
| ["3.3.8"] = { | ||
| nixpkgs_commit = "def456abc789", | ||
| commit_timestamp = "2025-01-14T12:00:00+00:00", | ||
| store_paths = { | ||
| ["x86_64-linux"] = "/nix/store/hash3-ruby-3.3.8", | ||
| -- Note: aarch64-darwin entry is intentionally missing for testing | ||
| }, | ||
| }, | ||
| }, | ||
| python = { | ||
| ["3.12.1"] = { | ||
| nixpkgs_commit = "ghi789jkl012", | ||
| commit_timestamp = "2025-01-16T12:00:00+00:00", | ||
| store_paths = { | ||
| ["x86_64-linux"] = "/nix/store/hash4-python-3.12.1", | ||
| ["aarch64-darwin"] = "/nix/store/hash5-python-3.12.1", | ||
| }, | ||
| }, | ||
| }, | ||
| }, | ||
| pkgs = { | ||
| ruby = { | ||
| ["3.3.9"] = { | ||
| nixpkgs_commit = "abc123def456", | ||
| commit_timestamp = "2025-01-15T12:00:00+00:00", | ||
| store_paths = { | ||
| ["x86_64-linux"] = "/nix/store/hash1-ruby-3.3.9", | ||
| ["aarch64-darwin"] = "/nix/store/hash2-ruby-3.3.9", | ||
| }, | ||
| }, | ||
| ["3.3.8"] = { | ||
| nixpkgs_commit = "def456abc789", | ||
| commit_timestamp = "2025-01-14T12:00:00+00:00", | ||
| store_paths = { | ||
| ["x86_64-linux"] = "/nix/store/hash3-ruby-3.3.8", | ||
| -- Note: aarch64-darwin entry is intentionally missing for testing | ||
| }, | ||
| }, | ||
| }, | ||
| python = { | ||
| ["3.12.1"] = { | ||
| nixpkgs_commit = "ghi789jkl012", | ||
| commit_timestamp = "2025-01-16T12:00:00+00:00", | ||
| store_paths = { | ||
| ["x86_64-linux"] = "/nix/store/hash4-python-3.12.1", | ||
| ["aarch64-darwin"] = "/nix/store/hash5-python-3.12.1", | ||
| }, | ||
| }, | ||
| }, | ||
| }, | ||
| } | ||
|
|
||
| M.sample_json = function() | ||
| local json = require("json") | ||
| return json.encode(M.sample_index) | ||
| local json = require("json") | ||
| return json.encode(M.sample_index) | ||
| end | ||
|
|
||
| return M |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,36 +1,37 @@ | ||
| local M = {} | ||
|
|
||
| function M.mock_file_module() | ||
| return { | ||
| read = function(path) | ||
| return '{"pkgs":{}}' | ||
| end, | ||
| join_path = function(...) | ||
| return table.concat({ ... }, "/") | ||
| end, | ||
| } | ||
| return { | ||
| read = function(path) | ||
| return '{"pkgs":{}}' | ||
| end, | ||
| join_path = function(...) | ||
| return table.concat({ ... }, "/") | ||
| end, | ||
| } | ||
| end | ||
|
|
||
| function M.mock_cmd_module() | ||
| return { | ||
| exec = function(cmd) | ||
| return "success" | ||
| end, | ||
| } | ||
| return { | ||
| exec = function(cmd) | ||
| return "success" | ||
| end, | ||
| } | ||
| end | ||
|
|
||
| function M.inject_modules(mocks) | ||
| for name, mock in pairs(mocks) do | ||
| package.loaded[name] = mock | ||
| end | ||
| for name, mock in pairs(mocks) do | ||
| package.loaded[name] = mock | ||
| end | ||
| end | ||
|
|
||
| function M.clear_modules() | ||
| package.loaded["file"] = nil | ||
| package.loaded["json"] = nil | ||
| package.loaded["cmd"] = nil | ||
| package.loaded["lib.nix"] = nil | ||
| package.loaded["lib.nixpkgs_mapping"] = nil | ||
| package.loaded["file"] = nil | ||
| package.loaded["json"] = nil | ||
| package.loaded["cmd"] = nil | ||
| package.loaded["lib.nix"] = nil | ||
| package.loaded["lib.nixpkgs_mapping"] = nil | ||
| package.loaded["lib.runtime_deps"] = nil | ||
| end | ||
|
|
||
| return M |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,20 +1,20 @@ | ||
| local M = {} | ||
|
|
||
| function M.create_runtime(opts) | ||
| opts = opts or {} | ||
| return { | ||
| osType = opts.osType or "linux", | ||
| archType = opts.archType or "amd64", | ||
| pluginDirPath = opts.pluginDirPath or "/tmp/test-plugin", | ||
| } | ||
| opts = opts or {} | ||
| return { | ||
| osType = opts.osType or "linux", | ||
| archType = opts.archType or "amd64", | ||
| pluginDirPath = opts.pluginDirPath or "/tmp/test-plugin", | ||
| } | ||
| end | ||
|
|
||
| function M.inject_runtime(runtime) | ||
| _G.RUNTIME = runtime | ||
| _G.RUNTIME = runtime | ||
| end | ||
|
|
||
| function M.restore_runtime() | ||
| _G.RUNTIME = nil | ||
| _G.RUNTIME = nil | ||
| end | ||
|
|
||
| return M |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐛 Bug
The runtime_deps module has a critical bug where library environment variables (LD_LIBRARY_PATH/DYLD_LIBRARY_PATH) are commented out in lib/runtime_deps.lua at lines 31-33. This means the get_env_vars() function will only return PKG_CONFIG_PATH variables, not the library paths needed for runtime dependencies to work properly. The library environment variables must be uncommented to expose shared libraries at runtime.
🤖 Prompt for AI Agents: