【问题标题】:Makefile to generate JSON from Python scripts in separate directoriesMakefile 从不同目录中的 Python 脚本生成 JSON
【发布时间】:2014-12-09 12:12:41
【问题描述】:

我有一个 Makefile,它从单个目录中的几个不同 Python 脚本(脚本打印到标准输出)生成 JSON,例如

/src
    scriptOne.py
    scriptTwo.py
    scriptThree.py

将 JSON 输出到文件夹:

/templates
   scriptOne.json
   scriptTwo.json
   scriptThree.json

我正在尝试进行重组,例如,每个脚本都位于其自己的子目录中,并且 Makefile 在其后续子目录中创建 JSON 模板,如下所示:

/src
   /importantTemplates
       scriptOne.py 
   /notSoImportantTemplates
       scriptTwo.py
       scriptThree.py

还有输出:

/templates
   /importantTemplates
       scriptOne.json 
   /notSoImportantTemplates
       scriptTwo.json
       scriptThree.json

当前的Makefile如下:

SOURCES := $(shell echo src/*.py)
TARGETS := $(patsubst src/%.py,templates/%.json,$(SOURCES))

all: $(TARGETS)

clean:
    rm -f $(TARGETS)

templates/%.json: src/%.py
    python2 $< > $@

我尝试更改通配符以包含每一行的子目录,例如/src/*/*.py,虽然我最终得到以下结果:

make: Nothing to be done for `all'.

【问题讨论】:

    标签: shell makefile


    【解决方案1】:

    您需要一个静态模式规则 (4.12 Static Pattern Rules)。

    SOURCES := $(wildcard src/*/*.py)
    TARGETS := $(patsubst src/%.py,templates/%.json,$(SOURCES))
    
    all: $(TARGETS)
    
    clean:
            rm -rf templates
    
    $(TARGETS) : templates/%.json: src/%.py
            mkdir -p $(@D)
            python2 $< > $@
    

    如果您愿意,您可以避免在该规则正文中使用 mkdir -p(并在目录上使用仅限订单的先决条件),但我不确定这种努力是否值得节省执行成本。如果你愿意的话,你可以通过组合 mkdir -p $(@D) &amp;&amp; python2 $&lt; &gt; $@ 这两行来避免额外的 shell。

    【讨论】:

      【解决方案2】:

      请注意,第二次运行 make 时,它​​会给你消息(如果没有新文件):

      make: Nothing to be done for `all'.
      

      尝试运行 make clean 并查看是否收到相同的消息。

      这里是 Makefile 可以做你想做的事:

      SOURCES := $(wildcard src/*/*.py)
      TARGETS := $(patsubst src/%.py,templates/%.json,$(SOURCES))
      FOLDERS := $(sort $(dir $(TARGETS)))
      
      all: $(TARGETS)
      
      clean:
          rm -rf $(TARGETS) $(FOLDERS)
      
      $(FOLDERS):
          mkdir -p $@
      
      $(TARGETS): $(SOURCES) $(FOLDERS)
          python2 $< > $@
      

      FOLDERS 变量将包含您需要在模板目录中创建的文件夹。 (排序将删除重复项,因此每个文件夹只会出现一次)

      $(FOLDERS) 规则将创建文件夹。 clean 规则也会删除文件夹。

      如果您需要添加更多来源,只需这样做:

      SOURCES := $(wildcard src/*/*.py)
      SOURCES += $(wildcard src/*.py)
      ...    
      

      【讨论】:

      • $(FOLDERS) 应该是仅限订单的先决条件,因此您可以从 mkdir 命令中删除 -p 标志。 rm -rf 应该是 $(RM) -r$(patsubst src/%.py,templates/%.json,$(SOURCES)) 可以是 $(SOURCES:src/%.py=templates/%.json)。而SOURCES 可以使用$(shell find ...)
      • @Chnossos 为什么你会推荐$(shell) 而不是$(wildcard)-f 在干净的目标上意味着它永远不会失败(否则它会在连续运行两次时失败)。
      • 这使得每个输出 json 文件都依赖于 每个 输入 python 文件。您需要静态模式规则而不是 $(TARGETS): $(SOURCES) 规则。 $(TARGETS) : templates/%.json : src/%.py 或类似的东西。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-26
      相关资源
      最近更新 更多