Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

makefile assign command to

I'm probably being stupid, but I cannot do the most basic variable assignment in my Makefile.

TEST = $(pwd);

all:
    echo $(TEST)

When I run "make all" from Bash (v4.2.42) in FreeBSD (v9.1) I get:

echo

No idea what I'm screwing up. I've also tried to assign the variable using $(shell ...) with the same result.

If I use back ticks (`) then basic assignment works, but it doesn't store the result, it stores the command. This breaks in the following example Makefile:

SERVERIP = `ifconfig em0 | grep -E 'inet.[0-9]' | awk '{ print $$2}'`

all:
    echo $(SERVERIP)
    sed -e 's/%LISTENIP%/${SERVERIP}/g' test.conf > work/test.conf.tmp

The result is:

[pete@pete] ~/make
echo `ifconfig em0 | grep -E 'inet.[0-9]' | awk '{ print $2}'`
10.128.28.151
sed -e 's/%LISTENIP%/`ifconfig em0 | grep -E 'inet.[0-9]' | awk '{ print $2}'`/g' test.conf > work/test.conf.tmp
sed: 1: "s/%LISTENIP%/`ifconfig  ...": unescaped newline inside substitute pattern
*** [all] Error code 1

You can see that basic variable assignment appears to work, but when you insert the result into sed, it inserts the whole command rather than the result, which breaks!

Any ideas?

Pete.

like image 982
Pete Avatar asked Apr 09 '26 00:04

Pete


2 Answers

Maybe the answer is too late but I hope I can help (somebody else).

If you don't want to install GNU's make you can use the !=:

TEST!=pwd
all:
    echo ${TEST}

will work. The explanation is very simple, please read carefully FreeBSD's man make, especially the "Variable assignment modifiers" inside the "VARIABLE ASSIGNMENTS" section:

Variable assignment modifiers

The five operators that can be used to assign values to variables are as follows: ...

!= Expand the value and pass it to the shell for execution and assign the result to the variable. Any newlines in the result are replaced with spaces.

like image 106
uzsolt Avatar answered Apr 12 '26 02:04

uzsolt


The makefile contains:

TEST = $(pwd);

all:
    echo $(TEST)

The first line assigns the value in the make variable pwd plus a semicolon to make variable TEST. The rule then echoes that. You forgot, I think, that $(...) is significant to both make and shell. Assuming you want to echo the output of the pwd command, then use a double-dollar so make expands that to one dollar:

TEST = $$(pwd)

all:
    echo $(TEST)

To get the output of a shell command into a make variable, you have to use GNU make extensions. There are two extensions in use: the := immediate assignment that evaluates the value of SERVERIP at the point of definition, rather than at the point of use; and $(shell ...cmd...) that is used to run a shell command and capture its output.

SERVERIP := $(shell ifconfig em0 | grep -E 'inet.[0-9]' | awk '{ print $$2}')

all:
    echo ${SERVERIP}
    sed -e 's/%LISTENIP%/${SERVERIP}/g' test.conf > work/test.conf.tmp

This should work. The original error, about a newline in the sed regular expression, is odd; the back-ticks should have removed the trailing newline from the output of the ifconfig pipeline. However, if there were in fact multiple lines returned, then you'd still have a newline inside, justifying the complaint from sed.

This generates the complaint:

SERVERIP = `printf "%s\n" a b c`

all:
    echo $(SERVERIP)
    sed -e "s/%LISTENIP%/${SERVERIP}/g" test.conf > work/test.conf.tmp

This works:

SERVERIP = `printf "%s\n" c`

all:
    echo $(SERVERIP)
    sed -e "s/%LISTENIP%/${SERVERIP}/g" test.conf > work/test.conf.tmp

Since you're using FreeBSD, it is quite possible that you don't have GNU make. In that case, you will need to:

  1. Make sure the ifconfig command pipeline only produces one line of output.
  2. Use make commands like this:

    SERVERIP = `ifconfig em0 | grep -E 'inet.[0-9]' | awk '{ print $$2}'`
    
    all:
        echo ${SERVERIP}
        sed -e "s/%LISTENIP%/${SERVERIP}/g" test.conf > work/test.conf.tmp
    

    That should work with any version of make provided condition 1 is met.

like image 23
Jonathan Leffler Avatar answered Apr 12 '26 00:04

Jonathan Leffler