Skip to content

Mix.install/1 on Linux tries to fetch a precompiled ...dll.tar.gz instead of ...so.tar.gz. #66

@chgeuer

Description

@chgeuer

This certainly isn't a bug, but my own lack of understanding of how Rustler and rustler_precompiled work, so please accept upfront my sincere apologies. Rustler and rustler_precompiled are pretty cool 😍.

I created an Elixir library ([:ex_windows_api_dataprotection](https://hex.pm/packages/ex_windows_api_dataprotection)), which calls into a Windows-specific API using Rustler. I use {:rustler_precompiled, "~> 0.7"} so that my users don't have to have Rust installed. Given that the API is a Windows-specific API, but the package might be installed by non-Windows users, the Rustler function returns the :only_available_on_windows. I took the :explorer .github/workflows files as a starting point to use rustler_precompiled.

When GitHub actions runs the release build, it creates perfectly fine Windows bits (ex_windows_api_dataprotection-v0.1.2-nif-2.15-x86_64-pc-windows-msvc.dll.tar.gz). When creating the Linux bits, it also correctly creates a libex_windows_api_dataprotection-v0.1.2-nif-2.15-x86_64-unknown-linux-gnu.so.tar.gz file (notice the .so.tar.gz in the filename).

However, when I run a simple script on a fresh Linux box:

Mix.install([{:ex_windows_api_dataprotection, "~> 0.1.2"}])

IO.inspect(Windows.API.DataProtection.wrap("Hello"))

Please note when you now run the same script, it'll work, because I did the workaround described below.

It tried to fetch the Linux bits from a .dll.tar.gz file (instead of .so.tar.gz):

15:50:47.621 [info] Attempt 3 failed with {:error, "couldn't fetch NIF from https://github.com/chgeuer/ex_windows_api_dataprotection/releases/download/v0.1.2/libex_windows_api_dataprotection-v0.1.2-nif-2.15-x86_64-unknown-linux-gnu.dll.tar.gz: {:ok, {{~c\"HTTP/1.1\", 404, ~c\"Not Found\"}, ...."}

15:50:48.647 [debug] Downloading NIF from https://github.com/chgeuer/ex_windows_api_dataprotection/releases/download/v0.1.2/libex_windows_api_dataprotection-v0.1.2-nif-2.15-x86_64-unknown-linux-gnu.dll.tar.gz

== Compilation error in file lib/internal/native.ex ==
** (RuntimeError) Error while downloading precompiled NIF: couldn't fetch NIF from https://github.com/chgeuer/ex_windows_api_dataprotection/releases/download/v0.1.2/libex_windows_api_dataprotection-v0.1.2-nif-2.15-x86_64-unknown-linux-gnu.dll.tar.gz: {:ok, {{~c"HTTP/1.1", 404, ~c"Not Found"}, "Not Found"}}.

You can force the project to build from scratch with:

    config :rustler_precompiled, :force_build, ex_windows_api_dataprotection: true

In order to force the build, you also need to add Rustler as a dependency in your `mix.exs`:

    {:rustler, ">= 0.0.0", optional: true}

I'm trying to understand why the mix deps.get or Mix.install/1 on Linux tries to fetch a .dll.tar.gz from the release share, instead of .so.tar.gz.

Workaround: I downloaded the existing .so... release, renamed to .dll... and manually added it to the release, which circumvents the problem for that specific release.

image-20240106170713037

After the workaround of manually adding the dll file to the release, you can see it being picked up by the sample script:

chgeuer@hp:~$ elixir wrap.exs

Resolving Hex dependencies...
Resolution completed in 0.115s

New:
  castore 1.0.5
  ex_windows_api_dataprotection 0.1.2
  rustler_precompiled 0.7.1
* Getting ex_windows_api_dataprotection (Hex package)
* Getting rustler_precompiled (Hex package)
* Getting castore (Hex package)
==> castore
Compiling 1 file (.ex)
Generated castore app
==> rustler_precompiled
Compiling 4 files (.ex)
Generated rustler_precompiled app
==> ex_windows_api_dataprotection
Compiling 2 files (.ex)

16:17:10.057 [debug] Downloading NIF from https://github.com/chgeuer/ex_windows_api_dataprotection/releases/download/v0.1.2/libex_windows_api_dataprotection-v0.1.2-nif-2.15-x86_64-unknown-linux-gnu.dll.tar.gz

16:17:10.973 [debug] NIF cached at /home/chgeuer/.cache/rustler_precompiled/precompiled_nifs/libex_windows_api_dataprotection-v0.1.2-nif-2.15-x86_64-unknown-linux-gnu.so.tar.gz and extracted to /home/chgeuer/.cache/mix/installs/elixir-1.16.0-erts-14.2.1/b77c538c8667667f7f4a42c185d7fffa/_build/dev/lib/ex_windows_api_dataprotection/priv/native/libex_windows_api_dataprotection-v0.1.2-nif-2.15-x86_64-unknown-linux-gnu.so
Generated ex_windows_api_dataprotection app

:only_available_on_windows

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions