1

I would like to use bash's arithmetic expansion for binary operations in a Makefile (GNU make + bash on Debian). These are not covered by expr. I need this in a Makefile:

$ x=$(( 255 & 2#11110000)); echo $x
240

Things that don't work:

$ cat Makefile 
all: a b

a: # $ interpreted by make
    x=$(( 255 & 2#11110000)); echo $$x

b: # escaped $
    x=$$(( 255 & 2#11110000)); echo $$x

(a) obviously doesn't work, and (b) doesn't either:

$ make b
x=$(( 255 & 2#11110000)); echo $x
/bin/sh: 1: arithmetic expression: expecting EOF: " 255 & 2#11110000"

What's a possible way? Generous amounts of quoting, backticking and escaping also yielded no results.

Volker Stolz
  • 7,274
  • 1
  • 32
  • 50
  • 1
    Does this answer your question? [How can I use Bash syntax in Makefile targets?](https://stackoverflow.com/questions/589276/how-can-i-use-bash-syntax-in-makefile-targets) – KamilCuk Mar 16 '20 at 10:33
  • Thank you Kamil, yes, that is closely related, but was just too general so it didn't pop up on my radar. – Volker Stolz Mar 16 '20 at 11:25

2 Answers2

4

add

SHELL = bash

to the makefile

ensc
  • 6,704
  • 14
  • 22
  • Very interesting, forgot to check where `/bin/sh` points to, indeed. But `dash` should also support arith expansion, though? – Volker Stolz Mar 16 '20 at 10:38
  • No. dash is a minimalist implementation of the POSIX standard for the `sh` (shell) utility. It doesn't provide hardly any extensions to the standard. This is a good thing as it makes it much more likely that your script will work on systems where `/bin/sh` is not bash. Bash on the other hand has a very large number of extra features that don't appear in the standard. Extended arithmetic is one of those features. – MadScientist Mar 16 '20 at 15:40
1
$ cat Makefile

# Make variable (recommended)
x := $(shell bash -c 'echo $$((255 & 2\#11110000))')
$(info [$x])

# Shell variable (not recommended)
a:
    x=`bash -c 'echo $$((255 & 2#11110000))'`; echo $$x

Giving

$ make
[240]
x=`bash -c 'echo $((255 & 2#11110000))'`; echo $x
240

Don't forget that # introduces a comment in a makefile!

I recommend using make facilities rather than shell facilities wherever possible. It usually turns out to be cleaner. (As @ensc says, I do — I use bash everywhere in my makefiles :-).)

bobbogo
  • 14,989
  • 3
  • 48
  • 57
  • Thanks for also mentioning the `#`. It's a pity that `make` variables don't work within targets, though, but only on top-level. – Volker Stolz Mar 23 '20 at 12:30
  • @ShiDoiSi Eh? Make variables work in every part of a makefile, both targets and recipes. You do have fine control using them. – bobbogo Mar 24 '20 at 10:38
  • Hm, then I'm still doing something wrong: the line `z := $(shell bash -c 'echo $$((255 & 2#11110000))')` in a target yields `gmake: z: Command not found`. – Volker Stolz Mar 24 '20 at 15:27
  • The `z := …` syntax is _make_, not _bash_. Looks like you have a tab character before the `z`, so that _make_ thinks the line is part of a recipe. Recipes are executed by the shell. – bobbogo Mar 27 '20 at 17:41