blob: 93608cea7df333da9181f8676178de9170f0f2cc [file] [log] [blame]
%% 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.
CopyIfDifferent = fun(Path, Contents) ->
case filelib:is_file(Path) of
true ->
case file:read_file(Path) of
{ok, Contents} ->
ok;
_ ->
file:write_file(Path, Contents)
end;
false ->
file:write_file(Path, Contents)
end
end.
CouchJSName = case os:type() of
{win32, _} ->
"couchjs.exe";
_ ->
"couchjs"
end.
CouchJSPath = filename:join(["priv", CouchJSName]).
Version = case os:getenv("COUCHDB_VERSION") of
false ->
string:strip(os:cmd("git describe --always"), right, $\n);
Version0 ->
string:strip(Version0, right)
end.
GitSha = case os:getenv("COUCHDB_GIT_SHA") of
false ->
""; % release builds won't get a fallback
GitSha0 ->
string:strip(GitSha0, right)
end.
CouchConfig = case filelib:is_file(os:getenv("COUCHDB_CONFIG")) of
true ->
{ok, Result} = file:consult(os:getenv("COUCHDB_CONFIG")),
Result;
false ->
[]
end.
SMVsn = case lists:keyfind(spidermonkey_version, 1, CouchConfig) of
{_, "1.8.5"} ->
"1.8.5";
{_, "60"} ->
"60";
{_, "68"} ->
"68";
undefined ->
"1.8.5";
{_, Unsupported} ->
io:format(standard_error, "Unsupported SpiderMonkey version: ~s~n", [Unsupported]),
erlang:halt(1);
false ->
"1.8.5"
end.
ConfigH = [
{"SM185", ""},
{"HAVE_JS_GET_STRING_CHARS_AND_LENGTH", "1"},
{"JSSCRIPT_TYPE", "JSObject*"},
{"COUCHJS_NAME", "\"" ++ CouchJSName++ "\""},
{"PACKAGE", "\"apache-couchdb\""},
{"PACKAGE_BUGREPORT", "\"https://github.com/apache/couchdb/issues\""},
{"PACKAGE_NAME", "\"Apache CouchDB\""},
{"PACKAGE_STRING", "\"Apache CouchDB " ++ Version ++ "\""},
{"PACKAGE_VERSION", "\"" ++ Version ++ "\""}
].
CouchJSConfig = "priv/couch_js/" ++ SMVsn ++ "/config.h".
ConfigSrc = [["#define ", K, " ", V, $\n] || {K, V} <- ConfigH].
ConfigBin = iolist_to_binary(ConfigSrc).
ok = CopyIfDifferent(CouchJSConfig, ConfigBin).
MD5Config = case lists:keyfind(erlang_md5, 1, CouchConfig) of
{erlang_md5, true} ->
[{d, 'ERLANG_MD5', true}];
_ ->
[]
end.
ProperConfig = case code:lib_dir(proper) of
{error, bad_name} -> [];
_ -> [{d, 'WITH_PROPER'}]
end.
{JS_CFLAGS, JS_LDFLAGS} = case os:type() of
{win32, _} when SMVsn == "1.8.5" ->
{
"/DXP_WIN",
"mozjs185-1.0.lib"
};
{unix, _} when SMVsn == "1.8.5" ->
{
"-DXP_UNIX -I/usr/include/js -I/usr/local/include/js",
"-L/usr/local/lib -lmozjs185 -lm"
};
{win32, _} when SMVsn == "60" ->
{
"/DXP_WIN",
"mozjs-60.lib"
};
{unix, darwin} when SMVsn == "60" ->
{
"-DXP_UNIX -I/usr/include/mozjs-60 -I/usr/local/include/mozjs-60 -std=c++14",
"-L/usr/local/lib -lmozjs-60 -lm -std=c++14 -lc++"
};
{unix, _} when SMVsn == "60" ->
{
"-DXP_UNIX -I/usr/include/mozjs-60 -I/usr/local/include/mozjs-60 -std=c++14 -Wno-invalid-offsetof",
"-L/usr/local/lib -std=c++14 -lmozjs-60 -lm -lstdc++"
};
{unix, _} when SMVsn == "68" ->
{
"-DXP_UNIX -I/usr/include/mozjs-68 -I/usr/local/include/mozjs-68 -std=c++14 -Wno-invalid-offsetof",
"-L/usr/local/lib -std=c++14 -lmozjs-68 -lm -lstdc++"
}
end.
{CURL_CFLAGS, CURL_LDFLAGS} = case lists:keyfind(with_curl, 1, CouchConfig) of
{with_curl, true} ->
case os:type() of
{win32, _} ->
{
"/DHAVE_CURL",
"/DHAVE_CURL libcurl.lib"
};
{unix, freebsd} ->
{
"-DHAVE_CURL -I/usr/local/include",
"-DHAVE_CURL -lcurl"
};
_ ->
{
"-DHAVE_CURL",
"-DHAVE_CURL -lcurl"
}
end;
_ ->
{"", ""}
end.
CouchJSSrc = case SMVsn of
"1.8.5" -> ["priv/couch_js/1.8.5/*.c"];
"60" -> ["priv/couch_js/60/*.cpp"];
"68" -> ["priv/couch_js/68/*.cpp"]
end.
CouchJSEnv = case SMVsn of
"1.8.5" ->
[
{"CFLAGS", JS_CFLAGS ++ " " ++ CURL_CFLAGS},
{"LDFLAGS", JS_LDFLAGS ++ " " ++ CURL_LDFLAGS}
];
_ ->
[
{"CXXFLAGS", JS_CFLAGS ++ " " ++ CURL_CFLAGS},
{"LDFLAGS", JS_LDFLAGS ++ " " ++ CURL_LDFLAGS}
]
end.
IcuPath = "priv/couch_icu_driver.so".
IcuSrc = ["priv/icu_driver/*.c"].
IcuEnv = [{"DRV_CFLAGS", "$DRV_CFLAGS -DPIC -O2 -fno-common"},
{"DRV_LDFLAGS", "$DRV_LDFLAGS -lm -licuuc -licudata -licui18n -lpthread"}].
IcuDarwinEnv = [{"CFLAGS", "-DXP_UNIX -I/usr/local/opt/icu4c/include"},
{"LDFLAGS", "-L/usr/local/opt/icu4c/lib"}].
IcuBsdEnv = [{"CFLAGS", "-DXP_UNIX -I/usr/local/include"},
{"LDFLAGS", "-L/usr/local/lib"}].
IcuWinEnv = [{"CFLAGS", "$DRV_CFLAGS /DXP_WIN"},
{"LDFLAGS", "icuin.lib icudt.lib icuuc.lib"}].
ComparePath = "priv/couch_ejson_compare.so".
CompareSrc = ["priv/couch_ejson_compare/*.c"].
BaseSpecs = [
%% couchjs
{".*", CouchJSPath, CouchJSSrc, [{env, CouchJSEnv}]},
% ICU
{"darwin", IcuPath, IcuSrc, [{env, IcuEnv ++ IcuDarwinEnv}]},
{"linux", IcuPath, IcuSrc, [{env, IcuEnv}]},
{"bsd", IcuPath, IcuSrc, [{env, IcuEnv ++ IcuBsdEnv}]},
{"win32", IcuPath, IcuSrc, [{env, IcuWinEnv}]},
% ejson_compare
{"darwin", ComparePath, CompareSrc, [{env, IcuEnv ++ IcuDarwinEnv}]},
{"linux", ComparePath, CompareSrc, [{env, IcuEnv}]},
{"bsd", ComparePath, CompareSrc, [{env, IcuEnv ++ IcuBsdEnv}]},
{"win32", ComparePath, CompareSrc, [{env, IcuWinEnv}]}
].
SpawnSpec = [
{"priv/couchspawnkillable", ["priv/spawnkillable/*.c"]}
].
%% hack required until switch to enc/rebar3
PortEnvOverrides = [
{"win32", "EXE_LINK_CXX_TEMPLATE",
"$LINKER $PORT_IN_FILES $LDFLAGS $EXE_LDFLAGS /OUT:$PORT_OUT_FILE"}
].
PortSpecs = case os:type() of
{win32, _} ->
BaseSpecs ++ SpawnSpec;
_ ->
{ok, CSK} = file:read_file("priv/spawnkillable/couchspawnkillable.sh"),
ok = CopyIfDifferent("priv/couchspawnkillable", CSK),
os:cmd("chmod +x priv/couchspawnkillable"),
BaseSpecs
end.
PlatformDefines = [
{platform_define, "win32", 'WINDOWS'}
].
AddConfig = [
{port_specs, PortSpecs},
{erl_opts, PlatformDefines ++ [
{d, 'COUCHDB_VERSION', Version},
{d, 'COUCHDB_GIT_SHA', GitSha},
{i, "../"}
] ++ MD5Config ++ ProperConfig},
{port_env, PortEnvOverrides},
{eunit_compile_opts, PlatformDefines}
].
lists:foldl(fun({K, V}, CfgAcc) ->
lists:keystore(K, 1, CfgAcc, {K, V})
end, CONFIG, AddConfig).