%% 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" }; {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" } 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}, {"LDFLAGS", JS_LDFLAGS} ]; _ -> [ {"CXXFLAGS", JS_CFLAGS}, {"LDFLAGS", JS_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).