【问题标题】:C++ Makefile %.c works, %.cpp not?C++ Makefile %.c 有效,%.cpp 无效?
【发布时间】:2013-07-22 05:59:06
【问题描述】:

我为 c++ 文件编写了一个简单的 makefile,但这是一个我不明白的问题。 我有 2 个文件夹

/src 用于 .cpp 文件

  • main.cpp
  • 检查 cpp

/include 用于 .hpp 文件

  • check.hpp

我的 Makefile 看起来像这样

LIBS = -lsfml-graphics -lsfml-window -lsfml-system
CC   = g++
VPATH = src include
CPPFLAGS = -I include

### Files ###
OBJ = main.o check.o

### Rules ###
all: sfml-app

sfml-app: $(OBJ)
    $(CC) -o sfml-app $(OBJ) $(LIBS)

%.o: %.c
    $(CC) -c $<

clean:
    rm -rf *o $(OBJ) 

如果我像这样使用我的 makefile,一切正常。 但是如果我将 %.o: %.c 更改为 %.o: %.cpp 他说

src/main.cpp:2:21: critical  error: check.hpp: file or folder not found

即使它是一个 c++ 项目,写 .cpp 而不是 .c 是错误的吗?这让我有点困惑。为什么 .c 有效而 .cpp 无效。

感谢您的帮助:)!

【问题讨论】:

  • CC = g++ - 错误
  • @H2CO3 实际上你需要这条规则,除非你重载自动链接规则(不要!)因为make使用$(CC)进行链接,不是 $(LD),至少在我的系统上(据我所知这很正常)。
  • 您遇到编译错误。发布您的main.cpp 文件。 main.hpp 是否存在于正确的文件夹中?
  • @KonradRudolph CC 在概念上(并且作为 GNU make 中的隐含规则)是 C 编译器。对于编译 C++,使用CXXCC = g++错了。

标签: c++ makefile


【解决方案1】:

因为 make 正在尝试从 .cpp 文件构建 .o,所以当您编写类似 %.o : %.c 的规则时,它对 make 没有影响,因为 make 不会尝试从 @987654325 构建 .o @。因此,make 使用自己的内置规则将.cpp 文件编译成.o 文件,并且内置规则工作正常。

当您将规则更改为 %.o : %.cpp 时,现在您的规则与 make 想要构建的匹配,因此 make 使用 your 规则而不是它自己的内置规则。显然你的规则被打破了并且不起作用。

为什么它不起作用?因为你没有使用$(CPPFLAGS),所以-I include标志没有传递给编译器,所以编译器找不到你的头文件。

【讨论】:

    【解决方案2】:

    C++ 语言的标志变量称为CXXFLAGS,您应该在代码中使用$(CXX) 而不是$(CC)CPPFLAGS 是预处理器参数的变量。

    【讨论】:

    • 请注意,他使用CPPFLAGS 作为预处理器参数:-I 是一个预处理器参数。唯一错误的变量是,正如您提到的,他应该使用 CXX 而不是 CC 用于 C++ 编译器。
    • 不同的预处理器参数。当您使用$(CPP) myfile.txt_pp &gt; myfile.txt 时使用 CPPFLAGS - 也就是说,您正在使用 C 预处理器来修改文本文件或其他一些“不适用于 C 编译器”的内容(或者如果您在编译之前出于某种原因进行预处理)
    • 如果你使用cpp(或$(CPP)宏)命令预处理文件,CPPFLAGS,如果你使用g++$(CXX)宏,或其他一些C++ 编译器,CXXFLAGS。两者都是有效变量,但上述 makefile 的正确变量是 CXXFLAGS
    • 不,CFLAGS 用于 C 编译器。
    • 垫子,这是不正确的。 CPPFLAGS 用于所有预处理器标志。将它们与CFLAGS 分开的原因是您可以将它们传递给想要预处理源代码但不编译它的工具(因此它们不接受编译器标志)。最好的例子,在 make 很年轻的时候,是lint,但还有很多其他的。您希望这些工具使用与您的编译相同的-I-D 标志,因此您将它们放在CPPFLAGS 中,然后在编译时使用CFLAGS(对于C)或CXXFLAGS(对于 C++)AND CPPFLAGS,在一起。
    【解决方案3】:

    使用标准的 make 文件标志

    CXX for g++ 用于 cpp 文件的 CPP

    并尝试:

    %.o: %.cpp
     $(CXX) $(CXXFLAGS) -c $<
    

    【讨论】:

      【解决方案4】:

      默认规则为:

      对于 C 文件:

      $(CC) -c $(CPPFLAGS) $(CFLAGS) $?
      

      对于 C++ 文件

      $(CXX) -c $(CPPFLAGS) $(CXXFLAGS) $?
      

      对于链接:

      $(CC) $(LDFLAGS) $^ $(LOADLIBES)
      

      CPPFLAGS 应该是预处理器标志。另外两个(CFLAGS CXXFLAGS)是特定语言的标志。你应该这样调整你的使用量。

      显式定义目标文件也不常见:

      OBJ = main.o check.o
      

      更常见的是定义源文件。然后根据源文件定义目标文件

      OBJ = $(patsubst %.cpp, %.o, $(SRC))
      

      我个人喜欢在目录中构建所有内容,所以使用

      SRC = $(wildcard *.cpp)
      

      但这在很大程度上取决于项目。

      【讨论】:

      • 谢谢!我个人更喜欢 makefile 列出他们要显式编译的文件,而不是尝试通过通配符获取它们。后者非常容易出错:可能存在额外文件并被意外编译;文件可能会丢失并且无法编译等。但是你是对的,我应该写源文件,而不是目标文件。 patsubst 很有帮助 :) !
      猜你喜欢
      • 1970-01-01
      • 2014-06-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-15
      相关资源
      最近更新 更多