Add support for static linking.

Use `make STATIC=1` to build a static library.

Some language ecosystems, like those of Rust, have a convention of
static linking in order to make binaries easier to distribute. In those
environments, this feature helps libui fit in more easily.

In order to prevent internal symbols from linking, we first create an
intermediate object file with `ld -r` and strip private symbols from it
before using `ar` to create the library.
This commit is contained in:
Patrick Walton 2016-05-25 15:18:48 -07:00
parent 18a84988fd
commit 5f1e8fa601
13 changed files with 77 additions and 18 deletions

View File

@ -46,9 +46,14 @@ export DESTDIR
# other important variables
export OBJDIR
export OUTDIR
export STATIC
ifneq (,$(STATIC))
STATICLIB = STATICLIB=1
endif
libui:
@$(MAKE) -f build/GNUmakefile.libui inlibuibuild=1
@$(MAKE) -f build/GNUmakefile.libui inlibuibuild=1 $(STATICLIB)
clean:
rm -rf $(OBJDIR) $(OUTDIR)

View File

@ -50,12 +50,7 @@ else
reallinker = $(CXX)
endif
$(OUT): $(OFILES) | $(OUTDIR)
@$(reallinker) -o $(OUT) $(OFILES) $(LDFLAGS)
ifeq ($(USESSONAME),1)
@ln -sf $(NAME)$(SUFFIX) $(OUTNOSONAME)
endif
@echo ====== Linked $(OUT)
include $(OS)/GNUosspecificlink.mk
.SECONDEXPANSION:

View File

@ -69,7 +69,11 @@ OUT = $(OUTDIR)/$(NAME)$(SUFFIX)
# TODO use $(CC), $(CXX), $(LD), and s$(RC)
$(OUT): $(OFILES) | $(OUTDIR)
ifeq (,$(STATICLIB))
@link -out:$(OUT) $(OFILES) $(LDFLAGS)
else
@lib -out:$(OUT) $(OFILES)
endif
@echo ====== Linked $(OUT)
.SECONDEXPANSION:

View File

@ -30,7 +30,11 @@ SUFFIX = $(EXESUFFIX)
# TODO merge with the one in build/GNUmakefile.test
ifeq ($(TOOLCHAIN),gcc)
ifeq (,$(STATIC))
LDFLAGS += -L$(OUTDIR) -lui
else
LDFLAGS += -L$(OUTDIR) -lui $(NATIVE_UI_LDFLAGS)
endif
# see build/GNUmakefile.test
ifeq ($(OS),darwin)
LDFLAGS += -Wl,-rpath,@executable_path/

View File

@ -17,10 +17,14 @@ HFILES += \
ui_$(OS)$(OSHSUFFIX)
NAME = libui
ifeq (,$(STATIC))
SUFFIX = $(LIBSUFFIX)
ifeq ($(USESSONAME),1)
SUFFIX = $(SONAMEEXT)
endif
else
SUFFIX = $(STATICLIBSUFFIX)
endif
ifeq ($(TOOLCHAIN),gcc)
# make every symbol hidden by default except _UI_EXTERN ones

View File

@ -42,10 +42,7 @@ HFILES += \
# LONGTERM split into a separate file or put in GNUmakefile.libui somehow?
# flags for Cocoa
LDFLAGS += \
-lobjc \
-framework Foundation \
-framework AppKit
LDFLAGS += $(NATIVE_UI_LDFLAGS)
# flags for OS X versioning
CFLAGS += \
@ -57,9 +54,11 @@ CXXFLAGS += \
LDFLAGS += \
-mmacosx-version-min=10.8
ifeq (,$(STATIC))
# flags for building a shared library
LDFLAGS += \
-dynamiclib
endif
# on warning about undefined symbols:
# the gcc flags don't work with Apple's linker

View File

@ -3,6 +3,7 @@
EXESUFFIX =
LIBSUFFIX = .dylib
OSHSUFFIX = .h
STATICLIBSUFFIX = .a
TOOLCHAIN = gcc
USESSONAME = 1
@ -11,3 +12,9 @@ SONAMEEXT = .$(SOVERSION)$(LIBSUFFIX)
# note the explicit need for @rpath
# LONGTERM -current_version, -compatibility_version
SONAMEFLAG = -Wl,-install_name,@rpath/
NATIVE_UI_LDFLAGS += \
-lobjc \
-framework Foundation \
-framework AppKit

View File

@ -0,0 +1,15 @@
# 28 may 2016
$(OUT): $(OFILES) | $(OUTDIR)
ifeq (,$(STATICLIB))
@$(reallinker) -o $(OUT) $(OFILES) $(LDFLAGS)
ifeq ($(USESSONAME),1)
@ln -sf $(NAME)$(SUFFIX) $(OUTNOSONAME)
endif
else
nm -m $(OFILES) | sed -E -n 's/^[0-9a-f]* \([A-Z_]+,[a-z_]+\) external //p' > $(OBJDIR)/symbols
$(LD) -exported_symbols_list $(OBJDIR)/symbols -r $(OFILES) -o $(OUT:%.a=%.o)
$(AR) rcs $(OUT) $(OUT:%.a=%.o)
endif
@echo ====== Linked $(OUT)

View File

@ -43,17 +43,16 @@ HFILES += \
# LONGTERM split into a separate file or put in GNUmakefile.libui somehow?
# flags for GTK+
CFLAGS += \
`pkg-config --cflags gtk+-3.0`
CXXFLAGS += \
`pkg-config --cflags gtk+-3.0`
LDFLAGS += \
`pkg-config --libs gtk+-3.0` -lm -ldl
CFLAGS += $(NATIVE_UI_CFLAGS)
CXXFLAGS += $(NATIVE_UI_CXXFLAGS)
LDFLAGS += $(NATIVE_UI_LDFLAGS)
# flags for building a shared library
# OS X does support -shared but it has a preferred name for this so let's use that there instead; hence this is not gcc-global
ifeq (,$(STATIC))
LDFLAGS += \
-shared
endif
# flags for warning on undefined symbols
# this is not gcc-global because OS X doesn't support these flags

View File

@ -3,6 +3,7 @@
EXESUFFIX =
LIBSUFFIX = .so
OSHSUFFIX = .h
STATICLIBSUFFIX = .a
TOOLCHAIN = gcc
# LONGTERM clean up all the NAMEs and SUFFIXs and NOSOSUFFIXs or whatever it was
@ -11,3 +12,11 @@ SOVERSION = $(SOVERSION0)
SONAMEEXT = $(LIBSUFFIX).$(SOVERSION)
# this is not gcc-global because OS X uses a different filename format
SONAMEFLAG = -Wl,-soname,
NATIVE_UI_CFLAGS = \
`pkg-config --cflags gtk+-3.0`
NATIVE_UI_CXXFLAGS = \
`pkg-config --cflags gtk+-3.0`
NATIVE_UI_LDFLAGS = \
`pkg-config --libs gtk+-3.0` -lm -ldl

15
unix/GNUosspecificlink.mk Normal file
View File

@ -0,0 +1,15 @@
# 28 may 2016
$(OUT): $(OFILES) | $(OUTDIR)
ifeq (,$(STATICLIB))
@$(reallinker) -o $(OUT) $(OFILES) $(LDFLAGS)
ifeq ($(USESSONAME),1)
@ln -sf $(NAME)$(SUFFIX) $(OUTNOSONAME)
endif
else
$(LD) -r $(OFILES) -o $(OUT:%.a=%.o)
objcopy --localize-hidden $(OUT:%.a=%.o)
$(AR) rcs $(OUT) $(OUT:%.a=%.o)
endif
@echo ====== Linked $(OUT)

View File

@ -73,8 +73,10 @@ LDFLAGS += \
user32.lib kernel32.lib usp10.lib gdi32.lib comctl32.lib uxtheme.lib msimg32.lib comdlg32.lib d2d1.lib dwrite.lib ole32.lib oleaut32.lib oleacc.lib uuid.lib
# flags for building a shared library
ifeq (,$(STATIC))
LDFLAGS += \
-dll
endif
# TODO flags for warning on undefined symbols

View File

@ -3,6 +3,7 @@
EXESUFFIX = .exe
LIBSUFFIX = .dll
OSHSUFFIX = .h
STATICLIBSUFFIX = .lib
TOOLCHAIN = msvc
USESSONAME = 0