g++标志只检查语法?

5
有没有一种方法让g++在编译时检查C++98语法,但同时编译时不会像未给出-std=一样?我的目标是确保我的源代码保持C++98,但我不想阻止g++使用任何更新的优化或技巧。目前,我将项目分别编译两次,一次使用CXXFLAGS=-std=c++98,另一次使用最终空的CXXFLAGS进行发布。
看起来,gcc 5将具有-Wc90-c99-compat-Wc99-c11-compat,这是朝着这个方向的一些东西。

我认为这样的开关对C++的效果不如对C的效果好。C++03和C++11之间的差异不仅仅局限于语法,还有标准库头文件、类和函数的重大差异。当然,这在C中也是一个问题,但远没有那么严重。 - user743382
“新的优化技巧”是什么意思?标准并不阻止在满足源代码为符合C++98标准的前提下进行任何优化。 - M.M
1个回答

8
您需要运行编译器两次,但您可以通过指定仅进行语法检查来节省编译时间并避免生成不需要的目标文件,从而在-std=c++98过程中节省编译时间。您可以通过传递选项-fsyntax-only来实现这一点。
您还需要修改make,以跳过C++98的链接,因为没有需要链接的内容。
您可以使用以下方式最有效地完成此操作:make如下所示:
.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

在这里,%.ii:%.cpp规则首先只是将.cpp预处理为.ii,然后将已经预处理过的源代码传递给C++98语法检查器, 这不会产生新文件。

空的%.o:%.cpp规则覆盖了否则会导致.cpp编译为.o的隐式规则,并被%.o:%.ii规则替换以编译.ii。 g++将.ii识别为表示已经预处理的C++源代码,因此它不会再次对源代码进行预处理。

代码只预处理一次,并且生成目标代码也只有一次。

链接与往常一样。只要C++98语法检查通过,make看起来像:

$ 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

您会注意到,make 自动删除预处理的 .ii,这没问题:它只是 .cpp.o 之间的一个通道。

尽管如此,我同意 @Matt McNabb 的观点,即您没有任何收获!既然您的代码确实是 C++98,那么编译器在被告知必须是 C++98 时不会比不指定更好地进行优化。当 GCC 到达其业务的优化阶段时,它不再关心源代码的类型。

您可能认为,将 -std=c++98 给 g++ 4.x 等编译器使用,会导致整个编译器像 g++ 2.x 一样运行。并非如此。它仍然是 g++ 4.x,具有 g++ 4.x 的优化技术等,只是按照 C++98 的语言定义操作。

如果您的代码出于某种原因必须作为 C++98 在发布编译器之前的某个较旧的编译器上通过,那么在这种情况下,您需要在 makefile 中区分编译器。但显然这不是这种情况。您可以像常规编译一样使用 -std=C++98 进行编译。


谢谢,这是一个聪明的做法。我不想要求使用更新的编译器,所以我想坚持使用通用语言集。但是强制使用-std=XXX会禁止g++进行一些优化等操作。我将这样做:先使用98进行语法检查,然后再真正编译时不使用-std=。 - Benoît

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接