diff options
-rw-r--r-- | build.config | 3 | ||||
-rw-r--r-- | core/core.mk | 2 | ||||
-rw-r--r-- | core/deps-tools.mk | 105 | ||||
-rw-r--r-- | core/deps.mk | 9 | ||||
-rw-r--r-- | doc/src/guide/deps.asciidoc | 49 | ||||
-rw-r--r-- | test/core_deps.mk | 137 |
6 files changed, 304 insertions, 1 deletions
diff --git a/build.config b/build.config index 41c2f0f..6a8d567 100644 --- a/build.config +++ b/build.config @@ -37,3 +37,6 @@ plugins/xref # Plugins enhancing the functionality of other plugins. plugins/cover + +# Core modules which can use variables from plugins. +core/deps-tools diff --git a/core/core.mk b/core/core.mk index 517ad18..167b1a1 100644 --- a/core/core.mk +++ b/core/core.mk @@ -121,6 +121,8 @@ help:: " all Run deps, app and rel targets in that order" \ " app Compile the project" \ " deps Fetch dependencies (if needed) and compile them" \ + " fetch-deps Fetch dependencies recursively (if needed) without compiling them" \ + " list-deps List dependencies recursively on stdout" \ " search q=... Search for a package in the built-in index" \ " rel Build a release for this project, if applicable" \ " docs Build the documentation for this project" \ diff --git a/core/deps-tools.mk b/core/deps-tools.mk new file mode 100644 index 0000000..d0b5203 --- /dev/null +++ b/core/deps-tools.mk @@ -0,0 +1,105 @@ +# Copyright (c) 2013-2015, Loïc Hoguin <essen@ninenines.eu> +# Copyright (c) 2015-2016, Jean-Sébastien Pédron <jean-sebastien@rabbitmq.com> +# This file is part of erlang.mk and subject to the terms of the ISC License. + +# Fetch dependencies recursively (without building them). + +.PHONY: fetch-deps fetch-doc-deps fetch-rel-deps fetch-test-deps \ + fetch-shell-deps + +.PHONY: $(ERLANG_MK_RECURSIVE_DEPS_LIST) \ + $(ERLANG_MK_RECURSIVE_DOC_DEPS_LIST) \ + $(ERLANG_MK_RECURSIVE_REL_DEPS_LIST) \ + $(ERLANG_MK_RECURSIVE_TEST_DEPS_LIST) \ + $(ERLANG_MK_RECURSIVE_SHELL_DEPS_LIST) + +fetch-deps: $(ERLANG_MK_RECURSIVE_DEPS_LIST) +fetch-doc-deps: $(ERLANG_MK_RECURSIVE_DOC_DEPS_LIST) +fetch-rel-deps: $(ERLANG_MK_RECURSIVE_REL_DEPS_LIST) +fetch-test-deps: $(ERLANG_MK_RECURSIVE_TEST_DEPS_LIST) +fetch-shell-deps: $(ERLANG_MK_RECURSIVE_SHELL_DEPS_LIST) + +ifneq ($(SKIP_DEPS),) +$(ERLANG_MK_RECURSIVE_DEPS_LIST) \ +$(ERLANG_MK_RECURSIVE_DOC_DEPS_LIST) \ +$(ERLANG_MK_RECURSIVE_REL_DEPS_LIST) \ +$(ERLANG_MK_RECURSIVE_TEST_DEPS_LIST) \ +$(ERLANG_MK_RECURSIVE_SHELL_DEPS_LIST): + $(verbose) :> $@ +else +# By default, we fetch "normal" dependencies. They are also included no +# matter the type of requested dependencies. +# +# $(ALL_DEPS_DIRS) includes $(BUILD_DEPS). + +$(ERLANG_MK_RECURSIVE_DEPS_LIST): $(ALL_DEPS_DIRS) +$(ERLANG_MK_RECURSIVE_DOC_DEPS_LIST): $(ALL_DEPS_DIRS) $(ALL_DOC_DEPS_DIRS) +$(ERLANG_MK_RECURSIVE_REL_DEPS_LIST): $(ALL_DEPS_DIRS) $(ALL_REL_DEPS_DIRS) +$(ERLANG_MK_RECURSIVE_TEST_DEPS_LIST): $(ALL_DEPS_DIRS) $(ALL_TEST_DEPS_DIRS) +$(ERLANG_MK_RECURSIVE_SHELL_DEPS_LIST): $(ALL_DEPS_DIRS) $(ALL_SHELL_DEPS_DIRS) + +# Allow to use fetch-deps and $(DEP_TYPES) to fetch multiple types of +# dependencies with a single target. +ifneq ($(filter doc,$(DEP_TYPES)),) +$(ERLANG_MK_RECURSIVE_DEPS_LIST): $(ALL_DOC_DEPS_DIRS) +endif +ifneq ($(filter rel,$(DEP_TYPES)),) +$(ERLANG_MK_RECURSIVE_DEPS_LIST): $(ALL_REL_DEPS_DIRS) +endif +ifneq ($(filter test,$(DEP_TYPES)),) +$(ERLANG_MK_RECURSIVE_DEPS_LIST): $(ALL_TEST_DEPS_DIRS) +endif +ifneq ($(filter shell,$(DEP_TYPES)),) +$(ERLANG_MK_RECURSIVE_DEPS_LIST): $(ALL_SHELL_DEPS_DIRS) +endif + +ERLANG_MK_RECURSIVE_TMP_LIST := $(abspath $(ERLANG_MK_TMP)/recursive-tmp-deps.log) + +$(ERLANG_MK_RECURSIVE_DEPS_LIST) \ +$(ERLANG_MK_RECURSIVE_DOC_DEPS_LIST) \ +$(ERLANG_MK_RECURSIVE_REL_DEPS_LIST) \ +$(ERLANG_MK_RECURSIVE_TEST_DEPS_LIST) \ +$(ERLANG_MK_RECURSIVE_SHELL_DEPS_LIST): +ifeq ($(IS_APP)$(IS_DEP),) + $(verbose) mkdir -p $(ERLANG_MK_TMP) + $(verbose) rm -f $(ERLANG_MK_RECURSIVE_TMP_LIST) +endif +ifndef IS_APP + $(verbose) for dep in $(ALL_APPS_DIRS) ; do \ + $(MAKE) -C $$dep $@ \ + IS_APP=1 \ + ERLANG_MK_RECURSIVE_TMP_LIST=$(ERLANG_MK_RECURSIVE_TMP_LIST) \ + || exit $$?; \ + done +endif + $(verbose) for dep in $^ ; do \ + if ! grep -qs ^$$dep$$ $(ERLANG_MK_RECURSIVE_TMP_LIST); then \ + echo $$dep >> $(ERLANG_MK_RECURSIVE_TMP_LIST); \ + if grep -qs -E "^[[:blank:]]*include[[:blank:]]+(erlang\.mk|.*/erlang\.mk)$$" \ + $$dep/GNUmakefile $$dep/makefile $$dep/Makefile; then \ + $(MAKE) -C $$dep fetch-deps \ + IS_DEP=1 \ + ERLANG_MK_RECURSIVE_TMP_LIST=$(ERLANG_MK_RECURSIVE_TMP_LIST) \ + || exit $$?; \ + fi \ + fi \ + done +ifeq ($(IS_APP)$(IS_DEP),) + $(verbose) sort < $(ERLANG_MK_RECURSIVE_TMP_LIST) | uniq > $@ + $(verbose) rm $(ERLANG_MK_RECURSIVE_TMP_LIST) +endif +endif # ifneq ($(SKIP_DEPS),) + +# List dependencies recursively. + +.PHONY: list-deps list-doc-deps list-rel-deps list-test-deps \ + list-shell-deps + +list-deps: $(ERLANG_MK_RECURSIVE_DEPS_LIST) +list-doc-deps: $(ERLANG_MK_RECURSIVE_DOC_DEPS_LIST) +list-rel-deps: $(ERLANG_MK_RECURSIVE_REL_DEPS_LIST) +list-test-deps: $(ERLANG_MK_RECURSIVE_TEST_DEPS_LIST) +list-shell-deps: $(ERLANG_MK_RECURSIVE_SHELL_DEPS_LIST) + +list-deps list-doc-deps list-rel-deps list-test-deps list-shell-deps: + $(verbose) cat $^ diff --git a/core/deps.mk b/core/deps.mk index 2d2e372..2207592 100644 --- a/core/deps.mk +++ b/core/deps.mk @@ -603,6 +603,15 @@ distclean-deps: $(gen_verbose) rm -rf $(DEPS_DIR) endif +# Forward-declare variables used in core/deps-tools.mk. This is required +# in case plugins use them. + +ERLANG_MK_RECURSIVE_DEPS_LIST = $(ERLANG_MK_TMP)/recursive-deps-list.log +ERLANG_MK_RECURSIVE_DOC_DEPS_LIST = $(ERLANG_MK_TMP)/recursive-doc-deps-list.log +ERLANG_MK_RECURSIVE_REL_DEPS_LIST = $(ERLANG_MK_TMP)/recursive-rel-deps-list.log +ERLANG_MK_RECURSIVE_TEST_DEPS_LIST = $(ERLANG_MK_TMP)/recursive-test-deps-list.log +ERLANG_MK_RECURSIVE_SHELL_DEPS_LIST = $(ERLANG_MK_TMP)/recursive-shell-deps-list.log + # External plugins. DEP_PLUGINS ?= diff --git a/doc/src/guide/deps.asciidoc b/doc/src/guide/deps.asciidoc index eb6f2f0..723deb0 100644 --- a/doc/src/guide/deps.asciidoc +++ b/doc/src/guide/deps.asciidoc @@ -286,6 +286,55 @@ different version of D, it will always be A's version that wins, because we fetch all dependencies of A before fetching those from B or C. +=== Fetching and listing dependencies only + +You can fetch all dependencies recursively without building anything, +with the `make fetch-deps` command. It follows the same rules described +in the section above. + +You can list all dependencies recursively, again without building +anything, with the `make list-deps` command. It will obviously need +to fetch all dependencies exactly like `make fetch-deps`. Once +everything is fetched, it prints a sorted list of absolute paths to the +dependencies. + +By default, `fetch-deps` and `list-deps` work on the `BUILD_DEPS` +and `DEPS` lists only. To also fetch/list `TEST_DEPS`, `DOC_DEPS`, +`REL_DEPS` and/or `SHELL_DEPS`, you have two possibilities: + +* You can use `make fetch-test-deps`, `make fetch-doc-deps`, `make + fetch-rel-deps` and `make fetch-shell-deps` commands respectively. + If you want to list them, you can use `make list-test-deps`, `make + list-doc-deps`, `make list-rel-deps` and `make list-shell-deps` + respectively. +* You can use `make fetch-deps` or `make list-deps` with the Makefile + variable `DEP_TYPES` set to a list of dependency types you want. + The types are `test`, `doc`, `rel` and `shell` respectively. For + example, you can list test and doc dependencies with `make list-deps + DEP_TYPES='test doc'`. + +Note that only first level `TEST_DEPS`, `DOC_DEPS`, `REL_DEPS` and +`SHELL_DEPS` are included, not dependencies' one. In other word, +`make list-test-deps` lists the `TEST_DEPS` of your project, but not +`TEST_DEPS` of the projects yours depend on. + +No matter which method you use, `BUILD_DEPS` and `DEPS` are always +included. + +Internally, the `make fetch-*` commands store the complete list of +dependencies in files named `$(ERLANG_MK_RECURSIVE_DEPS_LIST)`, +`$(ERLANG_MK_RECURSIVE_TEST_DEPS_LIST)`, +`$(ERLANG_MK_RECURSIVE_DOC_DEPS_LIST)`, +`$(ERLANG_MK_RECURSIVE_REL_DEPS_LIST)` and +`$(ERLANG_MK_RECURSIVE_SHELL_DEPS_LIST)`. Those files are simply printed +by the `make list-*` commands. + +`make list-*` commands are made for human beings. If you need the list +of dependencies in a Makefile or a script, you should use the content +of those files directly instead. The reason is that `make fetch-*` and +`make list-*` may have unwanted content in their output, such as actual +fetching of dependencies. + === Ignoring unwanted dependencies Sometimes, you may want to ignore dependencies entirely. diff --git a/test/core_deps.mk b/test/core_deps.mk index 767b66b..b89b885 100644 --- a/test/core_deps.mk +++ b/test/core_deps.mk @@ -1,6 +1,6 @@ # Core: Packages and dependencies. -CORE_DEPS_CASES = apps apps-build-count apps-conflict apps-deep-conflict apps-dir apps-dir-include-lib apps-new-app apps-new-lib apps-new-tpl apps-only autopatch-rebar build-c-8cc build-c-imagejs build-erl build-js dep-commit dir doc fetch-cp fetch-custom fetch-fail-bad fetch-fail-unknown fetch-git fetch-git-submodule fetch-hex fetch-hg fetch-legacy fetch-svn ignore mv mv-rebar no-autopatch no-autopatch-erlang-mk no-autopatch-rebar order-first order-top otp pkg rel search shell skip test +CORE_DEPS_CASES = apps apps-build-count apps-conflict apps-deep-conflict apps-dir apps-dir-include-lib apps-new-app apps-new-lib apps-new-tpl apps-only autopatch-rebar build-c-8cc build-c-imagejs build-erl build-js dep-commit dir doc fetch-cp fetch-custom fetch-fail-bad fetch-fail-unknown fetch-git fetch-git-submodule fetch-hex fetch-hg fetch-legacy fetch-svn ignore list-deps mv mv-rebar no-autopatch no-autopatch-erlang-mk no-autopatch-rebar order-first order-top otp pkg rel search shell skip test CORE_DEPS_TARGETS = $(addprefix core-deps-,$(CORE_DEPS_CASES)) .PHONY: core-deps $(CORE_DEPS_TARGETS) @@ -983,6 +983,141 @@ endif $i "Check that the correct dependencies were fetched" $t test -d $(APP)/deps/ranch +define add_dep_and_subdep + $i "Bootstrap a new OTP library named $(APP)-$(1)subdep" + $t mkdir $(APP)-$(1)subdep/ + $t cp ../erlang.mk $(APP)-$(1)subdep/ + $t $(MAKE) -C $(APP)-$(1)subdep --no-print-directory -f erlang.mk bootstrap-lib $$v + + $i "Create a Git repository for $(APP)-$(1)subdep" + $t (cd $(APP)-$(1)subdep && \ + git init -q && \ + git config user.name "Testsuite" && \ + git config user.email "testsuite@erlang.mk" && \ + git add . && \ + git commit -q -m "Initial commit") + + $i "Bootstrap a new OTP library named $(APP)-$(1)dep" + $t mkdir $(APP)-$(1)dep/ + $t cp ../erlang.mk $(APP)-$(1)dep/ + $t $(MAKE) -C $(APP)-$(1)dep --no-print-directory -f erlang.mk bootstrap-lib $$v + + $i "Add $(APP)-$(1)subdep as a dependency" + $t perl -ni.bak -e \ + 'print;if ($$.==1) {print "DEPS = $(1)subdep\ndep_$(1)subdep = git file://$(abspath $(APP)-$(1)subdep) master\n"}' \ + $(APP)-$(1)dep/Makefile + $t rm $(APP)-$(1)dep/Makefile.bak + + $i "Create a Git repository for $(APP)-$(1)dep" + $t (cd $(APP)-$(1)dep && \ + git init -q && \ + git config user.name "Testsuite" && \ + git config user.email "testsuite@erlang.mk" && \ + git add . && \ + git commit -q -m "Initial commit") +endef + +core-deps-list-deps: build clean + + $(call add_dep_and_subdep,) + $(call add_dep_and_subdep,doc) + $(call add_dep_and_subdep,rel) + $(call add_dep_and_subdep,test) + $(call add_dep_and_subdep,shell) + + $i "Bootstrap a new OTP library named $(APP)" + $t mkdir $(APP)/ + $t cp ../erlang.mk $(APP)/ + $t $(MAKE) -C $(APP) -f erlang.mk bootstrap-lib $v + + $i "Add $(APP)-dep and $(APP)-testdep as a dependency" + $t sed -i.bak '2i\ +DEPS = dep\ +DOC_DEPS = docdep\ +REL_DEPS = reldep\ +TEST_DEPS = testdep\ +SHELL_DEPS = shelldep\ +dep_dep = git file://$(abspath $(APP)-dep) master\ +dep_docdep = git file://$(abspath $(APP)-docdep) master\ +dep_reldep = git file://$(abspath $(APP)-reldep) master\ +dep_testdep = git file://$(abspath $(APP)-testdep) master\ +dep_shelldep = git file://$(abspath $(APP)-shelldep) master\ +' $(APP)/Makefile + $t rm $(APP)/Makefile.bak + + $i "Create a Git repository for $(APP)" + $t (cd $(APP) && \ + git init -q && \ + git config user.name "Testsuite" && \ + git config user.email "testsuite@erlang.mk" && \ + git add . && \ + git commit -q -m "Initial commit") + + $i "List application dependencies" + $t $(MAKE) -C $(APP) --no-print-directory list-deps $v + $t test -d $(APP)/deps/subdep + $t printf "%s\n%s\n" $(abspath $(APP)/deps/dep $(APP)/deps/subdep) > $(APP)/expected-deps.txt + $t cmp $(APP)/expected-deps.txt $(APP)/.erlang.mk/recursive-deps-list.log + $t $(MAKE) -C $(APP) --no-print-directory distclean $v + + $i "List application doc dependencies" + $t $(MAKE) -C $(APP) --no-print-directory list-doc-deps $v + $t test -d $(APP)/deps/subdep + $t test -d $(APP)/deps/docsubdep + $t printf "%s\n%s\n%s\n%s\n" \ + $(abspath $(APP)/deps/dep $(APP)/deps/subdep $(APP)/deps/docdep $(APP)/deps/docsubdep) \ + | sort > $(APP)/expected-doc-deps.txt + $t cmp $(APP)/expected-doc-deps.txt $(APP)/.erlang.mk/recursive-doc-deps-list.log + $t $(MAKE) -C $(APP) --no-print-directory distclean $v + + $i "List application rel dependencies" + $t $(MAKE) -C $(APP) --no-print-directory list-rel-deps $v + $t test -d $(APP)/deps/subdep + $t test -d $(APP)/deps/relsubdep + $t printf "%s\n%s\n%s\n%s\n" \ + $(abspath $(APP)/deps/dep $(APP)/deps/subdep $(APP)/deps/reldep $(APP)/deps/relsubdep) \ + | sort > $(APP)/expected-rel-deps.txt + $t cmp $(APP)/expected-rel-deps.txt $(APP)/.erlang.mk/recursive-rel-deps-list.log + $t $(MAKE) -C $(APP) --no-print-directory distclean $v + + $i "List application test dependencies" + $t $(MAKE) -C $(APP) --no-print-directory list-test-deps $v + $t test -d $(APP)/deps/subdep + $t test -d $(APP)/deps/testsubdep + $t printf "%s\n%s\n%s\n%s\n" \ + $(abspath $(APP)/deps/dep $(APP)/deps/subdep $(APP)/deps/testdep $(APP)/deps/testsubdep) \ + | sort > $(APP)/expected-test-deps.txt + $t cmp $(APP)/expected-test-deps.txt $(APP)/.erlang.mk/recursive-test-deps-list.log + $t $(MAKE) -C $(APP) --no-print-directory distclean $v + + $i "List application shell dependencies" + $t $(MAKE) -C $(APP) --no-print-directory list-shell-deps $v + $t test -d $(APP)/deps/subdep + $t test -d $(APP)/deps/shellsubdep + $t printf "%s\n%s\n%s\n%s\n" \ + $(abspath $(APP)/deps/dep $(APP)/deps/subdep $(APP)/deps/shelldep $(APP)/deps/shellsubdep) \ + | sort > $(APP)/expected-shell-deps.txt + $t cmp $(APP)/expected-shell-deps.txt $(APP)/.erlang.mk/recursive-shell-deps-list.log + $t $(MAKE) -C $(APP) --no-print-directory distclean $v + + $i "List application all dependencies (all kinds)" + $t $(MAKE) -C $(APP) --no-print-directory list-deps DEP_TYPES='doc rel test shell' $v + $t test -d $(APP)/deps/subdep + $t test -d $(APP)/deps/docsubdep + $t test -d $(APP)/deps/relsubdep + $t test -d $(APP)/deps/testsubdep + $t test -d $(APP)/deps/shellsubdep + $t printf "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n" \ + $(abspath \ + $(APP)/deps/dep $(APP)/deps/subdep \ + $(APP)/deps/docdep $(APP)/deps/docsubdep \ + $(APP)/deps/reldep $(APP)/deps/relsubdep \ + $(APP)/deps/testdep $(APP)/deps/testsubdep \ + $(APP)/deps/shelldep $(APP)/deps/shellsubdep) \ + | sort > $(APP)/expected-all-deps.txt + $t cmp $(APP)/expected-all-deps.txt $(APP)/.erlang.mk/recursive-deps-list.log + $t $(MAKE) -C $(APP) --no-print-directory distclean $v + core-deps-mv: build clean $i "Bootstrap a new OTP library named $(APP)" |