Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to load and export variables from an .env file in Makefile?

What is the best way to use a .env in a Makefile, i.e. loading that file and exporting all variables for subshells in make?

It would be great if the proposed solution would work with make only, e.g. not using any third party tools. Also .env files support multiline variables like:

FOO="this\nis\na\nmultiline\nvar"

this is why this solution is probably not adequate.

like image 428
Bastian Venthur Avatar asked Jun 19 '17 10:06

Bastian Venthur


People also ask

How do I export a variable in Makefile?

To pass down, or export, a variable, make adds the variable and its value to the environment for running each command. The sub-make, in turn, uses the environment to initialize its table of variable values. The special variables SHELL and MAKEFLAGS are always exported (unless you unexport them).

How do I export an .env file?

To export a environment variable you run the export command while setting the variable. We can view a complete list of exported environment variables by running the export command without any arguments. To view all exported variables in the current shell you use the -p flag with export.

How do I set an environment variable in Makefile?

Re: Setting Environment variable in MakefileTo get the shell to see one "$", you must use "$$" in the Makefile. 2.) Environment variables can only be inherited from parent to child processes, not vice versa. In this case, the parent process is the 'make' that is processing the Makefile.


2 Answers

Make does not offer any way to read a content of the file to some variable. So, I consider it impossible to achieve the result without using external tools. However, if I am wrong, I'd be glad to learn some new trick.

So, let's assume there are two files, .env, being a technically correct shell file:

FOO=bar  BAR="notfoo" # comment    #comment MULTILINE="This\nis\nSparta!" # comment 

and script.sh:

#!/bin/bash echo FOO=${FOO} echo BAR=${BAR} echo -e ${MULTILINE} 

One solution is to include the .env file, then make sure variables are exported:

include .env  $(eval export $(shell sed -ne 's/ *#.*$$//; /./ s/=.*$$// p' .env))  all:     ./script.sh 

Because of different treatment of quotes by shell and make, you will see the quotes in output.

You can avoid that by reprocessing the variables by make:

include .env  VARS:=$(shell sed -ne 's/ *\#.*$$//; /./ s/=.*$$// p' .env ) $(foreach v,$(VARS),$(eval $(shell echo export $(v)="$($(v))")))  all:     ./script.sh 

but then the multiline variable will become a one-liner.

Finally, you can generate a temporary file to be processed by bash and source it before any command is run:

SHELL=bash  all: .env-export     . .env-export && ./script.sh  .env-export: .env     sed -ne '/^export / {p;d}; /.*=/ s/^/export / p' .env > .env-export 

Oh, new lines got messed in this case in multiline variable. You need to additionally quote them.

Finally, you can add export to .env using above sed command, and do:

SHELL=bash %: .env-export     . .env-export && make -f secondary "$@" 
like image 124
ArturFH Avatar answered Sep 22 '22 18:09

ArturFH


Found this and it worked great:

at top of makefile

ifneq (,$(wildcard ./.env))
    include .env
    export
endif

Then you have make variables for all your env, for example MY_VAR use as $(MY_VAR)

like image 43
edencorbin Avatar answered Sep 22 '22 18:09

edencorbin