使用make将.o文件移动到单独的目录中

时间:2011-12-28 10:17:43

标签: c++ object compilation makefile

我尝试过多次尝试将.o文件移动到我的obj文件夹,但无论我做什么,它都无法正常工作。

从提供的makefile判断,将.o文件移动到指定文件夹的最佳方法是什么?

BIN = bin/
OBJ = obj/
TARGET = opengl_03
DEPS = main.o  displayinit.o initializer.o algorithms.o matrix3f.o window.o vertex3.o
CC = g++
CFLAGS = -g 
LIBS = -lglut -lGLEW -lGL 
INCLUDEPATH = -L/usr/include/ -L/usr/lib/ -L/usr/lib/x86_64-linux-gnu/

$(TARGET) : $(DEPS)
    $(CC) $(CFLAGS) -o $(BIN)$(TARGET) $(DEPS) $(LIBS) $(INCLUDEPATH) 

displayinit.o : displayinit.cpp displayinit.h
    $(CC) $(LIBS) $(INCLUDEPATH) -c displayinit.cpp && mv displayinit.o $(OBJ)displayinit.o
initializer.o : initializer.cpp initializer.h
    $(CC) $(LIBS) $(INCLUDEPATH) -c initializer.cpp $(OBJ)
algorithms.o : algorithms.cpp algorithms.h
    $(CC) -c algorithms.cpp $(OBJ)
matrix3f.o : matrix3f.cpp matrix3f.h
    $(CC) $(LIBS) $(INCLUDEPATH)  -c matrix3f.cpp $(OBJ)
vertex3.o : vertex3.cpp vertex3.h
    $(CC) $(LIBS) $(INCLUDEPATH)  -c vertex3.cpp $(OBJ)
window.o : window.cpp window.h
    $(CC) $(LIBS) $(INCLUDEPATH) -c window.cpp $(OBJ)
main.o : main.cpp
    $(CC) $(LIBS) $(INCLUDEPATH) -c main.cpp $(OBJ)

4 个答案:

答案 0 :(得分:18)

要指定对象的创建位置,请使用-o

window.o : window.cpp window.h
    $(CC) $(LIBS) $(INCLUDEPATH) -c window.cpp -o $(OBJ)/$@

以下是您可以做的事情:

  1. 指定目标文件的目录

    OBJDIR    =   objdir
    
  2. 通过将.cpp替换为.cpp并添加前缀{{1},从所有.o文件列表中创建需要编译的目标文件列表对它:

    $(OBJDIR)/

    所以你的$(OBJ)看起来像是:OBJ = $(addprefix $(OBJDIR)/, $(patsubst %.cpp, %.o, $(wildcard *.cpp))) 等等

  3. 添加目标以创建目录(如果该目录不存在):

    objdir/window.o objdir/main.o
  4. 在制作主要目标之前制作目录:

    $(OBJDIR):
        mkdir $(OBJDIR)
    
  5. 从当前目录中的all: $(OBJDIR) myapp 文件中编译.o中所有$(OBJDIR)个目标文件的规则:

    .cpp

    这将导致类似:

    $(OBJDIR)/%.o: %.cpp
        $(GCC) $(CPPFLAGS) -c $< -o $@
    
  6. 您的主要目标不变:

    g++ -c main.cpp -o objdir/main.o
    

    这看起来像是:

    $(TARGET): $(OBJ)
        $(GCC) $(LDFLAGS) -o $@ $^ 
    
  7. 为了完整性,将g++ -o myapp objdir/window.o objdir/main.o 目标添加到清理对象中:

    clean
  8. 定义clean: @rm -f $(TARGET) $(wildcard *.o) @rm -rf $(OBJDIR) 个目标,例如即使存在具有相同名称的目录或文件,也会进行这些操作:

    .PHONY
  9. 所以看起来应该是这样的:

    .PHONY: all clean
    

    如果你有OBJDIR = objdir OBJ = $(addprefix $(OBJDIR)/, $(patsubst %.cpp, %.o, $(wildcard *.cpp))) TARGET = my app .PHONY: all clean all: $(OBJDIR) $(TARGET) $(OBJDIR): mkdir $(OBJDIR) $(OBJDIR)/%.o: %.cpp $(GCC) $(CPPFLAGS) -c $< -o $@ $(TARGET): $(OBJ) $(GCC) $(LDFLAGS) -o $@ $^ clean: @rm -f $(TARGET) $(wildcard *.o) @rm -rf $(OBJDIR) main.cpp这样的文件,这就是a.cpp会做的事情:

    make

    如果您想了解有关上述任何内容的更多详细信息,请查看GNU make doc page

答案 1 :(得分:4)

在回应评论时,还有一些提示:

1)删除一些冗余

这部分非常重复:

displayinit.o : displayinit.cpp displayinit.h
    $(CC) $(LIBS) $(INCLUDEPATH) -c displayinit.cpp && mv displayinit.o $(OBJ)displayinit.o
initializer.o : initializer.cpp initializer.h
    $(CC) $(LIBS) $(INCLUDEPATH) -c initializer.cpp $(OBJ)
algorithms.o : algorithms.cpp algorithms.h
    $(CC) -c algorithms.cpp $(OBJ)
# ...

您可以将其替换为两部分:

1)更通用的规则,如:

%.o: %.cpp
    $(CC) -c $(LIBS) $(INCLUDEPATH) $< -o $@

$<$@自动变量$@扩展为当前构建目标的名称,$<是第一个依赖项({ {1}}将是“所有依赖项”,还有更多此类变量 - 请参阅Make manual)。

2)任何额外的deps(即标题):

$^

注意:对于每个displayinit.o: displayinit.h matrix3f.o: matrix3f.h main.o: main.h window.h displayinit.h #etc 文件,其依赖项应包含:

  • 构建它的.o(依赖性来自一般规则),
  • .cpp个文件中包含的所有.h个文件(稍后需要添加)。

请注意,您在原始makefile中省略了后一部分。这有一天会给你带来一些问题。

2)自动生成deps

基本上每次在任何文件中添加.cpp时,都需要修改makefile以反映#include / .cpp和{{1}之间的新依赖关系}文件。这非常麻烦,但幸运的是有自动解决方案。这里有两种C / C ++方法:

  • 使用编译器为您生成依赖项(例如.o / .h)。
  • 使用其他工具,例如gcc

无论哪种方式,您都需要在makefile中动态包含这组依赖项。这需要一些技巧,但一旦你拥有它,你永远不必担心依赖。有一个google的“C ++ makefile依赖”,应该有足够的资源。


Here's关于Make的最新文档。

答案 2 :(得分:0)

以下为我工作:

g++ test.cpp -c -o obj/test.o

因此,在您的情况下,您将进行以下修改:

displayinit.o : displayinit.cpp displayinit.h
    $(CC) $(LIBS) $(INCLUDEPATH) -c displayinit.cpp -o displayinit.o $(OBJ)displayinit.o

此外,对于最终编译,您需要从obj文件夹中选取.o文件,因此请将DEPS修改为bin/<xyz>.o。或者,您可以在最终构建之前cd obj

$(TARGET) : $(DEPS)
    cd $(OBJ)
    $(CC) $(CFLAGS) -o ../$(BIN)$(TARGET) $(DEPS) $(LIBS) $(INCLUDEPATH)

答案 3 :(得分:0)

在第一个目标中,添加命令以将文件移动到所需的目录。

$(TARGET) : $(DEPS)
    $(CC) $(CFLAGS) -o $(BIN)$(TARGET) $(DEPS) $(LIBS) $(INCLUDEPATH) 
    mv *.o obj/