[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lmi-commits] [lmi] odd/source_script_in_makefile 350571f: Source a shel

From: Greg Chicares
Subject: [lmi-commits] [lmi] odd/source_script_in_makefile 350571f: Source a shell script in a makefile
Date: Fri, 17 May 2019 09:53:35 -0400 (EDT)

branch: odd/source_script_in_makefile
commit 350571f9eb912c74bec1c1fa81a81c41971ee32e
Author: Gregory W. Chicares <address@hidden>
Commit: Gregory W. Chicares <address@hidden>

    Source a shell script in a makefile
    See the commentary in 'parent.make'.
 child.make  |  4 ++++
 parent.make | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 set.sh      | 13 +++++++++++++
 3 files changed, 79 insertions(+)

diff --git a/child.make b/child.make
new file mode 100644
index 0000000..3c05987
--- /dev/null
+++ b/child.make
@@ -0,0 +1,4 @@
+.PHONY: all
+       @echo "LMI_IN in 'child.make': $$LMI_IN"
+       @echo "LMI_OUT in 'child.make': $$LMI_OUT"
diff --git a/parent.make b/parent.make
new file mode 100644
index 0000000..e382efa
--- /dev/null
+++ b/parent.make
@@ -0,0 +1,62 @@
+# This demonstration shows a way to source a script in a makefile,
+# and export environment variables set by that script to make's
+# environment, thus:
+#  - add an 'env.make' prerequisite for the top-level makefile,
+#    with recipe "$(eval include env.make)"
+#  - add a phony target for 'env.make' that sources the script,
+#    then writes 'make' assignments like "export foo := bar"
+#    for each desired environment variable
+# To test:
+#   $export LMI_IN=X; make -f parent.make all
+#   $export LMI_IN=Q; make -f parent.make all
+# and check what appears on stdout.
+# A file named 'env.make' is created in the source directory.
+# That unwanted side effect can be avoided by replacing it
+# with, say, '/run/var/lmi/env.make'.
+# lmi's 'GNUmakefile' uses a double-colon rule like this:
+#parent.make $(srcdir)/parent.make:: ;
+# which becomes relevant below. Possible problem: adding a
+# prerequisite may impair the efficiency that was gained by
+# writing the double-colon rule.
+# No good: syntax error.
+#include set.sh
+# Neither necessary nor sufficient.
+#include env.make
+# This can't coexist with the desired double-colon rule (see above):
+#parent.make: env.make
+parent.make parent.make:: env.make ;
+# $(eval include) here is necessary and sufficient.
+       $(eval include env.make)
+       @echo "eval: LMI_IN in 'parent.make': $$LMI_IN"
+       @echo "eval: LMI_OUT in 'parent.make': $$LMI_OUT"
+# Doesn't execute recipe without ".PHONY":
+.PHONY: env.make
+# This prerequisite is unnecessary:
+#env.make: set.sh
+       @echo "Sourcing 'set.sh'"
+       . ./set.sh ; echo "export LMI_OUT := $$LMI_OUT" > env.make
+       @echo "target: LMI_IN in 'parent.make': $$LMI_IN"
+       @echo "target: LMI_OUT in 'parent.make': $$LMI_OUT ...but wait..."
+       @echo "LMI_OUT for targets in 'parent.make': $$LMI_OUT"
+       $(MAKE) --no-print-directory -f child.make
+# Obviously one could simply write a cover script to replace direct
+# invocation of 'make', but that's nasty. See:
+#   https://lists.gnu.org/archive/html/help-make/2006-04/msg00142.html
+# which suggests 'eval'.
+# This is unhelpful:
+# except that it has a link to:
+#   https://blog.153.io/2016/04/18/source-a-shell-script-in-make/
+# which doesn't actually work in its final, simplified version;
+# but earlier in that article it uses 'eval include', which does work.
diff --git a/set.sh b/set.sh
new file mode 100755
index 0000000..e6ece61
--- /dev/null
+++ b/set.sh
@@ -0,0 +1,13 @@
+#!/bin/sh this-script-must-be-sourced-not-run
+echo "LMI_IN in 'set.sh': $LMI_IN"
+echo "LMI_OUT entering 'set.sh': $LMI_OUT"
+export LMI_OUT="$LMI_IN"
+echo "LMI_OUT leaving 'set.sh': $LMI_OUT"
+unset -f foo

reply via email to

[Prev in Thread] Current Thread [Next in Thread]