c++ - Makefile:没有规则来制作目标:如何设置正确的规则?

标签 c++ makefile build

我有一个项目,我正在尝试为其创建 Makefile。文件夹结构如下所示:

|-- bin
|-- build
|-- Makefile
|-- src
|   |-- some_files.cpp
|   |-- some_files.h
|   |-- ForestFactory
|   |-- MMParSet
|   |-- century
|       |-- century_carbon.cpp
|       |-- century_carbon.h
|   `-- grass
`-- src_multithread
    |-- __history

我尝试使用this reference创建一个 Makefile。 我的 Makefile 是

CC := g++

SRCDIR := src
BUILDDIR := build
TARGETDIR := bin
INSTALLBINDIR := /usr/local/bin
TARGET := bin/formind

# CPP files
SOURCES := $(shell find $(SRCDIR) -type f -name *.cpp)
# remove the src path and add the build path and the .o extension
OBJECTS := $(addprefix $(BUILDDIR)/,$(patsubst %.cpp,%.o,$(notdir $(SOURCES))))

CFLAGS := -std=c++11 -stdlib=libc++

INC := -I/usr/local/include -I $(SRCDIR) -I $(SRCDIR)/century -I $(SRCDIR)/grass -I $(SRCDIR)/MMParSet -I $(SRCDIR)/ForestFactory

$(TARGET): $(OBJECTS)
    @mkdir -p $(TARGETDIR)
    @echo " Linking..."
    @echo " $(CC) $^ -o $(TARGET)"
    $(CC) $^ -o $(TARGET)

$(BUILDDIR)/%.o: $(SRCDIR)/%.cpp
    @mkdir -p $(BUILDDIR)
    @echo " $(CC) $(CFLAGS) $(INC) -c -o $@ $<"
    $(CC) $(CFLAGS) $(INC) -c -o $@ $<

clean:
    @echo " Cleaning...";
    @echo " $(RM) -r $(BUILDDIR) $(TARGET)"
    $(RM) -r $(BUILDDIR) $(TARGET)


.PHONY: clean

当我尝试make时,我收到以下错误消息:

make: *** No rule to make target `build/century_carbon.o', needed by `bin/formind'.  Stop.

源文件来自 src 内的一组嵌套子目录。我的理解是 OBJECTS 变量应该包含最终对象文件的完整路径,这样我就有类似的东西

$SOURCES = src/century/century_carbon.cpp ... src/for_branching.cpp ... src/grass/grass_log.cpp ...

$OBJECTS = build/century_carbon.o ... build/for_branching.o ... build/grass_log.o ...

我编写的编译规则有问题吗?

最佳答案

问题出在嵌套源目录世纪上。如果添加到 makefile:

info:
    @echo " Info..."
    @echo " SOURCES = $(SOURCES)"
    @echo " OBJECTS = $(OBJECTS)"

然后make info给出:

  Info...
  SOURCES = src/century/century_carbon.cpp src/some_files.cpp
  OBJECTS = build/century_carbon.o build/some_files.o

此检查表明您对这些宏的构造是正确的。正如您所报告的,它还表明 make 将告诉我们:

make: *** No rule to make target 'build/century_carbon.o', needed by 'bin/formind'.  Stop.

如果添加附加规则,并指定目录 century:

$(BUILDDIR)/%.o: $(SRCDIR)/century/%.cpp
    @mkdir -p $(BUILDDIR)
    $(CC) $(CFLAGS) $(INC) -c -o $@ $<

然后您的构建将继续。


另一种解决方案是使用VPATH。添加行:

VPATH = src:src/century

并从您的规则中删除 $(SRCDIR)/,现在变为:

$(BUILDDIR)/%.o: %.cpp
    @mkdir -p $(BUILDDIR)
    $(CC) $(CFLAGS) $(INC) -c -o $@ $<

更新:上述答案可以通过两种方式改进:

  • 使用 vpath 而不是 VPATH 来更精确地控制搜索。

  • 自动生成 vpath/VPATH 的参数。

这非常简单:只需将我的硬编码 VPATH 行替换为:

vpath %.cpp $(sort $(dir $(SOURCES)))

关于c++ - Makefile:没有规则来制作目标:如何设置正确的规则?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52745325/

相关文章:

.net - 如何在嵌入资源的 vb.net 中正确使用命名空间?

ios - React Native : Building for IOS failed on XCode 9. 2 和 9.4 以及 RN 55.4

c++ - bool 之前的预期声明说明符或 '...'

java - 用于开发 GUI 的更好语言?

c++ - 如何对结构进行位操作?

c++ - 在VIM中执行make后我可以去错误吗?

makefile - 传递参数以在 Makefile 中进行调用

c++ - osx 上的 Qt::WA_DeleteOnClose - 诺基亚教程

c++ - 让 g++ 指出这个错误/警告

java - 使用 ANT ,如何在 scriptdef 中创建模式集?