Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Build order with gprbuild

111 views
Skip to first unread message

Gautier write-only address

unread,
Feb 28, 2023, 4:11:01 PM2/28/23
to
When a GNAT project A depends on project B, is there a simple (*) way to make gprbuild build project B before starting the build of A?
It would be useful when project B generates Ada sources…
Example:

with "code_generation.gpr";

project Main is
for Source_Dirs use (".", "gen");
for Object_Dir use "obj";
for Create_Missing_Dirs use "True"; -- Flips by default the "-p" switch
for Main use ("main.adb");
end Main;

(*) By “simple” I mean simpler than the way described here:
https://www.adacore.com/gems/gem-157-gprbuild-and-code-generation

Dmitry A. Kazakov

unread,
Feb 28, 2023, 5:07:54 PM2/28/23
to
On 2023-02-28 22:10, Gautier write-only address wrote:
> When a GNAT project A depends on project B, is there a simple (*) way to make gprbuild build project B before starting the build of A?

But this is exactly how it works unless B builds a library. I have a
large number of interdependent projects and everything is built
automatically as necessary.

When it comes to a release, I generate the corresponding library
building projects from a script.

Another reason not to use libraries during the development phase is that
addr2line does not work with dynamic libraries. You must catch exception
in the program and find where addresses belong to. This cannot be done
when the program is no more running.

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

Gautier write-only address

unread,
Mar 1, 2023, 3:08:52 PM3/1/23
to
Between normal Ada projects, everything works as you describe (and as expected).
However, in the special case where project B, instead of transforming Ada files into .o files, transforms other kind of files into Ada files that are with-ed by units of project A, things get off the road: project A doesn't see out-of-date Ada files produced by project B.

Here is a full example. Files are reproduced below (they are meant to land into the same directory).
Then you do the following commands:

gprbuild -P fuzzy_gen.gpr
gprbuild -P code_generation.gpr
gnatstudio -P main.gpr

First build launched from GNAT Studio does the following on my machine:

Compile
[Ada] main.adb
[Fuzzy] x789.cfg
Ada file "fuzzy_x789.adb" is up to date
[Fuzzy] x456.cfg
Ada file "fuzzy_x456.adb" is up to date
[Fuzzy] x123.cfg
Ada file "fuzzy_x123.adb" is up to date
[Ada] fuzzy_x123.adb
[Ada] fuzzy_x456.adb
[Ada] fuzzy_x789.adb
Bind
[gprbind] main.bexch
[Ada] main.ali
Link
[link] main.adb

Second build has an expected output as well:

Compile
[Fuzzy] x789.cfg
Ada file "fuzzy_x789.adb" is up to date
[Fuzzy] x456.cfg
Ada file "fuzzy_x456.adb" is up to date
[Fuzzy] x123.cfg
Ada file "fuzzy_x123.adb" is up to date
gprbuild: "main.exe" up to date

Now, say you modify x123.cfg and save it.
Compile
[Fuzzy] x789.cfg
Ada file "fuzzy_x789.adb" is up to date
[Fuzzy] x456.cfg
Ada file "fuzzy_x456.adb" is up to date
[Fuzzy] x123.cfg
Converting "x123.cfg" into "fuzzy_x123.adb"...
gprbuild: "main.exe" up to date

That's *not* what I would like: gprbuild did not detect the out-of-date file "fuzzy_x123.adb" in time.
A second call to gprbuild compiles the changed "fuzzy_x123.adb" and all is well, but it is one step too late.

The files
=========

1) The code generator
=====================

fuzzy_gen.gpr:
-------------

project Fuzzy_Gen is
for Object_Dir use "obj";
for Exec_Dir use "gen";
for Create_Missing_Dirs use "True";
for Main use ("fuzzy_gen.adb");
end Fuzzy_Gen;

fuzzy_gen.adb:
-------------

with Ada.Calendar,
Ada.Command_Line,
Ada.Directories,
Ada.Text_IO;

procedure Fuzzy_Gen is
use Ada.Command_Line, Ada.Directories, Ada.Text_IO;

procedure Convert (arg : String) is
cfg : constant String := Simple_Name (arg);
cfg_file_name : constant String := "../" & cfg;
ada_unit_name : constant String :=
"fuzzy_" & cfg (cfg'First .. cfg'Last - 4);
ada_file_name : constant String := ada_unit_name & ".adb";
cfg_in, ada_out : File_Type;
use type Ada.Calendar.Time;
begin
if Exists (ada_file_name) and then
Modification_Time (ada_file_name) >=
Modification_Time (cfg_file_name)
then
Put_Line ("Ada file """ & ada_file_name & """ is up to date");
return;
end if;
Put_Line
("Converting """ & cfg & """ into """ & ada_file_name & """...");
Open (cfg_in, In_File, cfg_file_name);
Create (ada_out, Out_File, ada_file_name);
Put_Line
(ada_out, "function " & ada_unit_name & " return String is");
Put_Line (ada_out, "begin");
Put_Line (ada_out, " return """ & Get_Line (cfg_in) & """;");
Put_Line (ada_out, "end;");
Close (cfg_in);
Close (ada_out);
end Convert;


begin
if Argument_Count = 0 then
Put_Line (Current_Error, "config file name missing");
else
Convert (Argument (1));
end if;
end Fuzzy_Gen;

2) The project that generates Ada files ("project B")
=====================================================

code_generation.gpr:
-------------------
project Code_Generation is

for Languages use ("Fuzzy");
for Source_Dirs use (".");
for Object_Dir use "gen";
for Objects_Linked ("Fuzzy") use "False";

package Naming is
for Body_Suffix ("Fuzzy") use ".cfg";
end Naming;

package Compiler is
for Driver ("Fuzzy") use "fuzzy_gen";
end Compiler;

end Code_Generation;

x123.cfg:
--------
123

x456.cfg:
--------
456

x789.cfg:
--------
789

3) The main project (project A)
===============================

main.gpr:
--------
with "code_generation.gpr";

project Main is
for Source_Dirs use (".", "gen");
for Object_Dir use "obj";
for Create_Missing_Dirs use "True";
for Main use ("main.adb");
end Main;

main.adb:
--------
with Ada.Text_IO;
with Fuzzy_X123,
Fuzzy_X456,
Fuzzy_X789;

procedure Main is
begin
Ada.Text_IO.Put
("Messages from elsewhere:" &
" """ & Fuzzy_X123 & '"' &
" """ & Fuzzy_X456 & '"' &
" """ & Fuzzy_X789 & '"');
end;

AdaMagica

unread,
Mar 2, 2023, 9:12:00 AM3/2/23
to
I run all the following from the GPS window, not from a terminal (does this matter?).
I ran this on windows with GNAT CE 2021, one project after the other: OK
Then I changed one of the .cfg files, the main project did not notice the change as you said.
I had to run code_generation alone to recreate from tne new cfg file.
I ran main again: OK
Then i even deleted one of the generated Ada files and reran main: To my surprise, it did not realize that one Ada file is missing.

Project view of Gnat Studio for project main:
Main
> .
>>fuzzy_gen.adb
>> main.adb
>Code_Generation
>>.
>>>x123.cfg
>>>x456.cfg
>>>x789.cfg

Note that the generated Ada files are not shown, subdirectory gen is not shown.
(The > character is used for indentation, the group swallows blanks.)

Perhaps you have to define some surrogate for the .ali (Ada Library Information) files from the .cfg files additionally.

AdaMagica

unread,
Mar 2, 2023, 11:54:04 AM3/2/23
to
Project main seems to completely ignore the with clause for code_generation. I added to main
for Languages use ("Ada", "Fuzzy");
which results in
main.gpr:3:9: warning: there are no sources of language "Fuzzy" in this project

You need to teach gprbuild to look into project code_generation when some Ada files are missing.

I'm very impressed that you can teach gprbuild a new "language".

Simon Wright

unread,
Mar 2, 2023, 5:29:40 PM3/2/23
to
Gautier write-only address <gautier...@hotmail.com> writes:

> When a GNAT project A depends on project B, is there a simple (*) way
> to make gprbuild build project B before starting the build of A? It
> would be useful when project B generates Ada sources…

I know it's copping out, but I've been using an Alire pre-build action:
e.g.

[[actions]]
type = "pre-build"
command = ["make", "Simple_Buttons.gen", "Digital_IO.gen"]

AdaMagica

unread,
Mar 4, 2023, 2:01:17 PM3/4/23
to
package Compiler is
for Driver ("Fuzzy") use "fuzzy_gen";
end Compiler;

I'm still playing around and have problems with the Driver attribute. The documentation says;
>Driver: single, indexed, case-insensitive index
>Index is a language name. Value is the name of the executable for the compiler of the language.
However it does not say where the executable is located, how does gprbuild find it?
I moved fuzzy_gen into another directory and changed accordingly

for Driver ("Fuzzy") use "path/fuzzy_gen";

Now I get
unable to locate fuzzy_gen.

How do I solve this problem?

AdaMagica

unread,
Mar 5, 2023, 1:35:42 PM3/5/23
to
AdaMagica schrieb am Samstag, 4. März 2023 um 20:01:17 UTC+1:
> for Driver ("Fuzzy") use "path/fuzzy_gen";
>
> Now I get
> unable to locate fuzzy_gen.
>
> How do I solve this problem?

excuse me, I made a mistake in the path. Silly me.
0 new messages