[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[lmi-commits] [lmi] odd/source_script_in_makefile 350571f: Source a shel
[lmi-commits] [lmi] odd/source_script_in_makefile 350571f: Source a shell script in a makefile
Fri, 17 May 2019 09:53:35 -0400 (EDT)
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
@@ -0,0 +1,4 @@
+ @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
@@ -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.
+# Neither necessary nor sufficient.
+# This can't coexist with the desired double-colon rule (see above):
+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":
+# This prerequisite is unnecessary:
+ @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:
+# which suggests 'eval'.
+# This is unhelpful:
+# except that it has a link to:
+# 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
@@ -0,0 +1,13 @@
+echo "LMI_IN in 'set.sh': $LMI_IN"
+echo "LMI_OUT entering 'set.sh': $LMI_OUT"
+echo "LMI_OUT leaving 'set.sh': $LMI_OUT"
+unset -f foo