C 如何使用Makefile将多个文件提供给后台进程
我有一个Makefile,其中一个目标依赖于多个文件——每个文件都必须单独处理(不提供中间输出文件)。我的具体情况更为复杂: 我有一个C源代码,我想从中提取枚举定义。有一些皱纹我无法改变:C 如何使用Makefile将多个文件提供给后台进程,c,batch-file,makefile,c-preprocessor,C,Batch File,Makefile,C Preprocessor,我有一个Makefile,其中一个目标依赖于多个文件——每个文件都必须单独处理(不提供中间输出文件)。我的具体情况更为复杂: 我有一个C源代码,我想从中提取枚举定义。有一些皱纹我无法改变: 编译器不是GCC——它是由宇宙软件制作的定制编译器 除了编译器之外,我还可以单独运行解析器(我们称之为parser.exe),它还可以选择(-e)在STDOUT上输出预处理的源代码 make实际上是PTC Integrity软件包附带的专有版本。它不支持循环——如果我想使用循环,我必须执行Windows批处理
-e
)在STDOUT上输出预处理的源代码李>
|
)操作符。在Windows上,命名管道不会获得真实的文件名,这就是为什么您将看到ExtractEnums.exe-client
写入管道和后台进程ExtractEnums.exe-server
,后者在下面的示例中从管道读取
############################################################################
# Dummy files - these will never exist
#
D_FILES = $(SRCS:.c=.dummy) # All dummy files
server :
cmd /c start /B ExtractEnums.exe -server > temp.pipe
%.dummy : %.c server
cmd /c parser.exe $(DEFINES_AND_OPTS) -e $^ | cmd /c ExtractEnums.exe -client
# Extract enums from all the preprocessed source:
%.enums : $(D_FILES)
cmd /c echo ;;exit;; | cmd /c ExtractEnums.exe -client
cmd /c move temp.pipe $@
如果我调用make product\u name.enums
,所有这些都会运行SRCS
是所有源文件的列表<代码>;;退出是一个特殊的字符串,我发送到ExtractEnums.exe-server
,告诉它退出。问题是:
为了循环所有源代码并将它们输入预处理器,我列出了一个永远不存在的.dummy
文件列表。由于这些目标从未存在过,因此它们总是过时的。这意味着调用make product_name.enum
将始终通过预处理器运行所有源,即使源没有更改
我意识到我想出了一个复杂的解决办法。如果你有一个更简单的方法来解决这个问题,我愿意接受建议——在这种情况下,我将编辑这个问题的名称以使其合适。我在解决类似问题时遇到了这个老问题。只需将“虚拟”文件转换为真实(空)文件,即可跟踪上次处理源文件的时间。在下面的示例中,我将它们分组到一个子目录(
dummies
)中,这样它们就不会对源代码树造成太多干扰:
D_DIR = dummies
D_FILES = $(patsubst %.c,$(D_DIR)/%.dummy,$(SRCS)) # All dummy files
$(D_DIR)/%.dummy : %.c
[ -f server ] || { cmd /c start /B ExtractEnums.exe -server > temp.pipe && touch server; }
cmd /c parser.exe $(DEFINES_AND_OPTS) -e $^ | cmd /c ExtractEnums.exe -client
mkdir -p $(dir $@) # create dummy's directory if it does not exist
touch $@ # create dummy
# Extract enums from all the preprocessed source:
%.enums : $(D_FILES)
cmd /c echo ;;exit;; | cmd /c ExtractEnums.exe -client
rm -f server
cmd /c move temp.pipe $@
注意:我还使用一个空的虚拟文件(
server
)将服务器标记为正在运行,并仅在虚拟配方中需要时启动它。这样可以避免将其作为每个虚拟机的先决条件,并在其相应的源文件未更改但服务器未运行时重新构建虚拟机。您对问题2的描述不清楚。接收器(由服务器规则启动)将输出定向到产品名称.pipe
,而%.enums
规则将该文件重命名为其他文件。问题是什么?您可以使用问题中所述的批处理循环,将所有对象减少到单个目标%.enums
。有什么理由不这么做吗?@Beta--我想你是对的。product_name.pipe只是一个临时文件。我将编辑我的问题,以明确它是一个临时文件,并删除第#1项。@perencia——不知何故,使用批处理循环对我来说似乎有点脏。但是,我非常喜欢Windows(即cmd/cstart/B
)。是否要添加一个使用批处理循环作为答案的版本?