使用Gnu Make编译ada项目需要gnatprep和gnatchop
Using Gnu Make to compile ada project requiring gnatprep and gnatchop
我一直在尝试将多个大型 ada 编译从基于脚本的方法转换为使用 gnu make 3.82 makefile 并且可以使用一些经验丰富的知识。
一些背景:
- Red Hat Enterprise Linux 版本 7.9
上的 GNAT 4.8.5
- 每次编译都以约 1000 个 .ada 文件的源列表开始
- 不同的版本使用一些相同的文件,每个源列表中的文件总数约为 14k,而只有约 7000 个独特的文件
- 每个文件都需要准备、切碎,然后编译 - 绑定和链接在别处完成
我的做法:
- 方法 1:对于每个文件,将文件准备成 src/foo/prepped,然后切成 src/foo/chopped
- 方法 2:将方法 1 中创建的每个切碎文件复制到模块 SRC/ 文件夹中
- 方法 3:在 SRC/ 文件夹中编译方法 2 中的每个切碎文件并放置在 OBJ/ 文件夹中
问题:
- 切碎阶段会导致问题,因为文件名已更改,并且在某些情况下会创建更多文件。为了解决这个问题,我尝试为每个 src/foo/prepped 文件夹的内容通配符,并将它们复制到 SRC/ 文件夹中进行编译。由于此列表在 prep/chop 阶段之前是未知的,因此需要再次调用 make 以获取这些文件名。
- 在编译阶段,我盲目地运行 SRC/ 文件夹中的每个文件使用双冒号规则进行编译,因为我不确定在编译阶段输出的文件(.ali 或.o)
- 如果一个文件已经prepped/chopped来自以前的编译,它不会做双重工作prepping/chopping,但不会将文件复制到 SRC/
问题:
- 如何在事先不知道的情况下解释使用 gnatchop 输出的文件?
- 在编译阶段,我如何编写一个规则来从 .adb 或 .ads 文件创建 .o 或 .ali 文件?
FILE:= 'input' #read input from file
OBJECTS:=$(shell cat ${FILE}) #need to do this, no file function in gnu make 3.82
FPOBJECTS:= $(addprefix ../../src/, $(OBJECTS)) # path + source name from pwd
OBJFILE:=$(notdir $(OBJECTS)) #just get out source file name
PDIR:=$(addprefix ../../src/, $(addsuffix prepped/ , $(dir $(OBJECTS)))) #just get out directory part of objects, add prepped/ suffix and ../../src to beginning
CDIR:= $(addprefix ../../src/, $(addsuffix chopped/ , $(dir $(OBJECTS))))# same as PDIR but with chopped/ instead of prepped/
CDIR2:= $(sort $(CDIR)) # unique directories in CDIR for folder creation
PDIR2:= $(sort $(PDIR)) # unique directories in PDIR for folder creation
DIRS:= OBJ TMP SRC #directories inside lib/version*
POBJECTS:= $(basename $(join $(PDIR), $(OBJFILE))) # join prepped directory with objects
COBJECTS = $(addprefix OBJ/, $(notdir $(wildcard SRC/*))) # this is an incorrect way to generate the objects needed, but does allow me to pass each source file for compilation
GNATOPTIONS:= -c -O1 -w -fPIC -gnatE -gnatv -LSRC/ # gcc flags
CDIRwld:=$(shell echo $(addsuffix *, $(CDIR2))) #append * to each unique chopped directory, to try and get names of each chopped file
.RECIPEPREFIX = >
#compile creates the COBJECTS in the pwd and moves them where they belong
compile : $(COBJECTS)
>mv *.ali OBJ/
>mv *.o OBJ/
$(COBJECTS)::
>gcc $(GNATOPTIONS) SRC/$(@F)
copy : $(CDIRwld)
>cp $? SRC/
prep : $(POBJECTS)
$(POBJECTS):$(FPOBJECTS) | $(DIRS) $(PDIR2) $(CDIR2)
>gnatprep -cru -Dlil $(addsuffix .ada, $(subst prepped/,,$@)) $(basename $@)
>gnatchop -rw $@ $(subst prepped/,chopped/,$(dir $@))
$(DIRS):
>mkdir -p $@
$(PDIR2):
>mkdir -p $@
$(CDIR2):
>mkdir -p $@
.PHONY: clean move
clean :
>rm -f -r $(DIRS)
>rm -f -r $(PDIR2)
>rm -f -r $(CDIR2)
move :
>mv *.ali OBJ/
>mv *.o OBJ/
您可以使用项目文件和 GPRBuild 告诉 GNAT 一步预处理和编译多单元源。但是,有那么多文件,
以及必须指定多单元源的方式,您可能必须生成项目文件...
这些答案中的更多信息:
多单元源文件:
预处理:
编辑:正如@SimonWright 所建议的,gnatname
可能能够生成必要的命名规则
准备好的文件和切碎的文件之间存在一一对应关系。
最好让 GNAT 知道它何时需要编译规范,并了解依赖关系——尤其是内联和通用主体等不明显的依赖关系。
一个非常简单的 makefile(适用于 Make 3.81)可能是:
SOURCES = foo.ada bar.ada
DEFS = defs.def
CHOPPED_STAMPS = $(addsuffix .chopped, $(SOURCES))
compile: $(CHOPPED_STAMPS)
cd obj; gnatmake -c ../chopped/*
%.prepped: %
gnatprep $< prepped/ $(DEFS)
touch $@
%.chopped: %.prepped
gnatchop -w prepped/$(basename $<) chopped/
touch $@
它的缺点是会在当前目录中乱放 .prepped
、.chopped
标记文件,但可以将它们放入子目录中。
一个更糟糕的问题是gnatprep
阶段依赖于定义文件,我还没有想出如何将这种依赖引入到隐式规则中。
我是用gnatmake
编译的,总的来说还是用gprbuild
比较好,如果有库项目的话。 GPRBuild RM有点挑战,link是对当前版本的,所以可能会缺少一些功能。
我一直在尝试将多个大型 ada 编译从基于脚本的方法转换为使用 gnu make 3.82 makefile 并且可以使用一些经验丰富的知识。
一些背景:
- Red Hat Enterprise Linux 版本 7.9 上的 GNAT 4.8.5
- 每次编译都以约 1000 个 .ada 文件的源列表开始
- 不同的版本使用一些相同的文件,每个源列表中的文件总数约为 14k,而只有约 7000 个独特的文件
- 每个文件都需要准备、切碎,然后编译 - 绑定和链接在别处完成
我的做法:
- 方法 1:对于每个文件,将文件准备成 src/foo/prepped,然后切成 src/foo/chopped
- 方法 2:将方法 1 中创建的每个切碎文件复制到模块 SRC/ 文件夹中
- 方法 3:在 SRC/ 文件夹中编译方法 2 中的每个切碎文件并放置在 OBJ/ 文件夹中
问题:
- 切碎阶段会导致问题,因为文件名已更改,并且在某些情况下会创建更多文件。为了解决这个问题,我尝试为每个 src/foo/prepped 文件夹的内容通配符,并将它们复制到 SRC/ 文件夹中进行编译。由于此列表在 prep/chop 阶段之前是未知的,因此需要再次调用 make 以获取这些文件名。
- 在编译阶段,我盲目地运行 SRC/ 文件夹中的每个文件使用双冒号规则进行编译,因为我不确定在编译阶段输出的文件(.ali 或.o)
- 如果一个文件已经prepped/chopped来自以前的编译,它不会做双重工作prepping/chopping,但不会将文件复制到 SRC/
问题:
- 如何在事先不知道的情况下解释使用 gnatchop 输出的文件?
- 在编译阶段,我如何编写一个规则来从 .adb 或 .ads 文件创建 .o 或 .ali 文件?
FILE:= 'input' #read input from file
OBJECTS:=$(shell cat ${FILE}) #need to do this, no file function in gnu make 3.82
FPOBJECTS:= $(addprefix ../../src/, $(OBJECTS)) # path + source name from pwd
OBJFILE:=$(notdir $(OBJECTS)) #just get out source file name
PDIR:=$(addprefix ../../src/, $(addsuffix prepped/ , $(dir $(OBJECTS)))) #just get out directory part of objects, add prepped/ suffix and ../../src to beginning
CDIR:= $(addprefix ../../src/, $(addsuffix chopped/ , $(dir $(OBJECTS))))# same as PDIR but with chopped/ instead of prepped/
CDIR2:= $(sort $(CDIR)) # unique directories in CDIR for folder creation
PDIR2:= $(sort $(PDIR)) # unique directories in PDIR for folder creation
DIRS:= OBJ TMP SRC #directories inside lib/version*
POBJECTS:= $(basename $(join $(PDIR), $(OBJFILE))) # join prepped directory with objects
COBJECTS = $(addprefix OBJ/, $(notdir $(wildcard SRC/*))) # this is an incorrect way to generate the objects needed, but does allow me to pass each source file for compilation
GNATOPTIONS:= -c -O1 -w -fPIC -gnatE -gnatv -LSRC/ # gcc flags
CDIRwld:=$(shell echo $(addsuffix *, $(CDIR2))) #append * to each unique chopped directory, to try and get names of each chopped file
.RECIPEPREFIX = >
#compile creates the COBJECTS in the pwd and moves them where they belong
compile : $(COBJECTS)
>mv *.ali OBJ/
>mv *.o OBJ/
$(COBJECTS)::
>gcc $(GNATOPTIONS) SRC/$(@F)
copy : $(CDIRwld)
>cp $? SRC/
prep : $(POBJECTS)
$(POBJECTS):$(FPOBJECTS) | $(DIRS) $(PDIR2) $(CDIR2)
>gnatprep -cru -Dlil $(addsuffix .ada, $(subst prepped/,,$@)) $(basename $@)
>gnatchop -rw $@ $(subst prepped/,chopped/,$(dir $@))
$(DIRS):
>mkdir -p $@
$(PDIR2):
>mkdir -p $@
$(CDIR2):
>mkdir -p $@
.PHONY: clean move
clean :
>rm -f -r $(DIRS)
>rm -f -r $(PDIR2)
>rm -f -r $(CDIR2)
move :
>mv *.ali OBJ/
>mv *.o OBJ/
您可以使用项目文件和 GPRBuild 告诉 GNAT 一步预处理和编译多单元源。但是,有那么多文件, 以及必须指定多单元源的方式,您可能必须生成项目文件...
这些答案中的更多信息:
多单元源文件:
预处理:
编辑:正如@SimonWright 所建议的,gnatname
可能能够生成必要的命名规则
准备好的文件和切碎的文件之间存在一一对应关系。
最好让 GNAT 知道它何时需要编译规范,并了解依赖关系——尤其是内联和通用主体等不明显的依赖关系。
一个非常简单的 makefile(适用于 Make 3.81)可能是:
SOURCES = foo.ada bar.ada
DEFS = defs.def
CHOPPED_STAMPS = $(addsuffix .chopped, $(SOURCES))
compile: $(CHOPPED_STAMPS)
cd obj; gnatmake -c ../chopped/*
%.prepped: %
gnatprep $< prepped/ $(DEFS)
touch $@
%.chopped: %.prepped
gnatchop -w prepped/$(basename $<) chopped/
touch $@
它的缺点是会在当前目录中乱放 .prepped
、.chopped
标记文件,但可以将它们放入子目录中。
一个更糟糕的问题是gnatprep
阶段依赖于定义文件,我还没有想出如何将这种依赖引入到隐式规则中。
我是用gnatmake
编译的,总的来说还是用gprbuild
比较好,如果有库项目的话。 GPRBuild RM有点挑战,link是对当前版本的,所以可能会缺少一些功能。