Skip to content
Draft
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
5 changes: 4 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ on:
workflow_dispatch:

jobs:

build:
name: Build
runs-on: ${{ matrix.os }}
Expand All @@ -27,3 +26,7 @@ jobs:
run: nix develop .#ci --command -- mix test
- name: Check fixture derivations
run: nix flake check
- name: Check deps.nix is up to date
run: |
nix run .# -- --no-app-config
git diff --exit-code -- deps.nix
1 change: 1 addition & 0 deletions VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.1.1
243 changes: 243 additions & 0 deletions deps.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
{
lib,
beamPackages,
cmake,
extend,
lexbor,
fetchFromGitHub,
oniguruma,
overrides ? (x: y: { }),
overrideFenixOverlay ? null,
rustlerPrecompiledOverrides ? { },
stdenv,
pkg-config,
vips,
writeText,
}:

let
buildMix = lib.makeOverridable beamPackages.buildMix;
buildRebar3 = lib.makeOverridable beamPackages.buildRebar3;

workarounds = {
portCompiler = _unusedArgs: old: {
buildPlugins = [ beamPackages.pc ];
};

rustlerPrecompiled =
{
toolchain ? null,
buildInputs ? [ ],
nativeBuildInputs ? [ ],
env ? { },
...
}:
old:
let
extendedPkgs = extend fenixOverlay;
fenixOverlay =
if overrideFenixOverlay == null then
import "${
fetchTarball {
url = "https://github.com/nix-community/fenix/archive/6399553b7a300c77e7f07342904eb696a5b6bf9d.tar.gz";
sha256 = "sha256-C6tT7K1Lx6VsYw1BY5S3OavtapUvEnDQtmQB5DSgbCc=";
}
}/overlay.nix"
else
overrideFenixOverlay;
nativeDir = "${old.src}/native/${with builtins; head (attrNames (readDir "${old.src}/native"))}";
fenix =
if toolchain == null then
extendedPkgs.fenix.stable
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;
}
).overrideAttrs
rustlerPrecompiledOverrides.${old.beamModuleName} or { };

in
{
nativeBuildInputs = [ extendedPkgs.cargo ];

env.RUSTLER_PRECOMPILED_FORCE_BUILD_ALL = "true";
env.RUSTLER_PRECOMPILED_GLOBAL_CACHE_PATH = "unused-but-required";

preConfigure = ''
mkdir -p priv/native
for lib in ${native}/lib/*
do
dest="$(basename "$lib")"
if [[ "''${dest##*.}" = "dylib" ]]
then
dest="''${dest%.dylib}.so"
fi
dest="''${dest#lib}"
ln -s "$lib" "priv/native/$dest"
done
'';

preBuild = ''
suggestion() {
echo "***********************************************"
echo " deps_nix "
echo
echo " Rust dependency build failed. "
echo
echo " If you saw network errors, you might need "
echo " to disable compilation on the appropriate "
echo " RustlerPrecompiled module in your "
echo " application config. "
echo
echo " We think you need this: "
echo
echo -n " "
grep -Rl 'use RustlerPrecompiled' lib \
| xargs grep 'defmodule' \
| sed 's/defmodule \(.*\) do/config :${old.beamModuleName}, \1, skip_compilation?: true/'
echo "***********************************************"
exit 1
}
trap suggestion ERR
'';
};

elixirMake = _unusedArgs: old: {
preConfigure = ''
export ELIXIR_MAKE_CACHE_DIR="$TEMPDIR/elixir_make_cache"
'';
};

lazyHtml = _unusedArgs: old: {
preConfigure = ''
export ELIXIR_MAKE_CACHE_DIR="$TEMPDIR/elixir_make_cache"
'';

postPatch = ''
substituteInPlace mix.exs \
--replace-fail "Fine.include_dir()" '"${packages.fine}/src/c_include"' \
--replace-fail '@lexbor_git_sha "244b84956a6dc7eec293781d051354f351274c46"' '@lexbor_git_sha ""'
'';

preBuild = ''
install -Dm644 -t _build/c/third_party/lexbor/$LEXBOR_GIT_SHA/build ${lexbor}/lib/liblexbor_static.a
'';
};
};

defaultOverrides = (
final: prev:

let
apps = {
crc32cer = [
{
name = "portCompiler";
}
];
explorer = [
{
name = "rustlerPrecompiled";
toolchain = {
name = "nightly-2025-06-23";
sha256 = "sha256-UAoZcxg3iWtS+2n8TFNfANFt/GmkuOMDf7QAE0fRxeA=";
};
}
];
snappyer = [
{
name = "portCompiler";
}
];
};

applyOverrides =
appName: drv:
let
allOverridesForApp = builtins.foldl' (
acc: workaround: acc // (workarounds.${workaround.name} workaround) drv
) { } apps.${appName};

in
if builtins.hasAttr appName apps then drv.override allOverridesForApp else drv;

in
builtins.mapAttrs applyOverrides prev
);

self = packages // (defaultOverrides self packages) // (overrides self packages);

packages =
with beamPackages;
with self;
{

ex_nar =
let
version = "0.3.0";
drv = buildMix {
inherit version;
name = "ex_nar";

src = fetchHex {
inherit version;
pkg = "ex_nar";
sha256 = "cbb42d047764feac6c411efddcadc31866e9a998dd6e2bc1eb428cec1c49fdcd";
};
};
in
drv;

hpax =
let
version = "1.0.3";
drv = buildMix {
inherit version;
name = "hpax";

src = fetchHex {
inherit version;
pkg = "hpax";
sha256 = "8eab6e1cfa8d5918c2ce4ba43588e894af35dbd8e91e6e55c817bca5847df34a";
};
};
in
drv;

mint =
let
version = "1.7.1";
drv = buildMix {
inherit version;
name = "mint";

src = fetchHex {
inherit version;
pkg = "mint";
sha256 = "fceba0a4d0f24301ddee3024ae116df1c3f4bb7a563a731f45fdfeb9d39a231b";
};

beamDeps = [
hpax
];
};
in
drv;

};
in
self
9 changes: 7 additions & 2 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,21 @@
{
packages = forAllSystems (
{ pkgs, ... }:
let
beamPackages = pkgs.beamMinimal29Packages.overrideScope (_: prev: { elixir = prev.elixir_1_20; });
in
(pkgs.callPackages ./fixtures/example/deps.nix { })
// {
// rec {
example = pkgs.callPackage ./fixtures/example/package.nix { };
default = deps_nix;
deps_nix = pkgs.callPackage ./package.nix { inherit beamPackages; };
}
);

devShells = forAllSystems (
{ pkgs, ... }:
let
beamPackages = pkgs.beam29Packages.overrideScope (_: prev: { elixir = prev.elixir_1_20; });
beamPackages = pkgs.beamMinimal29Packages.overrideScope (_: prev: { elixir = prev.elixir_1_20; });
in
{
default = pkgs.callPackage ./shells/local.nix { inherit beamPackages; };
Expand Down
21 changes: 18 additions & 3 deletions lib/deps_nix.ex
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,12 @@ defmodule DepsNix do
|> wrap(opts.output)
end

@spec parse_args(list()) :: Options.t()
@version Mix.Project.config()[:version]

@spec version() :: String.t()
def version, do: @version

@spec parse_args(list()) :: Options.t() | :help | :version
def parse_args(args) do
args
|> OptionParser.parse(
Expand All @@ -67,7 +72,9 @@ defmodule DepsNix do
output: :string,
app_config: :boolean,
app_config_path: :string,
include_paths: :boolean
include_paths: :boolean,
help: :boolean,
version: :boolean
]
)
|> to_opts()
Expand Down Expand Up @@ -149,7 +156,7 @@ defmodule DepsNix do
end
end

@spec to_opts({list(), any(), any()}) :: Options.t()
@spec to_opts({list(), any(), any()}) :: Options.t() | :help | :version
defp to_opts({[], _, _}) do
%Options{
cwd: File.cwd!(),
Expand All @@ -159,6 +166,14 @@ defmodule DepsNix do
end

defp to_opts({opts, _, _}) do
cond do
Keyword.get(opts, :help) -> :help
Keyword.get(opts, :version) -> :version
true -> build_opts(opts)
end
end

defp build_opts(opts) do
default = to_opts({[], [], []})

%{
Expand Down
27 changes: 27 additions & 0 deletions lib/deps_nix/cli.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
defmodule DepsNix.CLI do
def main(args) do
case DepsNix.parse_args(args) do
:help ->
IO.ANSI.Docs.print_headings(["deps_nix"])
IO.ANSI.Docs.print(DepsNix.Docs.markdown("deps_nix"), "text/markdown", [])

:version ->
IO.puts("deps_nix #{DepsNix.version()}")

opts ->
generate(opts)
end
end

defp generate(opts) do
{:ok, _started_apps} = Application.ensure_all_started([:mint, :mix])

Code.compile_file(Path.absname(System.get_env("MIX_EXS", "mix.exs")))

Mix.Project.get!()

{path, output} = DepsNix.run(opts, &Mix.Dep.Converger.converge/1)

File.write!(path, output)
end
end
Loading
Loading