I am trying to use gcc preprocessor for its macro expansion capabilities (I'm not trying to produce code).
I have a macro — MY_MACRO — that needs to get an argument that has double quotes inside
As you can see, the preprocessor produces an error: unterminated argument list
Is there a way to escape the quotes?
#define MY_MACRO(X)
MY_MACRO(prefix"suffix)
For example:
$ gcc -E -P -w a.txt
error: unterminated argument list invoking macro "MY_MACRO"
$
The C preprocessor works on C source code. A lone " is not valid C, so the cpp rejects it. You can cpp for other purposes only if you're willing to stick to the C syntax rules.
m4 is a general-purpose macro-processor and standard installed on anything Unix-like, though nobody likes it. There aren't many alternatives.
Related
I am trying to run static analysis on my code using a tool. The Makefile contains:
export TASK=MY_TASK_NAME
my_static_code_tool.exe <arguments> -- gcc <arguments..> -D__TASK_NAME__=\"$(TASK)\" -o missionFile.o missionFile.c
I find that this executes without an issue on RedHat but fails to run on my Cygwin environment. I assign __TASK_NAME__ variable to an unsigned char in a C file such as:
const unsigned char TASK_NAME[] = __TASK_NAME__;
I get the error as:
gcc: no input files
I am very sure my arguments are all correct and I am referring to sources in the correct directory. To me it looks as if the -- stops the parsing of escape sequences in the command on Windows. Can anybody help me with a workaround?
The -- is used by the tool to introduce the compiler and its arguments [and thereby inform the tool that the following is compiler specific]. The GCC had all the required source/files/configuration defined in the Makefile. However it was not processed completely in the Cygwin shell (the command processing stopped with the escaping hence the corresponding gcc error).
The solution I employed to make this work was pre-processor stringification.
C file:
#define STRINGIFY_IT(str) STRING_OF(str)
#define STRING_OF(str) #str
const unsigned char TASK_NAME[] = STRINGIFY_IT(__TASK_NAME__);
Makefile:
export TASK=MY_TASK_NAME
my_static_code_tool.exe <arguments> -- gcc <arguments..> -D__TASK_NAME__=$(TASK) -o missionFile.o missionFile.c
So, if any of you face such problems in the future with 3rd party tools, try not to pass string arguments through the command line to GCC (as they will need to be escaped and might break the command)
I am trying to download the Shakespeare to C compiler, and I have gotten to the point where I am trying to run the Makefile. I have tried nmake -f Makefile, but that returns fatal error U1000 on line 41:
I can't find anything wrong with the Makefile. There is the same number of "(" and ")".Line 41 says MAKESCANNERINCLUDE = $(wildcard $(INCLUDEPATH)/*.{wordlist,metaflex}).
$(wildcard …) is a function call. Function calls are a GNU make extension to the standard make syntax. Nmake expects a variable reference which would be just $(something), so when it sees a space instead of a closing parenthesis, it reports a syntax error.
Use GNU make instead of Nmake.
I'm trying to build some c programs with gnu make (4.1) through a shell script. I want to use different CFLAGS parameters, which I read from a file. The file contains lines like:
"-O1 -freorder-functions"
I am trying to do something like
while read line
do
opts="$line"
make CFLAGS="$opts"
done < $1
but all my attempts end up in the following error:
cc1: error: argument to ‘-O’ should be a non-negative integer, ‘g’, ‘s’ or ‘fast’
So I tried to change the file's contents to only the parameters after -O1 (-freorder-functions), and add the -O1 in the shell script:
opts=$(printf "\"-O%d %s\"", 1, "$line")
(and a lot of other things that seem less sensible) but I still get the same error message.
Hard-coding the parameter to make in the shell script works fine:
make CFLAGS="-O1 -freorder-functions"
Sorry if this is a stupid question, but I can't seem to find any examples of how something like this is done, and I'm new to shell scripting, so I don't really understand how it's treating the variables here. An echo of what I'm attempting to pass to CFLAGS looks okay to me.
With double quotes around the flags in the file and you dutifully quoting your shell variables properly, your make call ends up being
make CFLAGS="\"-O1 -freorder-functions\""
That is to say, with double quotes in the flags. This is passed all the way down to the compiler call, which means that the compiler call is something like
cc "-O1 -freorder-functions" -c foo.c
...which asks the compiler to use optimization level 1 -freorder-functions, and it complains that that is not valid.
To solve this, I would remove the quotes from the file. You could also use opts=$line with $line unquoted, but that is not exactly safe.
I have a project whose makefile uses features exclusive to GNU Make. Sadly, there are platforms we must support where GNU make is still not the default when running make.
One of my colleagues was bitten by this, when a non-GNU make implementation silently failed to build our code correctly (it expanded an automatic variable to an empty string). I want to prevent that from happening again, by generating an explicit error message instead.
What can I write in a Makefile to distinguish GNU make from non-GNU make, print a clear error, and exit?
I've already figured out a workaround in renaming my real makefile to GNUmakefile, and putting a small stub in Makefile, but I'd rather something more direct.
The answers by Beta and Dan Moulding look really nice and simple, but on AIX 6.1, the make implementation can't handle either of them:
$ cat testmake
foo:
touch foo
ifeq ($(shell $(MAKE) -v | grep GNU),)
$(error this is not GNU Make)
endif
ifeq "${MAKE_VERSION}" ""
$(info GNU Make not detected)
$(error ${MIN_MAKE_VER_MSG})
endif
$ /usr/bin/make -f testmake
"testmake", line 5: make: 1254-055 Dependency line needs colon or double colon operator.
"testmake", line 6: make: 1254-055 Dependency line needs colon or double colon operator.
"testmake", line 7: make: 1254-055 Dependency line needs colon or double colon operator.
"testmake", line 8: make: 1254-055 Dependency line needs colon or double colon operator.
"testmake", line 11: make: 1254-055 Dependency line needs colon or double colon operator.
"testmake", line 12: make: 1254-055 Dependency line needs colon or double colon operator.
"testmake", line 13: make: 1254-055 Dependency line needs colon or double colon operator.
make: 1254-058 Fatal errors encountered -- cannot continue.
I run into similar issues on both archaic and modern versions (Solaris 8 & 10) of Sun's make. That one's less critical, but would be nice to manage.
As noted, GNU make checks for GNUmakefile before makefile or Makefile, I've used a trivial fix such as you described, a default (decoy) Makefile that causes an error/warning:
default:
#echo "This requires GNU make, run gmake instead"
exit 70
The GNU make documentation recommends using the GNUmakefile name when the Makefile is GNU make specific, so that's my preferred solution.
On platforms where the native make prefers a different Makefile name, you can do a variation on this, e.g. on FreeBSD I have the above decoy in the BSDmakefile which is used in preference to Makefile (thus preventing the system make from mangling my build). AFAICT the AIX or Solaris make do not have an alternate name you could use in this way.
One problem with a wrapper Makefile which tries to call GNU make is passing all the arguments.
A seemingly portable test (so far, I've found it to work on a mix of ancient OSF1, BSD and Solaris systems) you can use SOMETHING=$(shell ...) to detect if GNU make is running, non GNU versions will not set SOMETHING. Because of deferred evaluation of variables, you cannot use this as easily as might be expected though. This relies on the implementation silently handling macro names with spaces when expanded with $() (i.e. treats $(shell foo) as a variable/macro name rather than a function, even though an assignment to such a name in that implementation would cause an error).
The only portable way you can print a clear error is to have a dummy target that is always run, using the above trick:
GNUMAKE=$(shell echo GNUMAKE)
default: gnumake all
gnumake:
#[ "$(GNUMAKE)" = "GNUMAKE" ] || { echo GNU make required ; exit 70; }
This assumes you have a POSIX sh shell.
(I have seen tests which inspect $(MAKE) -v fail when both system and GNU make are called "make", the system make conspires against you and invokes GNU make ... You'd need some carefully checking of environment variables PATH, MAKE and possibly SHELL to handle every case.)
I don't know of any internal feature that is definitely unique to GNUMake, but here's a kludge: call "make -v" and parse the output for "GNU" (since it seems unlikely that a non-GNU Make would have MAKE set to a GNU Make):
ifeq ($(shell $(MAKE) -v | grep GNU),)
$(error this is not GNU Make)
endif
EDIT:
Like Dan Moulding, I am starting to see the real size of this problem. As written, it requires a Makefile that is syntactically correct in all versions of Make. I don't have access to Sun Make (and I can't find manuals for it) so I don't know whether that's even possible, or how to write it if it is, or how to test it if I did.
But I can suggest an approach that might work. Maybe something like this can be made universal:
default:
./runGNUMake.pl
That's it, that's the whole makefile. Then write the runGNUMake script in Perl (or bash, or whatever you like) that will do something like my "make -v" kludge and then either print the error message or run "make -f realMakefile".
Are multi-line macros supported(compilable) in gcc version 3.2.4. I am trying to build my source which has multi-line macros on a linux host using above mentioned gcc version.
I get compilation error at the macro, which is multiline.
#define YYCOPY(To, From, Count) \
do \
{ \
YYSIZE_T yyi; \
for (yyi = 0; yyi < (Count); yyi++) \
(To)[yyi] = (From)[yyi]; \
} \
while (0)
If they are not supported, what is the workaround for this, converting the macro to a function or some other compiler option can help?
thank you.
-AD
Backslashes to continue the macro is standard preprocessor. Check for extra spaces or other invisible characters after your backslash.
The ANSI C specification requires compilers to support this -- specifically, the standard says that if a line ends in a backslash immediately before the newline, the preprocessor is to treat that line and the subsequent line as one logical line, as if both the backslash and the newline did not exist. If a preprocessor does not do this, it is not a conforming preprocessor (or more technically, a translator, as the standard calls it).
GCC strives to be as conforming as possible to the ANSI C standard. Yes, it support multiline macros defined with backslashes at the end of lines.
The reason you're getting compiler errors is something else. You're not using the macro properly. Without posting the exact error messages you're receiving and the code which invokes the macro, it's impossible to say what you're doing wrong.