balena/elixir-sippet

Unable to link Sippet on Apple Silicon with LDFLAGS set

sgfn opened this issue · 3 comments

sgfn commented

Hi,
It appears that because of the structure of the Makefile, having LDFLAGS set in the env makes the compilation of Sippet fail on Apple Silicon.

In our app, we're using Sippet as well as fast_tls. The issue is, fast_tls needs LDFLAGS to contain the path to the OpenSSL library (i.e. LDFLAGS=-L/opt/homebrew/opt/openssl/lib), and will not compile otherwise. When we try to compile everything at once, though, linking of Sippet fails because the Makefile uses conditional variable assignment ?= and does not overwrite/append to LDFLAGS if it is already set -- which is the case.

As far as I've tested, the only linker flag necessary for Sippet to compile successfully with this setup is -undefined suppress.

The most straightforward way of alleviating this issue I can think of is to always append the -undefined suppress flag, since it is necessary to link anyway. This is a simple fix, and doesn't change the general behaviour of the Makefile:

diff --git a/c_src/Makefile b/c_src/Makefile
index c20a402..a6dc5f1 100644
--- a/c_src/Makefile
+++ b/c_src/Makefile
@@ -73,7 +73,9 @@ endif
        CC ?= cc
        CFLAGS ?= -O3 -std=c11 $(ARCHFLAGS) -fstack-protector -Wall -Wmissing-prototypes
        CXXFLAGS ?= -O3 -std=c++11 $(ARCHFLAGS) -fstack-protector -Wall
-       LDFLAGS ?= $(ARCHFLAGS) -flat_namespace -undefined suppress
+       LDFLAGS ?= $(ARCHFLAGS) -flat_namespace
+       # Necessary to link successfully on Apple Silicon
+       LDFLAGS += -undefined suppress
 else ifeq ($(PLATFORM),freebsd)
        CC ?= cc
        CFLAGS ?= -O3 -std=c11 -finline-functions -fstack-protector -Wall -Wmissing-prototypes

Please let me know whether you're OK with this solution, and I'll be happy to make the relevant PR.

Logs from the failed linking for reference:

ld: Undefined symbols:
  _enif_alloc_binary, referenced from:
      (anonymous namespace)::ParseMultipleUriParams(enif_environment_t*, std::__1::__wrap_iter<char const*>, std::__1::__wrap_iter<char const*>) in parser.o
      ...
  _enif_get_list_cell, referenced from:
      parse_wrapper(enif_environment_t*, int, unsigned long const*) in parser.o
  _enif_get_map_value, referenced from:
      parse_wrapper(enif_environment_t*, int, unsigned long const*) in parser.o
  [...] etc.

Hi @balena, what do you think about @sgfn's proposition?

Could we open a PR with proposed changes @balena ?

Hi @Rados13 and @sgfn, sorry the delay to respond.

Definitely it seems a reasonable solution, if you have time, please open a PR so this change can be easily merged and a new version pushed to Hex.