gprbuild 获取外部信息到源
gprbuild get external information into source
我试图让 gprbuild 在我的源代码中自动设置一些变量的值 - 一种或另一种方式。特别是我希望可以从代码中访问某些命令的输出。在带有 Makefile 的 C 中,这很容易:
来源:
#include <stdio.h>
int main() { printf("%s\n", COMMAND_OUTPUT); return 0; }
制作:
result : source.c
$(CC) -DCOMMAND_OUTPUT=`command -with -options`
但是我不知道如何用 gprbuild 和 Ada 做这样的事情。 (缺少放弃 gprbuild 并仅使用 make - 但我更喜欢 gprbuild)
Ada 不使用像 C 这样的预处理器 does.You 不能指望 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)
是的,gnatprep 预处理器允许与您的 C 代码中的完全相同:
main.adb:
with Ada.Text_IO; use Ada.Text_IO;
procedure Main is
begin
Put_Line ($Command_Output);
end Main;
simple_gnatprep.gpr:
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
请注意,我已将命令输出包含在所用的 obj/ 目录中,如果该命令输出任何不能出现在目录名称中的符号,它将失败。但是,如果您省略它,那么 gprbuild 会说您的可执行文件是最新的,除了命令的输出没有任何变化。
另一种选择是在编译之前始终删除对象目录,但如果可能,最好在对象路径中包含任何预处理器符号的值,以便从一种配置(例如调试/发布)切换到另一种配置返回不会丢弃中间结果并减慢您的开发过程。
Gnatprep 仅包含在 GNAT 编译器中,因为 Ada 标准中还没有任何预处理规定。对于其他编译器,你将需要运行每个文件在Makefile中分别通过gnatprep,然后传递给编译器。在这种情况下,不需要 fiddle 对象目录名称,因为源文件将始终是新的,编译器将始终必须重新编译所有内容。
我试图让 gprbuild 在我的源代码中自动设置一些变量的值 - 一种或另一种方式。特别是我希望可以从代码中访问某些命令的输出。在带有 Makefile 的 C 中,这很容易:
来源:
#include <stdio.h>
int main() { printf("%s\n", COMMAND_OUTPUT); return 0; }
制作:
result : source.c
$(CC) -DCOMMAND_OUTPUT=`command -with -options`
但是我不知道如何用 gprbuild 和 Ada 做这样的事情。 (缺少放弃 gprbuild 并仅使用 make - 但我更喜欢 gprbuild)
Ada 不使用像 C 这样的预处理器 does.You 不能指望 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)
是的,gnatprep 预处理器允许与您的 C 代码中的完全相同:
main.adb:
with Ada.Text_IO; use Ada.Text_IO;
procedure Main is
begin
Put_Line ($Command_Output);
end Main;
simple_gnatprep.gpr:
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
请注意,我已将命令输出包含在所用的 obj/ 目录中,如果该命令输出任何不能出现在目录名称中的符号,它将失败。但是,如果您省略它,那么 gprbuild 会说您的可执行文件是最新的,除了命令的输出没有任何变化。
另一种选择是在编译之前始终删除对象目录,但如果可能,最好在对象路径中包含任何预处理器符号的值,以便从一种配置(例如调试/发布)切换到另一种配置返回不会丢弃中间结果并减慢您的开发过程。
Gnatprep 仅包含在 GNAT 编译器中,因为 Ada 标准中还没有任何预处理规定。对于其他编译器,你将需要运行每个文件在Makefile中分别通过gnatprep,然后传递给编译器。在这种情况下,不需要 fiddle 对象目录名称,因为源文件将始终是新的,编译器将始终必须重新编译所有内容。