aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLoïc Hoguin <[email protected]>2015-12-14 18:35:48 +0100
committerLoïc Hoguin <[email protected]>2015-12-14 18:37:56 +0100
commit4ea38e2319482b316a474d6fc82876e6fdcd7911 (patch)
tree56b8a02a842672d03e961e309dc6a4982f98d908
parent0f11e62b647c735bb13f957eeec9586be7e7b51a (diff)
downloaderlang.mk-4ea38e2319482b316a474d6fc82876e6fdcd7911.tar.gz
erlang.mk-4ea38e2319482b316a474d6fc82876e6fdcd7911.tar.bz2
erlang.mk-4ea38e2319482b316a474d6fc82876e6fdcd7911.zip
Fix compilation of NIFs on Windows
Thanks to two users of the ninenines/esdl2 project, a correct way to build NIFs on Windows has been found. At the moment we require a specific compiler (MingW's gcc). Maybe we can change this in the future and allow Visual Studio and others. Some small changes have been made to the documentation, and the meaning of one configuration variable has changed to not include the extension (which is decided automatically by Erlang.mk; and configurable separately). Enjoy!
-rw-r--r--doc/src/guide/installation.asciidoc7
-rw-r--r--doc/src/guide/ports.asciidoc16
-rw-r--r--plugins/c_src.mk47
-rw-r--r--test/plugin_c_src.mk12
4 files changed, 68 insertions, 14 deletions
diff --git a/doc/src/guide/installation.asciidoc b/doc/src/guide/installation.asciidoc
index f03dafa..a271e2d 100644
--- a/doc/src/guide/installation.asciidoc
+++ b/doc/src/guide/installation.asciidoc
@@ -95,6 +95,13 @@ to find all packages related to GCC:
[source,bash]
$ pacman -Ss gcc
+If you are going to compile C/C++ code, you will need to
+install this package, as Erlang.mk cannot use the normal
+"gcc" package:
+
+[source,bash]
+$ pacman -S mingw-w64-x86_64-gcc
+
You can also run commands under the MSYS2 environment from
the Windows command line or batch files. This command will
install GNU Make and Git:
diff --git a/doc/src/guide/ports.asciidoc b/doc/src/guide/ports.asciidoc
index b436c13..efe4ff7 100644
--- a/doc/src/guide/ports.asciidoc
+++ b/doc/src/guide/ports.asciidoc
@@ -64,9 +64,19 @@ before including Erlang.mk:
[source,make]
C_SRC_TYPE = executable
-The generated file will be saved to '$(C_SRC_OUTPUT)'. It
-defaults to '$(CURDIR)/priv/$(PROJECT).so', the filename
-adequately fitting a Unix shared library.
+The generated file name varies depending on the type of project
+you have (shared library or executable) and on the platform you
+build the project on.
+
+For shared libraries, the generated file name will be
+'$(C_SRC_OUTPUT)$(C_SRC_SHARED_EXTENSION)', with the default
+being '$(CURDIR)/priv/$(PROJECT)' followed by the extension:
+`.dll` on Windows, `.so` everywhere else.
+
+For executables, the generated file name is
+'$(C_SRC_OUTPUT)$(C_SRC_EXECUTABLE_EXTENSION)', with the same
+default except for the extension: `.exe` on Windows, and otherwise
+nothing.
Erlang.mk sets appropriate compile and linker flags by default.
These flags vary depending on the platform, and can of course
diff --git a/plugins/c_src.mk b/plugins/c_src.mk
index e5d6e51..87fd32f 100644
--- a/plugins/c_src.mk
+++ b/plugins/c_src.mk
@@ -7,12 +7,32 @@
C_SRC_DIR ?= $(CURDIR)/c_src
C_SRC_ENV ?= $(C_SRC_DIR)/env.mk
-C_SRC_OUTPUT ?= $(CURDIR)/priv/$(PROJECT).so
+C_SRC_OUTPUT ?= $(CURDIR)/priv/$(PROJECT)
C_SRC_TYPE ?= shared
# System type and C compiler/flags.
-ifeq ($(PLATFORM),darwin)
+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
+ CFLAGS ?= -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes
+ CXXFLAGS ?= -O3 -finline-functions -Wall
+else ifeq ($(PLATFORM),darwin)
CC ?= cc
CFLAGS ?= -O3 -std=c99 -arch x86_64 -finline-functions -Wall -Wmissing-prototypes
CXXFLAGS ?= -O3 -arch x86_64 -finline-functions -Wall
@@ -27,10 +47,15 @@ else ifeq ($(PLATFORM),linux)
CXXFLAGS ?= -O3 -finline-functions -Wall
endif
-CFLAGS += -fPIC -I $(ERTS_INCLUDE_DIR) -I $(ERL_INTERFACE_INCLUDE_DIR)
-CXXFLAGS += -fPIC -I $(ERTS_INCLUDE_DIR) -I $(ERL_INTERFACE_INCLUDE_DIR)
+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) -lerl_interface -lei
+LDLIBS += -L"$(ERL_INTERFACE_LIB_DIR)" -lerl_interface -lei
# Verbosity.
@@ -67,15 +92,15 @@ 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)
+app:: $(C_SRC_ENV) $(C_SRC_OUTPUT_FILE)
-test-build:: $(C_SRC_ENV) $(C_SRC_OUTPUT)
+test-build:: $(C_SRC_ENV) $(C_SRC_OUTPUT_FILE)
-$(C_SRC_OUTPUT): $(OBJECTS)
+$(C_SRC_OUTPUT_FILE): $(OBJECTS)
$(verbose) mkdir -p priv/
$(link_verbose) $(CC) $(OBJECTS) \
$(LDFLAGS) $(if $(filter $(C_SRC_TYPE),shared),-shared) $(LDLIBS) \
- -o $(C_SRC_OUTPUT)
+ -o $(C_SRC_OUTPUT_FILE)
%.o: %.c
$(COMPILE_C) $(OUTPUT_OPTION) $<
@@ -92,13 +117,13 @@ $(C_SRC_OUTPUT): $(OBJECTS)
clean:: clean-c_src
clean-c_src:
- $(gen_verbose) rm -f $(C_SRC_OUTPUT) $(OBJECTS)
+ $(gen_verbose) rm -f $(C_SRC_OUTPUT_FILE) $(OBJECTS)
endif
ifneq ($(wildcard $(C_SRC_DIR)),)
$(C_SRC_ENV):
- $(verbose) $(ERL) -eval "file:write_file(\"$(C_SRC_ENV)\", \
+ $(verbose) $(ERL) -eval "file:write_file(\"$(call core_native_path,$(C_SRC_ENV))\", \
io_lib:format( \
\"ERTS_INCLUDE_DIR ?= ~s/erts-~s/include/~n\" \
\"ERL_INTERFACE_INCLUDE_DIR ?= ~s~n\" \
diff --git a/test/plugin_c_src.mk b/test/plugin_c_src.mk
index ffce3d8..ac9c2a0 100644
--- a/test/plugin_c_src.mk
+++ b/test/plugin_c_src.mk
@@ -34,7 +34,11 @@ c-src-nif: build clean-c-src-nif
$t test -f $(APP)/c_src/env.mk
$t test -f $(APP)/ebin/$(APP).app
$t test -f $(APP)/ebin/$(APP).beam
+ifeq ($(PLATFORM),msys2)
+ $t test -f $(APP)/priv/$(APP).dll
+else
$t test -f $(APP)/priv/$(APP).so
+endif
$i "Check that the application was compiled correctly"
$t $(ERL) -pa $(APP)/ebin/ -eval " \
@@ -55,7 +59,11 @@ c-src-nif: build clean-c-src-nif
$t test -f $(APP)/c_src/env.mk
$t test -f $(APP)/ebin/$(APP).app
$t test -f $(APP)/ebin/$(APP).beam
+ifeq ($(PLATFORM),msys2)
+ $t test -f $(APP)/priv/$(APP).dll
+else
$t test -f $(APP)/priv/$(APP).so
+endif
$i "Check that the application was compiled correctly"
$t $(ERL) -pa $(APP)/ebin/ -eval " \
@@ -75,7 +83,11 @@ c-src-nif: build clean-c-src-nif
$t test ! -e $(APP)/c_src/$(APP).o
$t test ! -e $(APP)/ebin/$(APP).app
$t test ! -e $(APP)/ebin/$(APP).beam
+ifeq ($(PLATFORM),msys2)
+ $t test ! -e $(APP)/priv/$(APP).dll
+else
$t test ! -e $(APP)/priv/$(APP).so
+endif
$i "Distclean the application"
$t $(MAKE) -C $(APP) distclean $v