Why Exported Variables in Makefile Is Not Received by Executable

Why exported variables in Makefile is not received by executable?

If I'm not mistaken each line in a Makefile is a separate shell-process. So shell-export does not work for several processes: One way to do it is to put them into one line:

test:
@ echo
@ echo "Testing Electric Fence."
@ echo "After the last test, it should print that the test has PASSED."
./eftest
./tstheap 3072
EF_ERRTRACK_START=3 EF_ERRTRACK_END=5 ./time-interval-measurement-test
@ echo
@ echo "Electric Fence confidence test PASSED."
@ echo

or line-break-escaped with '\'

test:
[..]
EF_ERRTRACK_START=3 \
EF_ERRTRACK_END=5 \
./time-interval-measurement-test

Like that the ENV-variables are available to ./time-interval-measrument

C Makefile: How to build environment variable into executable

You can use the -D option to create preprocessor variables on the command line.

CC=gcc
CFLAGS=-I
BUILD_TIME=`date`
example: example.c
$(CC) -D "BUILD_TIME=\"$(BUILD_TIME)\"" -o example example.c
#include <stdio.h>

int main()
{
printf("build time = %s\n", BUILD_TIME);
return 0;
}

How to set child process' environment variable in Makefile

Make variables are not exported into the environment of processes make invokes... by default. However you can use make's export to force them to do so. Change:

test: NODE_ENV = test

to this:

test: export NODE_ENV = test

(assuming you have a sufficiently modern version of GNU make >= 3.77 ).

Export current user id in makefile for docker-compose

Here is my solution

#!/usr/bin/make

SHELL = /bin/sh

CURRENT_UID := $(shell id -u)
CURRENT_GID := $(shell id -g)

export CURRENT_UID
export CURRENT_GID

up:

docker-compose up -d

Eclipse Makefile: Make Variables are skipped

This is not right:

obstacleDetection_cpp: src/obstacleDetection.cpp protoc_middleman
export APR_INCLUDE=/usr/include/apr-1
export CMS_HOME=~/Desktop/activemq-cpp-library-3.8.4
g++ $(APR_INCLUDE) -I $(CMS_HOME)/src/main ...

All lines in the recipe (that is, lines that are indented with a TAB in a target context like this) are passed to the shell. These are not make variable assignments. There are two things wrong with that:

First, each logical line in the recipe is passed to a new shell. That means any changes to the process context (such as the environment or the working directory) are present only for the duration of that logical line; once the shell processing that line exits, all those changes are lost. So, these lines have no impact: they set an environment variable in the shell, then the shell exits and that setting is gone.

Second, the variable references you make in your compile line, such as $(APR_INCLUDE), are make variable references, not environment variable references. So even if those environment variable assignments still had effect, they would not be used because you're not referring to environment variables here.

You want to create make variable assignments. That can only be done outside of a recipe. Also, you don't need to export them because only make needs to see them (make will expand them before invoking the shell). So, your makefile should look like this:

APR_INCLUDE = /usr/include/apr-1
CMS_HOME = $(HOME)/Desktop/activemq-cpp-library-3.8.4

obstacleDetection_cpp: src/obstacleDetection.cpp protoc_middleman
g++ -I $(APR_INCLUDE) -I $(CMS_HOME)/src/main -g -o src/obstacleDetection.o -c src/obstacleDetection.cpp
cd libs && cp $(CMS_HOME)/src/main/.libs/libactivemq-cpp.so.18.0.4 . && ln -sf libactivemq-cpp.so.18.0.4 libactivemq-cpp.so.18
g++ -L $(CMS_HOME)/src/main/.libs/ -g -o bin/obstacleDetection src/obstacleDetection.o src-gen/Point.pb.cc src-gen/Point.pb.h -lactivemq-cpp -lssl -lprotobuf -pthread
@echo "Success. Run the executable from the binary directory with: LD_LIBRARY_PATH=../libs/ ./obstacleDetection"

How to set environment variables in makefile?

Your question isn't entirely clear but there are a number of obvious things wrong there.

First off you are running make under Windows but writing recipes as if they were shell scripts. That's not the case on Windows (by default at least).

So export is being attempted to be run as an external command which is failing (hence the error message about CreateProcess failing).

You also don't show us the target that is actually throwing that error.

Additionally you are expecting the export and assignment on the first line of the recipe to be in effect for the second line in the recipe body (for the start target).

But that isn't the case. Each line in a makefile target's recipe runs in an independent environment. So the export and assignment on the first line of the START target's recipe doesn't affect the second line.

To do that you need to use one long line or use the .ONESHELL feature of recent versions of make.

Additionally, you are using $(NODE_ENV) in your recipe expecting that to be the shell variable you previously set. And even ignoring the previously stated problem that isn't correct.

make is going to expand $(NODE_ENV) as a make variable before it even runs the recipe at all. You meant ${NODE_ENV} or $NODE_ENV for a shell variable. That said for a make recipe you actually need to escape the $ because ${NODE_ENV} is also a valid make variable expansion. So you need $${NODE_ENV} or $$NODE_ENV there.

Put together you end up with this (assuming you have a shell somewhere to use).

SHELL := /path/to/your/shell

START:
export NODE_ENV=110; \
echo "$${NODE_ENV}"

(though you don't actually need export at that point but that's a different issue entirely).

But if you don't have a shell to use then you get to use cmd.exe and I'm not sure what the equivalent of export there is (though as I just said you don't need it for this) and you end up with something like this (entirely untested):

START:
NODE_ENV=110; \
echo %NODE_ENV%

load environment variables from a file in a makefile on windows

The . command is a feature of the POSIX shell. You are not using a POSIX shell on Windows, you're using Windows cmd.exe.

First, you can't name the file win.env. Windows cares a lot about file extensions so you'll have to name this file win.bat or something like that.

Second, in Windows cmd.exe you just run the script; it doesn't start a new command program like POSIX systems do.

run:
ifeq ($(OS),Windows_NT)
win.bat; go run .
else
. ./lin.env && go run .
endif


Related Topics



Leave a reply



Submit