%% -*- erlang -*- % Licensed under the Apache License, Version 2.0 (the "License"); you may not % use this file except in compliance with the License. You may obtain a copy of % the License at % % http://www.apache.org/licenses/LICENSE-2.0 % % Unless required by applicable law or agreed to in writing, software % distributed under the License is distributed on an "AS IS" BASIS, WITHOUT % WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the % License for the specific language governing permissions and limitations under % the License. % % Blacklist some bad releases. % {ok, Version} = file:read_file(filename:join( [code:root_dir(), "releases", erlang:system_info(otp_release), "OTP_VERSION"] )). % Version may be binary if file has /n at end :( % there is no string:trim/1 in Erlang 19 :( VerString = case Version of V when is_binary(V) -> string:strip(binary_to_list(V), right, $\n); _ -> string:strip(Version, right, $\n) end. VerList = lists:map(fun(X) -> {Int, _} = string:to_integer(X), Int end, string:tokens(VerString, ".")). DisplayMsg = fun(Msg, Args) -> Base = iolist_to_binary(io_lib:format(Msg, Args)), Lines = binary:split(Base, <<"\n">>, [global]), MaxLen = lists:foldl(fun(Line, Acc) -> max(Acc, size(Line)) end, 0, Lines), Decoration = iolist_to_binary(["*" || _ <- lists:seq(1, MaxLen)]), ReNewLined = [[L, "~n"] || L <- Lines], NewLines = ["~n", Decoration, "~n", ReNewLined, Decoration, "~n~n"], MsgBin = iolist_to_binary(NewLines), io:format(binary_to_list(MsgBin), []) end. ErlangTooOld = fun(Ver) -> DisplayMsg( "This version of Erlang (~p) is too old for use with Apache CouchDB.~n~n" "See https://docs.couchdb.org/en/stable/install/unix.html#dependencies~n" "for the latest information on dependencies.", [Ver] ), halt(1) end. NotSupported = fun(Ver) -> DisplayMsg( "This version of Erlang (~p) is not officially supported by Apache~n" "CouchDB. While we do not officially support this version, there~n" "are also no known bugs or incompatibilities.~n~n" "See https://docs.couchdb.org/en/stable/install/unix.html#dependencies~n" "for the latest information on dependencies.", [Ver] ) end. BadErlang = fun(Ver) -> DisplayMsg( "This version of Erlang (~p) is known to contain bugs that directly~n" "affect the correctness of Apache CouchDB.~n~n" "You should *NOT* use this version of Erlang.~n~n" "See https://docs.couchdb.org/en/stable/install/unix.html#dependencies~n" "for the latest information on dependencies.", [Ver] ), case os:getenv("TRAVIS") of "true" -> io:fwrite("Travis run, ignoring bad release. You have been warned!~n"), ok; _ -> halt(1) end end. case VerList of [OldVer | _] when OldVer < 19 -> ErlangTooOld(VerString); [19 | _] -> NotSupported(VerString); [20 | _] = V20 when V20 < [20, 3, 8, 11] -> BadErlang(VerString); [21 | _] = V21 when V21 < [21, 2, 3] -> BadErlang(VerString); [22, 0, N | _] when N < 5 -> BadErlang(VerString); _ -> ok end. % Set the path to the configuration environment generated % by `./configure`. COUCHDB_ROOT = filename:dirname(SCRIPT). os:putenv("COUCHDB_ROOT", COUCHDB_ROOT). ConfigureEnv = filename:join(COUCHDB_ROOT, "config.erl"). os:putenv("COUCHDB_CONFIG", ConfigureEnv). CouchConfig = case filelib:is_file(ConfigureEnv) of true -> {ok, Result} = file:consult(ConfigureEnv), Result; false -> [] end. os:putenv("COUCHDB_APPS_CONFIG_DIR", filename:join([COUCHDB_ROOT, "rel/apps"])). SubDirs = [ %% must be compiled first as it has a custom behavior "src/couch_epi", "src/couch_log", "src/chttpd", "src/couch", "src/couch_event", "src/mem3", "src/couch_index", "src/couch_mrview", "src/couch_replicator", "src/couch_plugins", "src/couch_pse_tests", "src/couch_stats", "src/couch_peruser", "src/couch_tests", "src/couch_dist", "src/custodian", "src/ddoc_cache", "src/dreyfus", "src/fabric", "src/global_changes", "src/ioq", "src/jwtf", "src/ken", "src/mango", "src/rexi", "src/setup", "src/smoosh", "src/weatherreport", "src/couch_prometheus", "rel" ]. DepDescs = [ %% Independent Apps {config, "config", {tag, "2.1.9"}}, {b64url, "b64url", {tag, "1.0.2"}}, {ets_lru, "ets-lru", {tag, "1.1.0"}}, {khash, "khash", {tag, "1.1.0"}}, {snappy, "snappy", {tag, "CouchDB-1.0.7"}}, %% Non-Erlang deps {docs, {url, "https://github.com/apache/couchdb-documentation"}, {tag, "3.2.1-RC1"}, [raw]}, {fauxton, {url, "https://github.com/apache/couchdb-fauxton"}, {tag, "v1.2.8"}, [raw]}, %% Third party deps {folsom, "folsom", {tag, "CouchDB-0.8.4"}}, {hyper, "hyper", {tag, "CouchDB-2.2.0-7"}}, {ibrowse, "ibrowse", {tag, "CouchDB-4.4.2-5"}}, {jiffy, "jiffy", {tag, "CouchDB-1.0.9-1"}}, {mochiweb, "mochiweb", {tag, "CouchDB-v2.21.0-1"}}, {meck, "meck", {tag, "0.9.2"}}, {recon, "recon", {tag, "2.5.2"}} ]. WithProper = lists:keyfind(with_proper, 1, CouchConfig) == {with_proper, true}. OptionalDeps = case WithProper of true -> [{proper, {url, "https://github.com/proper-testing/proper"}, {tag, "v1.4"}}]; false -> [] end. BaseUrl = "https://github.com/apache/". MakeDep = fun ({AppName, {url, Url}, Version}) -> {AppName, ".*", {git, Url, Version}}; ({AppName, {url, Url}, Version, Options}) -> {AppName, ".*", {git, Url, Version}, Options}; ({AppName, RepoName, Version}) -> Url = BaseUrl ++ "couchdb-" ++ RepoName ++ ".git", {AppName, ".*", {git, Url, Version}}; ({AppName, RepoName, Version, Options}) -> Url = BaseUrl ++ "couchdb-" ++ RepoName ++ ".git", {AppName, ".*", {git, Url, Version}, Options} end. ErlOpts = case os:getenv("ERL_OPTS") of false -> []; Opts -> [list_to_atom(O) || O <- string:tokens(Opts, ",")] end. AddConfig = [ {require_otp_vsn, "20|21|22|23|24"}, {deps_dir, "src"}, {deps, lists:map(MakeDep, DepDescs ++ OptionalDeps)}, {sub_dirs, SubDirs}, {lib_dirs, ["src"]}, {erl_opts, [{i, "../"}] ++ [{d, 'COUCHDB_ERLANG_VERSION', VerString}] ++ ErlOpts}, {eunit_opts, [verbose, {report,{eunit_surefire,[{dir,"."}]}}]}, {plugins, [eunit_plugin]}, {dialyzer, [ {plt_location, local}, {plt_location, COUCHDB_ROOT}, {plt_extra_apps, [ asn1, compiler, crypto, inets, kernel, runtime_tools, sasl, setup, ssl, stdlib, syntax_tools, xmerl]}, {warnings, [unmatched_returns, error_handling, race_conditions]}]}, {post_hooks, [{compile, "escript support/build_js.escript"}]} ]. lists:foldl(fun({K, V}, CfgAcc) -> case lists:keyfind(K, 1, CfgAcc) of {K, Existent} when is_list(Existent) andalso is_list(V) -> lists:keystore(K, 1, CfgAcc, {K, Existent ++ V}); false -> lists:keystore(K, 1, CfgAcc, {K, V}) end end, CONFIG, AddConfig).