代码之家  ›  专栏  ›  技术社区  ›  Manfredo

Makefile:无规则生成目标:如何设置正确的规则?

  •  1
  • Manfredo  · 技术社区  · 6 年前

    我有一个项目,我正试图创建一个生成文件。文件夹结构如下所示:

    |-- 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是

    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.
    

    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 ...
    

    1 回复  |  直到 6 年前
        1
  •  1
  •   Joseph Quinsey Taseen    6 年前

    问题在于 嵌套的 源目录 century . 如果添加到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.
    

    明确规定:

    $(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 %.cpp $(sort $(dir $(SOURCES)))