Improve dependencies for dirlinks.

This PR updates the dependencies for `dirlinks` so they're all real files. This allows `dirlinks` rule to not have to be rerun every time.
This PR also changes the name from `dirlinks` to `.dirlinks`, since a file named `.dirlinks` is created to denote that all symlinks have been created

Changes:
* tools/link.sh
  * link.sh now detects broken symlinks. Previously, it would return `0` if the symlink existed, but didn't point to anything.

* tools/Makefile.unix
  * Added dependencies to symlinks as order-only prerequisites. See https://www.gnu.org/software/make/manual/html_node/Prerequisite-Types.html
  * Removed `touch` from symlink recipes by specifying them as order only prerequisites.
  * Check Kconfig variables before adding directories as symlinks
  * Added rule for `$(TOPDIR)/arch/dummy/Kconfig`
  * Added rule for `$(ARCH_SRC)/board/board`
  * Added pattern rule (similar to `CONTEXTDIRS_DEPS`) for external folder dirlink dependencies
  * Use $(APPDIR) instead of $(CONFIG_APPS_DIR), since on line 64 $(APPDIR) is validated and `realpath` is called on the path
  * Added a rule `clean_dirlinks` to cleanup the symlinks in the correct order

* .gitignore
  * Added ignore rule for `.dirlinks`

Testing
Step 1: configure nuttx:
```
$ (cd tools && ./configure.sh -a ../incubator-nuttx-apps stm32f3discovery:nsh)
```
part of the configure step ends up calling `.dirlinks`.

Step 2: We can confirm that `.dirlinks` doesn't need to be run again by running with the question flag: `--question`
```
$ make .dirlinks --question
$ echo $?
0
```

Step 3: confirm `make` succeeds.
```
make
```
This commit is contained in:
Alan Rosenthal 2021-12-28 12:21:50 -05:00 committed by Abdelatif Guettouche
parent 4b190fbce1
commit 2366795786
5 changed files with 130 additions and 53 deletions

2
.gitignore vendored
View file

@ -49,3 +49,5 @@ uImage
/external /external
# $(TOPDIR)/Makefile.[unix|win]::$(CONTEXTDIRS_DEPS) # $(TOPDIR)/Makefile.[unix|win]::$(CONTEXTDIRS_DEPS)
.context .context
# $(TOPDIR)/Makefile.[unix|win]::$(DIRLINKS_EXTERNAL_DIRS)
.dirlinks

View file

@ -45,6 +45,7 @@ else
# Generate .version every time from GIT history # Generate .version every time from GIT history
.PHONY: $(TOPDIR)/.version .PHONY: $(TOPDIR)/.version
endif endif
# Process architecture specific directories # Process architecture specific directories
@ -146,7 +147,7 @@ endif
BIN = nuttx$(EXEEXT) BIN = nuttx$(EXEEXT)
all: $(BIN) all: $(BIN)
.PHONY: dirlinks context clean_context config oldconfig menuconfig nconfig qconfig gconfig export subdir_clean clean subdir_distclean distclean apps_clean apps_distclean .PHONY: context clean_context config oldconfig menuconfig nconfig qconfig gconfig export subdir_clean clean subdir_distclean distclean apps_clean apps_distclean
.PHONY: pass1 pass1dep .PHONY: pass1 pass1dep
.PHONY: pass2 pass2dep .PHONY: pass2 pass2dep
@ -246,7 +247,7 @@ tools/mkdeps$(HOSTEXEEXT):
tools/cnvwindeps$(HOSTEXEEXT): tools/cnvwindeps$(HOSTEXEEXT):
$(Q) $(MAKE) -C tools -f Makefile.host cnvwindeps$(HOSTEXEEXT) $(Q) $(MAKE) -C tools -f Makefile.host cnvwindeps$(HOSTEXEEXT)
# dirlinks, and helpers # .dirlinks, and helpers
# #
# Directories links. Most of establishing the NuttX configuration involves # Directories links. Most of establishing the NuttX configuration involves
# setting up symbolic links with 'generic' directory names to specific, # setting up symbolic links with 'generic' directory names to specific,
@ -255,71 +256,147 @@ tools/cnvwindeps$(HOSTEXEEXT):
# Link the arch/<arch-name>/include directory to include/arch # Link the arch/<arch-name>/include directory to include/arch
include/arch: include/arch:
@echo "LN: include/arch to $(ARCH_DIR)/include" @echo "LN: $@ to $(ARCH_DIR)/include"
$(Q) $(DIRLINK) $(TOPDIR)/$(ARCH_DIR)/include include/arch $(Q) $(DIRLINK) $(TOPDIR)/$(ARCH_DIR)/include $@
$(Q) touch $@
# Link the boards/<arch>/<chip>/<board>/include directory to include/arch/board # Link the boards/<arch>/<chip>/<board>/include directory to include/arch/board
include/arch/board: include/arch include/arch/board: | include/arch
@echo "LN: include/arch/board to $(BOARD_DIR)/include" @echo "LN: $@ to $(BOARD_DIR)/include"
$(Q) $(DIRLINK) $(BOARD_DIR)/include include/arch/board $(Q) $(DIRLINK) $(BOARD_DIR)/include $@
$(Q) touch $@
ifneq ($(BOARD_COMMON_DIR),)
# Link the boards/<arch>/<chip>/common dir to arch/<arch-name>/src/board # Link the boards/<arch>/<chip>/common dir to arch/<arch-name>/src/board
# Link the boards/<arch>/<chip>/<board>/src dir to arch/<arch-name>/src/board/board # Link the boards/<arch>/<chip>/<board>/src dir to arch/<arch-name>/src/board/board
$(ARCH_SRC)/board: ifneq ($(BOARD_COMMON_DIR),)
@echo "LN: $(ARCH_SRC)/board to $(BOARD_COMMON_DIR)" ARCH_SRC_BOARD_SYMLINK=$(BOARD_COMMON_DIR)
$(Q) $(DIRLINK) $(BOARD_COMMON_DIR) $(ARCH_SRC)/board ARCH_SRC_BOARD_BOARD_SYMLINK=$(BOARD_DIR)/src
@echo "LN: $(ARCH_SRC)/board/board to $(BOARD_DIR)/src"
$(Q) $(DIRLINK) $(BOARD_DIR)/src $(ARCH_SRC)/board/board
$(Q) touch $@
else else
# Link the boards/<arch>/<chip>/<board>/src dir to arch/<arch-name>/src/board ARCH_SRC_BOARD_SYMLINK=$(BOARD_DIR)/src
endif
ifneq ($(ARCH_SRC_BOARD_SYMLINK),)
$(ARCH_SRC)/board: $(ARCH_SRC)/board:
@echo "LN: $(ARCH_SRC)/board to $(BOARD_DIR)/src" @echo "LN: $@ to $(ARCH_SRC_BOARD_SYMLINK)"
$(Q) $(DIRLINK) $(BOARD_DIR)/src $(ARCH_SRC)/board $(Q) $(DIRLINK) $(ARCH_SRC_BOARD_SYMLINK) $@
$(Q) touch $@ endif
ifneq ($(ARCH_SRC_BOARD_BOARD_SYMLINK),)
$(ARCH_SRC)/board/board: | $(ARCH_SRC)/board
@echo "LN: $@ to $(ARCH_SRC_BOARD_BOARD_SYMLINK)"
$(Q) $(DIRLINK) $(ARCH_SRC_BOARD_BOARD_SYMLINK) $@
endif endif
# Link the boards/<arch>/<chip>/drivers dir to drivers/platform # Link the boards/<arch>/<chip>/drivers dir to drivers/platform
drivers/platform: drivers/platform:
@echo "LN: $(TOPDIR)/drivers/platform to $(BOARD_DRIVERS_DIR)" @echo "LN: $@ to $(BOARD_DRIVERS_DIR)"
$(Q) $(DIRLINK) $(BOARD_DRIVERS_DIR) $(TOPDIR)/drivers/platform $(Q) $(DIRLINK) $(BOARD_DRIVERS_DIR) $@
$(Q) touch $@
# Link arch/<arch-name>/src/<chip-name> to arch/<arch-name>/src/chip # Link arch/<arch-name>/src/<chip-name> to arch/<arch-name>/src/chip
$(ARCH_SRC)/chip:
ifeq ($(CONFIG_ARCH_CHIP_CUSTOM),y) ifeq ($(CONFIG_ARCH_CHIP_CUSTOM),y)
@echo "LN: $(ARCH_SRC)/chip to $(CHIP_DIR)" ARCH_SRC_CHIP_SYMLINK_DIR=$(CHIP_DIR)
$(Q) $(DIRLINK) $(CHIP_DIR) $(ARCH_SRC)/chip
else ifneq ($(CONFIG_ARCH_CHIP),) else ifneq ($(CONFIG_ARCH_CHIP),)
@echo "LN: $(ARCH_SRC)/chip to $(ARCH_SRC)/$(CONFIG_ARCH_CHIP)" ARCH_SRC_CHIP_SYMLINK_DIR=$(TOPDIR)/$(ARCH_SRC)/$(CONFIG_ARCH_CHIP)
$(Q) $(DIRLINK) $(TOPDIR)/$(ARCH_SRC)/$(CONFIG_ARCH_CHIP) $(ARCH_SRC)/chip endif
ifneq ($(ARCH_SRC_CHIP_SYMLINK_DIR),)
$(ARCH_SRC)/chip:
@echo "LN: $@ to $(ARCH_SRC_CHIP_SYMLINK_DIR)"
$(Q) $(DIRLINK) $(ARCH_SRC_CHIP_SYMLINK_DIR) $@
endif endif
$(Q) cp -f $(CHIP_KCONFIG) $(TOPDIR)/arch/dummy/Kconfig
$(Q) touch $@
# Link arch/<arch-name>/include/<chip-name> to include/arch/chip # Link arch/<arch-name>/include/<chip-name> to include/arch/chip
include/arch/chip: include/arch
ifeq ($(CONFIG_ARCH_CHIP_CUSTOM),y) ifeq ($(CONFIG_ARCH_CHIP_CUSTOM),y)
@echo "LN: include/arch/chip to $(CHIP_DIR)/include" INCLUDE_ARCH_CHIP_SYMLINK_DIR=$(CHIP_DIR)/include
$(Q) $(DIRLINK) $(CHIP_DIR)/include include/arch/chip
else ifneq ($(CONFIG_ARCH_CHIP),) else ifneq ($(CONFIG_ARCH_CHIP),)
@echo "LN: include/arch/chip to $(ARCH_INC)/$(CONFIG_ARCH_CHIP)" INCLUDE_ARCH_CHIP_SYMLINK_DIR=$(TOPDIR)/$(ARCH_INC)/$(CONFIG_ARCH_CHIP)
$(Q) $(DIRLINK) $(TOPDIR)/$(ARCH_INC)/$(CONFIG_ARCH_CHIP) include/arch/chip
endif endif
ifneq ($(INCLUDE_ARCH_CHIP_SYMLINK_DIR),)
include/arch/chip:
@echo "LN: $@ to $(INCLUDE_ARCH_CHIP_SYMLINK_DIR)"
$(DIRLINK) $(INCLUDE_ARCH_CHIP_SYMLINK_DIR) $@
endif
# Copy $(CHIP_KCONFIG) to arch/dummy/Kconfig
arch/dummy/Kconfig:
@echo "CP: $@ to $(CHIP_KCONFIG)"
$(Q) cp -f $(CHIP_KCONFIG) $@
DIRLINKS_SYMLINK = \
include/arch \
include/arch/board \
drivers/platform \
DIRLINKS_FILE = \
arch/dummy/Kconfig \
ifneq ($(INCLUDE_ARCH_CHIP_SYMLINK_DIR),)
DIRLINKS_SYMLINK += include/arch/chip
endif
ifneq ($(ARCH_SRC_CHIP_SYMLINK_DIR),)
DIRLINKS_SYMLINK += $(ARCH_SRC)/chip
endif
ifneq ($(ARCH_SRC_BOARD_SYMLINK),)
DIRLINKS_SYMLINK += $(ARCH_SRC)/board
endif
ifneq ($(ARCH_SRC_BOARD_BOARD_SYMLINK),)
DIRLINKS_SYMLINK += $(ARCH_SRC)/board/board
endif
DIRLINKS_EXTERNAL_DIRS = boards
ifneq ($(APPDIR),)
DIRLINKS_EXTERNAL_DIRS += $(APPDIR)
endif
# Generate a pattern to build $(DIRLINKS_EXTERNAL_DIRS)
DIRLINKS_EXTERNAL_DEP = $(patsubst %,%/.dirlinks,$(DIRLINKS_EXTERNAL_DIRS))
DIRLINKS_FILE += $(DIRLINKS_EXTERNAL_DEP)
.dirlinks: $(DIRLINKS_FILE) | $(DIRLINKS_SYMLINK)
touch $@
# Pattern rule for $(DIRLINKS_EXTERNAL_DEP)
%/.dirlinks:
$(Q) $(MAKE) -C $(patsubst %/.dirlinks,%,$@) dirlinks
$(Q) touch $@ $(Q) touch $@
dirlinks: include/arch include/arch/board include/arch/chip $(ARCH_SRC)/board $(ARCH_SRC)/chip drivers/platform # clean_dirlinks
$(Q) $(MAKE) -C boards dirlinks #
$(Q) $(MAKE) -C $(CONFIG_APPS_DIR) dirlinks # This is part of the distclean target. It removes all symbolic links created by the dirlink target.
# The symlink subfolders need to be removed before the parent symlinks
.PHONY: clean_dirlinks
clean_dirlinks:
$(Q) $(call DELFILE, $(DIRLINKS_FILE))
$(Q) $(call DELFILE, .dirlinks)
$(Q) $(DIRUNLINK) drivers/platform
ifneq ($(INCLUDE_ARCH_CHIP_SYMLINK_DIR),)
$(Q) $(DIRUNLINK) include/arch/chip
endif
$(Q) $(DIRUNLINK) include/arch/board
$(Q) $(DIRUNLINK) include/arch
ifneq ($(ARCH_SRC_BOARD_BOARD_SYMLINK),)
$(Q) $(DIRUNLINK) $(ARCH_SRC)/board/board
endif
ifneq ($(ARCH_SRC_BOARD_SYMLINK),)
$(Q) $(DIRUNLINK) $(ARCH_SRC)/board
endif
ifneq ($(ARCH_SRC_CHIP_SYMLINK_DIR),)
$(Q) $(DIRUNLINK) $(ARCH_SRC)/chip
endif
# context # context
# #
@ -332,14 +409,14 @@ dirlinks: include/arch include/arch/board include/arch/chip $(ARCH_SRC)/board $(
CONTEXTDIRS_DEPS = $(patsubst %,%/.context,$(CONTEXTDIRS)) CONTEXTDIRS_DEPS = $(patsubst %,%/.context,$(CONTEXTDIRS))
context: include/nuttx/config.h include/nuttx/version.h dirlinks $(CONTEXTDIRS_DEPS) | staging context: include/nuttx/config.h include/nuttx/version.h .dirlinks $(CONTEXTDIRS_DEPS) | staging
staging: staging:
$(Q) mkdir -p $@ $(Q) mkdir -p $@
# Pattern rule for $(CONTEXTDIRS_DEPS) # Pattern rule for $(CONTEXTDIRS_DEPS)
%.context: include/nuttx/config.h dirlinks %.context: include/nuttx/config.h .dirlinks
$(Q) $(MAKE) -C $(patsubst %.context,%,$@) TOPDIR="$(TOPDIR)" context $(Q) $(MAKE) -C $(patsubst %.context,%,$@) TOPDIR="$(TOPDIR)" context
$(Q) touch $@ $(Q) touch $@
@ -364,7 +441,7 @@ endif
# This is part of the distclean target. It removes all of the header files # This is part of the distclean target. It removes all of the header files
# and symbolic links created by the context target. # and symbolic links created by the context target.
clean_context: clean_context: clean_dirlinks
$(Q) for dir in $(CCLEANDIRS) ; do \ $(Q) for dir in $(CCLEANDIRS) ; do \
if [ -e $$dir/Makefile ]; then \ if [ -e $$dir/Makefile ]; then \
$(MAKE) -C $$dir clean_context ; \ $(MAKE) -C $$dir clean_context ; \
@ -378,13 +455,6 @@ clean_context:
$(call DELFILE, include/setjmp.h) $(call DELFILE, include/setjmp.h)
$(call DELFILE, arch/dummy/Kconfig) $(call DELFILE, arch/dummy/Kconfig)
$(call DELFILE, $(CONTEXTDIRS_DEPS)) $(call DELFILE, $(CONTEXTDIRS_DEPS))
$(Q) $(DIRUNLINK) include/arch/board
$(Q) $(DIRUNLINK) include/arch/chip
$(Q) $(DIRUNLINK) include/arch
$(Q) $(DIRUNLINK) $(ARCH_SRC)/board/board
$(Q) $(DIRUNLINK) $(ARCH_SRC)/board
$(Q) $(DIRUNLINK) $(ARCH_SRC)/chip
$(Q) $(DIRUNLINK) $(TOPDIR)/drivers/platform
# Archive targets. The target build sequence will first create a series of # Archive targets. The target build sequence will first create a series of
# libraries, one per configured source file directory. The final NuttX # libraries, one per configured source file directory. The final NuttX
@ -648,7 +718,7 @@ endif
# apps_distclean: Perform the distclean operation only in the user application # apps_distclean: Perform the distclean operation only in the user application
# directory. # directory.
apps_preconfig: dirlinks apps_preconfig: .dirlinks
ifneq ($(APPDIR),) ifneq ($(APPDIR),)
$(Q) $(MAKE) -C $(APPDIR) preconfig $(Q) $(MAKE) -C $(APPDIR) preconfig
endif endif

View file

@ -154,7 +154,7 @@ kconfig2html.c
or more quickly with: or more quickly with:
make dirlinks make .dirlinks
Libraries.mk, FlatLibs.mk, ProtectedLibs.mk, and KernelLib.mk Libraries.mk, FlatLibs.mk, ProtectedLibs.mk, and KernelLib.mk
------------------------------------------------------------- -------------------------------------------------------------

View file

@ -335,7 +335,7 @@ function binutils {
Darwin) Darwin)
brew install binutils brew install binutils
# It is possible we cached prebuilt but did brew install so recreate # It is possible we cached prebuilt but did brew install so recreate
# simlink if it exists # symlink if it exists
rm -f "${prebuilt}"/bintools/bin/objcopy rm -f "${prebuilt}"/bintools/bin/objcopy
ln -s /usr/local/opt/binutils/bin/objcopy "${prebuilt}"/bintools/bin/objcopy ln -s /usr/local/opt/binutils/bin/objcopy "${prebuilt}"/bintools/bin/objcopy
;; ;;

View file

@ -82,15 +82,20 @@ ln -s "${src}" "${dest}" || \
# Verify that the link was created # Verify that the link was created
if [ ! -h ${dest} ]; then if [ -e ${dest} ] && [ -h ${desg} ]; then
# The file exists and is a symlink (i.e. the symlink isn't broken)
exit 0
else
# The MSYS 'ln' command actually does a directory copy # The MSYS 'ln' command actually does a directory copy
if [ -d ${dest} ]; then if [ -d ${dest} ]; then
# Create the .fakelnk for unlink.sh # Create the .fakelnk for unlink.sh
touch ${dest}/.fakelnk touch ${dest}/.fakelnk
exit 0
else else
echo "Error: link at ${dest} not created." echo "Error: link at ${dest} not created."
exit 1 exit 1
fi fi
fi fi