make和c ++文件,“包含”在cpp

时间:2015-10-18 02:29:20

标签: c++ makefile

这是我目前的makefile:

# Compiler #
CXX      = g++
DEBUG    = -g
LFLAGS   =
CXXFLAGS = -Wall

# Directories #
SRCDIR   = src/
INCDIR   = include/
BUILDDIR = build/
BINDIR   = bin/

# Objects #
OBJ_NAMES = main.o dfa.o dfaException.o state.o
OBJS       = $(addprefix $(BUILDDIR), $(OBJ_NAMES))

# Output #
NAME = pract3
TARGET = $(BINDIR)pract3

# Clean #
ifeq ($(OS),Windows_NT)
    RM = del /q /s $(BUILDDIR:/=\)*.o $(BINDIR:/=\)$(NAME)*
else
    RM = rm -rf $(BUILDDIR)*.o $(TARGET)*
endif

# Files #
$(TARGET): $(OBJS)
    $(CXX) $(CXXFLAGS) $(LFLAGS) $(OBJS) -o $(TARGET)

$(BUILDDIR)%.o: $(SRCDIR)%.cpp
    $(CXX) $(CXXFLAGS) $(LFLAGS) -c $< -o $@

clean:
    $(RM)

这是我的项目树:

Porject/

    bin/

    build/

    doc/
        ...

    include/
        connection.hpp
        dfa.hpp
        dfaException.hpp
        state.hpp

    src/
        dfa.cpp
        dfaException.cpp
        main.cpp
        state.cpp

    Makefile
    Readme

现在,我有三个“问题”。

首先,我希望我的makefile创建bin并构建目录,以防万一。我想我只需要使用:

mkdir $(BUILDDIR)
mkdir $(BINDIR)

但我应该把它们放在哪里?而且,我怎样才能阻止mkdir和rm(或windows中的del)消息,例如“找不到......”或“x目录已经存在......”

其次,我猜我可以从src /中读取对象名称(将.cpp转换为.o),但是如何从目录中读取文件名?

最后,我有一个模板类:connection.hpp(所有函数都在标题中)。此文件包含在state.hpp中,使用:#include "../include/connection.hpp"。我一次运行make一次正确,然后故意在connection.hpp中出现语法错误。然后我再次运行make,但它只使用构建中的.o文件编译目标文件而没有任何错误。每当我想要修改connection.hpp时,我必须使用make clean然后make。有没有更好的方法呢?

1 个答案:

答案 0 :(得分:1)

  1. 如果您需要一个目录才能继续,只需输入

    即可
    mkdir -p ${DIRECTORY}
    

    在您的规则中需要它之前。如果目录已经存在,mkdir -p将很乐意无所事事。

    同样,如果您使用rm -f FILE,如果首先不存在FILE,则不应该抱怨。

  2. 没有可移植的方法来创建一个包含目录中所有文件名称的变量。但是你已经在使用GNU Make功能了,所以你可以使用

    SOURCES = $(wildcard ${SRCDIR}/*.cpp)
    

    然后

    OBJECTS = $(SOURCES:.cpp=.o)
    

    将它们转换为目标文件名。我猜你也可能想要替换主要目录名称。

  3. 您没有在make文件中列出任何*.hpp个文件作为先决条件。您可以手动添加它们,如

    foo.o: foo.cpp bar.hpp baz.hpp
    

    但这很快就会变得不愉快。另一个技巧是使用编译器通过文件告诉你标题(传递)#include d。如果您使用的是GCC,则可以运行

    gcc -MM foo.cpp
    

    将其输出到make-file代码段上方。您可以设置类似以下

    的模式规则
    %.deps: %.cpp
        ${CXX} -MM ${CPPFLAGS} $< > $@
    

    到您的make文件中,然后include生成的*.deps个文件。

    include $(SOURCES:.cpp=.deps)
    

    GNU Make将足够智能,首先解析make文件,认识到*.deps文件不存在,因此不能include d但是要知道有一个规则要生成他们。因此它将执行该规则,然后继续解析make文件。

    我从彼得·米勒的精彩文章Recursive Make Considered Harmful中学到了这个技巧,如果你想学习如何编写好的制作文件,这是一个很好的阅读。