123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 |
- # Copyright (c) 2014-2016, Loïc Hoguin <essen@ninenines.eu>
- # This file is part of erlang.mk and subject to the terms of the ISC License.
- .PHONY: clean-c_src distclean-c_src-env
- # Configuration.
- C_SRC_DIR ?= $(CURDIR)/c_src
- C_SRC_ENV ?= $(C_SRC_DIR)/env.mk
- C_SRC_OUTPUT ?= $(CURDIR)/priv/$(PROJECT)
- C_SRC_TYPE ?= shared
- # System type and C compiler/flags.
- ifeq ($(PLATFORM),msys2)
- C_SRC_OUTPUT_EXECUTABLE_EXTENSION ?= .exe
- C_SRC_OUTPUT_SHARED_EXTENSION ?= .dll
- else
- C_SRC_OUTPUT_EXECUTABLE_EXTENSION ?=
- C_SRC_OUTPUT_SHARED_EXTENSION ?= .so
- endif
- ifeq ($(C_SRC_TYPE),shared)
- C_SRC_OUTPUT_FILE = $(C_SRC_OUTPUT)$(C_SRC_OUTPUT_SHARED_EXTENSION)
- else
- C_SRC_OUTPUT_FILE = $(C_SRC_OUTPUT)$(C_SRC_OUTPUT_EXECUTABLE_EXTENSION)
- endif
- ifeq ($(PLATFORM),msys2)
- # We hardcode the compiler used on MSYS2. The default CC=cc does
- # not produce working code. The "gcc" MSYS2 package also doesn't.
- CC = /mingw64/bin/gcc
- export CC
- CFLAGS ?= -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes
- CXXFLAGS ?= -O3 -finline-functions -Wall
- else ifeq ($(PLATFORM),darwin)
- CC ?= cc
- CFLAGS ?= -O3 -std=c99 -Wall -Wmissing-prototypes
- CXXFLAGS ?= -O3 -Wall
- LDFLAGS ?= -flat_namespace -undefined suppress
- else ifeq ($(PLATFORM),freebsd)
- CC ?= cc
- CFLAGS ?= -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes
- CXXFLAGS ?= -O3 -finline-functions -Wall
- else ifeq ($(PLATFORM),linux)
- CC ?= gcc
- CFLAGS ?= -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes
- CXXFLAGS ?= -O3 -finline-functions -Wall
- endif
- ifneq ($(PLATFORM),msys2)
- CFLAGS += -fPIC
- CXXFLAGS += -fPIC
- endif
- CFLAGS += -I"$(ERTS_INCLUDE_DIR)" -I"$(ERL_INTERFACE_INCLUDE_DIR)"
- CXXFLAGS += -I"$(ERTS_INCLUDE_DIR)" -I"$(ERL_INTERFACE_INCLUDE_DIR)"
- LDLIBS += -L"$(ERL_INTERFACE_LIB_DIR)" -lei
- # Verbosity.
- c_verbose_0 = @echo " C " $(filter-out $(notdir $(MAKEFILE_LIST) $(C_SRC_ENV)),$(^F));
- c_verbose = $(c_verbose_$(V))
- cpp_verbose_0 = @echo " CPP " $(filter-out $(notdir $(MAKEFILE_LIST) $(C_SRC_ENV)),$(^F));
- cpp_verbose = $(cpp_verbose_$(V))
- link_verbose_0 = @echo " LD " $(@F);
- link_verbose = $(link_verbose_$(V))
- # Targets.
- ifeq ($(wildcard $(C_SRC_DIR)),)
- else ifneq ($(wildcard $(C_SRC_DIR)/Makefile),)
- app:: app-c_src
- test-build:: app-c_src
- app-c_src:
- $(MAKE) -C $(C_SRC_DIR)
- clean::
- $(MAKE) -C $(C_SRC_DIR) clean
- else
- ifeq ($(SOURCES),)
- SOURCES := $(sort $(foreach pat,*.c *.C *.cc *.cpp,$(call core_find,$(C_SRC_DIR)/,$(pat))))
- endif
- OBJECTS = $(addsuffix .o, $(basename $(SOURCES)))
- COMPILE_C = $(c_verbose) $(CC) $(CFLAGS) $(CPPFLAGS) -c
- COMPILE_CPP = $(cpp_verbose) $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c
- app:: $(C_SRC_ENV) $(C_SRC_OUTPUT_FILE)
- test-build:: $(C_SRC_ENV) $(C_SRC_OUTPUT_FILE)
- $(C_SRC_OUTPUT_FILE): $(OBJECTS)
- $(verbose) mkdir -p $(dir $@)
- $(link_verbose) $(CC) $(OBJECTS) \
- $(LDFLAGS) $(if $(filter $(C_SRC_TYPE),shared),-shared) $(LDLIBS) \
- -o $(C_SRC_OUTPUT_FILE)
- $(OBJECTS): $(MAKEFILE_LIST) $(C_SRC_ENV)
- %.o: %.c
- $(COMPILE_C) $(OUTPUT_OPTION) $<
- %.o: %.cc
- $(COMPILE_CPP) $(OUTPUT_OPTION) $<
- %.o: %.C
- $(COMPILE_CPP) $(OUTPUT_OPTION) $<
- %.o: %.cpp
- $(COMPILE_CPP) $(OUTPUT_OPTION) $<
- clean:: clean-c_src
- clean-c_src:
- $(gen_verbose) rm -f $(C_SRC_OUTPUT_FILE) $(OBJECTS)
- endif
- ifneq ($(wildcard $(C_SRC_DIR)),)
- ERL_ERTS_DIR = $(shell $(ERL) -eval 'io:format("~s~n", [code:lib_dir(erts)]), halt().')
- $(C_SRC_ENV):
- $(verbose) $(ERL) -eval "file:write_file(\"$(call core_native_path,$(C_SRC_ENV))\", \
- io_lib:format( \
- \"# Generated by Erlang.mk. Edit at your own risk!~n~n\" \
- \"ERTS_INCLUDE_DIR ?= ~s/erts-~s/include/~n\" \
- \"ERL_INTERFACE_INCLUDE_DIR ?= ~s~n\" \
- \"ERL_INTERFACE_LIB_DIR ?= ~s~n\" \
- \"ERTS_DIR ?= $(ERL_ERTS_DIR)~n\", \
- [code:root_dir(), erlang:system_info(version), \
- code:lib_dir(erl_interface, include), \
- code:lib_dir(erl_interface, lib)])), \
- halt()."
- distclean:: distclean-c_src-env
- distclean-c_src-env:
- $(gen_verbose) rm -f $(C_SRC_ENV)
- -include $(C_SRC_ENV)
- ifneq ($(ERL_ERTS_DIR),$(ERTS_DIR))
- $(shell rm -f $(C_SRC_ENV))
- endif
- endif
- # Templates.
- define bs_c_nif
- #include "erl_nif.h"
- static int loads = 0;
- static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
- {
- /* Initialize private data. */
- *priv_data = NULL;
- loads++;
- return 0;
- }
- static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info)
- {
- /* Convert the private data to the new version. */
- *priv_data = *old_priv_data;
- loads++;
- return 0;
- }
- static void unload(ErlNifEnv* env, void* priv_data)
- {
- if (loads == 1) {
- /* Destroy the private data. */
- }
- loads--;
- }
- static ERL_NIF_TERM hello(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
- {
- if (enif_is_atom(env, argv[0])) {
- return enif_make_tuple2(env,
- enif_make_atom(env, "hello"),
- argv[0]);
- }
- return enif_make_tuple2(env,
- enif_make_atom(env, "error"),
- enif_make_atom(env, "badarg"));
- }
- static ErlNifFunc nif_funcs[] = {
- {"hello", 1, hello}
- };
- ERL_NIF_INIT($n, nif_funcs, load, NULL, upgrade, unload)
- endef
- define bs_erl_nif
- -module($n).
- -export([hello/1]).
- -on_load(on_load/0).
- on_load() ->
- PrivDir = case code:priv_dir(?MODULE) of
- {error, _} ->
- AppPath = filename:dirname(filename:dirname(code:which(?MODULE))),
- filename:join(AppPath, "priv");
- Path ->
- Path
- end,
- erlang:load_nif(filename:join(PrivDir, atom_to_list(?MODULE)), 0).
- hello(_) ->
- erlang:nif_error({not_loaded, ?MODULE}).
- endef
- new-nif:
- ifneq ($(wildcard $(C_SRC_DIR)/$n.c),)
- $(error Error: $(C_SRC_DIR)/$n.c already exists)
- endif
- ifneq ($(wildcard src/$n.erl),)
- $(error Error: src/$n.erl already exists)
- endif
- ifndef n
- $(error Usage: $(MAKE) new-nif n=NAME [in=APP])
- endif
- ifdef in
- $(verbose) $(MAKE) -C $(APPS_DIR)/$(in)/ new-nif n=$n in=
- else
- $(verbose) mkdir -p $(C_SRC_DIR) src/
- $(verbose) $(call core_render,bs_c_nif,$(C_SRC_DIR)/$n.c)
- $(verbose) $(call core_render,bs_erl_nif,src/$n.erl)
- endif
|