g++ flag to only check syntax?

2020-06-27 02:01发布

问题:

Is there a way to have g++ check for C++98 syntax when compiling but at the same time compile as if no -std= has been given ? My goal is to make sure that my source code stays C++98 but I don't want to prevent g++ from using any newer optimisation or trick. For the moment, I compile my projet twice, once with CXXFLAGS=-std=c++98 and one with a final empty CXXFLAGS for release.

It looks like gcc 5 will have -Wc90-c99-compat and -Wc99-c11-compat, that something in that direction.

回答1:

You will have to run the compiler twice, but you can save compiletime on the -std=c++98 pass and avoid generating unwanted object files by specifying syntax-checking only. You do that by passing the option -fsyntax-only.

You'd also need to modify your make to skip linkage for C++98, as there'll be nothing to link.

Probably the most efficient way you could do this is with a make on the following lines:

.phony: all clean

SRCS = foo.cpp
FLAT_SRCS = $(patsubst %.cpp,%.ii,$(SRCS))
OBJS = $(patsubst %.ii,%.o,$(FLAT_SRCS))

%.ii: %.cpp
    g++ -std=c++98 $(CPPFLAGS) -E $< > $@ && g++ -std=c++98 -fsyntax-only $@

%.o: %.cpp
%.o: %.ii
    g++ -c -o $@ $(CPPFLAGS) $(CXXFLAGS) $<


all: foo

foo: $(OBJS) 
    g++ -o $@ $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LDLIBS)

clean:
    rm -f $(OBJS) $(FLAT_SRCS) foo

Here, the %.ii: %.cpp rule will first just preprocess the .cpp to the .ii, then pass the already preprocessed source to a C++98 syntax-checking pass, which produces no new file.

The empty %.o: %.cpp rule overrides the implicit rule that would otherwise cause the .cpp to be compiled to .o, and it is replaced with the %.o: %.ii rule to compile the .ii. g++ recognises .ii as denoting already-preprocessed C++ source code, so it will not preprocess the source a second time.

Code is only preprocessed once, and object code is only generated once.

The linkage is as usual. Provided the C++98 syntax check passes, a make will look like:

$ make
g++ -std=c++98  -E foo.cpp > foo.ii && g++ -std=c++98 -fsyntax-only foo.ii
g++ -c -o foo.o   foo.ii
g++ -o foo   foo.o 
rm foo.ii

You'll note that make automatically deletes the preprocessed .ii, which is fine: it's just a conduit between the .cpp and the .o.

All that being said, I side with @Matt McNabb's observation that you have nothing to gain by this! Given your code is C++98, the compiler won't optimize it any better when instructed that it must be C++98 than when not. By time GCC gets to the optimization stage of its business, it no longer cares what kind of source code it started off with.

You may be supposing that -std=c++98, when given say to g++ 4.x, causes the whole compiler to behave as if was g++ 2.x. Not so. It's still g++ 4.x, with the g++ 4.x optimization tech, etc., just operating by the language definition of C++98.

There would certainly be a point in this if your code for some reason had to pass, as C++98, on some older compiler than your release compiler, and in that case you would need to distinguish the compilers in the makefile. But apparently this is not the case. You might as well just compile conventionally with -std=C++98