How to handle shell expansions in GNU Make under Ubuntu?
Asked Answered
I

3

23

Given this very simple Makefile:

all:
    @mkdir -pv test/{a,b}

I get this output on OS X 10.6.8 and CentOS 5.5:

mkdir: created directory `test'
mkdir: created directory `test/a'
mkdir: created directory `test/b'

But on Ubuntu 11.04 I get this:

mkdir: created directory `test'
mkdir: created directory `test/{a,b}'

Running the command mkdir -pv test/{a,b} manually in the shell on all platforms gives the expected result.

The version of GNU Make is the same on all platforms:

GNU Make 3.81
Copyright (C) 2006  Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.

This program is built for [PLATFORM]

What's different under Ubuntu and why doesn't the shell expansion work there?

Integument answered 13/7, 2011 at 15:42 Comment(0)
P
38

The problem is probably that Make spawns /bin/sh. It is usually a symlink to your system's default shell.

Option 1

You could make sure it points to bash (as this is a bashism). Probably, it is now /bin/dash or /bin/sh, depending on your version of Ubuntu.

Option 2

Easier option:

SHELL=/bin/bash

all:
    @echo a{3,4}
    @bash -c 'echo a{3,4}'

This prints the same output twice unless you comment-out the SHELL= line

Option 3

If you can't/don't want to modify the make file, you can invoke it like so:

make SHELL=/bin/bash

beware of interactions with sub-makefiles or includes. You might want to look at the make -e option and the make export keyword: http://www.gnu.org/s/hello/manual/make/Variables_002fRecursion.html

Planchette answered 13/7, 2011 at 15:47 Comment(1)
This was the case. We're having makefiles that should run on all these different platforms, so setting the SHELL variable was the way to go.Integument
A
2

Make has a function to do this:

    @mkdir -pv $(addprefix test/,a b)

gets expanded to

    @mkdir -pv test/a test/b

The docs are very thorough.

Aixlachapelle answered 25/8, 2022 at 2:10 Comment(0)
C
1

It's been a long, long time since I've used Make...

There are several ways to specify a particular shell to use. The default shell for old Make was the original Bourne shell. If you wanted a different shell, you had to set it yourself.

You're using Linux and GNU, so I'll assume that you're using BASH as the default shell. Try this command in your Make:

echo "random = $RANDOM"

If this simply prints random = and doesn't include a random number, your Make is using Bourne shell as its default shell instead of BASH. (Which is weird because I didn't think there was a real Bourne shell in Linux...) To get around this:

  • You can add in a SHELL macro pointing to the BASH shell.
  • You can include the shell in your command.

Instead of:

@mkdir -pv test/{a,b}

Put this:

/bin/bash -c @mkdir -pv test/{a,b}

This specifies you want to use BASH and not the standard /bin/sh Bourne shell.

If the echo random = $RANDOM does print a random number, you're using BASH (or at least Kornshell), but the BRACE EXPANSION might not be set. Try using this in your Makefile:

set -o

And make sure braceexpand is on. It could be off when you run Make.

Clerihew answered 13/7, 2011 at 16:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.