| %% 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"; |
| {_, "78"} -> |
| "78"; |
| {_, "86"} -> |
| "86"; |
| 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 = case SMVsn of |
| "78" -> |
| "priv/couch_js/86/config.h"; |
| _ -> |
| "priv/couch_js/" ++ SMVsn ++ "/config.h" |
| end. |
| 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" |
| }; |
| {unix, _} when SMVsn == "78" -> |
| { |
| "-DXP_UNIX -I/usr/include/mozjs-78 -I/usr/local/include/mozjs-78 -std=c++17 -Wno-invalid-offsetof", |
| "-L/usr/local/lib -std=c++17 -lmozjs-78 -lm" |
| }; |
| {unix, _} when SMVsn == "86" -> |
| { |
| "-DXP_UNIX -I/usr/include/mozjs-86 -I/usr/local/include/mozjs-86 -I/opt/homebrew/include/mozjs-86/ -std=c++17 -Wno-invalid-offsetof", |
| "-L/usr/local/lib -L /opt/homebrew/lib/ -std=c++17 -lmozjs-86 -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"]; |
| "78" -> ["priv/couch_js/86/*.cpp"]; |
| "86" -> ["priv/couch_js/86/*.cpp"] |
| end. |
| |
| CouchJSEnv = case SMVsn of |
| "1.8.5" -> |
| [ |
| {"CFLAGS", JS_CFLAGS}, |
| {"LDFLAGS", JS_LDFLAGS} |
| ]; |
| _ -> |
| [ |
| {"CXXFLAGS", JS_CFLAGS}, |
| {"LDFLAGS", JS_LDFLAGS} |
| ] |
| end. |
| |
| 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 -I/opt/homebrew/opt/icu4c/include"}, |
| {"LDFLAGS", "-L/usr/local/opt/icu4c/lib -L/opt/homebrew/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}]}, |
| % 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}, |
| {d, 'COUCHDB_SPIDERMONKEY_VERSION', SMVsn}, |
| {i, "../"} |
| ] ++ MD5Config ++ ProperConfig}, |
| {port_env, PortEnvOverrides}, |
| {eunit_compile_opts, PlatformDefines} |
| ]. |
| |
| 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). |