我正在努力更新一个脚本,该脚本在构建时为我们的每个构建生成C和Java的源代码文件。
这需要在 Windows 和 Linux 上运行。
需要为每种语言创建两种文件类型:Enums 和 Tables。
每组四个文件(C Enum、C Table、Java Enum、Java Table)都是从相应的 CSV 文件生成的。
给定一个名为
A.csv
的输入 CSV 文件,输出文件为 AEnum.inc
、ATable.inc
、AEnum.java
和 ATable.java
。
可以通过调用 python 脚本并激活 venv 来一次创建所有四个文件,如下所示:
python main.py --input A.csv --output ./output --enum-c --table-c --enum-java --table-java
在 makefile 中使用名为
run_autogen_all
的函数对其进行了缩短。
创建文件后,需要将它们复制到不同的目录:
$(C_AUTOGEN)/
$(JAVA_ENUM)/
$(JAVA_TABLE)/
我无法弄清楚如何确保 python 脚本只运行一次(运行时是不可忽略的),同时还将所有文件复制到正确的目录。
如何使用 Make 实现此行为?
这是我当前的解决方案,有效,但它运行 python 脚本两次并复制文件两次。
MAIN_4_CSV_FILES = A.CSV B.CSV C.CSV D.CSV E.CSV F.CSV G.CSV H.CSV I.CSV J.CSV K.CSV L.CSV M.CSV N.CSV O.CSV P.CSV Q.CSV R.CSV S.CSV T.CSV U.CSV V.CSV W.CSV X.CSV Y.CSV Z.CSV
.PHONY : JavaFiles CFiles
JavaFiles : *.java
CFiles : *.inc
*.java *.inc : $(MAIN_4_CSV_FILES)
$(call run_autogen_all,$^)
$(COPYF) *Enum.java $(JAVA_ENUM)
$(COPYF) *Table.java $(JAVA_TABLE)
$(COPYF) *.inc $(C_AUTOGEN)
运行
make JavaFiles CFiles -n
给出以下输出
python "../../../../../build/Common/CSV_Parser/autogenerate_from_csv.py" --output "./" --csv-files A.CSV B.CSV C.CSV D.CSV E.CSV F.CSV G.CSV H.CSV I.CSV J.CSV K.CSV L.CSV M.CSV N.CSV O.CSV P.CSV Q.CSV R.CSV S.CSV T.CSV U.CSV V.CSV W.CSV X.CSV Y.CSV Z.CSV
cp -f *Enum.java ../../../../Project/java/enums
cp -f *Table.java ../../../../Project/java/tables
cp -f *Enum.inc ../../../../Project/c
cp -f *Table.inc ../../../../Project/c
python "../../../../../build/Common/CSV_Parser/autogenerate_from_csv.py" --output "./" --csv-files A.CSV B.CSV C.CSV D.CSV E.CSV F.CSV G.CSV H.CSV I.CSV J.CSV K.CSV L.CSV M.CSV N.CSV O.CSV P.CSV Q.CSV R.CSV S.CSV T.CSV U.CSV V.CSV W.CSV X.CSV Y.CSV Z.CSV
cp -f *Enum.java ../../../../Project/java/enums
cp -f *Table.java ../../../../Project/java/tables
cp -f *Enum.inc ../../../../Project/c
cp -f *Table.inc ../../../../Project/c
我尝试了很多选择,以下是一些不起作用的
%Enum.inc %Enum.java %Table.inc %Table.java :
$(call run_autogen_all,$<)
$(call copy_attrib,$(notdir $@),$@)
AFiles = $(C_AUTOGEN)/AEnum.c $(C_AUTOGEN)/ATable.c $(JAVA_ENUM)/AEnum.java $(JAVA_TABLE)/ATable.java
$(AFiles) : A.csv
[...]
JavaEnums : $(JAVA_ENUM)/AEnum.java $(JAVA_ENUM)/BEnum.java [...]
$(JAVA_ENUM)/%Enum.java : %Enum.java
$(call run_autogen_all,$*.csv)
$(call copy_attrib,$(notdir $@),$@)
[...]
%Enum.java %Enum.c %Table.java %Table.c : %.csv
$(call run_autogen_all,$<)
$(call copy_attrib,$(notdir $@),$@)
[...]
我也尝试过弄乱
.INTERMEDIATE
和.SECONDARY
,但无济于事。
假设您使用 GNU make 并且所有生成的文件都在当前目录中生成,您可以使用具有 4 个目标的模式规则。
.PHONY: all
all: $(C_AUTOGEN)/AEnum.inc $(C_AUTOGEN)/ATable.inc $(JAVA_ENUM)/AEnum.java $(JAVA_TABLE)/ATable.java
$(C_AUTOGEN)/%Enum.inc $(C_AUTOGEN)/%Table.inc $(JAVA_ENUM)/%Enum.java $(JAVA_TABLE)/%Table.java: %.csv
python main.py --input $< --output ./output --enum-c --table-c --enum-java --table-java
mv $*Enum.inc $*Table.inc $(C_AUTOGEN)
mv $*Enum.java $(JAVA_ENUM)
mv $*Table.java $(JAVA_TABLE)
使用最新版本的 GNU make,您还可以使用分组目标 (
&:
):
$(C_AUTOGEN)/AEnum.inc $(C_AUTOGEN)/ATable.inc $(JAVA_ENUM)/AEnum.java $(JAVA_TABLE)/ATable.java &: A.csv
python main.py --input $< --output ./output --enum-c --table-c --enum-java --table-java
mv AEnum.inc ATable.inc $(C_AUTOGEN)
mv AEnum.java $(JAVA_ENUM)
mv ATable.java $(JAVA_TABLE)
在这两种情况下,GNU make 仅执行一次配方来构建 4 个目标。不要在此类规则的配方中使用
$@
(至少在阅读文档之前不要使用)。
一旦你测试了这个,也许可以尝试重新引入你的宏。