使用makefile创建目录
我是makefiles的新手,我想使用makefile创建目录。我的项目目录如下使用makefile创建目录,makefile,object,directory,Makefile,Object,Directory,我是makefiles的新手,我想使用makefile创建目录。我的项目目录如下 +--Project +--output +--source +Testfile.cpp +Makefile 我想把所有的对象和输出放到相应的输出文件夹中。我想创建文件夹结构,编译后会像这样 +--Project +--output +--debug (or release) +--objs +Testfile.o
+--Project
+--output
+--source
+Testfile.cpp
+Makefile
我想把所有的对象和输出放到相应的输出文件夹中。我想创建文件夹结构,编译后会像这样
+--Project
+--output
+--debug (or release)
+--objs
+Testfile.o
+Testfile (my executable file)
+--source
+Testfile.cpp
+Makefile
我尝试了几种选择,但没有成功。请帮助我使用make file创建目录。我将发布我的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)
#---------------------------------------------------------------------
#输入目录、名称、文件
#---------------------------------------------------------------------
输出根:=输出/
TITLE\u NAME:=TestProj
ifdef调试
标题\u名称+=\u调试
其他的
ifdef释放
标题\u名称+=\u发布
恩迪夫
恩迪夫
#在目录树中包含所有源文件
资料来源:=\
source/TestFile.cpp\
#---------------------------------------------------------------------
#配置
#---------------------------------------------------------------------
ifdef调试
OUT\u DIR:=$(输出\u根)调试
CC_标志:=-c-墙
其他的
ifdef释放
OUT\u DIR:=$(输出\u根目录)发布
CC_标志:=-c-墙
其他的
$(错误:未定义生成类型)
恩迪夫
恩迪夫
#将对象放入输出目录。
OUT\u O\u DIR:=$(OUT\u DIR)/objs
#---------------------------------------------------------------------
#背景
#---------------------------------------------------------------------
OBJS=$(来源:.cpp=.o)
DIRS=$(subst/,/,$(sort$(dir$(OBJS)))
DIR\u TARGET=$(OUT\u DIR)
输出\目标=$(输出\目录)/$(标题\名称)
CC_标志+=
LCF_标志:=
劳工处旗帜:
#---------------------------------------------------------------------
#可执行文件
#---------------------------------------------------------------------
MD:=mkdir
RM:=RM
CC:=g++
#---------------------------------------------------------------------
#规则
#---------------------------------------------------------------------
.冒牌货:全是干净的头衔
全部:标题
清洁:
$(RM)-rf$(输出方向)
$(DIR_目标):
$(MD)-p$(目录)
.cpp.o:
@$(CC)-c$<-o$@
$(OBJS):$(OUT\u O\u DIR)/%.O:%.cpp
@$(CC)-c$<-o$@
标题:$(目录目标)$(OBJS)
提前谢谢。如果我也犯了错误,请指导我 既然你是个新手,我想说现在还不要尝试这么做。这当然是可能的,但会不必要地使Makefile复杂化。坚持简单的方法,直到你对make更满意为止
也就是说,在不同于源目录的目录中构建的一种方法是;我更喜欢这样做——假设是一个类似Unix的环境
MKDIR_P = mkdir -p
.PHONY: directories
all: directories program
directories: ${OUT_DIR}
${OUT_DIR}:
${MKDIR_P} ${OUT_DIR}
这必须在顶级目录中运行,或者${OUT_DIR}的定义必须相对于它的运行位置是正确的。当然,如果您遵循Peter Miller的“”论文中的法令,那么您将在顶级目录中运行make
我现在正在玩这个(RMCH)。它需要对我用作测试场的软件套件进行一些调整。该套件有十几个独立的程序,其源代码分布在15个目录中,其中一些是共享的。但只要小心一点,这是可以做到的。OTOH,这可能不适合新手
如注释中所述,将“mkdir”命令列为“directories”的操作是错误的。如注释中所述,还有其他方法可以修复导致的“不知道如何进行输出/调试”错误。一种是删除“目录”行上的依赖项。这是因为如果要求“mkdir-p”创建的所有目录都已存在,则“mkdir-p”不会生成错误。另一个是所示的机制,仅当目录不存在时才会尝试创建该目录。“修订后的”版本是我昨晚想到的-但这两种技术都可以工作(如果存在输出/调试,但都是文件而不是目录,那么这两种技术都会有问题)。在我看来,目录不应该被视为makefile的目标,无论是在技术上还是在设计上。您应该创建文件,如果文件创建需要一个新目录,则在相关文件的规则内安静地创建目录 如果您针对的是一个普通的或“模式化”文件,只需使用
make
的内部变量$(@D)
,这意味着“当前目标所在的目录”(对于目标,使用$@
的cmp。比如说,
$(OUT_O_DIR)/%.o: %.cpp
@mkdir -p $(@D)
@$(CC) -c $< -o $@
title: $(OBJS)
我刚刚提出了一个相当合理的解决方案,允许您定义要构建的文件并自动创建目录。首先,定义一个变量
ALL_TARGET_FILES
,该变量保存生成文件的每个文件的文件名。然后使用以下代码:
define depend_on_dir
$(1): | $(dir $(1))
ifndef $(dir $(1))_DIRECTORY_RULE_IS_DEFINED
$(dir $(1)):
mkdir -p $$@
$(dir $(1))_DIRECTORY_RULE_IS_DEFINED := 1
endif
endef
$(foreach file,$(ALL_TARGET_FILES),$(eval $(call depend_on_dir,$(file))))
下面是它的工作原理。我定义了一个函数depend_on_dir
,它接受一个文件名并生成一个规则,使文件依赖于包含它的目录,然后定义一个规则来创建该目录(如果需要)。然后我使用foreach
对每个文件名调用此函数,并eval
结果
请注意,您需要一个支持eval
的GNU make版本,我认为它是3.81版和更高版本。所有解决方案,包括公认的解决方案,都有一些问题,请参见各自的评论。已经很好了,但是没有考虑到先决条件不一定要按顺序构建(例如在make-j
期间)。但是,只要将目录
先决条件从all
移动到program
就会在每次运行时引发重建。
以下解决方案不存在该问题,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)
操作系统独立性对我来说至关重要,因此mkdir-p
不是一个选项。我创建了这一系列函数,它们使用eval
在父目录上创建具有先决条件的目录目标。这有make的好处
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)
DIRS=build build/bins
...
$(shell mkdir -p $(DIRS))
outDir/someTarget: Makefile outDir
touch outDir/someTarget
outDir:
mkdir -p outDir
$ make
mkdir -p outDir
touch outDir/someTarget
$ make
touch outDir/someTarget
$ make
touch outDir/someTarget
$ make
touch outDir/someTarget
# The pipe symbol tells make that the following prerequisites are order-only
# |
# v
outDir/someTarget: Makefile | outDir
touch outDir/someTarget
outDir:
mkdir -p outDir
$ make
mkdir -p outDir
touch outDir/someTarget
$ make
make: 'outDir/someTarget' is up to date.
$(OUT_DIR):
mkdir -p $(OUT_DIR)
$(OUT_DIR)/someTarget: ... | $(OUT_DIR)
REQUIRED_DIRS = ...
_MKDIRS := $(shell for d in $(REQUIRED_DIRS); \
do \
[[ -d $$d ]] || mkdir -p $$d; \
done)
$(objects) : $(sources)
SHELL := /bin/bash # Use bash syntax