Search code examples
makefilecmd

setlocal EnableDelayedExpansion in Makefile (Microsoft Windows)


src/Makefile

SHELL := cmd.exe

target:
    setlocal EnableDelayedExpansion
    set foo=hello
    echo !foo! %foo%

run the target

cd src
mingw32-make.exe
// output: !foo!

Why setlocal EnableDelayedExpansion not work in Makefile ?

mingw32-make.exe --version
GNU Make 3.82.90
Built for i686-pc-mingw32

Solution

  • Each action in a recipe is executed in separate shell. It means, that your recipe is equivalent of a shell script:

    cmd.exe /c setlocal EnableDelayedExpansion
    cmd.exe /c set foo=hello
    cmd.exe /c echo !foo! %foo%
    

    There are two ways to execute a recipe in one shell invocation.

    First, is you can either write a multi line:

    target:
        setlocal EnableDelayedExpansion \
        set foo=hello                   \
        echo !foo! %foo%
    

    Another way to do recipe in one shell is to use a special target .ONESHELL Then your makefile can be

    .ONESHELL:
    target:
        setlocal EnableDelayedExpansion
        set foo=hello
        echo !foo! %foo%
    

    Both approaches have limitations and caveats described in documentation. Choose what approach is better for you and your case.