Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 69 additions & 36 deletions .nanvix/Makefile.nanvix
Original file line number Diff line number Diff line change
Expand Up @@ -6,49 +6,48 @@
# NANVIX_TOOLCHAIN=<toolchain> [target]
#
# Targets:
# all Build libxslt.a, libexslt.a, and the test ELF, then stage via install
# install Stage built artifacts into LIB_OUT/INCLUDE_OUT/TEST_OUT
# all Build libxslt.{a,so}, libexslt.{a,so}, and the test ELF
# test Verify functional-test prerequisites (build artifacts).
# The runtime execution is driven by z.py on the host.
# clean Remove build artifacts
#
# Dependencies:
# The shared-library build requires:
# * The Nanvix dynamic loader to honour `.init_array` constructors and
# DT_NEEDED resolution chains (esaurez/nanvix#27).
# * `libxml2.so` to be present in the buildroot, shipped by the
# companion esaurez/libxml2 release that ships libxml2.so.
# libxslt.so is linked with DT_NEEDED libxml2.so, and libexslt.so is
# linked with DT_NEEDED libxslt.so libxml2.so, so the loader pulls
# the lower-level libraries automatically at dlopen time.

# ===========================================================================
# Global Variables
# ===========================================================================

# Some assumptions:
# 1. This makefile is expected to be invoked via z.py.
# 2. Build goals (all, install) require the cross-toolchain at
# $(NANVIX_TOOLCHAIN); other goals (test-*, clean) are pure host-side.
# 2. Build goals require the cross-toolchain at $(NANVIX_TOOLCHAIN); other
# goals (test-*, clean) are pure host-side.
# 3. Build ALWAYS runs before test and release.
# 4. Release packaging is handled by the inherited ZScript.release(), which
# packages release_dir() (= .nanvix/out/release/) into dist_dir();
# the install target below stages artifacts into that tree.
# 4. Release packaging is handled in z.py (pure-Python tarfile); no
# package/verify-package targets here.

.DEFAULT_GOAL=all
EXE = .elf

STATICLIB_XSLT := libxslt/.libs/libxslt.a
STATICLIB_EXSLT := libexslt/.libs/libexslt.a
SHAREDLIB_XSLT := libxslt/.libs/libxslt.so
SHAREDLIB_EXSLT := libexslt/.libs/libexslt.so
TEST_SRC := .nanvix/test/test_libxslt.c
TEST_ELF := test_libxslt$(EXE)

_NANVIX_DOCKER_BUILD_GOALS := all install $(STATICLIB_XSLT) $(STATICLIB_EXSLT) $(TEST_ELF)
_NANVIX_DOCKER_BUILD_GOALS := all $(STATICLIB_XSLT) $(STATICLIB_EXSLT) $(SHAREDLIB_XSLT) $(SHAREDLIB_EXSLT) $(TEST_ELF)
_NANVIX_GOALS := $(or $(MAKECMDGOALS),$(.DEFAULT_GOAL))

# Ensure required variables are defined.
_REQUIRED := PLATFORM \
PROCESS_MODE \
MEMORY_SIZE \
NANVIX_HOME \
NANVIX_BUILDROOT \
NANVIX_TOOLCHAIN \
NANVIX_ROOT \
OUT_DIR \
DIST_DIR \
LIB_OUT \
INCLUDE_OUT \
TEST_OUT
_REQUIRED := PLATFORM PROCESS_MODE MEMORY_SIZE NANVIX_HOME NANVIX_BUILDROOT NANVIX_TOOLCHAIN
ifneq ($(filter-out clean,$(_NANVIX_GOALS)),)
$(foreach v,$(_REQUIRED),\
$(if $($v),,$(error Required variable $v not set))\
Expand Down Expand Up @@ -79,8 +78,13 @@ endif
# Build Targets
# ===========================================================================

all: $(STATICLIB_XSLT) $(STATICLIB_EXSLT) $(TEST_ELF) install
all: $(STATICLIB_XSLT) $(STATICLIB_EXSLT) $(SHAREDLIB_XSLT) $(SHAREDLIB_EXSLT) $(TEST_ELF)

# Build the static archives with -fPIC so the same objects can be
# linked into position-independent .so files below. autotools'
# libtool shared-library detection does not know about i686-nanvix,
# so we keep --disable-shared and link the .so files ourselves from
# the .a archives.
$(STATICLIB_XSLT) $(STATICLIB_EXSLT):
sh -c '\
export PATH="$(NANVIX_TOOLCHAIN)/bin:$$PATH" && \
Expand All @@ -90,15 +94,46 @@ $(STATICLIB_XSLT) $(STATICLIB_EXSLT):
--enable-static --disable-shared --disable-maintainer-mode \
--without-python --without-crypto \
--without-debugger --without-plugins \
--with-pic \
--with-libxml-prefix="$(BUILDROOT_PATH)" \
--with-libxml-include-prefix="$(BUILDROOT_PATH)/include/libxml2" \
--with-libxml-libs-prefix="$(BUILDROOT_PATH)/lib" \
CFLAGS="-I$(BUILDROOT_PATH)/include -I$(BUILDROOT_PATH)/include/libxml2" \
CFLAGS="-I$(BUILDROOT_PATH)/include -I$(BUILDROOT_PATH)/include/libxml2 -fPIC" \
LDFLAGS="-L$(BUILDROOT_PATH)/lib" \
LIBS="-lxml2 -lz" && \
make -C libxslt -j$(NPROC) && \
make -C libexslt -j$(NPROC)'

# libxslt.so: links against libxml2.so (DT_NEEDED libxml2.so), with
# libxslt's own .o files embedded via --whole-archive. libxml2 itself
# is NOT embedded — the loader will dlopen libxml2.so transitively
# when libxslt.so is loaded, so the libxml2 code is shared across
# every consumer. libposix/libc/libm symbols stay unresolved and
# bind at dlopen time against the host executable's `.dynsym`.
$(SHAREDLIB_XSLT): $(STATICLIB_XSLT)
sh -c '\
export PATH="$(NANVIX_TOOLCHAIN)/bin:$$PATH" && \
i686-nanvix-gcc -shared -fPIC -nostdlib \
-Wl,-soname,libxslt.so -Wl,-z,noexecstack \
-L$(BUILDROOT_PATH)/lib \
-Wl,--whole-archive $(STATICLIB_XSLT) -Wl,--no-whole-archive \
-lxml2 \
-o $(SHAREDLIB_XSLT)'

# libexslt.so: links against libxslt.so (DT_NEEDED libxslt.so), which
# transitively brings in libxml2.so. Only libexslt's own .o files are
# embedded. libposix/libc/libm symbols stay unresolved and bind at
# dlopen time against the host executable.
$(SHAREDLIB_EXSLT): $(STATICLIB_EXSLT) $(SHAREDLIB_XSLT)
sh -c '\
export PATH="$(NANVIX_TOOLCHAIN)/bin:$$PATH" && \
i686-nanvix-gcc -shared -fPIC -nostdlib \
-Wl,-soname,libexslt.so -Wl,-z,noexecstack \
-L$(BUILDROOT_PATH)/lib -Llibxslt/.libs \
-Wl,--whole-archive $(STATICLIB_EXSLT) -Wl,--no-whole-archive \
-lxslt -lxml2 \
-o $(SHAREDLIB_EXSLT)'

$(TEST_ELF): $(TEST_SRC)
@test -f $(STATICLIB_XSLT) || { echo " FAIL: $(STATICLIB_XSLT) not found; run 'build' first"; exit 1; }
@test -f $(STATICLIB_EXSLT) || { echo " FAIL: $(STATICLIB_EXSLT) not found; run 'build' first"; exit 1; }
Expand All @@ -118,18 +153,6 @@ $(TEST_ELF): $(TEST_SRC)
-Wl,--end-group \
-o $@

# ===========================================================================
# Install (stage artifacts into release/test output tree)
# ===========================================================================

install: $(STATICLIB_XSLT) $(STATICLIB_EXSLT) $(TEST_ELF)
@mkdir -p $(LIB_OUT) $(INCLUDE_OUT)/libxslt $(INCLUDE_OUT)/libexslt $(TEST_OUT)
cp -f $(STATICLIB_XSLT) $(LIB_OUT)/
cp -f $(STATICLIB_EXSLT) $(LIB_OUT)/
cp -f libxslt/*.h $(INCLUDE_OUT)/libxslt/
cp -f libexslt/*.h $(INCLUDE_OUT)/libexslt/
cp -f $(TEST_ELF) $(TEST_OUT)/

# ===========================================================================
# Test Targets
# ===========================================================================
Expand All @@ -138,7 +161,17 @@ test:
@echo "=== libxslt functional tests ==="
@test -f $(STATICLIB_XSLT) || { echo " FAIL: $(STATICLIB_XSLT) not found"; exit 1; }
@test -f $(STATICLIB_EXSLT) || { echo " FAIL: $(STATICLIB_EXSLT) not found"; exit 1; }
@test -f $(SHAREDLIB_XSLT) || { echo " FAIL: $(SHAREDLIB_XSLT) not found"; exit 1; }
@test -f $(SHAREDLIB_EXSLT) || { echo " FAIL: $(SHAREDLIB_EXSLT) not found"; exit 1; }
@test -s $(TEST_ELF) || { echo " FAIL: $(TEST_ELF) missing or empty"; exit 1; }
@$(NANVIX_TOOLCHAIN)/bin/i686-nanvix-readelf -d $(SHAREDLIB_XSLT) | grep -q 'SONAME.*libxslt.so' \
|| { echo " FAIL: SONAME=libxslt.so not set on $(SHAREDLIB_XSLT)"; exit 1; }
@$(NANVIX_TOOLCHAIN)/bin/i686-nanvix-readelf -d $(SHAREDLIB_EXSLT) | grep -q 'SONAME.*libexslt.so' \
|| { echo " FAIL: SONAME=libexslt.so not set on $(SHAREDLIB_EXSLT)"; exit 1; }
@$(NANVIX_TOOLCHAIN)/bin/i686-nanvix-nm -D $(SHAREDLIB_XSLT) | grep -q 'T xsltApplyStylesheet' \
|| { echo " FAIL: xsltApplyStylesheet missing from $(SHAREDLIB_XSLT) .dynsym"; exit 1; }
@$(NANVIX_TOOLCHAIN)/bin/i686-nanvix-nm -D $(SHAREDLIB_EXSLT) | grep -q 'T exsltRegisterAll' \
|| { echo " FAIL: exsltRegisterAll missing from $(SHAREDLIB_EXSLT) .dynsym"; exit 1; }
@echo " OK: build artifacts present (runtime execution is driven by z.py on the host)"
@echo "=== libxslt functional test prerequisites PASSED ==="

Expand All @@ -149,6 +182,6 @@ test:
clean:
-$(MAKE) clean 2>/dev/null || true
rm -f $(TEST_ELF) Makefile
rm -rf $(OUT_DIR) dist/ libxslt/.libs/ libexslt/.libs/
rm -rf dist/ libxslt/.libs/ libexslt/.libs/
Comment thread
esaurez marked this conversation as resolved.

.PHONY: all install clean test
.PHONY: all clean test
6 changes: 4 additions & 2 deletions .nanvix/z.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

Usage:
./z setup # Download Nanvix sysroot
./z build # Cross-compile libxslt.a and libexslt.a
./z build # Cross-compile libxslt.a/.so and libexslt.a/.so
./z test # Run test suite (smoke + integration + functional)
./z release # Package release tarball
./z clean # Remove build artifacts
Expand Down Expand Up @@ -87,7 +87,9 @@ def _staged_output_files(self) -> list[str]:
root = repo_root()
return [
str((lib_out() / "libxslt.a").relative_to(root)),
str((lib_out() / "libxslt.so").relative_to(root)),
str((lib_out() / "libexslt.a").relative_to(root)),
str((lib_out() / "libexslt.so").relative_to(root)),
str((test_out() / "test_libxslt.elf").relative_to(root)),
]

Expand Down Expand Up @@ -139,7 +141,7 @@ def translate(p: Path):
return args

def build(self) -> None:
"""Cross-compile libxslt.a and libexslt.a for Nanvix."""
"""Cross-compile libxslt.a/.so and libexslt.a/.so for Nanvix."""
run(*self._make_args("all"), cwd=repo_root(), docker=self.docker)

def test(self) -> None:
Expand Down
Loading