Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 66 additions & 20 deletions lib/deps_nix.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@ defmodule DepsNix do
defmodule Options do
@type t :: %Options{
envs: map(),
github_prefetcher: (String.t(), String.t(), String.t() -> String.t()),
github_prefetcher: (
String.t(),
String.t(),
String.t(),
String.t() | nil
-> {String.t(), String.t()}
),
output: String.t(),
app_config: boolean(),
app_config_path: String.t() | nil,
Expand Down Expand Up @@ -73,7 +79,7 @@ defmodule DepsNix do
|> to_opts()
end

def github_prefetcher(owner, repo, rev) do
def github_prefetcher(owner, repo, rev, subdir \\ nil) do
Mix.shell().info("deps_nix: fetching hash for GitHub dependency #{owner}/#{repo}")

with dir <- System.tmp_dir() |> realpath(),
Expand All @@ -85,7 +91,7 @@ defmodule DepsNix do
nar = ExNar.serialize!(path),
nar_hash = :crypto.hash(:sha256, nar),
hash = "sha256-" <> Base.encode64(nar_hash) do
{hash, find_builder_from_path(path)}
{hash, find_builder_from_path(path, subdir)}
end
end

Expand Down Expand Up @@ -141,10 +147,12 @@ defmodule DepsNix do
end
end

defp find_builder_from_path(path) do
defp find_builder_from_path(path, subdir) do
root = if subdir, do: Path.join(path, subdir), else: path

cond do
File.exists?(Path.join(path, "mix.exs")) -> "buildMix"
File.exists?(Path.join(path, "rebar.config")) -> "buildRebar3"
File.exists?(Path.join(root, "mix.exs")) -> "buildMix"
File.exists?(Path.join(root, "rebar.config")) -> "buildRebar3"
true -> :unknown
end
end
Expand All @@ -154,7 +162,7 @@ defmodule DepsNix do
%Options{
cwd: File.cwd!(),
envs: %{"prod" => :all},
github_prefetcher: &github_prefetcher/3
github_prefetcher: &github_prefetcher/4
}
end

Expand Down Expand Up @@ -259,28 +267,58 @@ defmodule DepsNix do
}/overlay.nix"
else
overrideFenixOverlay;
nativeDir = "${old.src}/native/${with builtins; head (attrNames (readDir "${old.src}/native"))}";
repoSubdir = if old ? sourceRoot then lib.removePrefix "source/" old.sourceRoot else "";
nativeRoot = if repoSubdir == "" then "${old.src}" else "${old.src}/${repoSubdir}";
nativeName = with builtins; head (attrNames (readDir "${nativeRoot}/native"));
nativeCargoLock = "${nativeRoot}/native/${nativeName}/Cargo.lock";
workspaceCrate = !builtins.pathExists nativeCargoLock;
nativeBuild =
if workspaceCrate then
{
src = old.src;
cargoLock.lockFile = "${old.src}/Cargo.lock";
buildAndTestSubdir = "${repoSubdir}/native/${nativeName}";
}
else
{
src = "${nativeRoot}/native/${nativeName}";
cargoLock.lockFile = nativeCargoLock;
};
nativeToolchainFile =
if builtins.pathExists "${nativeRoot}/rust-toolchain.toml" then
"${nativeRoot}/rust-toolchain.toml"
else if repoSubdir != "" && builtins.pathExists "${old.src}/rust-toolchain.toml" then
"${old.src}/rust-toolchain.toml"
else
null;
nativeToolchain =
if nativeToolchainFile == null then
null
else
(builtins.fromTOML (builtins.readFile nativeToolchainFile)).toolchain.channel;
fenix =
if toolchain == null then
extendedPkgs.fenix.stable
if nativeToolchain == null || nativeToolchain == "stable" then
extendedPkgs.fenix.stable
else
extendedPkgs.fenix.toolchainOf { channel = nativeToolchain; }
else
extendedPkgs.fenix.fromToolchainName toolchain;
native =
(
(extendedPkgs.makeRustPlatform {
inherit (fenix) cargo rustc;
}).buildRustPackage
{
inherit env buildInputs;
pname = "${old.beamModuleName}-native";
version = old.version;
src = nativeDir;
cargoLock = {
lockFile = "${nativeDir}/Cargo.lock";
};
nativeBuildInputs = [ extendedPkgs.cmake ] ++ nativeBuildInputs;
doCheck = false;
}
(
{
inherit env buildInputs;
pname = "${old.beamModuleName}-native";
version = old.version;
nativeBuildInputs = [ extendedPkgs.cmake ] ++ nativeBuildInputs;
doCheck = false;
}
// nativeBuild
)
).overrideAttrs
rustlerPrecompiledOverrides.${old.beamModuleName} or { };

Expand All @@ -303,6 +341,14 @@ defmodule DepsNix do
dest="''${dest#lib}"
ln -s "$lib" "priv/native/$dest"
done
''
+ lib.optionalString workspaceCrate ''

# The native crate is a Cargo workspace member: rustler's
# cargo metadata call needs the workspace root, which the
# mix source does not ship. The prebuilt library above makes
# compiling the crate unnecessary, so remove it.
rm -rf native
'';

preBuild = ''
Expand Down
22 changes: 18 additions & 4 deletions lib/deps_nix/derivation.ex
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ defmodule DepsNix.Derivation do
DepsNix.FetchFromGitHub.t()
| DepsNix.FetchGit.t()
| DepsNix.FetchHex.t(),
beam_deps: list(atom())
beam_deps: list(atom()),
subdir: String.t() | nil
}

@enforce_keys [
Expand All @@ -30,7 +31,8 @@ defmodule DepsNix.Derivation do
:name,
:version,
:src,
:beam_deps
:beam_deps,
:subdir
]

def new(dep, opts) do
Expand All @@ -48,14 +50,15 @@ defmodule DepsNix.Derivation do
def from(%Mix.Dep{scm: Mix.SCM.Git} = dep, options) do
{:git, url, rev, _} = dep.opts[:lock]
private = !!dep.opts[:private]
subdir = dep.opts[:subdir]

case parse_git_url(url, private) do
[owner: owner, repo: repo] ->
prefetcher = options.github_prefetcher

{hash, builder} =
if prefetcher do
prefetcher.(owner, repo, rev)
prefetcher.(owner, repo, rev, subdir)
else
{"", "buildMix"}
end
Expand All @@ -71,6 +74,7 @@ defmodule DepsNix.Derivation do
version: dep.opts[:app_properties][:vsn],
src: fetcher,
builder: builder,
subdir: subdir,
app_config_path: app_config_path(options)
)

Expand All @@ -81,6 +85,7 @@ defmodule DepsNix.Derivation do
version: dep.opts[:app_properties][:vsn],
src: fetcher,
builder: "buildMix",
subdir: subdir,
app_config_path: app_config_path(options)
)
end
Expand Down Expand Up @@ -241,7 +246,7 @@ defmodule DepsNix.Derivation do
version = "#{drv.version}";
drv = #{drv.builder} {
inherit version;
name = "#{drv.name}";#{format_app_config_path(drv)}
name = "#{drv.name}";#{format_app_config_path(drv)}#{source_root(drv)}

src = #{src(drv.src)}#{beam_deps(drv.beam_deps)}#{patches(drv)}#{post_unpack(drv)}
};
Expand All @@ -250,6 +255,15 @@ defmodule DepsNix.Derivation do
"""
end

defp source_root(%DepsNix.Derivation{subdir: nil}), do: ""

defp source_root(%DepsNix.Derivation{subdir: subdir}) do
"\nsourceRoot = \"source/#{subdir}\";"
|> Util.indent(from: 1)
|> Util.indent(from: 1)
|> Util.indent(from: 1)
end

defp patches(%DepsNix.Derivation{name: :unicode}) do
"""

Expand Down
2 changes: 1 addition & 1 deletion test/deps_nix/derivation_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ defmodule DepsNix.DerivationTest do
} =
Derivation.from(dep, %DepsNix.Options{
github_prefetcher: fn
"code-supply", "mudbrick", ^rev ->
"code-supply", "mudbrick", ^rev, _subdir ->
{generated_hash, "buildMix"}
end
})
Expand Down
Loading