aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/deps.mk178
-rw-r--r--plugins/c_src.mk12
2 files changed, 92 insertions, 98 deletions
diff --git a/core/deps.mk b/core/deps.mk
index c1e3862..228bef5 100644
--- a/core/deps.mk
+++ b/core/deps.mk
@@ -136,14 +136,15 @@ define dep_autopatch_rebar.erl
{ok, Conf0} -> Conf0;
_ -> []
end,
- Conf = case filelib:is_file("$(DEPS_DIR)/$(1)/rebar.config.script") of
- false -> Conf1;
+ {Conf, OsEnv} = case filelib:is_file("$(DEPS_DIR)/$(1)/rebar.config.script") of
+ false -> {Conf1, []};
true ->
Bindings0 = erl_eval:new_bindings(),
Bindings1 = erl_eval:add_binding('CONFIG', Conf1, Bindings0),
Bindings = erl_eval:add_binding('SCRIPT', "$(DEPS_DIR)/$(1)/rebar.config.script", Bindings1),
+ Before = os:getenv(),
{ok, Conf2} = file:script("$(DEPS_DIR)/$(1)/rebar.config.script", Bindings),
- Conf2
+ {Conf2, lists:foldl(fun(E, Acc) -> lists:delete(E, Acc) end, os:getenv(), Before)}
end,
Write = fun (Text) ->
file:write_file("$(DEPS_DIR)/$(1)/Makefile", Text, [append])
@@ -153,6 +154,8 @@ define dep_autopatch_rebar.erl
end,
Write("IGNORE_DEPS = edown eper eunit_formatters meck node_package "
"rebar_lock_deps_plugin rebar_vsn_plugin reltool_util\n\n"),
+ Write("C_SRC_DIR = /path/do/not/exist\n\n"),
+ Write("DRV_CFLAGS = -fPIC\nexport DRV_CFLAGS\n\n"),
fun() ->
Write("ERLC_OPTS = +debug_info\n"),
case lists:keyfind(erl_opts, 1, Conf) of
@@ -237,87 +240,6 @@ define dep_autopatch_rebar.erl
Write(["COMPILE_FIRST +=", [[" ", atom_to_list(M)] || M <- First,
lists:member("$(DEPS_DIR)/$(1)/src/" ++ atom_to_list(M) ++ ".erl", ErlFiles)], "\n"])
end(),
- PortSpecWrite = fun(Name, Output, Input, Env) ->
- filelib:ensure_dir("$(DEPS_DIR)/$(1)/" ++ Output),
- file:write_file("$(DEPS_DIR)/$(1)/c_src/Makefile." ++ Name, [
- [["override ", K, " = $$$$\(shell echo ", Escape(V), "\)\n"]
- || {_, K, V} <- Env],
- "\nall:\n\t$$$$\(CC\) $$$$\(CFLAGS\) $$$$\(LDLIBS\) $$$$\(LDFLAGS\) ",
- "-o $(DEPS_DIR)/$(1)/", Output,
- [[" ../", F] || F <- Input]
- ])
- end,
- PortSpecNoop = fun(Name) -> file:write_file("$(DEPS_DIR)/$(1)/c_src/Makefile." ++ Name, "noop:\n") end,
- PortSpec = fun
- (Name, {Output, Input}) ->
- PortSpecWrite(Name, Output, Input, []);
- (Name, {Regex, Output, Input}) ->
- case rebar_utils:is_arch(Regex) of
- true -> PortSpecWrite(Name, Output, Input, []);
- false -> PortSpecNoop(Name)
- end;
- (Name, {Regex, Output, Input, [{env, Env}]}) ->
- case rebar_utils:is_arch(Regex) of
- true -> PortSpecWrite(Name, Output, Input, Env);
- false -> PortSpecNoop(Name)
- end
- end,
- fun() ->
- case filelib:is_dir("$(DEPS_DIR)/$(1)/c_src") of
- false -> ok;
- true ->
- Sources = filelib:fold_files("$(DEPS_DIR)/$(1)/c_src", ".*\\\\.(c|C|cc|cpp)$$$$", true, fun(F, Acc) -> [F|Acc] end, []),
- Write(io_lib:format("SOURCES :=~s\n", [[[" ", S] || S <- Sources]]))
- end
- end(),
- fun() ->
- case lists:keyfind(port_specs, 1, Conf) of
- {_, [{Output, Wildcards}]} ->
- filelib:ensure_dir("$(DEPS_DIR)/$(1)/" ++ Output),
- Write("C_SRC_OUTPUT = " ++ Escape(Output) ++ "\n"),
- Sources = [[[" ", S] || S <- filelib:wildcard("$(DEPS_DIR)/$(1)/" ++ W)] || W <- Wildcards],
- Write(io_lib:format("SOURCES :=~s\n", [Sources]));
- {_, [First, Second]} ->
- PortSpec("1", First),
- PortSpec("2", Second),
- file:write_file("$(DEPS_DIR)/$(1)/c_src/Makefile",
- "all:\n\t$$$$\(MAKE\) -f Makefile.1\n\t$$$$\(MAKE\) -f Makefile.2\n");
- _ -> ok
- end
- end(),
- EnvValue = fun(V) ->
- Escape(re:replace(V, "\\\\$$$$\ERLANG_ARCH", rebar_utils:wordsize(), [{return, list}]))
- end,
- fun() ->
- case lists:keyfind(port_env, 1, Conf) of
- {_, Vars} ->
- lists:foldl(fun
- ({K, V}, Acc) ->
- case lists:member(K, Acc) of
- true -> Acc;
- false ->
- Write(K ++ " = $$$$\(shell echo " ++ EnvValue(V) ++ "\)\n"),
- [K|Acc]
- end;
- ({Regex, K, V}, Acc) ->
- case lists:member(K, Acc) of
- true -> Acc;
- false ->
- case rebar_utils:is_arch(Regex) of
- true ->
- Write(K ++ " = $$$$\(shell echo " ++ EnvValue(V) ++ "\)\n"),
- [K|Acc];
- false ->
- Acc
- end
- end
- end, [], Vars),
- Write("CFLAGS += $$$$\(DRV_CFLAGS\)\n"),
- Write("CXXFLAGS += $$$$\(DRV_CFLAGS\)\n"),
- Write("LDFLAGS += $$$$\(DRV_LDFLAGS\)\n");
- _ -> ok
- end
- end(),
Write("\n\nrebar_dep: pre-deps deps pre-app app\n"),
Write("\npre-deps::\n"),
Write("\npre-app::\n"),
@@ -348,21 +270,93 @@ define dep_autopatch_rebar.erl
end || H <- Hooks]
end
end(),
- Write("\ninclude ../../erlang.mk"),
- fun() ->
- case filelib:is_dir("$(DEPS_DIR)/$(1)/c_src") of
- false -> ok;
- true ->
- Write("\n\nCFLAGS := $$$$\(filter-out -std=c99 -Wmissing-prototypes,$$$$\(CFLAGS\)\)\n")
+ ShellToMk = fun(V) ->
+ re:replace(V, "(\\\\$$$$)(\\\\w*)", "\\\\1(\\\\2)", [{return, list}, global])
+ end,
+ PortSpecs = fun() ->
+ case lists:keyfind(port_specs, 1, Conf) of
+ false ->
+ case filelib:wildcard("$(DEPS_DIR)/$(1)/c_src/*.c") of
+ [] -> [];
+ Src -> [{"priv/$(1)_drv.so", ["c_src/*.c"], []}]
+ end;
+ {_, Specs} ->
+ lists:flatten([case S of
+ {Output, Input} -> {ShellToMk(Output), Input, []};
+ {Regex, Output, Input} ->
+ case rebar_utils:is_arch(Regex) of
+ true -> {ShellToMk(Output), Input, []};
+ false -> []
+ end;
+ {Regex, Output, Input, [{env, Env}]} ->
+ case rebar_utils:is_arch(Regex) of
+ true -> {ShellToMk(Output), Input, Env};
+ false -> []
+ end
+ end || S <- Specs])
end
end(),
+ PortSpecWrite = fun (Text) ->
+ file:write_file("$(DEPS_DIR)/$(1)/c_src/Makefile.erlang.mk", Text, [append])
+ end,
+ case PortSpecs of
+ [] -> ok;
+ _ ->
+ Write("\npre-app::\n\t$$$$\(MAKE) -f c_src/Makefile.erlang.mk\n"),
+ PortSpecWrite(io_lib:format("ERL_CFLAGS = -finline-functions -Wall -fPIC -I ~s/erts-~s/include -I ~s\n",
+ [code:root_dir(), erlang:system_info(version), code:lib_dir(erl_interface, include)])),
+ PortSpecWrite(io_lib:format("ERL_LDFLAGS = -L ~s -lerl_interface -lei\n",
+ [code:lib_dir(erl_interface, lib)])),
+ PortSpecWrite(["\nERLANG_ARCH = ", rebar_utils:wordsize(), "\n"]),
+ [PortSpecWrite(["\n", E, "\n"]) || E <- OsEnv],
+ FilterEnv = fun(Env) ->
+ lists:flatten([case E of
+ {_, _} -> E;
+ {Regex, K, V} ->
+ case rebar_utils:is_arch(Regex) of
+ true -> {K, V};
+ false -> []
+ end
+ end || E <- Env])
+ end,
+ MergeEnv = fun(Env) ->
+ lists:foldl(fun ({K, V}, Acc) ->
+ case lists:keyfind(K, 1, Acc) of
+ false -> [{K, rebar_utils:expand_env_variable(V, K, "")}|Acc];
+ {_, V0} -> [{K, rebar_utils:expand_env_variable(V, K, V0)}|Acc]
+ end
+ end, [], Env)
+ end,
+ PortEnv = case lists:keyfind(port_env, 1, Conf) of
+ false -> [];
+ {_, PortEnv0} -> FilterEnv(PortEnv0)
+ end,
+ PortSpec = fun ({Output, Input0, Env}) ->
+ filelib:ensure_dir("$(DEPS_DIR)/$(1)/" ++ Output),
+ Input = [[" ", I] || I <- Input0],
+ PortSpecWrite([
+ [["\n", K, " = ", ShellToMk(V)] || {K, V} <- lists:reverse(MergeEnv(PortEnv ++ FilterEnv(Env)))],
+ "\n\nall:: ", Output, "\n\n",
+ "%.o: %.c\n\t$$$$\(CC) -c -o $$$$\@ $$$$\< $$$$\(CFLAGS) $$$$\(ERL_CFLAGS) $$$$\(DRV_CFLAGS) $$$$\(EXE_CFLAGS)\n\n",
+ "%.o: %.C\n\t$$$$\(CXX) -c -o $$$$\@ $$$$\< $$$$\(CXXFLAGS) $$$$\(ERL_CFLAGS) $$$$\(DRV_CFLAGS) $$$$\(EXE_CFLAGS)\n\n",
+ "%.o: %.cc\n\t$$$$\(CXX) -c -o $$$$\@ $$$$\< $$$$\(CXXFLAGS) $$$$\(ERL_CFLAGS) $$$$\(DRV_CFLAGS) $$$$\(EXE_CFLAGS)\n\n",
+ "%.o: %.cpp\n\t$$$$\(CXX) -c -o $$$$\@ $$$$\< $$$$\(CXXFLAGS) $$$$\(ERL_CFLAGS) $$$$\(DRV_CFLAGS) $$$$\(EXE_CFLAGS)\n\n",
+ Output, ": $$$$\(foreach ext,.c .C .cc .cpp,",
+ "$$$$\(patsubst %$$$$\(ext),%.o,$$$$\(filter %$$$$\(ext),$$$$\(wildcard", Input, "))))\n",
+ "\t$$$$\(CC) -o $$$$\@ $$$$\? $$$$\(LDFLAGS) $$$$\(ERL_LDFLAGS) $$$$\(DRV_LDFLAGS) $$$$\(EXE_LDFLAGS)",
+ case filename:extension(Output) of
+ [] -> "\n";
+ _ -> " -shared\n"
+ end])
+ end,
+ [PortSpec(S) || S <- PortSpecs]
+ end,
+ Write("\ninclude ../../erlang.mk"),
fun() ->
case lists:keyfind(plugins, 1, Conf) of
{_, [Plugin]} when is_atom(Plugin) ->
ErlFile = "$(DEPS_DIR)/$(1)/plugins/" ++ atom_to_list(Plugin) ++ ".erl",
try
- {ok, PF} = file:read_file(ErlFile),
- ok = file:write_file(ErlFile, PF),
{ok, Mod, Bin} = compile:file(ErlFile, [binary]),
{module, Mod} = code:load_binary(Mod, ErlFile, Bin),
c:cd("$(DEPS_DIR)/$(1)/"),
diff --git a/plugins/c_src.mk b/plugins/c_src.mk
index 710566d..34e4952 100644
--- a/plugins/c_src.mk
+++ b/plugins/c_src.mk
@@ -5,9 +5,10 @@
# Configuration.
-C_SRC_DIR = $(CURDIR)/c_src
+C_SRC_DIR ?= $(CURDIR)/c_src
C_SRC_ENV ?= $(C_SRC_DIR)/env.mk
C_SRC_OUTPUT ?= $(CURDIR)/priv/$(PROJECT).so
+C_SRC_TYPE ?= shared
# System type and C compiler/flags.
@@ -30,7 +31,10 @@ CFLAGS += -fPIC -I $(ERTS_INCLUDE_DIR) -I $(ERL_INTERFACE_INCLUDE_DIR)
CXXFLAGS += -fPIC -I $(ERTS_INCLUDE_DIR) -I $(ERL_INTERFACE_INCLUDE_DIR)
LDLIBS += -L $(ERL_INTERFACE_LIB_DIR) -lerl_interface -lei
+
+ifeq ($(C_SRC_TYPE),shared)
LDFLAGS += -shared
+endif
# Verbosity.
@@ -52,11 +56,7 @@ app:: app-c_src
test-build:: app-c_src
app-c_src:
- $(MAKE) -C $(C_SRC_DIR) \
- CFLAGS="$(CFLAGS)" \
- CXXFLAGS="$(CXXFLAGS)" \
- LDLIBS="$(LDLIBS)" \
- LDFLAGS="$(LDFLAGS)"
+ $(MAKE) -C $(C_SRC_DIR)
clean::
$(MAKE) -C $(C_SRC_DIR) clean