Search code examples
linuxbashembeddedcross-compilingbuildroot

How to define local variable in Buildroot which is an execution result of bash script


There's a local variable in netmap/LINUX/configure named BUILDDIR and its value is BUILDDIR=$PWD.It should have to be redirected to $(@D) which is netmap package build directory, /usr/local/buildroot/output/build/netmap-master in my case;otherwise, object files will be outputed to buildroot root directory.

I created a variable named NETMAP_CURRENT_BUILD and let it be /usr/local/buildroot/output/build/netmap-master,$(@D), and then I wanna replace BUILDDIR=$PWD to BUILDDIR=/usr/local/buildroot/output/build/netmap-master. By using sample code as following, it can't be done.

Sample Code :(sed part worked fine at terminal console)

    define NETMAP_BUILD_CMDS
    NETMAP_CURRENT_DIR = $(sed -e 's/\//\\\//g' <<< "$(@D)")   --   empty
    echo "$$(sed -e 's/\//\\\//g' <<< "$(@D)")"               -- this line works fine
...
    sed -e 's/BUILDDIR=$$PWD/BUILDDIR=$(NETMAP_CURRENT_DIR)/g' -i $(@D)/LINUX/configure     
(double $$PWD, it has to be like this, which means string $PWD is needed rather than its value.)
    ...
        endef

Solution

  • You don't actually need this, see below. However, if you do need the result of a shell command in a make variable, use $(shell ...)

    Since this is a makefile, the $ are interpreted by make, not by the shell. Therefore, make will try to evaluate sed -e 's/\//\\\//g' <<< "$(@D)" as a variable name. There is of course no variable with that name, so you get an empty string.

    To let make run a shell command and store the result in a make variable, use the $(shell ...) function. So

    NETMAP_CURRENT_DIR = $(shell sed -e 's/\//\\\//g' <<< "$(@D)")
    

    Note that that should be done outside of the NETMAP_BUILD_CMDS, because the contents of NETMAP_BUILD_CMDS is in fact a shell script: make first expands all variables in that script, then passes it to the shell line-by-line. The shell will actually error out on the above statement because you have spaces around the = so NETMAP_CURRENT_DIR is interpreted as a command name.

    If you want to store the result in a shell variable rather than a make variable, then the easiest solution is to use backticks `...` to delimit the command instead of $(...):

    define NETMAP_BUILD_CMDS
            NETMAP_CURRENT_DIR=`sed -e 's/\//\\\//g' <<< "$(@D)"`; \
            sed -e 's/BUILDDIR=$$PWD/BUILDDIR=$$NETMAP_CURRENT_DIR/g' -i $(@D)/LINUX/configure
    endef
    

    However, in your case you don't need this at all.

    First of all, you can do simple substitutions directly in make.

    NETMAP_CURRENT_DIR = $(subst /,\/,$(@D))
    

    Even better, you can simply use a different delimiter than / in your sed expression, then there is no need to quote it:

    sed -e 's@BUILDDIR=$$PWD@BUILDDIR=$(@D)@g' -i $(@D)/LINUX/configure
    

    One final note: modifications to the code like this are better done in NETMAP_POST_PATCH_HOOKS than in NETMAP_BUILD_CMDS. So finally, the best solution is:

    define NETMAP_FIX_BUILDDIR
            sed -e 's@BUILDDIR=$$PWD@BUILDDIR=$(@D)@g' -i $(@D)/LINUX/configure
    endef
    NETMAP_POST_PATCH_HOOKS += NETMAP_FIX_BUILDDIR