检查Erlang OTP版本以在Elixir上执行不同功能

qc6wkl3g  于 2022-12-08  发布在  Erlang
关注(0)|答案(2)|浏览(307)

I'm creating a new Elixir library that require to be executed with different versions of the language.
This library uses the Erlang :crypto.hmac function but this function was replaced on version 22 of Erlang OTP by :crypto.mac (with same functionality).
I'm using the following private macro to execute the newer or older functions:

defmacrop hmac(key, data) do
  if System.otp_release() >= "22" do
    quote do: :crypto.mac(:hmac, :sha256, unquote(key), unquote(data))
  else
    quote do: :crypto.hmac(:sha256, unquote(key), unquote(data))
  end
end

And using it in the following way:

hmac(key, data)

Two questions:

  1. Is this a correct way of execute code based in the OTP release version?
  2. Any better obvious way to address this problem?
    Thanks.
ercv8c1e

ercv8c1e1#

这是基于OTP发布版本的正确代码执行方式吗?
您不应检查OTP版本,而应检查应用程序(在本例中为crypto)版本。因为OTP版本可能与应用程序版本不同。
有没有更好的方法来解决这个问题?
是,检查给定函数是否导出,而不是检查OTP/应用程序的版本。
在运行时,有两种方法可以实现这一点:

def hmac(key, data) do
  if Code.ensure_loaded?(:crypto) and function_exported?(:crypto, :mac, 4) do
    :crypto.mac(:mac, :sha256, key, data)
  else
    :crypto.hmac(:sha256, key, data)
  end
end

或在编译期间:

if Code.ensure_loaded?(:crypto) and function_exported?(:crypto, :mac, 4) do
  def hmac(key, data), do: :crypto.mac(:mac, :sha256, key, data)
else
  def hmac(key, data), do: :crypto.hmac(:sha256, key, data)
end
v9tzhpje

v9tzhpje2#

宏是编译时的产物,编译后没有宏的踪迹;相反,它注入的AST发生在释放中。
也就是说,如果您希望它是编译时的,这意味着您需要许多环境来编译,并且每个版本都只在编译时的同一平台上工作,这是正确的方法。
如果您希望一次组装一个发行版并使其在不同的目标平台上工作,最好使用Kernel.apply/3作为

def hmac(key, data) do
  if String.to_integer(System.otp_release) >= 22,
    do: apply(:crypto, :mac, [:hmac, :sha256, key, data]),
    else: apply(:crypto, :hmac, [:sha256, key, data])
end
  • 旁注:* 即使你希望它是编译时的,声明不同的函数比声明一个宏更干净。
if String.to_integer(System.otp_release) >= 22 do
  def hmac(key, data),
    do: :crypto.mac(:hmac, :sha256, key, data)
else
  def hmac(key, data),
    do: :crypto.hmac(:sha256, key, data)
end

这将在编译时进行评估,相应的功能将在生成的BEAM代码中发生。

相关问题