gbuild: LinkTarget: only re-link libraries if exported symbols change

Write out the exported symbols of a Library to a "libfoo.so.exports"
file, which is only touched when linking if the exported symbols
actually change, and let dependent LinkTargets depend on this
exports file instead of the library itself, for faster rebuilds.

This is currently supposed to work on ELF and MacOSX platforms.

Thanks to Ami Fischman of Chromium for the idea.

Change-Id: Ie4b5da0853140709e517028b514800b044527e61
This commit is contained in:
Michael Stahl 2013-04-08 10:59:59 +02:00
parent eacf12eeb1
commit 3213cd54b7
6 changed files with 47 additions and 1 deletions

View file

@ -402,6 +402,7 @@ $(call gb_LinkTarget_get_clean_target,%) :
$(call gb_LinkTarget_get_headers_target,$*) \
$(call gb_LinkTarget_get_external_headers_target,$*) \
$(call gb_LinkTarget_get_objects_list,$*) \
$(call gb_LinkTarget_get_target,$*).exports \
$(DLLTARGET) \
$(AUXTARGETS)) && \
cat $${RESPONSEFILE} /dev/null | xargs -n 200 rm -fr && \
@ -442,6 +443,14 @@ mv $${TEMPFILE} $(call gb_LinkTarget_get_objects_list,$(2))
endef
# Target for the .exports of the shared library, to speed up incremental build.
# This deliberately does nothing if the file exists; the file is actually
# written in gb_LinkTarget__command_dynamiclink.
# Put this pattern rule here so it overrides the one below.
# (this is rather ugly: because of % the functions cannot be used)
$(call gb_LinkTarget_get_target,Library/%.exports) : $(gb_Library_OUTDIRLOCATION)/%
$(if $(wildcard $@),true,touch $@)
$(call gb_LinkTarget_get_target,%) : $(call gb_LinkTarget_get_headers_target,%) $(gb_Helper_MISCDUMMY)
$(call gb_LinkTarget__command,$@,$*)
$(call gb_LinkTarget__command_objectlist,$@,$*)
@ -830,7 +839,10 @@ endif
$(call gb_LinkTarget_get_target,$(1)) : LINKED_LIBS += $(3)
$(call gb_LinkTarget_get_target,$(1)) : $(foreach lib,$(3),$(call gb_Library_get_target,$(lib)))
# depend on the exports of the library, not on the library itself
# for faster incremental builds when the ABI is unchanged
$(call gb_LinkTarget_get_target,$(1)) : \
$(foreach lib,$(3),$(call gb_Library_get_exports_target,$(lib)))
$(call gb_LinkTarget_get_external_headers_target,$(1)) : \
$(foreach lib,$(2),$(call gb_Library_get_headers_target,$(lib)))

View file

@ -240,6 +240,10 @@ $(call gb_Helper_abbreviate_dirs,\
)
endef
define gb_Library_get_exports_target
$(call gb_LinkTarget_get_target,$(call gb_Library_get_linktargetname,$(1))).exports
endef
# YaccTarget class
ifeq ($(ANCIENT_BISON),YES)

View file

@ -351,6 +351,11 @@ define gb_Library_get_dllname
$(patsubst $(1):%,%,$(filter $(1):%,$(gb_Library_DLLFILENAMES)))
endef
# this is nerfed, it just points to the library to disable the .exports
define gb_Library_get_exports_target
$(call gb_LinkTarget_get_target,$(call gb_Library_get_linktargetname,$(1)))
endef
# StaticLibrary class

View file

@ -163,6 +163,14 @@ $(call gb_Helper_abbreviate_dirs,\
$(if $(MACOSX_CODESIGNING_IDENTITY), \
$(if $(filter Executable,$(TARGETTYPE)), \
codesign --timestamp=none --identifier=$(MACOSX_BUNDLE_IDENTIFIER).$(notdir $(1)) --sign $(MACOSX_CODESIGNING_IDENTITY) $(1) &&)) \
$(if $(filter Library,$(TARGETTYPE)),\
otool -l $(1) | grep -A 5 LC_ID_DYLIB > $(1).exports.tmp && \
$(NM) -g -P $(1) | cut -d' ' -f1-2 | grep -v U$$ \
>> $(1).exports.tmp && \
if cmp -s $(1).exports.tmp $(1).exports; \
then rm $(1).exports.tmp; \
else mv $(1).exports.tmp $(1).exports; touch -r $(1) $(1).exports; \
fi &&) \
:)
endef

View file

@ -199,6 +199,14 @@ $(call gb_Helper_abbreviate_dirs,\
$(LIBS) \
$(patsubst lib%.a,-l%,$(patsubst lib%.so,-l%,$(foreach lib,$(LINKED_LIBS),$(call gb_Library_get_filename,$(lib))))) \
-o $(1))
$(if $(filter Library,$(TARGETTYPE)),\
$(NM) --extern-only --dynamic --format=posix $(1) \
| cut -d' ' -f1-2 | grep -v U$$ \
> $(1).exports.tmp && \
if cmp -s $(1).exports.tmp $(1).exports; \
then rm $(1).exports.tmp; \
else mv $(1).exports.tmp $(1).exports; touch -r $(1) $(1).exports; \
fi)
endef
define gb_LinkTarget__command_staticlink

View file

@ -202,6 +202,15 @@ $(call gb_Helper_abbreviate_dirs,\
$(patsubst lib%.a,-l%,$(patsubst lib%.so,-l%,$(foreach lib,$(LINKED_LIBS),$(call gb_Library_get_filename,$(lib))))) \
-o $(if $(SOVERSION),$(1).$(SOVERSION),$(1)))
$(if $(SOVERSION),ln -sf $(notdir $(1)).$(SOVERSION) $(1))
$(if $(filter Library,$(TARGETTYPE)),\
readelf -d $(1) | grep SONAME > $(1).exports.tmp ; \
$(NM) --dynamic --extern-only --defined-only --format=posix $(1) \
| cut -d' ' -f1-2 \
>> $(1).exports.tmp && \
if cmp -s $(1).exports.tmp $(1).exports; \
then rm $(1).exports.tmp; \
else mv $(1).exports.tmp $(1).exports; touch -r $(1) $(1).exports; \
fi)
endef
define gb_LinkTarget__command_staticlink