Ada gprbuild将外部信息获取到源中

Ada gprbuild将外部信息获取到源中,ada,gnat,Ada,Gnat,我正试图让gprbuild在我的源代码中自动设置一些变量的值——以这样或那样的方式。我特别希望某些命令的输出可以从代码中访问。在使用Makefiles的C中,这很简单: 资料来源: #include <stdio.h> int main() { printf("%s\n", COMMAND_OUTPUT); return 0; } 然而,我不知道如何用gprbuild和Ada做这样的事情。(除了放弃gprbuild,只使用make——但我更喜欢gprbuild)Ada不像C那样使用

我正试图让gprbuild在我的源代码中自动设置一些变量的值——以这样或那样的方式。我特别希望某些命令的输出可以从代码中访问。在使用Makefiles的C中,这很简单:

资料来源:

#include <stdio.h>
int main() { printf("%s\n", COMMAND_OUTPUT); return 0; }

然而,我不知道如何用gprbuild和Ada做这样的事情。(除了放弃gprbuild,只使用make——但我更喜欢gprbuild)

Ada不像C那样使用预处理器。你不能指望Ada编译器修改代码中的字符串。
使用这种内联编辑很容易违反Ada强类型,这将很难诊断,并且对源代码静态分析完全不可见。

Ada不像C那样使用预处理器。您不能期望Ada编译器修改代码中的字符串。
使用这种内联编辑很容易违反Ada强类型,这将很难诊断,并且对源代码静态分析完全不可见。

我通过在构建之前从makefile生成Ada文件来解决这个问题

例如:

HG_STATE_SOURCE     = src/mercurial.ads
HG_MODIFIER         = `test $$(hg status | wc -c || echo 0) -gt 0 && echo "plus changes" || echo "as committed"`
HG_REVISION         = `hg tip --template '{node}' 2>/dev/null || echo N/A_____________________________________`

[...]

$(HG_STATE_SOURCE): Makefile $(REPOSITORY_CONFIG) $(REPOSITORY_STATE) $(PROJECT_ROOT_SOURCE)
    @mkdir -p src
    @echo 'package 'Mercurial is'                                >  $(HG_STATE_SOURCE)
    @echo '   Revision : constant String (1 .. 53) :='           >> $(HG_STATE_SOURCE)
    @echo '                "'$(HG_REVISION)' '$(HG_MODIFIER)'";' >> $(HG_STATE_SOURCE)
    @echo 'end 'Mercurial;'                                      >> $(HG_STATE_SOURCE)

我通过在构建之前从makefile生成一个Ada文件来解决这个问题

例如:

HG_STATE_SOURCE     = src/mercurial.ads
HG_MODIFIER         = `test $$(hg status | wc -c || echo 0) -gt 0 && echo "plus changes" || echo "as committed"`
HG_REVISION         = `hg tip --template '{node}' 2>/dev/null || echo N/A_____________________________________`

[...]

$(HG_STATE_SOURCE): Makefile $(REPOSITORY_CONFIG) $(REPOSITORY_STATE) $(PROJECT_ROOT_SOURCE)
    @mkdir -p src
    @echo 'package 'Mercurial is'                                >  $(HG_STATE_SOURCE)
    @echo '   Revision : constant String (1 .. 53) :='           >> $(HG_STATE_SOURCE)
    @echo '                "'$(HG_REVISION)' '$(HG_MODIFIER)'";' >> $(HG_STATE_SOURCE)
    @echo 'end 'Mercurial;'                                      >> $(HG_STATE_SOURCE)

是的,gnatprep预处理器允许与C代码中完全相同的操作:

main.adb:
带有Ada.Text\u IO;使用Ada.Text\u IO;
主要程序是
开始
Put_行($Command_Output);
端干管;
simple_gnatprep.gpr: 生成文件: 注意:我已将命令输出包含在所使用的obj/目录中,如果命令输出任何不能出现在目录名中的符号,则命令输出将失败。但是,如果您省略它,那么gprbuild会说您的可执行文件是最新的,除了命令的输出外,没有任何更改

另一种选择是在编译之前始终删除对象目录,但如果可能,最好在对象路径中包含任何预处理器符号的值,以便从一种配置(例如调试/发布)切换到另一种配置并返回不会丢弃中间结果并减慢开发过程


Gnatprep只包含在GNAT编译器中,因为Ada标准中还没有任何预处理的规定。对于其他编译器,您需要在Makefile中分别通过gnatprep运行每个文件,然后将其传递给编译器。在这种情况下,不需要修改对象目录名,因为源文件总是新的,编译器总是需要重新编译所有内容。

是的,gnatprep预处理器允许与C代码中完全相同的内容:

main.adb:
带有Ada.Text\u IO;使用Ada.Text\u IO;
主要程序是
开始
Put_行($Command_Output);
端干管;
simple_gnatprep.gpr: 生成文件: 注意:我已将命令输出包含在所使用的obj/目录中,如果命令输出任何不能出现在目录名中的符号,则命令输出将失败。但是,如果您省略它,那么gprbuild会说您的可执行文件是最新的,除了命令的输出外,没有任何更改

另一种选择是在编译之前始终删除对象目录,但如果可能,最好在对象路径中包含任何预处理器符号的值,以便从一种配置(例如调试/发布)切换到另一种配置并返回不会丢弃中间结果并减慢开发过程


Gnatprep只包含在GNAT编译器中,因为Ada标准中还没有任何预处理的规定。对于其他编译器,您需要在Makefile中分别通过gnatprep运行每个文件,然后将其传递给编译器。在这种情况下,不需要修改对象目录名,因为源文件总是新的,编译器将始终需要重新编译所有内容。

如果有某种方法只使用gprbuild传递它,这将非常有效,尽管我想我总是可以将gprbuild包装在make中。如果gprbuild本机无法实现,那么我将接受您的答案为正确。在看到Simon Wright的建议后,我将接受此答案为正确,直到gnatprep允许运行外部命令来生成其内容。这不是一个令人愉快的解决方案。我有一个更整洁的地方。博客描述了我如何使用gprbuild做同样的事情:如果有某种方法可以使用gprbuild来传递它,这将非常有效,尽管我想我总是可以用make包装gprbuild。如果gprbuild本机无法实现,那么我将接受您的答案为正确。在看到Simon Wright的建议后,我将接受此答案为正确,直到gnatprep允许运行外部命令来生成其内容。这不是一个令人愉快的解决方案。我有一个更整洁的地方。博客描述了我如何用gprbuild做同样的事情:它应该仍然可以初始化一个字符串,就像雅各布·斯帕雷·安德森(Jacob Sparre Andersen)的回答一样。如果不是的话,我想我只能使用这个解决方案。这不是真的,虽然不雅致且有一定的限制(可能是出于设计),但它将对源代码进行预处理,而gnatprep并不是Ada语言的一部分。这是一个由一个供应商提供的工具,它应该仍然可以初始化一个字符串,就像Jacob Sparre Andersen的响应一样。如果不是的话,我想我只能使用这个解决方案。这不是真的,虽然不雅致且有一定的限制(可能是出于设计),但它将对源代码进行预处理,而gnatprep并不是Ada语言的一部分。这是一个由一个供应商提供的工具。您可以使用,特别是在模式下。我使用了gnatprep,但没有使用集成的预处理。为什么信息必须在源代码中?通常,您可以将信息放入文件中,并让程序读取该文件。您可以使用,特别是在模式下。我用过啃咬法,但是
project simple_gnatprep is

   for Create_Missing_Dirs use "True";

   Command_Output := external ("Command_Output");

   for Source_Dirs use (".");
   for Exec_Dir use ".";
   for Main use ("main.adb");

   for Object_Dir use "obj/" & "CommandOutput_" & Command_Output;

   package Compiler is
      for Switches ("Ada") use ("-gnateDCommand_Output=""" & Command_Output & """");
   end Compiler;
end simple_gnatprep;
COMMAND_OUTPUT=$(shell echo hello there)

all:
    gprbuild -d -p -g -XCommand_Output='${COMMAND_OUTPUT}'

clean:
    rm -rf obj/ *.exe