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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With