Skip to content

Commit fa66358

Browse files
authored
Deprecate availability key in nif_versions (#81)
1 parent 43f29f8 commit fa66358

File tree

2 files changed

+48
-29
lines changed

2 files changed

+48
-29
lines changed

PRECOMPILATION_GUIDE.md

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,7 @@ def project do
4343
make_precompiler_filename: "nif",
4444
make_precompiler_priv_paths: ["nif.*"],
4545
make_precompiler_nif_versions: [
46-
versions: ["2.14", "2.15", "2.16"],
47-
availability: &target_available_for_nif_version?/2
46+
versions: ["2.14", "2.15", "2.16"]
4847
]
4948
# ...
5049
]
@@ -113,22 +112,40 @@ The default value for `make_precompiler_nif_versions` is
113112
[versions: ["#{:erlang.system_info(:nif_version)}"]]
114113
```
115114

116-
There're three sub-keys for `make_precompiler_nif_versions`:
115+
There're two sub-keys for `make_precompiler_nif_versions`:
117116

118117
- `versions`
119118
- `fallback_version`
120-
- `availability`
121119

122120
##### `versions` sub-key
123121

124-
The `versions` sub-key is a list of NIF versions that the precompiled artefacts are available for:
122+
The `versions` sub-key is either a list of NIF versions of a function that returns a list of NIF versions that the precompiled artefacts are available for:
125123

126124
```elixir
127125
make_precompiler_nif_versions: [
128126
versions: ["2.15", "2.16"]
129127
]
130128
```
131129

130+
The above example tells `:elixir_make` that all targets have precompiled artefacts for NIF version `2.15` and `2.16`.
131+
132+
For some platforms maybe we only have precompiled artefacts after a certain NIF version, say for x86_64 Windows we have precompiled artefacts available when NIF version >= `2.16` while other platforms have precompiled artefacts available from NIF version >= `2.15`.
133+
134+
In such case we can inform `:elixir_make` that Windows targets don't have precompiled artefacts available except for NIF version `2.16` by passing a function to the `availability` sub-key. This function should accept two arguments, `target` and `nif_version`, and returns a boolean value indicating whether the precompiled artefacts for the target and NIF version are available.
135+
136+
```elixir
137+
make_precompiler_nif_versions: [
138+
versions: fn opts ->
139+
target = opts.target
140+
if String.contains?(target, "windows") do
141+
["2.16"]
142+
else
143+
["2.15", "2.16"]
144+
end
145+
end
146+
]
147+
```
148+
132149
The default behaviour is to use the exact NIF version that is available to the current target. If one is not available, it may fallback (see `fallback_version` next) to the highest matching major version prior to the current version. For example:
133150

134151
- if the current host is using Erlang/OTP 23 (NIF version `2.15`), `elixir_make` will use the precompiled artefacts for NIF version `2.15`;
@@ -139,25 +156,11 @@ If the current host is using Erlang/OTP with a new major Erlang NIF version (NIF
139156

140157
##### `fallback_version` sub-key
141158

142-
The behaviour when `elixir_make` cannot find the exact NIF version of the precompiled binary can be customized by setting the `fallback_version` sub-key. The value of the `fallback_version` sub-key should be a function that accepts three arguments, `target`, `current_nif_version` and `target_versions`. The `target` is the target triplet (or other name format, defined by the precompiler of your choice), `current_nif_version` is the NIF version on the current host, and `target_versions` is a list of NIF versions that are available to the target.
143-
144-
The `fallback_version` function should return either the NIF version that `elixir_make` should use from the `target_versions` list or the `current_nif_version`.
159+
The behaviour when `elixir_make` cannot find the exact NIF version of the precompiled binary can be customized by setting the `fallback_version` sub-key.
145160

146-
##### `availability` sub-key
161+
The value of the `fallback_version` sub-key should be a function that accepts one argument, `opts`, which is a map that include one key `target`. The `target` is the target triplet (or other naming format, defined by the precompiler of your choice).
147162

148-
For some platforms maybe we only have precompiled artefacts after a certain NIF version, say for x86_64 Windows we have precompiled artefacts available when NIF version >= `2.16` while other platforms have precompiled artefacts available from NIF version >= `2.15`.
149-
150-
In such case we can inform `:elixir_make` that Windows targets don't have precompiled artefacts available except for NIF version `2.16` by passing a function to the `availability` sub-key. This function should accept two arguments, `target` and `nif_version`, and returns a boolean value indicating whether the precompiled artefacts for the target and NIF version are available.
151-
152-
```elixir
153-
defp target_available_for_nif_version?(target, nif_version) do
154-
if String.contains?(target, "windows") do
155-
nif_version == "2.16"
156-
else
157-
true
158-
end
159-
end
160-
```
163+
The `fallback_version` function should return the NIF version that is available and should be chosen for the current target.
161164

162165
### (Optional) Customise Precompilation Targets
163166

lib/elixir_make/artefact.ex

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -146,13 +146,14 @@ defmodule ElixirMake.Artefact do
146146
{String.to_integer(major), String.to_integer(minor)}
147147
end
148148

149-
defp fallback_version(_current_target, current_nif_version, versions) do
149+
defp fallback_version(opts) do
150+
current_nif_version = "#{:erlang.system_info(:nif_version)}"
150151
{major, minor} = nif_version_to_tuple(current_nif_version)
151152

152153
# Get all matching major versions, earlier than the current version
153154
# and their distance. We want the closest (smallest distance).
154155
candidates =
155-
for version <- versions,
156+
for version <- opts.versions,
156157
{^major, candidate_minor} <- [nif_version_to_tuple(version)],
157158
candidate_minor <= minor,
158159
do: {minor - candidate_minor, version}
@@ -163,6 +164,16 @@ defmodule ElixirMake.Artefact do
163164
end
164165
end
165166

167+
defp get_versions_for_target(versions, current_target) do
168+
case versions do
169+
version_list when is_list(version_list) ->
170+
version_list
171+
172+
version_func when is_function(version_func, 1) ->
173+
version_func.(%{target: current_target})
174+
end
175+
end
176+
166177
@doc """
167178
Returns all available {{target, nif_version}, url} pairs available.
168179
"""
@@ -179,15 +190,19 @@ defmodule ElixirMake.Artefact do
179190
config[:make_precompiler_nif_versions] ||
180191
[versions: [current_nif_version]]
181192

182-
versions = nif_versions[:versions]
183-
184193
Enum.reduce(targets, [], fn target, archives ->
194+
versions = get_versions_for_target(nif_versions[:versions], target)
195+
185196
archive_filenames =
186197
Enum.reduce(versions, [], fn nif_version_for_target, acc ->
187198
availability = nif_versions[:availability]
188199

189200
available? =
190201
if is_function(availability, 2) do
202+
IO.warn(
203+
":availability key in elixir_make is deprecated, pass a function as :versions instead"
204+
)
205+
191206
availability.(target, nif_version_for_target)
192207
else
193208
true
@@ -220,14 +235,15 @@ defmodule ElixirMake.Artefact do
220235
config[:make_precompiler_nif_versions] ||
221236
[versions: []]
222237

223-
versions = nif_versions[:versions]
238+
versions = get_versions_for_target(nif_versions[:versions], current_target)
224239

225240
nif_version_to_use =
226241
if current_nif_version in versions do
227242
current_nif_version
228243
else
229-
fallback_version = nif_versions[:fallback_version] || (&fallback_version/3)
230-
fallback_version.(current_target, current_nif_version, versions)
244+
fallback_version = nif_versions[:fallback_version] || (&fallback_version/1)
245+
opts = %{target: current_target, versions: versions}
246+
fallback_version.(opts)
231247
end
232248

233249
available_urls = available_target_urls(config, precompiler)

0 commit comments

Comments
 (0)