Bug 934864 - Add option to make INSTALL_TARGETS and PP_TARGETS keep the original path when copying/preprocessing. r=gps
authorMike Hommey <mh+mozilla@glandium.org>
Sat, 09 Nov 2013 10:32:53 +0900
changeset 154592 97daebf6405b17fe368e76809b8926b4892e3f9b
parent 154591 06d3a099e96be3acc0f08c27aec3aeaea2943ef3
child 154593 4810e8f4eb98462aa7134d691d5dc240163e2f53
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
reviewersgps
bugs934864
milestone28.0a1
Bug 934864 - Add option to make INSTALL_TARGETS and PP_TARGETS keep the original path when copying/preprocessing. r=gps Also, refactored them for more debuggability and clarity.
config/rules.mk
js/src/config/rules.mk
security/build/Makefile.in
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -1476,44 +1476,77 @@ endif
 #
 # FOO_FILES := foo bar
 # FOO_EXECUTABLES := baz
 # FOO_DEST := target_path
 # INSTALL_TARGETS += FOO
 #
 # Additionally, a FOO_TARGET variable may be added to indicate the target for
 # which the files and executables are installed. Default is "libs".
+#
+# Finally, a FOO_KEEP_PATH variable may be set to 1 to indicate the paths given
+# in FOO_FILES/FOO_EXECUTABLES are to be kept at the destination. That is,
+# if FOO_FILES is bar/baz/qux.h, and FOO_DEST is $(DIST)/include, the installed
+# file would be $(DIST)/include/bar/baz/qux.h instead of $(DIST)/include/qux.h
 
 # If we're using binary nsinstall and it's not built yet, fallback to python nsinstall.
 ifneq (,$(filter $(CONFIG_TOOLS)/nsinstall$(HOST_BIN_SUFFIX),$(install_cmd)))
 ifeq (,$(wildcard $(CONFIG_TOOLS)/nsinstall$(HOST_BIN_SUFFIX)))
 nsinstall_is_usable = $(if $(wildcard $(CONFIG_TOOLS)/nsinstall$(HOST_BIN_SUFFIX)),yes)
 
 define install_cmd_override
 $(1): install_cmd = $$(if $$(nsinstall_is_usable),$$(INSTALL),$$(NSINSTALL_PY)) $$(1)
 endef
 endif
 endif
 
-define install_file_template
-$(or $(3),libs):: $(2)/$(notdir $(1))
-$(call install_cmd_override,$(2)/$(notdir $(1)))
-$(2)/$(notdir $(1)): $(1)
-	$$(call install_cmd,$(4) "$$<" "$${@D}")
+install_target_tier = $(or $($(1)_TARGET),libs)
+INSTALL_TARGETS_TIERS := $(sort $(foreach category,$(INSTALL_TARGETS),$(call install_target_tier,$(category))))
+
+install_target_result = $($(1)_DEST:%/=%)/$(if $($(1)_KEEP_PATH),$(2),$(notdir $(2)))
+install_target_files = $(foreach file,$($(1)_FILES),$(call install_target_result,$(category),$(file)))
+install_target_executables = $(foreach file,$($(1)_EXECUTABLES),$(call install_target_result,$(category),$(file)))
+
+# Work around a GNU make 3.81 bug where it gives $< the wrong value.
+# See details in bug 934864.
+define create_dependency
+$(1): $(2)
+$(1): $(2)
 endef
+
+define install_target_template
+$(call install_cmd_override,$(2))
+$(call create_dependency,$(2),$(1))
+endef
+
 $(foreach category,$(INSTALL_TARGETS),\
-  $(if $($(category)_DEST),,$(error Missing $(category)_DEST))\
-  $(foreach file,$($(category)_FILES),\
-    $(eval $(call install_file_template,$(file),$($(category)_DEST),$($(category)_TARGET),$(IFLAGS1)))\
-  )\
-  $(foreach file,$($(category)_EXECUTABLES),\
-    $(eval $(call install_file_template,$(file),$($(category)_DEST),$($(category)_TARGET),$(IFLAGS2)))\
-  )\
+  $(if $($(category)_DEST),,$(error Missing $(category)_DEST)) \
+  $(foreach tier,$(call install_target_tier,$(category)),\
+    $(eval INSTALL_TARGETS_FILES_$(tier) += $(call install_target_files,$(category))) \
+    $(eval INSTALL_TARGETS_EXECUTABLES_$(tier) += $(call install_target_executables,$(category))) \
+  ) \
+  $(foreach file,$($(category)_FILES) $($(category)_EXECUTABLES), \
+    $(eval $(call install_target_template,$(file),$(call install_target_result,$(category),$(file)))) \
+  ) \
 )
 
+$(foreach tier,$(INSTALL_TARGETS_TIERS), \
+  $(eval $(tier):: $(INSTALL_TARGETS_FILES_$(tier)) $(INSTALL_TARGETS_EXECUTABLES_$(tier))) \
+)
+
+install_targets_sanity = $(if $(filter-out $(notdir $@),$(notdir $(<))),$(error Looks like $@ has an unexpected dependency on $< which breaks INSTALL_TARGETS))
+
+$(sort $(foreach tier,$(INSTALL_TARGETS_TIERS),$(INSTALL_TARGETS_FILES_$(tier)))):
+	$(install_targets_sanity)
+	$(call install_cmd,$(IFLAGS1) "$<" "$(@D)")
+
+$(sort $(foreach tier,$(INSTALL_TARGETS_TIERS),$(INSTALL_TARGETS_EXECUTABLES_$(tier)))):
+	$(install_targets_sanity)
+	$(call install_cmd,$(IFLAGS2) "$<" "$(@D)")
+
 ################################################################################
 # Preprocessing rules
 #
 # The PP_TARGETS variable contains a list of all preprocessing target
 # categories. Each category has associated variables listing input files, the
 # output directory, extra preprocessor flags, and so on. For example:
 #
 #   FOO := input-file
@@ -1533,36 +1566,48 @@ endef
 #   this variable is optional; if unset, we install the files in $(CURDIR).
 #
 # - <C>_FLAGS lists flags to pass to Preprocessor.py, in addition to the usual
 #   bunch. Setting this variable is optional.
 #
 # - <C>_TARGET names the 'make' target that should depend on creating the output
 #   files. Setting this variable is optional; if unset, we preprocess the
 #   files for the 'libs' target.
+#
+# - <C>_KEEP_PATH may be set to 1 to indicate the paths given in <C> are to be
+#   kept under <C>_PATH. That is, if <C> is bar/baz/qux.h.in and <C>_PATH is
+#   $(DIST)/include, the preprocessed file would be $(DIST)/include/bar/baz/qux.h
+#   instead of $(DIST)/include/qux.h.
 
-# preprocess_file_template defines preprocessing rules.
-# $(call preprocess_file_template, source_file, output_file,
-#                                  makefile_target, extra_flags)
-define preprocess_file_template
-$(2): $(1) $$(GLOBAL_DEPS)
-	$$(RM) "$$@"
-	$$(PYTHON) $$(topsrcdir)/config/Preprocessor.py $(4) $$(DEFINES) $$(ACDEFINES) $$(XULPPFLAGS) "$$<" -o "$$@"
-$(3):: $(2)
-endef
+pp_target_tier = $(or $($(1)_TARGET),libs)
+PP_TARGETS_TIERS := $(sort $(foreach category,$(PP_TARGETS),$(call pp_target_tier,$(category))))
+
+pp_target_result = $(or $($(1)_PATH:%/=%),$(CURDIR))/$(if $($(1)_KEEP_PATH),$(2:.in=),$(notdir $(2:.in=)))
+pp_target_results = $(foreach file,$($(1)),$(call pp_target_result,$(category),$(file)))
 
-$(foreach category,$(PP_TARGETS),						\
-  $(foreach file,$($(category)),						\
-    $(eval $(call preprocess_file_template,					\
-                  $(file),							\
-                  $(or $($(category)_PATH),$(CURDIR))/$(notdir $(file:.in=)),	\
-                  $(or $($(category)_TARGET),libs),				\
-                  $($(category)_FLAGS)))					\
-   )										\
- )
+$(foreach category,$(PP_TARGETS), \
+  $(foreach tier,$(call pp_target_tier,$(category)), \
+    $(eval PP_TARGETS_RESULTS_$(tier) += $(call pp_target_results,$(category))) \
+  ) \
+  $(foreach file,$($(category)), \
+    $(eval $(call create_dependency,$(call pp_target_result,$(category),$(file)), \
+                                    $(file) $(GLOBAL_DEPS))) \
+  ) \
+  $(eval $(call pp_target_results,$(category)): PP_TARGET_FLAGS=$($(category)_FLAGS)) \
+)
+
+$(foreach tier,$(PP_TARGETS_TIERS), \
+  $(eval $(tier):: $(PP_TARGETS_RESULTS_$(tier))) \
+)
+
+$(sort $(foreach tier,$(PP_TARGETS_TIERS),$(PP_TARGETS_RESULTS_$(tier)))):
+	$(if $(filter-out $(notdir $@),$(notdir $(<:.in=))),$(error Looks like $@ has an unexpected dependency on $< which breaks PP_TARGETS))
+	$(RM) "$@"
+	$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(PP_TARGET_FLAGS) $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) "$<" -o "$@"
+
 
 # Pull in non-recursive targets if this is a partial tree build.
 ifndef TOPLEVEL_BUILD
 include $(topsrcdir)/config/makefiles/nonrecursive.mk
 endif
 
 ################################################################################
 # Special gmake rules.
--- a/js/src/config/rules.mk
+++ b/js/src/config/rules.mk
@@ -1476,44 +1476,77 @@ endif
 #
 # FOO_FILES := foo bar
 # FOO_EXECUTABLES := baz
 # FOO_DEST := target_path
 # INSTALL_TARGETS += FOO
 #
 # Additionally, a FOO_TARGET variable may be added to indicate the target for
 # which the files and executables are installed. Default is "libs".
+#
+# Finally, a FOO_KEEP_PATH variable may be set to 1 to indicate the paths given
+# in FOO_FILES/FOO_EXECUTABLES are to be kept at the destination. That is,
+# if FOO_FILES is bar/baz/qux.h, and FOO_DEST is $(DIST)/include, the installed
+# file would be $(DIST)/include/bar/baz/qux.h instead of $(DIST)/include/qux.h
 
 # If we're using binary nsinstall and it's not built yet, fallback to python nsinstall.
 ifneq (,$(filter $(CONFIG_TOOLS)/nsinstall$(HOST_BIN_SUFFIX),$(install_cmd)))
 ifeq (,$(wildcard $(CONFIG_TOOLS)/nsinstall$(HOST_BIN_SUFFIX)))
 nsinstall_is_usable = $(if $(wildcard $(CONFIG_TOOLS)/nsinstall$(HOST_BIN_SUFFIX)),yes)
 
 define install_cmd_override
 $(1): install_cmd = $$(if $$(nsinstall_is_usable),$$(INSTALL),$$(NSINSTALL_PY)) $$(1)
 endef
 endif
 endif
 
-define install_file_template
-$(or $(3),libs):: $(2)/$(notdir $(1))
-$(call install_cmd_override,$(2)/$(notdir $(1)))
-$(2)/$(notdir $(1)): $(1)
-	$$(call install_cmd,$(4) "$$<" "$${@D}")
+install_target_tier = $(or $($(1)_TARGET),libs)
+INSTALL_TARGETS_TIERS := $(sort $(foreach category,$(INSTALL_TARGETS),$(call install_target_tier,$(category))))
+
+install_target_result = $($(1)_DEST:%/=%)/$(if $($(1)_KEEP_PATH),$(2),$(notdir $(2)))
+install_target_files = $(foreach file,$($(1)_FILES),$(call install_target_result,$(category),$(file)))
+install_target_executables = $(foreach file,$($(1)_EXECUTABLES),$(call install_target_result,$(category),$(file)))
+
+# Work around a GNU make 3.81 bug where it gives $< the wrong value.
+# See details in bug 934864.
+define create_dependency
+$(1): $(2)
+$(1): $(2)
 endef
+
+define install_target_template
+$(call install_cmd_override,$(2))
+$(call create_dependency,$(2),$(1))
+endef
+
 $(foreach category,$(INSTALL_TARGETS),\
-  $(if $($(category)_DEST),,$(error Missing $(category)_DEST))\
-  $(foreach file,$($(category)_FILES),\
-    $(eval $(call install_file_template,$(file),$($(category)_DEST),$($(category)_TARGET),$(IFLAGS1)))\
-  )\
-  $(foreach file,$($(category)_EXECUTABLES),\
-    $(eval $(call install_file_template,$(file),$($(category)_DEST),$($(category)_TARGET),$(IFLAGS2)))\
-  )\
+  $(if $($(category)_DEST),,$(error Missing $(category)_DEST)) \
+  $(foreach tier,$(call install_target_tier,$(category)),\
+    $(eval INSTALL_TARGETS_FILES_$(tier) += $(call install_target_files,$(category))) \
+    $(eval INSTALL_TARGETS_EXECUTABLES_$(tier) += $(call install_target_executables,$(category))) \
+  ) \
+  $(foreach file,$($(category)_FILES) $($(category)_EXECUTABLES), \
+    $(eval $(call install_target_template,$(file),$(call install_target_result,$(category),$(file)))) \
+  ) \
 )
 
+$(foreach tier,$(INSTALL_TARGETS_TIERS), \
+  $(eval $(tier):: $(INSTALL_TARGETS_FILES_$(tier)) $(INSTALL_TARGETS_EXECUTABLES_$(tier))) \
+)
+
+install_targets_sanity = $(if $(filter-out $(notdir $@),$(notdir $(<))),$(error Looks like $@ has an unexpected dependency on $< which breaks INSTALL_TARGETS))
+
+$(sort $(foreach tier,$(INSTALL_TARGETS_TIERS),$(INSTALL_TARGETS_FILES_$(tier)))):
+	$(install_targets_sanity)
+	$(call install_cmd,$(IFLAGS1) "$<" "$(@D)")
+
+$(sort $(foreach tier,$(INSTALL_TARGETS_TIERS),$(INSTALL_TARGETS_EXECUTABLES_$(tier)))):
+	$(install_targets_sanity)
+	$(call install_cmd,$(IFLAGS2) "$<" "$(@D)")
+
 ################################################################################
 # Preprocessing rules
 #
 # The PP_TARGETS variable contains a list of all preprocessing target
 # categories. Each category has associated variables listing input files, the
 # output directory, extra preprocessor flags, and so on. For example:
 #
 #   FOO := input-file
@@ -1533,36 +1566,48 @@ endef
 #   this variable is optional; if unset, we install the files in $(CURDIR).
 #
 # - <C>_FLAGS lists flags to pass to Preprocessor.py, in addition to the usual
 #   bunch. Setting this variable is optional.
 #
 # - <C>_TARGET names the 'make' target that should depend on creating the output
 #   files. Setting this variable is optional; if unset, we preprocess the
 #   files for the 'libs' target.
+#
+# - <C>_KEEP_PATH may be set to 1 to indicate the paths given in <C> are to be
+#   kept under <C>_PATH. That is, if <C> is bar/baz/qux.h.in and <C>_PATH is
+#   $(DIST)/include, the preprocessed file would be $(DIST)/include/bar/baz/qux.h
+#   instead of $(DIST)/include/qux.h.
 
-# preprocess_file_template defines preprocessing rules.
-# $(call preprocess_file_template, source_file, output_file,
-#                                  makefile_target, extra_flags)
-define preprocess_file_template
-$(2): $(1) $$(GLOBAL_DEPS)
-	$$(RM) "$$@"
-	$$(PYTHON) $$(topsrcdir)/config/Preprocessor.py $(4) $$(DEFINES) $$(ACDEFINES) $$(XULPPFLAGS) "$$<" -o "$$@"
-$(3):: $(2)
-endef
+pp_target_tier = $(or $($(1)_TARGET),libs)
+PP_TARGETS_TIERS := $(sort $(foreach category,$(PP_TARGETS),$(call pp_target_tier,$(category))))
+
+pp_target_result = $(or $($(1)_PATH:%/=%),$(CURDIR))/$(if $($(1)_KEEP_PATH),$(2:.in=),$(notdir $(2:.in=)))
+pp_target_results = $(foreach file,$($(1)),$(call pp_target_result,$(category),$(file)))
 
-$(foreach category,$(PP_TARGETS),						\
-  $(foreach file,$($(category)),						\
-    $(eval $(call preprocess_file_template,					\
-                  $(file),							\
-                  $(or $($(category)_PATH),$(CURDIR))/$(notdir $(file:.in=)),	\
-                  $(or $($(category)_TARGET),libs),				\
-                  $($(category)_FLAGS)))					\
-   )										\
- )
+$(foreach category,$(PP_TARGETS), \
+  $(foreach tier,$(call pp_target_tier,$(category)), \
+    $(eval PP_TARGETS_RESULTS_$(tier) += $(call pp_target_results,$(category))) \
+  ) \
+  $(foreach file,$($(category)), \
+    $(eval $(call create_dependency,$(call pp_target_result,$(category),$(file)), \
+                                    $(file) $(GLOBAL_DEPS))) \
+  ) \
+  $(eval $(call pp_target_results,$(category)): PP_TARGET_FLAGS=$($(category)_FLAGS)) \
+)
+
+$(foreach tier,$(PP_TARGETS_TIERS), \
+  $(eval $(tier):: $(PP_TARGETS_RESULTS_$(tier))) \
+)
+
+$(sort $(foreach tier,$(PP_TARGETS_TIERS),$(PP_TARGETS_RESULTS_$(tier)))):
+	$(if $(filter-out $(notdir $@),$(notdir $(<:.in=))),$(error Looks like $@ has an unexpected dependency on $< which breaks PP_TARGETS))
+	$(RM) "$@"
+	$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(PP_TARGET_FLAGS) $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) "$<" -o "$@"
+
 
 # Pull in non-recursive targets if this is a partial tree build.
 ifndef TOPLEVEL_BUILD
 include $(topsrcdir)/config/makefiles/nonrecursive.mk
 endif
 
 ################################################################################
 # Special gmake rules.
--- a/security/build/Makefile.in
+++ b/security/build/Makefile.in
@@ -379,18 +379,16 @@ DEFFILE = nss3.def
 
 nss3.def: $(NSS_STATIC_LIBS_DEFS) $(DEPTH)/db/sqlite3/src/sqlite-processed.def
 	echo LIBRARY nss3$(DLL_SUFFIX) > $@.tmp
 	echo EXPORTS >> $@.tmp
 	grep -v -h -e ^LIBRARY -e ^EXPORTS -e ^\; $^ >> $@.tmp
 	mv $@.tmp $@
 endif
 
-else
-$(NSS_DIST_DLL_FILES) $(NSS_SDK_LIB_FILES): libs-nss/lib
 endif # MOZ_FOLD_LIBS
 
 include $(topsrcdir)/config/rules.mk
 
 ifdef MOZ_FOLD_LIBS
 # Force the linker to include everything from the static libraries.
 EXPAND_LIBS_EXEC += --extract
 
@@ -441,16 +439,18 @@ ifndef NSS_DISABLE_DBM
 libs-nss/lib/softoken: libs-nss/lib/dbm
 endif
 libs-nss/lib/softoken: $(DIST)/lib/$(IMPORT_PREFIX)nssutil3$(IMPORT_SUFFIX)
 libs-nss/lib/freebl: $(DIST)/lib/$(IMPORT_PREFIX)nssutil3$(IMPORT_SUFFIX) $(NSPR_IMPORT_LIBS)
 
 # For each directory where we build static libraries, force the NSS build system
 # to only build static libraries.
 $(addprefix libs-,$(NSS_STATIC_DIRS)): DEFAULT_GMAKE_FLAGS += SHARED_LIBRARY= IMPORT_LIBRARY=
+else
+$(NSS_DIST_DLL_FILES) $(NSS_SDK_LIB_FILES): libs-nss/lib
 endif # MOZ_FOLD_LIBS
 
 ifeq ($(NSINSTALL_PY),$(NSINSTALL))
 DEFAULT_GMAKE_FLAGS += PYTHON='$(PYTHON)'
 DEFAULT_GMAKE_FLAGS += NSINSTALL_PY='$(abspath $(topsrcdir)/config/nsinstall.py)'
 DEFAULT_GMAKE_FLAGS += NSINSTALL='$$(PYTHON) $$(NSINSTALL_PY)'
 else
 DEFAULT_GMAKE_FLAGS += NSINSTALL='$(NSINSTALL)'