DMA*_*361 3 portability cross-platform makefile
我希望通过制作一个相当通用的makefile来为自己节省一些精力,这个makefile将为我提供相对简单的C++项目,只需对makefile进行最少的修改.
到目前为止,我已经得到它所以它将使用.cpp同一目录中的所有文件和指定的子目录,将所有这些放在子目录中的匹配结构中obj,并将生成的文件放在另一个名为的子目录中bin.几乎是我想要的.
但是,尝试获取它以便创建所需的obj和bin目录(如果它们不存在)提供了跨平台工作的尴尬 - 具体来说,我只是测试Windows 7和Ubuntu(不记得版本),我无法让它同时在两者上工作.
窗户误读mkdir -p dir并创建一个-p目录,显然这两个平台使用\,并/分别为路径分隔符-并且使用了错误的一个,当我得到的错误.
以下是makefile的一些相关部分:
# Manually edited directories (in this example with forward slashes)
SRC_DIR = src src/subdir1 src/subdir2
# Automagic object directories + the "fixed" bin directory
OBJ_DIR = obj $(addprefix obj/,$(SRC_DIR))
BIN_DIR = bin
# Example build target
debug: checkdirs $(BIN)
# At actual directory creation
checkdirs: $(BIN_DIR) $(OBJ_DIR)
$(BIN_DIR):
@mkdir $@
$(OBJ_DIR):
@mkdir -p $@
Run Code Online (Sandbox Code Playgroud)
在过去一周左右我已经阅读了这些内容(主要是关于Stack Overflow),所以如果碰巧是我正在关注一些可怕的不良做法或任何这种性质,请告诉我.
问题简而言之:
是否有一种简单的方法可以通过提供尽可能多的可移植性的方式从单个makefile中创建此目录?
我不知道autoconf.我所拥有的每一次经历都是乏味的.zwol的解决方案的问题是在Windows上mkdir返回错误,与mkdir -pLinux 不同.这可能会打破你的制定规则.解决方法是-在命令之前忽略带有标志的错误,如下所示:
-mkdir dir
Run Code Online (Sandbox Code Playgroud)
这样做的问题make仍然是为用户抛出一个丑陋的警告.这种情况的解决方法是运行一个"总是为真"命令后,mkdir所描述的失败在这里,就像这样:
mkdir dir || true
Run Code Online (Sandbox Code Playgroud)
这里的问题是,Windows和Linux有不同的语法正确.
无论如何,我花了太多时间在这上面.我想要一个make既适用于POSIX又适用于Windows环境的文件.最后我想出了以下内容:
ifeq ($(shell echo "check_quotes"),"check_quotes")
WINDOWS := yes
else
WINDOWS := no
endif
ifeq ($(WINDOWS),yes)
mkdir = mkdir $(subst /,\,$(1)) > nul 2>&1 || (exit 0)
rm = $(wordlist 2,65535,$(foreach FILE,$(subst /,\,$(1)),& del $(FILE) > nul 2>&1)) || (exit 0)
rmdir = rmdir $(subst /,\,$(1)) > nul 2>&1 || (exit 0)
echo = echo $(1)
else
mkdir = mkdir -p $(1)
rm = rm $(1) > /dev/null 2>&1 || true
rmdir = rmdir $(1) > /dev/null 2>&1 || true
echo = echo "$(1)"
endif
Run Code Online (Sandbox Code Playgroud)
函数/变量的用法如下:
rule:
$(call mkdir,dir)
$(call echo, CC $@)
$(call rm,file1 file2)
$(call rmdir,dir1 dir2)
Run Code Online (Sandbox Code Playgroud)
定义的理由:
del中,如果指定其中一个文件位于不存在的目录中,则不会删除任何文件.例如,如果您尝试删除一组文件并且dir/file.c在列表中但dir不存在,则不会删除任何文件.此实现通过del为每个文件调用一次来解决该问题.""Windows中的无关.我花了很多时间在这上面.也许我会更好地花时间学习autoconf.
也可以看看:
Windows mkdir始终执行Unix mkdir对-p开关的操作.你可以用$(subst)处理反斜杠问题.所以,在Windows上,你想要这个:
$(BIN_DIR) $(OBJ_DIR):
mkdir $(subst /,\\,$@)
Run Code Online (Sandbox Code Playgroud)
在Unix上你想要这个:
$(BIN_DIR) $(OBJ_DIR):
mkdir -p -- $@
Run Code Online (Sandbox Code Playgroud)
在makefile中选择它们是不切实际的.这就是Autoconf的用途.
作为旁注,永远不要@command在makefile中使用该功能.有一天你需要在一台你无法直接访问的机器上调试你的构建过程,那一天你会后悔的.