Jab*_*bez 90 directory makefile object
我是一个非常新的makefile,我想使用makefile创建目录.我的项目目录是这样的
+--Project
+--output
+--source
+Testfile.cpp
+Makefile
Run Code Online (Sandbox Code Playgroud)
我想将所有对象和输出放入相应的输出文件夹中.我想创建文件夹结构,编译后就像这样.
+--Project
+--output
+--debug (or release)
+--objs
+Testfile.o
+Testfile (my executable file)
+--source
+Testfile.cpp
+Makefile
Run Code Online (Sandbox Code Playgroud)
我尝试了几种选择,但无法成功.请帮我用make文件制作目录.我发布了Makefile供你考虑.
#---------------------------------------------------------------------
# Input dirs, names, files
#---------------------------------------------------------------------
OUTPUT_ROOT := output/
TITLE_NAME := TestProj
ifdef DEBUG
TITLE_NAME += _DEBUG
else
ifdef RELEASE
TITLE_NAME += _RELEASE
endif
endif
# Include all the source files here with the directory tree
SOURCES := \
source/TestFile.cpp \
#---------------------------------------------------------------------
# configs
#---------------------------------------------------------------------
ifdef DEBUG
OUT_DIR := $(OUTPUT_ROOT)debug
CC_FLAGS := -c -Wall
else
ifdef RELEASE
OUT_DIR := $(OUTPUT_ROOT)release
CC_FLAGS := -c -Wall
else
$(error no build type defined)
endif
endif
# Put objects in the output directory.
OUT_O_DIR := $(OUT_DIR)/objs
#---------------------------------------------------------------------
# settings
#---------------------------------------------------------------------
OBJS = $(SOURCES:.cpp=.o)
DIRS = $(subst /,/,$(sort $(dir $(OBJS))))
DIR_TARGET = $(OUT_DIR)
OUTPUT_TARGET = $(OUT_DIR)/$(TITLE_NAME)
CC_FLAGS +=
LCF_FLAGS :=
LD_FLAGS :=
#---------------------------------------------------------------------
# executables
#---------------------------------------------------------------------
MD := mkdir
RM := rm
CC := g++
#---------------------------------------------------------------------
# rules
#---------------------------------------------------------------------
.PHONY: all clean title
all: title
clean:
$(RM) -rf $(OUT_DIR)
$(DIR_TARGET):
$(MD) -p $(DIRS)
.cpp.o:
@$(CC) -c $< -o $@
$(OBJS): $(OUT_O_DIR)/%.o: %.cpp
@$(CC) -c $< -o $@
title: $(DIR_TARGET) $(OBJS)
Run Code Online (Sandbox Code Playgroud)
提前致谢.如果我犯了任何错误,请指导我.
P S*_*ved 129
在我看来,无论是技术还是设计意义上的目录都不应被视为makefile的目标.您应该创建文件,如果文件创建需要新目录,则在规则中静静地创建相关文件的目录.
如果您的目标是通常的或"图案化"的文件,只需使用make内部变量$(@D),即"当前目标所在的目录"(cmp.$@目标为).例如,
$(OUT_O_DIR)/%.o: %.cpp
@mkdir -p $(@D)
@$(CC) -c $< -o $@
title: $(OBJS)
Run Code Online (Sandbox Code Playgroud)
然后,你实际上是这样做的:为所有人创建目录$(OBJS),但你会以一种不那么复杂的方式来做.
在各种应用程序中使用相同的策略(文件是目标,目录永远不会).例如,git修订控制系统不存储目录.
注意:如果您打算使用它,引入便利变量并利用make扩展规则可能会很有用.
dir_guard=@mkdir -p $(@D)
$(OUT_O_DIR)/%.o: %.cpp
$(dir_guard)
@$(CC) -c $< -o $@
$(OUT_O_DIR_DEBUG)/%.o: %.cpp
$(dir_guard)
@$(CC) -g -c $< -o $@
title: $(OBJS)
Run Code Online (Sandbox Code Playgroud)
Jon*_*ler 79
这样做 - 假设类似Unix的环境.
MKDIR_P = mkdir -p
.PHONY: directories
all: directories program
directories: ${OUT_DIR}
${OUT_DIR}:
${MKDIR_P} ${OUT_DIR}
Run Code Online (Sandbox Code Playgroud)
这必须在顶级目录中运行 - 或者$ {OUT_DIR}的定义必须相对于它运行的位置是正确的.当然,如果你遵循Peter Miller的" Recursive Make Considered Harmful "论文的规定,那么无论如何你都将在顶级目录中运行make.
我现在正在玩这个(RMCH).它需要对我作为测试场所使用的软件套件进行一些调整.该套件有十几个单独的程序,源代码分布在15个目录中,其中一些是共享的.但有点小心,可以做到.OTOH,它可能不适合新手.
如评论中所述,将'mkdir'命令列为'目录'的操作是错误的.正如评论中所指出的,还有其他方法可以解决导致"不知道如何输出/调试"错误的问题.一种是删除对'目录'行的依赖.这是因为'mkdir -p'如果要求创建的所有目录都已存在,则不会生成错误.另一种是显示的机制,如果它不存在,它将只尝试创建目录."修改后的"版本是我昨晚想到的 - 但这两种技术都有效(如果存在输出/调试但是文件而不是目录,则两者都有问题).
Nic*_*kiy 21
或者,亲吻.
DIRS=build build/bins
...
$(shell mkdir -p $(DIRS))
Run Code Online (Sandbox Code Playgroud)
这将在解析Makefile后创建所有目录.
makein和off本身处理与文件目标相同的目录目标.所以,编写这样的规则很容易:
outDir/someTarget: Makefile outDir
touch outDir/someTarget
outDir:
mkdir -p outDir
Run Code Online (Sandbox Code Playgroud)
唯一的问题是,目录时间戳取决于对内部文件所做的操作.对于上述规则,这会导致以下结果:
$ make
mkdir -p outDir
touch outDir/someTarget
$ make
touch outDir/someTarget
$ make
touch outDir/someTarget
$ make
touch outDir/someTarget
Run Code Online (Sandbox Code Playgroud)
这绝对不是你想要的.无论何时触摸该文件,您还可以触摸该目录.由于文件取决于目录,因此文件似乎已过期,迫使文件重建.
但是,您可以通过告诉make忽略目录的时间戳来轻松打破此循环.这是通过将目录声明为仅订单的预备点来完成的:
# The pipe symbol tells make that the following prerequisites are order-only
# |
# v
outDir/someTarget: Makefile | outDir
touch outDir/someTarget
outDir:
mkdir -p outDir
Run Code Online (Sandbox Code Playgroud)
这正确地产生:
$ make
mkdir -p outDir
touch outDir/someTarget
$ make
make: 'outDir/someTarget' is up to date.
Run Code Online (Sandbox Code Playgroud)
TL; DR:
编写规则来创建目录:
$(OUT_DIR):
mkdir -p $(OUT_DIR)
Run Code Online (Sandbox Code Playgroud)
内部的东西的目标取决于目录顺序:
$(OUT_DIR)/someTarget: ... | $(OUT_DIR)
Run Code Online (Sandbox Code Playgroud)
包括已接受的解决方案在内的所有解决方案都存在一些问 在通过@乔纳森-莱弗勒接受的答案已经是相当不错,但并没有考虑到效果的先决条件不一定是为了建立(期间make -j为例).然而,只需移动directories前提条件就all可以program在每次运行AFAICT时引发重建.以下解决方案没有该问题,AFAICS按预期工作.
MKDIR_P := mkdir -p
OUT_DIR := build
.PHONY: directories all clean
all: $(OUT_DIR)/program
directories: $(OUT_DIR)
$(OUT_DIR):
${MKDIR_P} $(OUT_DIR)
$(OUT_DIR)/program: | directories
touch $(OUT_DIR)/program
clean:
rm -rf $(OUT_DIR)
Run Code Online (Sandbox Code Playgroud)