ADA GNAT项目,其中包括不同命名的文件,用于不同的构建配置

发布于 2025-01-28 01:21:26 字数 428 浏览 3 评论 0 原文

我有一个具有多种构建配置的GNAT/GPRBUILD项目。我有一个主源文件和一个辅助广告文件,主要源文件包含:

with Secondary_File; use Secondary_File;

问题是,在每种配置中,辅助文件具有不同的名称。例如,它可以称为一个config和secondary_file_2.ads的secontary_file_1.ads。这使得无法将上述语句一起使用。

在C中,我会做这样的事情:

#ifdef BUILD_CFG_1
#include "secondary_file_1.h"
#else
#include "secondary_file_2.h"
#endif

使用GPRBuild系统,是否有一种聪明的方式在ADA中做这样的事情?

I have a Gnat/Gprbuild project with several build configurations. I have a main source file and an secondary ads file which the main source file includes:

with Secondary_File; use Secondary_File;

The problem is that in each configuration, the secondary file has a different name. For example, it may be called Secondary_File_1.ads for one config and Secondary_File_2.ads for another. This makes it impossible to use the above with statement.

In C, I would do something like this:

#ifdef BUILD_CFG_1
#include "secondary_file_1.h"
#else
#include "secondary_file_2.h"
#endif

Is there a clever way to do something like this in ADA, using the Gprbuild system?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

乖乖公主 2025-02-04 01:21:26

许多纯粹主义者拒绝预处理的想法,但是可以使用gnat

您可以通过编写源来将其包括在基于GPR的构建环境中,例如 main.adb ,例如:(

with Secondary_File_$NUMBER;
procedure Main is
begin
   null;
end Main;

观察 $ numbern :

project Prj is

   for Main use ("main.adb");

   --  Configurations
   type Config_Type is ("config_1", "config_2");
   --  Which one? (default is "config_1")
   Config : Config_Type := external ("CONFIG", "config_1");

   package Compiler is
      case Config is
         when "config_1" =>
            for Switches ("main.adb") use ("-gnateDNUMBER=1");
         when "config_2" =>
            for Switches ("main.adb") use ("-gnateDNUMBER=2");
      end case;
   end Compiler;

end Prj;

编译给予

$ gprbuild -Pprj
Compile
   [Ada]          main.adb
main.adb:1:06: error: file "secondary_file_1.ads" not found
gprbuild: *** compilation phase failed

(汇编查找 secondary_file_1.ads

$ gprbuild -Pprj -XCONFIG=config_2
Compile
   [Ada]          main.adb
main.adb:1:06: error: file "secondary_file_2.ads" not found
gprbuild: *** compilation phase failed

(汇编寻找 second> secondary_file_2.ads

Many purists reject the idea of preprocessing, but it’s possible using GNAT.

You can include this in a GPR-based build environment by writing your source, e.g. main.adb, like so:

with Secondary_File_$NUMBER;
procedure Main is
begin
   null;
end Main;

(observe the $NUMBER) and the project file like so:

project Prj is

   for Main use ("main.adb");

   --  Configurations
   type Config_Type is ("config_1", "config_2");
   --  Which one? (default is "config_1")
   Config : Config_Type := external ("CONFIG", "config_1");

   package Compiler is
      case Config is
         when "config_1" =>
            for Switches ("main.adb") use ("-gnateDNUMBER=1");
         when "config_2" =>
            for Switches ("main.adb") use ("-gnateDNUMBER=2");
      end case;
   end Compiler;

end Prj;

Compiling gives

$ gprbuild -Pprj
Compile
   [Ada]          main.adb
main.adb:1:06: error: file "secondary_file_1.ads" not found
gprbuild: *** compilation phase failed

(the compilation looked for secondary_file_1.ads)

$ gprbuild -Pprj -XCONFIG=config_2
Compile
   [Ada]          main.adb
main.adb:1:06: error: file "secondary_file_2.ads" not found
gprbuild: *** compilation phase failed

(the compilation looked for secondary_file_2.ads)

人事已非 2025-02-04 01:21:26

Simon Wright 的答案的一个小变化是使用 naming naming package> package spec> spec spec 。当文件名不同时,此变化很有用,但是软件包名称是相同的: secondary_file 。因此,不确定这在您的情况下是否有效。

main.adb

with Ada.Text_IO;
with Secondary_File;

procedure Main is
begin
   Ada.Text_IO.Put_Line (Secondary_File.Foo);
end Main;

secondary_file_1.ads

package Secondary_File is
   Foo : constant String := "Package 1";
end Secondary_File;

secondary_file_2.ads

package Secondary_File is
   Foo : constant String := "Package 2";
end Secondary_File;

prj.gpr

project Prj is

   for Main use ("main.adb");
   for Source_Dirs use ("src/**");
   for Object_Dir use "obj";

   type Config_Type is ("config_1", "config_2");
   Config : Config_Type := external ("CONFIG", "config_1");

   package Naming is      
      case Config is         
         when "config_1" =>
            for Spec ("Secondary_File") use "secondary_file_1.ads";            
         when "config_2" =>
            for Spec ("Secondary_File") use "secondary_file_2.ads";            
      end case;
   end Naming;

end Prj;

uptump (编译器) )

$ gprbuild -Pprj -XCONFIG=config_1 && ./obj/main
Compile
   [Ada]          main.adb
   [Ada]          secondary_file_1.ads
Bind
   [gprbind]      main.bexch
   [Ada]          main.ali
Link
   [link]         main.adb
Package 1
$ gprbuild -Pprj -XCONFIG=config_2 && ./obj/main
Compile
   [Ada]          main.adb
   [Ada]          secondary_file_2.ads
Bind
   [gprbind]      main.bexch
   [Ada]          main.ali
Link
   [link]         main.adb
Package 2

A small variation on the answer of Simon Wright is one that uses a Naming package and Spec attributes in the GPRbuild file. This variation is useful when file names are different, but package names are the same: Secondary_File. So, not sure if this works in your case.

main.adb

with Ada.Text_IO;
with Secondary_File;

procedure Main is
begin
   Ada.Text_IO.Put_Line (Secondary_File.Foo);
end Main;

secondary_file_1.ads

package Secondary_File is
   Foo : constant String := "Package 1";
end Secondary_File;

secondary_file_2.ads

package Secondary_File is
   Foo : constant String := "Package 2";
end Secondary_File;

prj.gpr

project Prj is

   for Main use ("main.adb");
   for Source_Dirs use ("src/**");
   for Object_Dir use "obj";

   type Config_Type is ("config_1", "config_2");
   Config : Config_Type := external ("CONFIG", "config_1");

   package Naming is      
      case Config is         
         when "config_1" =>
            for Spec ("Secondary_File") use "secondary_file_1.ads";            
         when "config_2" =>
            for Spec ("Secondary_File") use "secondary_file_2.ads";            
      end case;
   end Naming;

end Prj;

output (compiler)

$ gprbuild -Pprj -XCONFIG=config_1 && ./obj/main
Compile
   [Ada]          main.adb
   [Ada]          secondary_file_1.ads
Bind
   [gprbind]      main.bexch
   [Ada]          main.ali
Link
   [link]         main.adb
Package 1
$ gprbuild -Pprj -XCONFIG=config_2 && ./obj/main
Compile
   [Ada]          main.adb
   [Ada]          secondary_file_2.ads
Bind
   [gprbind]      main.bexch
   [Ada]          main.ali
Link
   [link]         main.adb
Package 2
挽手叙旧 2025-02-04 01:21:26

simon's

许多纯粹主义者拒绝预处理的想法

和纯粹主义者的回答的想法是:使用GPR项目文件,他们提供“ 方案变量 ”功能,这些功能应该完全可以完成您想要的事情,而无需重命名或依赖文件一些预处理步骤。

我猜 secondary_file.ads 是唯一的(接口/合同),因此您将每个 Secondary_file.adb 放在其自己的文件夹中(不同的实现)。

然后,它易于根据方案变量调整GPR source_dir/source_files列表。该变量可以在GNATSTUDIO IDE,ENV VAR和命令行标志中设置。

因此,您可以拥有此文件夹树:

src
|-- main.adb
|-- Secondary_File.ads
|-- implA
    |-- Secondary_File.adb
|-- implB
    |-- Secondary_File.adb
|-- implC
    |-- Secondary_File.adb

然后使用此GPR文件 my_project.gpr

project my_project is
    -- enum value shall match folders
    type Secondary_Impl is ("implA", "implB", "implC");
    the_secondary_impl_val : Secondary_Impl := external("secondary_impl_env_var", "implA"); -- gprbuild will look for env var if any, otherwise defaults to implA
    for Source_Dirs use ("src", "src/" & the_secondary_impl_val );
    -- other useful settings : obj dir, compiler/linker switches etc.
    -- ...
end my_project;

然后,您要做的就是使用GPR构建构建:

# build with impl A
gprbuild -Pmy_project.gpr -Xsecondary_impl_env_var=implA

# build with impl C
gprbuild -Pmy_project.gpr -Xsecondary_impl_env_var=implC

或偶数:

# bash commands, syntax to set env var depends on the OS/shell
secondary_impl_env_var=implB
gprbuild -Pmy_project.gpr

根据您的特定软件,您也可以考虑对象在某些情况下可以帮助获得类似结果的定向设计模式。

Bouncing on Simon's answer

Many purists reject the idea of preprocessing

And a purist's answer would be: use GPR project files, they offer the "scenario variables" feature that should do exactly what you want, without having to rename files or rely on some preprocessing step.

I guess Secondary_File.ads is unique (interface/contract), so you put each Secondary_File.adb in its own folder (distinct implementations).

Then its easy to adapt the GPR source_dir/source_files list according to a scenario variable. The variable can be set in the GnatStudio IDE, in an env var, and in a command line flag.

So you could have this folder tree:

src
|-- main.adb
|-- Secondary_File.ads
|-- implA
    |-- Secondary_File.adb
|-- implB
    |-- Secondary_File.adb
|-- implC
    |-- Secondary_File.adb

Then use this GPR file my_project.gpr:

project my_project is
    -- enum value shall match folders
    type Secondary_Impl is ("implA", "implB", "implC");
    the_secondary_impl_val : Secondary_Impl := external("secondary_impl_env_var", "implA"); -- gprbuild will look for env var if any, otherwise defaults to implA
    for Source_Dirs use ("src", "src/" & the_secondary_impl_val );
    -- other useful settings : obj dir, compiler/linker switches etc.
    -- ...
end my_project;

All you have to do is then build using gpr build:

# build with impl A
gprbuild -Pmy_project.gpr -Xsecondary_impl_env_var=implA

# build with impl C
gprbuild -Pmy_project.gpr -Xsecondary_impl_env_var=implC

or even :

# bash commands, syntax to set env var depends on the OS/shell
secondary_impl_env_var=implB
gprbuild -Pmy_project.gpr

Depending on your specific software, you may also consider object oriented design patterns that can help achieve a similar result in some cases.

何以笙箫默 2025-02-04 01:21:26

如果某些文件不同,那么为什么没有两个不同的.gpr配置文件?您可以将不同的代码分为不同的目录,并具有第三个目录的通用代码,然后在.gpr中在类似的块中指定。

for Source_Dirs use ("main_directory",
                     "common_code_directory");

现在

for Source_Dirs use ("secondary_directory",
                     "common_code_directory");

,您在同一项目中具有不同的配置,并且可以构建一个。您甚至可以走得更远,创建包含两个配置之间共享功能的常见ADA规格文件(.1.ADA),但具有不同的行为不同的ADA Body Files(.2.ADA)。

If some of the files are different then why not have two different .gpr configuration files? You can separate the different code into different directories and have a third directory for common code and then specify in the .gpr in a block like this

for Source_Dirs use ("main_directory",
                     "common_code_directory");

and this

for Source_Dirs use ("secondary_directory",
                     "common_code_directory");

Now you have different configurations in the same project and can build either one. You can even go further and create common ada spec files (.1.ada) that contain shared functions between the two configuration but have two different ada body files (.2.ada) that behave differently.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文