Skip to content

Commit

Permalink
Use dynamic linkage for tests (cossacklabs#460)
Browse files Browse the repository at this point in the history
* Link tests dynamically: Soter

Switch to dynamic linkage for test binaries. This will allow us to
better track missing exported symbols and make sure that all public API
is actually tested.

The switch itself is more or less trivial: build the dynamic library
as the prerequisite, and link using '-Lbuild -lsoter' instead of adding
the static library to the object list. Since now the cryptographic
backend is managed by the dynamic library, we no longer have to link
against it explicitly.

Caveat for Linux: we need to set "rpath" to the build directory so that
the dynamic loader can locate Soter library there. Otherwise we'll have
to set LD_LIBRARY_PATH when running tests.

* Link tests dynamically: Themis

Link Themis Core tests dynamically, just like we do for Soter now.

Caveats:

  - the tests actually use some symbols from libsoter so we have
    to link against it as well, not only with just libthemis

  - setting LDFLAGS will leak them to libthemis and libsoter
    compilation by default, avoid that by using a separate variable

* Link tests dynamically: ThemisPP

Link ThemisPP tests dynamically, just like we do for Themis and Soter.
Overall it's just like with Themis.

* Disallow unresolved symbols during builds

The default behavior of linkers is to allow unresolved symbols in
libraries (but not executables). This is sometimes useful for
interposition but not in our case. Add a global linker flag to
ensure that all imported symbols can be resolved.

(Obviously, Linux and macOS linkers use a bit different syntax.)

* Link Emscripten tests statically

Unfortunately, Emscripten and Wasm do not support dynamic linkage (easily)
so they are configured for static linkage by default. This means that we
have to link in all the dependencies manually. Add cryptographic backend
to compilation flags so that it resolves correctly.

* Really link Emscripten statically

While linking with "-lthemis" and *.so files seems to work at first,
that's not true for the case when Themis is already installed in the
system. Then emcc for some reason ignores the 'shared' Wasm libraries
in the build directory and tries linking against the native system
libraries (and failes).

Use the correct static linkage for Wasm targets: build the static libs,
and link against them instead of shared objects. However, continue
using shared objects for everything else.
  • Loading branch information
ilammy authored and vixentael committed Apr 24, 2019
1 parent 56e28c6 commit 25d75b7
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 9 deletions.
8 changes: 8 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,14 @@ ifneq ($(shell $(CC) --version 2>&1 | grep -oi "Emscripten"),)
IS_EMSCRIPTEN := true
endif

# Detect early if we have undefined symbols due to missing exports
ifdef IS_MACOS
LDFLAGS += -Wl,-undefined,error
endif
ifdef IS_LINUX
LDFLAGS += -Wl,--no-undefined
endif

ifdef IS_EMSCRIPTEN
CMAKE = emconfigure cmake
endif
Expand Down
20 changes: 16 additions & 4 deletions tests/soter/soter.mk
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ FMT_FIXUP += $(patsubst %,$(OBJ_PATH)/%.fmt_fixup, $(SOTER_TEST_FMT))
FMT_CHECK += $(patsubst %,$(OBJ_PATH)/%.fmt_check, $(SOTER_TEST_FMT))

ifdef IS_EMSCRIPTEN
$(SOTER_TEST_BIN): LDFLAGS += -s SINGLE_FILE=1

# Emscripten cannot conveniently run NIST STS therefore we disable it.
NO_NIST_STS := true
endif
Expand All @@ -47,9 +45,23 @@ $(OBJ_PATH)/tests/soter/%: CFLAGS += -DNIST_STS_EXE_PATH=$(realpath $(NIST_STS_D
$(SOTER_TEST_BIN): nist_rng_test_suite
endif

$(SOTER_TEST_BIN): CMD = $(CC) -o $@ $(filter %.o %.a, $^) $(LDFLAGS) $(CRYPTO_ENGINE_LDFLAGS)
ifdef IS_EMSCRIPTEN
# Emscripten does not support dynamic linkage, do a static build for it.
SOTER_TEST_LDFLAGS += -s SINGLE_FILE=1
$(SOTER_TEST_BIN): $(SOTER_STATIC)
else
# Link dynamically against the Soter library in the build directory,
# not the one in the standard system paths (if any).
SOTER_TEST_LDFLAGS += -L$(BIN_PATH) -lsoter
ifdef IS_LINUX
SOTER_TEST_LDFLAGS += -Wl,-rpath,$(abspath $(BIN_PATH))
endif
$(SOTER_TEST_BIN): $(BIN_PATH)/$(LIBSOTER_SO)
endif

$(SOTER_TEST_BIN): CMD = $(CC) -o $@ $(filter %.o %.a, $^) $(LDFLAGS) $(SOTER_TEST_LDFLAGS)

$(SOTER_TEST_BIN): $(SOTER_TEST_OBJ) $(COMMON_TEST_OBJ) $(SOTER_STATIC)
$(SOTER_TEST_BIN): $(SOTER_TEST_OBJ) $(COMMON_TEST_OBJ)
@mkdir -p $(@D)
@echo -n "link "
@$(BUILD_CMD)
Expand Down
17 changes: 14 additions & 3 deletions tests/themis/themis.mk
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,23 @@ FMT_FIXUP += $(patsubst %,$(OBJ_PATH)/%.fmt_fixup, $(THEMIS_TEST_FMT))
FMT_CHECK += $(patsubst %,$(OBJ_PATH)/%.fmt_check, $(THEMIS_TEST_FMT))

ifdef IS_EMSCRIPTEN
$(THEMIS_TEST_BIN): LDFLAGS += -s SINGLE_FILE=1
# Emscripten does not support dynamic linkage, do a static build for it.
THEMIS_TEST_LDFLAGS += -s SINGLE_FILE=1
$(THEMIS_TEST_BIN): $(THEMIS_STATIC)
else
# Link dynamically against the Themis library in the build directory,
# not the one in the standard system paths (if any).
# We also need to link against Soter explicitly because of private imports.
THEMIS_TEST_LDFLAGS += -L$(BIN_PATH) -lthemis -lsoter
ifdef IS_LINUX
THEMIS_TEST_LDFLAGS += -Wl,-rpath,$(abspath $(BIN_PATH))
endif
$(THEMIS_TEST_BIN): $(BIN_PATH)/$(LIBTHEMIS_SO)
endif

$(THEMIS_TEST_BIN): CMD = $(CC) -o $@ $(filter %.o %.a, $^) $(LDFLAGS) $(CRYPTO_ENGINE_LDFLAGS)
$(THEMIS_TEST_BIN): CMD = $(CC) -o $@ $(filter %.o %.a, $^) $(LDFLAGS) $(THEMIS_TEST_LDFLAGS)

$(THEMIS_TEST_BIN): $(THEMIS_TEST_OBJ) $(COMMON_TEST_OBJ) $(THEMIS_STATIC)
$(THEMIS_TEST_BIN): $(THEMIS_TEST_OBJ) $(COMMON_TEST_OBJ)
@mkdir -p $(@D)
@echo -n "link "
@$(BUILD_CMD)
19 changes: 17 additions & 2 deletions tests/themispp/themispp.mk
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,24 @@ THEMISPP_TEST_FMT = $(THEMISPP_TEST_SOURCES) $(THEMISPP_TEST_HEADERS)
FMT_FIXUP += $(patsubst %,$(OBJ_PATH)/%.fmt_fixup, $(THEMISPP_TEST_FMT))
FMT_CHECK += $(patsubst %,$(OBJ_PATH)/%.fmt_check, $(THEMISPP_TEST_FMT))

$(TEST_BIN_PATH)/themispp_test: CMD = $(CXX) -o $@ $(filter %.o %.a, $^) $(LDFLAGS) $(CRYPTO_ENGINE_LDFLAGS)
ifdef IS_EMSCRIPTEN
# Emscripten does not support dynamic linkage, do a static build for it.
THEMISPP_TEST_LDFLAGS += -s SINGLE_FILE=1
$(TEST_BIN_PATH)/themispp_test: $(THEMIS_STATIC)
else
# Link dynamically against Themis library in the build directory,
# not the one in the standard system paths (if any).
# We also need to link against Soter explicitly because of private imports.
THEMISPP_TEST_LDFLAGS += -L$(BIN_PATH) -lthemis -lsoter
ifdef IS_LINUX
THEMISPP_TEST_LDFLAGS += -Wl,-rpath,$(abspath $(BIN_PATH))
endif
$(TEST_BIN_PATH)/themispp_test: $(BIN_PATH)/$(LIBTHEMIS_SO)
endif

$(TEST_BIN_PATH)/themispp_test: $(THEMISPP_TEST_OBJ) $(COMMON_TEST_OBJ) $(THEMIS_STATIC)
$(TEST_BIN_PATH)/themispp_test: CMD = $(CXX) -o $@ $(filter %.o %.a, $^) $(LDFLAGS) $(THEMISPP_TEST_LDFLAGS)

$(TEST_BIN_PATH)/themispp_test: $(THEMISPP_TEST_OBJ) $(COMMON_TEST_OBJ)
@echo -n "link "
@$(BUILD_CMD)

Expand Down

0 comments on commit 25d75b7

Please sign in to comment.