How to create a local ADA Library with GPS?

Viewed 204

I installed GPS and ADA and stated ready a couple of books ant looking at websites on Internet.

After doing a few of exercises, I transformed a couple to a local library since they where constantly used in further chapters.

I do not see (understand?) How I can setup a local library in the project file of the exercises.

Directory structure of my test environment:
Directory structure of my test environment

The file Test01 uses Basic_IO and Test02 uses Both Basic_IO and the generic Basic_Stack.

Here is the project file for Test01: test01.adb

Can someone explain to me how to get setup the lib so the program would compile and link?

2 Answers

The trick is to create seperate project files (.gpr files) for Basic_IO and Basic_Stack and reference these project files (using with) in your test project files. You might want to take a look on learn.adacore.com and in the GPRbuild user’s guide. I would also change the directory structure to (something like) this:

|
+-- learning_ada.gpr
|
+-- tests/
|   |
|   +-- test01/
|   |   |
|   |   +-- test01.gpr  
|   |   +-- obj/
|   |   +-- src/
|   |       |
|   |       +-- test01.adb
|   |      
|   +-- test02/
|       |
|       +-- test02.gpr  
|       +-- obj/
|       +-- src/
|           |
|           +-- test02.adb
|
+-- shared/
    |
    +-- basic_io/
    |   |
    |   +-- basic_io.gpr  
    |   +-- obj/
    |   +-- src/
    |       |
    |       +-- basic_io.ads
    |       +-- basic_io.adb
    |      
    +-- basic_stack/
        |
        +-- basic_stack.gpr  
        +-- obj/
        +-- src/
            |
            +-- basic_stack.ads
            +-- basic_stack.adb

The "library" projects could (in your case) remain quite simple. As an example, for Basic_IO, I'm pretty sure that something like

basic_io.gpr

project Basic_IO is
   for Source_Dirs use ("src");
   for Object_Dir use "obj";
end Basic_IO;

could already work. This project can then be referenced from test01.gpr using

test01.gpr

with "..\..\shared\basic_io\basic_io.gpr";

project Test01 is
   for Source_Dirs use ("src");
   for Object_Dir use "obj";
   for Main use ("test01.adb");
end Test01;

First of all, your library's gpr file should specify that it is a library, for example:

library project Some_Library_Name is
   for Languages use ("Ada");
   for Source_Dirs use ("src");
   for Library_Name use "Some_Library_Name";
   for Library_Version use "1.0.0";
end Some_Library_Name;

Next, you need to add a with Some_Library.gpr statement to your client's gpr file. There are three ways to do is, in order of increasing initial complexity but also long-term utility.

Relative dir (simplest)

You can with Some_Dir/Another_Dir/library.gpr specifying the directory from the client's gpr file to the library's gprfile. If this means going up with .. that qualifies as a rather pungent code smell.

Through GPR_PROJECT_PATH

To find the gprfile specified above, gprbuild will look in the current directory of the client gprfile, and in each directory given in GPR_PROJECT_PATH. You can find more information on this method in AdaCore's own documentation of this variable.

For instance, if you had C:/ada_projects or ~/ada_projects defined, and inside that were several libraries, you might add to your client.gpr file:

with Library_One/lib1.gpr

Or if you added each individual library's own directory to GPR_PROJECT_PATH, you would omit Library_One from the above.

If in resolving the with statement there are multiple matches, compilation will fail. (Thank you, Ada!)

Note this was previously called ADA_PROJECT_PATH, which still works but is deprecated.

Alire Ada package manager (most flexible)

There are some problems with the above; it requires you to set things per-machine (or per-user) which, when you add a new developer to your team or need to set up a new computer, you will quickly run into as your projects won't compile until that is done. Next, you will run into versioning problems because you never wrote down which version of said libraries you were building against. Finally, even if you meticulously record that and inform your development team, you will still run into problems when you return to an old project after creating some new ones, and you find you want to use two different versions of the same library, which isn't possible with this approach.

Alire solves this in a similar way to Rust's cargo, python's pip, C#'s NuGet, Haskell's stackage and no doubt many others, by placing the library inside your client's directory, adding each library's root to GPR_PROJECT_PATH, building the project, and then resetting the environment again. If you have an online environment and only want to use, not publish alire package, then you don't need to know the details, you just add with Project_File.gpr (without relative directory) and run alr build instead of gprbuild.

Alire makes you record the version you want of each library, and allows for multiple versions of the same library being used in different projects, and even indirectly in the same project; i.e. library1 and library2 refer to different versions of sublibrary_foo, and your client can now include both library1 and library2; if it needs sublibrary_foo, it must include it itself or specifically include the version under library1 or library2.

AdaCore is working on support in GNATStudio (the new name for GPS 20 and beyond), in the meantime you can just run alr build from the commandline.

See the official website for more about Alire.

Related