Get Ada (compiled with GNAT) to import files from outside current directory?
Asked Answered
E

4

9

I'm doing an intro to programming course at university, and the language of choice is Ada. I'm coding in Kate and compiling with GNAT 4.6.3. We have to use teacher-provided libraries for our programs, like so:

with foo;
use  foo;

Of course, then the file foo.adb has to be contained in the same directory as my source file. Since multiple projects depend on this one library, and I like to keep each project in its own subdirectory, I have to copy the library files into each new project. Not to mention have my library code and source code all in the same directory.

So is there any way to sort of go:

with ../../lib/foo
use ../../lib/foo

?

I've tried looking around a bit but all I've found is stuff about compiler options. I'd rather not have to mess around with those, especially because only certain projects are going to be requiring this particular library, so it wouldn't make sense to add it to a global compiler setting and have the compiler pointlessly searching paths it doesn't need to search.

Emmittemmons answered 25/9, 2012 at 12:17 Comment(0)
I
8

I would use the GNAT Project facility with command-line gnatmake.

I just set up a little example (so I can be sure what I say works!). I have 3 directories; teacher/ contains the teacher-provided source, which I assume you won't want to change and may not have write access to anyway, jacks_lib/ contains teacher.gpr which points to teacher/ (you could put your own library code there as well) and jack/ contains your code main.adb and main.gpr.

jacks_lib/teacher.gpr:

project Teacher is
   --  This project calls up the teacher-supplied source.

   --  This is a list of paths, which can be absolute but
   --  if relative are relative to the directory where this .gpr
   --  is found.
   for Source_Dirs use ("../teacher");

   --  Keep the built objects (.ali, .o) out of the way. Use the -p
   --  gnatmake flag to have directories like this built
   --  automatically.
   for Object_Dir use ".build";
end Teacher;

jack/main.gpr:

--  teacher.gpr tells where to find library source and how to build it.
with "../jacks_lib/teacher";

project Main is
   --  for Source_Dirs use ("."); (commented out because it's the default)

   --  Keep built objects out of the way
   for Object_Dir use ".build";

   --  Build executables here rather than in Object_Dir
   for Exec_Dir use ".";

   --  What's the main program? (there can be more than one)
   for Main use ("main.adb");
end Main;

jack/main.adb:

with Foo;
procedure Main is
begin
   null;
end Main;

Then, in jack/,

$ gnatmake -p -P main.gpr
object directory "/Users/simon/tmp/jacks_lib/.build" created for project teacher
object directory "/Users/simon/tmp/jack/.build" created for project main
gcc -c -I- -gnatA /Users/simon/tmp/jack/main.adb
gcc -c -I- -gnatA /Users/simon/tmp/teacher/foo.ads
gnatbind -I- -x /Users/simon/tmp/jack/.build/main.ali
gnatlink /Users/simon/tmp/jack/.build/main.ali -o /Users/simon/tmp/jack/main

I should add that I'm using GCC 4.7.0 on Mac OS X, but this should work fine with any recent GNAT.

Induration answered 25/9, 2012 at 17:21 Comment(2)
Can we add multiple arguments in the following portion: for Source_Dirs use ("../teacher");Insurmountable
@lousycoder, yes, that’s why the parens: ("a", "b", "../c")Induration
F
5

Compiler options are the way you manage source code locations for a build--defining "search paths"--particularly the "-I" (include) option for gcc-based (like GNAT) and most other compilers.

If you're building from the command line, it's simply a matter of:

gnatmake -I../../lib/foo -Iother/path -Iyet/another/path project1_main.adb

gnatmake -I../../lib/foo -Isome/path -Iyet/another/path project2_main.adb

If you're using GPS (GNAT Programming Studio), then open the Project Properties dialog, select the Source dirs tab, and add the search paths there. (You can also directly edit a Project Properties file (".gpr") directly, but I rarely do that. YMMV.) Compiler settings are easily set up on a per-project basis, so there's no "global compiler setting" issue with which one would have to concern themself.

Fetter answered 25/9, 2012 at 13:0 Comment(2)
I'm afraid we're using a pretty bare bones text editor, not GPS... I guess I could write a bash script to handle setting the command line options for me, or something?Emmittemmons
If you can invoke gnatmake from the command line, you can equally well invoke it from a script.Fetter
C
4

Its not been explicitly mentioned in the answers sofar, so I will say it:

The with & use clauses in Ada make no claims about the location of the withed & used units, only that they exist.

When it comes to actually finding the units, that is entirely up to the make scripts & .gpr files & compilation options or whatever else you come up with.

This is how Ada creates a degree of code portability (by not binding the code to a directory structure!), You just need to correct the compilation options :)

Also, learning about compiler options is almost never a bad idea, it will serve you well in Ada & many other languages.

Corroboree answered 26/9, 2012 at 8:9 Comment(1)
Yes, is an implementation detail that GNAT uses the file system for library units.Coprolalia
C
2

Amplifying on @MarcC's answer, the GNAT User's Guide covers gnatmake in chapter 6, under §6.2 Switches for gnatmake: Source and library search path switches; the guide should be included with your distribution.

The gnatmake command is a convenient target for make, as shown in this example.

Coprolalia answered 25/9, 2012 at 16:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.