【问题标题】:How to compile a c++ project with multiple directories using Makefiles?如何使用 Makefiles 编译具有多个目录的 c++ 项目?
【发布时间】:2017-04-05 08:07:42
【问题描述】:

我读过其他类似问题的问题,唉,我仍然很困惑。

这是我当前的 Makefile:

CC = g++

EXEFILE = template

IFLAGS= -I/usr/include/freetype2 -I../Camera
LFLAGS= -L/usr/lib/nvidia-375 -L/usr/local/lib -L/usr/include/GL -L/usr/local/include/freetype2 -L/usr/local/lib/
LIBS = -lglfw -lGL -lGLU -lOpenGL -lGLEW -pthread -lfreetype

SRC=*.cpp
DEPS=*.h

$(EXEFILE): 
    $(CC) -std=c++11 -o $(EXEFILE) -Wall -Wno-comment $(SRC) $(IFLAGS) $(LFLAGS) $(LIBS)

all: run clean

run: $(EXEFILE)
    ./$(EXEFILE)
clean:
    rm $(EXEFILE)

现在我所有的 .h 文件和 .cpp 文件都在工作目录中,一切都可以编译和运行。我的问题是我已经有大量文件,而且变得非常混乱。我想创建多个目录(甚至可能是这些目录中的目录)来组织我的文件。但是,一旦我将头文件及其对应的 cpp 文件移动到当前目录内的目录中,编译器就不再知道如何链接它们。

如何告诉我的 make 文件编译和链接当前根目录下的所有内容?

或者,是否有关于 makefile 语法的 ELI5 指南?

【问题讨论】:

  • 如果您将$(EXEFILE): 替换为$(EXEFILE): $(SRC),您会发现您的构建过程会更好 - 无需删除可执行文件即可重新构建它。虽然你真的想要$(OBJ) 在最后阶段因为你不想每次都重新编译每个源文件。
  • 为了更容易编译 - 查看 Cmake。

标签: c++ linux


【解决方案1】:

解决问题的最快方法是在所有子目录中添加文件包含的 SRC 和 DEPS,例如:

 SRC=*.cpp src/*.cpp
 DEPS=*.h inc/*.h

现在你可以考虑编写一个规则来首先编译单独目录中的每个文件:

# Group compilation option
CXXFLAGS := -std=c++11 -Wall -Wno-comment $(IFLAGS)

# A directory to store object files (.o)
ODIR := ./objects

# Read this ugly line from the end:
#  - grep all the .cpp files in SRC with wildcard
#  - add the prefix $(ODIR) to all the file names with addprefix
#  - replace .cpp in .o with patsubst
OBJS := $(patsubst %.cpp,%.o,$(addprefix $(ODIR)/,$(wildcard $(SRC)/*.cpp)))

# Compile all the files in object files
# $@ refers to the rule name, here $(ODIR)/the_current_file.o
# $< refers to first prerequisite, here $(SRC)/the_current_file.cpp
$(ODIR)/%.o:$(SRC)/%.cpp $(DEPS)/%.h
    $(CXX) $(CXXFLAGS) -c -o $@ $<

# Finally link everything in the executable
# $^ refers to ALL the prerequisites
$(EXEFILE): $(OBJS)
    $(CXX) $(CXXFLAGS) -o $@  $^ $(LFLAGS) $(LIBS)

【讨论】:

    【解决方案2】:

    我找到了一个解决方案,按照我的口味,它看起来很优雅,或者至少很容易使用通配符运算符进行跟踪。这是我当前的makefile:

        EXEFILE := $(shell basename $(CURDIR))
    
    
    DIRECTORIES = $(filter-out ./ ./.%, $(shell find ./ -maxdepth 10 -type d))
    IFLAGS= -I/usr/include/freetype2
    LOCAL_I_DIRS =$(addprefix -I./, $(DIRECTORIES))
    LFLAGS= -L/usr/lib/nvidia-375 -L/usr/local/lib -L/usr/include/GL -L/usr/local/include/freetype2 -L/usr/local/lib/
    LIBS = -lglfw -lGL -lGLU -lOpenGL -lGLEW -pthread -lfreetype
    
    SRC := $(wildcard *.cpp) $(wildcard **/*.cpp)
    
    $(EXEFILE): $(EXEFILE).cpp
        g++ -std=c++11 -o $(EXEFILE) -Wall -Wno-comment $(SRC) $(IFLAGS) $(LOCAL_I_DIRS) $(LFLAGS) $(LIBS) 
    
    all: run clean
    
    run: $(EXEFILE)
        ./$(EXEFILE)
    
    clean:
        rm $(EXEFILE)
    
    print-%: ; @echo $* = $($*)
    

    所以我将所有目录的深度设置为 10。然后我取出当前根目录 (./) 和任何隐藏目录 (./.) 留下存储在“DIRECTORIES”下的标准子目录,然后添加 -I每个目录都使其成为包含目录并将它们存储在 LOCAL_I_DIRS 所以我现在可以根据需要创建尽可能多的子目录(最多 10 级),编译器会很高兴。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-16
      • 2017-08-23
      • 2012-11-15
      • 2012-01-26
      相关资源
      最近更新 更多