使用make将.o文件移动到一个单独的目录
Using make to move .o files to a separate directory
我已经尝试过无数次将我的.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)
指定创建对象的位置,使用-o
window.o : window.cpp window.h
$(CC) $(LIBS) $(INCLUDEPATH) -c window.cpp -o $(OBJ)/$@
你可以这样做:
指定目标文件的存放目录
OBJDIR = objdir
创建一个需要编译的目标文件列表,从所有
.cpp
文件列表中通过将.cpp
替换为.o
并添加前缀$(OBJDIR)/
:OBJ = $(addprefix $(OBJDIR)/, $(patsubst %.cpp, %.o, $(wildcard *.cpp)))
你的$(OBJ)看起来像:
objdir/window.o objdir/main.o
等等如果目录不存在,添加目标创建目录:
$(OBJDIR): mkdir $(OBJDIR)
在创建主目标之前创建目录目标:
all: $(OBJDIR) myapp
从当前目录下的
.cpp
文件编译$(OBJDIR)
中所有.o
对象文件的规则:$(OBJDIR)/%.o: %.cpp $(GCC) $(CPPFLAGS) -c $< -o $@
结果如下:
g++ -c main.cpp -o objdir/main.o
你的主要目标没有改变:
$(TARGET): $(OBJ) $(GCC) $(LDFLAGS) -o $@ $^
这看起来像:
g++ -o myapp objdir/window.o objdir/main.o
为完整起见,添加
clean
目标来清理对象:clean: @rm -f $(TARGET) $(wildcard *.o) @rm -rf $(OBJDIR)
并定义
.PHONY
目标,例如,即使存在同名的目录或文件,也会创建这些目标:.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
会做:
> ls
Makefile a.cpp main.cpp
> make
mkdir objdir
g++ -I. -c a.cpp -o objdir/a.o
g++ -I. -c main.cpp -o objdir/main.o
g++ -o myapp objdir/a.o objdir/main.o
> ls
Makefile a.cpp main.cpp objdir myapp
> make clean
> ls
Makefile a.cpp main.cpp
如果你想了解更多关于以上任何一个的细节,请查看GNU make doc页面
回应评论,更多提示:
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 $@
$<
和$@
是自动变量, $@
扩展为当前构建的目标的名称,$<
是第一个依赖项($^
将是"所有依赖项",有更多这样的变量-参见Make手册)。
2)任何额外的深度(即头):
displayinit.o: displayinit.h
matrix3f.o: matrix3f.h
main.o: main.h window.h displayinit.h
#etc
注意:对于每个.o
文件,它的依赖项应该包含:
- 构建它的
.cpp
(依赖项来自一般规则), -
.cpp
文件中包含的所有.h
文件(稍后需要添加)。
注意,您在原始的makefile中省略了后面的部分。总有一天这会给你带来麻烦的。
2)自动生成深度
基本上每次在任何文件中添加#include
时,您都需要修改makefile以反映.cpp
/.o
和.h
文件之间的新依赖关系。这是非常麻烦的,但幸运的是,有自动化的解决方案。这里有两种C/c++方法:
- 使用编译器为您生成依赖项(例如
gcc
/g++ -MM
)。 使用额外的工具,如
makedepend
。无论哪种方式,您都需要在makefile中动态地包含该依赖集。这需要一些技巧,但是一旦你有了它,你就再也不用担心依赖了。在google上搜索"c++ makefile dependencies",应该会有很多资源。
这是一个关于Make的切题文档
我的经验如下:
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)
在第一个目标中,添加将文件移动到所需目录的命令。
$(TARGET) : $(DEPS)
$(CC) $(CFLAGS) -o $(BIN)$(TARGET) $(DEPS) $(LIBS) $(INCLUDEPATH)
mv *.o obj/
- Howo 使用 cl 预处理为 masm 组装生成一个单独的文件
- 显示数组的问题.一切都放在一个单独的行中,但不放入单独的列中
- 如何在这个交换函数(一个单独的链表)中找到错误
- 如何将正则表达式中组的每次迭代都作为一个单独的组
- 如何将我的C++DLL包含在一个单独的项目中
- 元编程:函数定义的失败定义了一个单独的函数
- 每个方法都在一个单独的文件c++中
- 使用websockettpp库在多线程程序中为endpoint.listen()创建一个单独的提升线程
- C++-释放在main中分配但指向一个单独类的内存
- 读取整数文件并将每一行存储在一个单独的数组中
- 隔离易崩溃(SEGV),但将关键的遗留代码加速到一个单独的二进制文件中
- 如何用C++/OSX打开一个单独的程序
- 将指针设置为一个值加上一个单独的值
- 为什么您必须声明/创建一个单独的变量来通过引用调用,而不仅仅是在函数调用中创建一个自动对象
- 如何决定是否为窗口的小部件创建一个单独的类
- 如何调用一个函数,它在一个单独的类中打印出一个结构体数组
- 使用make将.o文件移动到一个单独的目录
- 如何从一个线程发出信号,并将信号与一个单独的函数连接起来
- Boost::为每个客户端创建一个单独的数组
- 在一个单独的线程中管理OpenGL上下文