Make:Improve directory generation portability.
authorEvan Lloyd <evan.lloyd@arm.com>
Thu, 3 Dec 2015 12:19:30 +0000 (12:19 +0000)
committerEvan Lloyd <evan.lloyd@arm.com>
Fri, 1 Apr 2016 11:33:09 +0000 (12:33 +0100)
Because of command differences in some build environments the "inline"
method of generating the build directory structure is not portable.
(e.g. in DOS environments the mkdir shell command fails if a directory
already exists, whereas in UNIX environments it succeeds.)

To improve portability we generate the directories needed using make,
but use the "order-only prerequisites" feature of make to prevent writes
of files into the directories generating re-builds, as suggested in the
GNU make Manual (Version 4.1 September 2014).

Change-Id: Ic9af475831063c7fe6f8bccffef184d79e799419

make_helpers/build_macros.mk

index 5a67c4c1b022315e23c2db2b0add33b92723f299..f82ba534d20ef13ea4b23b2e010ffeb7e1ace2e1 100644 (file)
@@ -210,10 +210,8 @@ $(OBJ): $(2)
        @echo "  CC      $$<"
        $$(Q)$$(CC) $$(CFLAGS) -D$(IMAGE) -c $$< -o $$@
 
-
-$(PREREQUISITES): $(2)
+$(PREREQUISITES): $(2) | bl$(3)_dirs
        @echo "  DEPS    $$@"
-       @mkdir -p $(1)
        $$(Q)$$(CC) $$(CFLAGS) -M -MT $(OBJ) -MF $$@ $$<
 
 ifdef IS_ANYTHING_TO_BUILD
@@ -237,9 +235,8 @@ $(OBJ): $(2)
        @echo "  AS      $$<"
        $$(Q)$$(AS) $$(ASFLAGS) -D$(IMAGE) -c $$< -o $$@
 
-$(PREREQUISITES): $(2)
+$(PREREQUISITES): $(2) | bl$(3)_dirs
        @echo "  DEPS    $$@"
-       @mkdir -p $(1)
        $$(Q)$$(AS) $$(ASFLAGS) -M -MT $(OBJ) -MF $$@ $$<
 
 ifdef IS_ANYTHING_TO_BUILD
@@ -260,9 +257,8 @@ $(1): $(2)
        @echo "  PP      $$<"
        $$(Q)$$(AS) $$(ASFLAGS) -P -E -D__LINKER__ -o $$@ $$<
 
-$(PREREQUISITES): $(2)
+$(PREREQUISITES): $(2) | $(dir ${1})
        @echo "  DEPS    $$@"
-       @mkdir -p $$(dir $$@)
        $$(Q)$$(AS) $$(ASFLAGS) -M -MT $(1) -MF $$@ $$<
 
 ifdef IS_ANYTHING_TO_BUILD
@@ -327,14 +323,28 @@ define MAKE_BL
         $(eval DUMP       := $(call IMG_DUMP,$(1)))
         $(eval BIN        := $(call IMG_BIN,$(1)))
         $(eval BL_LINKERFILE := $(BL$(call uppercase,$(1))_LINKERFILE))
+        # We use sort only to get a list of unique object directory names.
+        # ordering is not relevant but sort removes duplicates.
+        $(eval TEMP_OBJ_DIRS := $(sort $(BUILD_DIR)/ $(dir ${OBJS})))
+        # The $(dir ) function leaves a trailing / on the directory names
+        # We append a . then strip /. from each, to remove the trailing / characters
+        # This gives names suitable for use as make rule targets.
+        $(eval OBJ_DIRS   := $(subst /.,,$(addsuffix .,$(TEMP_OBJ_DIRS))))
+
+# Create generators for object directory structure
+
+$(eval $(foreach objd,${OBJ_DIRS},$(call MAKE_PREREQ_DIR,${objd},)))
+
+.PHONY : bl${1}_dirs
 
-        $(eval $(call MAKE_OBJS,$(BUILD_DIR),$(SOURCES),$(1)))
-        $(eval $(call MAKE_LD,$(LINKERFILE),$(BL_LINKERFILE)))
+# We use order-only prerequisites to ensure that directories are created,
+# but do not cause re-builds every time a file is written.
+bl${1}_dirs: | ${OBJ_DIRS}
 
-$(BUILD_DIR):
-       $$(Q)mkdir -p "$$@"
+$(eval $(call MAKE_OBJS,$(BUILD_DIR),$(SOURCES),$(1)))
+$(eval $(call MAKE_LD,$(LINKERFILE),$(BL_LINKERFILE)))
 
-$(ELF): $(OBJS) $(LINKERFILE)
+$(ELF): $(OBJS) $(LINKERFILE) | bl$(1)_dirs
        @echo "  LD      $$@"
        @echo 'const char build_message[] = "Built : "$(BUILD_MESSAGE_TIMESTAMP); \
               const char version_string[] = "${VERSION_STRING}";' | \
@@ -354,7 +364,7 @@ $(BIN): $(ELF)
        @echo
 
 .PHONY: bl$(1)
-bl$(1): $(BUILD_DIR) $(BIN) $(DUMP)
+bl$(1): $(BIN) $(DUMP)
 
 all: bl$(1)