Missing Separator when using shell function?

1.6k views Asked by At

I'm working on Solaris 11, fully patched. I'm trying to determine if the compiler supports an ISA by dumping preprocessor macros under the ISA.

Make is dying due to a Missing Separator. I'm having trouble finding information about the Missing Separator error when used with GNU make's shell function.

Here is the reduced case. There are no spaces, so its not a space/tab problem like in Make error: missing separator and friends.

$ cat -n GNUmakefile-test
 1  EGREP ?= egrep
 2  SUN_COMPILER := $(shell $(CXX) -V 2>&1 | $(EGREP) -i -c "CC: (Sun|Studio)")
 3
 4  # Begin SunCC
 5  ifeq ($(SUN_COMPILER),1)
 6  $(info "Sun compiler")
 7  $(shell $(CXX) $(CXXFLAGS) -E -xarch=ssse3 -xdumpmacros /dev/null 2>/dev/null)
 8  ifeq ($(.SHELLSTATUS),0)
 9  $(info "SSSE3")
10  SSSE3_FLAG = -xarch=ssse3 -D__SSSE3__=1
11  endif
12  endif
13  # End SunCC
14
15  all:
16          $(info "Do nothing")

The idea above is, SunCC does not provide macros for an ISA, like __AES__ or __SHA__. However, SunCC will error if the ISA is not supported, like -xarch=sha on SunCC 12.4. If I don't get an error, then I know the compiler supports the ISA, like -xarch=aes on SunCC 12.4. If there's an error I can fetch it from .SHELLSTATUS. (SunCC is not like Clang, GCC, Intel ICC, or MSVC in this area).

Here is the result:

$ CXX=/opt/solarisstudio12.4/bin/CC gmake -f GNUmakefile-test
"Sun compiler"
GNUmakefile-test:7: *** missing separator.  Stop.

Where is the missing separator? Or, what is the real error that make is not reporting? Maybe something else?


My apologies for asking this question given how many times its been asked before.

I added tabs in an attempt to appease make. It produced the same error.

$ cat -n GNUmakefile-test
 1  EGREP ?= egrep
 2  SUN_COMPILER := $(shell $(CXX) -V 2>&1 | $(EGREP) -i -c "CC: (Sun|Studio)")
 3
 4  # Begin SunCC
 5  ifeq ($(SUN_COMPILER),1)
 6       $(info "Sun compiler")
 7       $(shell $(CXX) $(CXXFLAGS) -E -xarch=ssse3 -xdumpmacros /dev/null 2>/dev/null)
 8       ifeq ($(.SHELLSTATUS),0)
 9            $(info "SSSE3")
10            SSSE3_FLAG = -xarch=ssse3 -D__SSSE3__=1
11       endif
12  endif
13  # End SunCC
14
15  all:
16       $(info "Do nothing")
2

There are 2 answers

3
MadScientist On BEST ANSWER

The way the shell function works (as discussed in the manual) is that it runs the command, and then it expands to the output of the command. That's why, when you see:

SUN_COMPILER := $(shell $(CXX) -V 2>&1 | $(EGREP) -i -c "CC: (Sun|Studio)")

the variable SUN_COMPILER is set to the output of that shell command.

So when you write this:

$(shell $(CXX) $(CXXFLAGS) -E -xarch=ssse3 -xdumpmacros /dev/null 2>/dev/null)

the command is run, then the output is substituted. After that, make tries to parse the results as make syntax. But the output of that command is clearly NOT make syntax, so you get this error.

If you don't care about the output and only care about the exit code, you need to either throw away the output:

$(shell $(CXX) $(CXXFLAGS) -E -xarch=ssse3 -xdumpmacros /dev/null >/dev/null 2>&1)

or else assign it to a dummy variable:

_x := $(shell $(CXX) $(CXXFLAGS) -E -xarch=ssse3 -xdumpmacros /dev/null 2>/dev/null)

so that make assigns the result to a variable rather than thinking it's make syntax.

1
jww On

We decided to avoid .SHELLSTATUS since it seems to have some problems. We fell back to grep and the string "illegal value ignored".

ifeq ($(SUN_COMPILER),1)
  COUNT := $(shell $(CXX) $(CXXFLAGS) -E -xarch=ssse3 -xdumpmacros /dev/null 2>&1 | $(EGREP) -i -c "illegal value ignored")
  ifeq ($(COUNT),0)
    SSSE3_FLAG = -xarch=ssse3 -D__SSSE3__=1
    ARIA_FLAG = -xarch=ssse3 -D__SSSE3__=1
  endif
  COUNT := $(shell $(CXX) $(CXXFLAGS) -E -xarch=sse4_2 -xdumpmacros /dev/null 2>&1 | $(EGREP) -i -c "illegal value ignored")
  ifeq ($(COUNT),0)
    BLAKE2_FLAG = -xarch=sse4_2 -D__SSE4_2__=1
    CRC_FLAG = -xarch=sse4_2 -D__SSE4_2__=1
  endif
  COUNT := $(shell $(CXX) $(CXXFLAGS) -E -xarch=aes -xdumpmacros /dev/null 2>&1 | $(EGREP) -i -c "illegal value ignored")
  ifeq ($(COUNT),0)
    GCM_FLAG = -xarch=aes -D__PCLMUL__=1
    AES_FLAG = -xarch=aes -D__AES__=1
  endif
  COUNT := $(shell $(CXX) $(CXXFLAGS) -E -xarch=sha -xdumpmacros /dev/null 2>&1 | $(EGREP) -i -c "illegal value ignored")
  ifeq ($(COUNT),0)
    SHA_FLAG = -xarch=sha -D__SHA__=1
  endif
endif
# End SunCC

We are not sure about -xarch=sha. At the moment we are trying to figure out what is needed.