Current section
Files
Jump to
Current section
Files
rebar.config.script
FDBReleasesBaseUrl = "https://api.github.com/repos/apple/foundationdb/releases".
% Detect rebar3 or mix
RebarApi = {error, nofile} =/= code:ensure_loaded(rebar_api).
% Look for fdbcli on PATH, but also check /usr/local/bin explicitly since that is the common location
FdbCli =
case os:find_executable("fdbcli") of
false ->
case os:find_executable("fdbcli", "/usr/local/bin") of
false -> "fdbcli";
Exec -> Exec
end;
Exec ->
Exec
end.
% Logs to stdout/stderr from either rebar3 or mix
Log = fun(Level, Fmt, Args) ->
if
RebarApi ->
rebar_api:Level("[erlfdb] " ++ Fmt, Args);
true ->
Message = iolist_to_binary(io_lib:format(Fmt, Args)),
Level2 =
if
Level =:= abort -> error;
true -> Level
end,
('Elixir.Mix':shell()):Level2(io_lib:format("===> [erlfdb] ~s", [Message])),
if
Level =:= abort ->
'Elixir.Mix':raise(Message);
true ->
ok
end
end
end.
% Check architecture against regex
IsArch = fun(ArchRe) ->
match =:= re:run(erlang:system_info(system_architecture), ArchRe, [{capture, none}])
end.
% Hacky means to extract API version from fdbcli protocol version output
% See https://github.com/apple/foundationdb/blob/master/flow/ProtocolVersion.h
MaxAPIVersion =
begin
VsnInfo = os:cmd(FdbCli ++ " --version"),
case re:run(VsnInfo, "protocol ([a-f0-9]*)", [{capture, [1], list}]) of
{match, [ProtocolStr]} ->
ProtocolVsn = list_to_integer(ProtocolStr, 16),
APIVersionBytes = (ProtocolVsn band 16#0000000FFF00000) bsr 20,
list_to_integer(integer_to_list(APIVersionBytes, 16));
nomatch ->
undefined
end
end.
% Make an HTTP GET request, expect JSON body
GetJson = fun(Url) ->
case code:ensure_loaded(json) of
{module, _} ->
Log(info, " GET ~s", [Url]),
case httpc:request(get, {Url, [{"User-Agent", "rebar3 erlfdb"}]}, [], []) of
{ok, {{"HTTP/1.1", 200, "OK"}, _, Body}} ->
{ok, json:decode(iolist_to_binary(Body))};
_ ->
{error, "HTTP GET Failed"}
end;
{error, _} ->
{error, "Minimum OTP 27 required for release auto-detection"}
end
end.
% Gets the latest release version from the official FoundationDB GitHub Releases
GetLatestRelease = fun() ->
case GetJson(FDBReleasesBaseUrl ++ "/latest") of
{ok, #{<<"tag_name">> := LatestTag}} ->
case
re:run(LatestTag, "(?<major>\\d+)\\.(?<minor>\\d+)\\.(?<patch>\\d+)", [
{capture, [major, minor, patch], list}
])
of
{match, Matches} ->
{ok, [list_to_integer(X) || X <- Matches]};
_ ->
{error, "Failed to parse FoundationDB version"}
end;
Error ->
Error
end
end.
% From the list of assets in the FDB Release, get those that match the regex
GetAssetByNameRe = fun(NameRe, Assets) ->
case
lists:filter(
fun(#{<<"name">> := Name}) ->
match =:= re:run(Name, NameRe, [{capture, none}])
end,
Assets
)
of
[Asset | _] -> Asset;
_ -> undefined
end
end.
% Filter the list of assets in the FDB Release by the known supported architectures
GetSupportedAssets = fun(Assets) ->
[
{"(aarch64-apple-darwin)", #{
server => GetAssetByNameRe("^FoundationDB.*arm64\\.pkg$", Assets),
clients => undefined
}},
{"(x86_64-.*-linux)", #{
server => GetAssetByNameRe("^foundationdb-server.*amd64\\.deb$", Assets),
clients => GetAssetByNameRe("^foundationdb-clients.*amd64\\.deb$", Assets)
}}
]
end.
% Gets the asset map for the latest non-AVX FDB Release on the current architecture
GetLatestNonAVXAssets = fun() ->
% AVX releases have odd patch numbers, so we make sure we have the even one
% If you want the AVX release, please install it manually.
RVsn =
case GetLatestRelease() of
{ok, [Major, Minor, Patch]} when Patch rem 2 == 1 ->
{ok, [Major, Minor, Patch - 1]};
Res ->
Res
end,
case RVsn of
{ok, Vsn = [_, _, _]} ->
Url = lists:flatten([FDBReleasesBaseUrl ++ "/tags/", io_lib:format("~p.~p.~p", Vsn)]),
case GetJson(Url) of
{ok, #{<<"assets">> := Assets}} ->
SupportedAssets = GetSupportedAssets(Assets),
case
lists:filter(fun({ArchRe, Assets}) -> IsArch(ArchRe) end, SupportedAssets)
of
[{_, AssetsMap} | _] ->
{ok, AssetsMap};
[] ->
{error, "Architecture may not have an official FoundationDB release."}
end;
Error ->
Error
end;
Error ->
Error
end
end.
% Logs the list of assets to stdout
LogAssetsMap = fun
LL(#{server := ServerAsset, clients := undefined}) ->
Log(
info,
"For both the foundationdb-server and foundationdb-clients packages, download and install~n~n ~ts~n",
[maps:get(<<"browser_download_url">>, ServerAsset)]
);
LL(#{server := ServerAsset, clients := ClientsAsset}) ->
Log(
info,
"For the foundationdb-server package, download and install~n~n ~ts~n",
[
maps:get(<<"browser_download_url">>, ServerAsset)
]
),
Log(
info,
"For the foundationdb-clients package, download and install~n~n ~ts~n",
[
maps:get(<<"browser_download_url">>, ClientsAsset)
]
)
end.
% If MaxAPIVersion undetected, print helpful informatiom about where to download the latest FDB Release
case MaxAPIVersion of
undefined ->
Log(info, "Checking for latest FoundationDB release...", []),
{ok, _} = application:ensure_all_started(inets),
Message =
case application:ensure_all_started(ssl) of
{ok, _} ->
case GetLatestNonAVXAssets() of
{ok, AssetsMap} ->
LogAssetsMap(AssetsMap),
undefined;
{error, _Reason} ->
"The foundationdb-clients package is required to compile erlfdb. Please visit~n~n https://github.com/apple/foundationdb/releases~n"
end;
{error, _Reason} ->
"The foundationdb-clients package is required to compile erlfdb. Please visit~n~n https://github.com/apple/foundationdb/releases~n"
end,
[Log(info, Message, []) || Message =/= undefined],
AssertFdbCli = "0" =/= os:getenv("ERLFDB_ASSERT_FDBCLI"),
if
AssertFdbCli ->
Log(abort, "Error: fdbcli not found on PATH.", []);
true ->
Log(error, "fdbcli not found on PATH. Continuing anyway...", [])
end;
_ ->
ok
end.
% https://github.com/markusn/coveralls-erl#example-usage-rebar3-and-github-actions
CoverallConfig =
case {os:getenv("GITHUB_ACTIONS"), os:getenv("GITHUB_TOKEN")} of
{"true", Token} when is_list(Token) ->
CONFIG1 = [
{coveralls_repo_token, Token},
{coveralls_service_job_id, os:getenv("GITHUB_RUN_ID")},
{coveralls_service_number, os:getenv("GITHUB_RUN_NUMBER")},
{coveralls_commit_sha, os:getenv("GITHUB_SHA")},
{coveralls_flag_name, os:getenv("COVERALLS_FLAG_NAME")}
| CONFIG
],
case
os:getenv("GITHUB_EVENT_NAME") =:= "pull_request" andalso
string:tokens(os:getenv("GITHUB_REF"), "/")
of
[_, "pull", PRNO, _] ->
[{coveralls_service_pull_request, PRNO} | CONFIG1];
_ ->
CONFIG1
end;
_ ->
CONFIG
end.
ErlOpts = proplists:get_value(erl_opts, CONFIG, []).
[
{erl_opts, ErlOpts ++ [{d, erlfdb_api_version, MaxAPIVersion}]},
{port_env, [
{
"(linux|solaris|freebsd|netbsd|openbsd|dragonfly|darwin|gnu)",
"CFLAGS",
"$CFLAGS -I/usr/local/include -Ic_src/ -g -Wall -Werror " ++
(if
MaxAPIVersion < 730 ->
"-DFDB_API_VERSION=" ++ integer_to_list(MaxAPIVersion);
true ->
"-DFDB_USE_LATEST_API_VERSION=1"
end)
},
{
"win32",
"CFLAGS",
"$CFLAGS /I\"c:/Program Files/foundationdb/include\" /O2 /DNDEBUG " ++
(if
MaxAPIVersion < 730 ->
"-DFDB_API_VERSION=" ++ integer_to_list(MaxAPIVersion);
true ->
"-DFDB_USE_LATEST_API_VERSION=1"
end)
},
{
"(linux|solaris|freebsd|netbsd|openbsd|dragonfly|gnu)",
"LDFLAGS",
"$LDFLAGS -L/usr/local/lib -lfdb_c"
},
{
"(darwin)",
"LDFLAGS",
"$LDFLAGS -rpath /usr/local/lib -L/usr/local/lib -lfdb_c"
},
{
"win32",
"LDFLAGS",
"$LDFLAGS /LIBPATH:\"c:/Program Files/foundationdb/lib/foundationdb\" fdb_c.lib"
}
]}
] ++ CoverallConfig.