如何让使用GNAT编译的Ada程序导入当前目录以外的文件?

10

我正在一所大学参加编程入门课程,所选的语言是Ada。我在Kate中编写代码,并使用GNAT 4.6.3进行编译。我们必须使用老师提供的程序库来编写程序,就像这样:

with foo;
use  foo;
当然,这意味着文件foo.adb必须与我的源文件保存在同一个目录中。由于多个项目依赖此库,并且我喜欢将每个项目保存在自己的子目录中,因此我必须将库文件复制到每个新项目中。更不用说让我的库代码和源代码都在同一个目录中。
那么有没有什么方法可以做到类似这样:
with ../../lib/foo
use ../../lib/foo

我尝试搜索了一下,但所有的结果都是关于编译器选项的内容。我不想去处理这些选项,特别是因为只有某些项目会需要这个特定的库,所以将其添加到全局编译器设置中并让编译器无意义地搜索不需要搜索的路径是没有意义的。

4个回答

9
我会使用命令行工具gnatmake和GNAT项目进行翻译。
我设置了一个小例子(以确保我的说法是正确的!)。我有3个目录:teacher/包含老师提供的源代码,我假设你不想更改它,也可能没有写入权限;jacks_lib/包含teacher.gpr,它指向teacher/(你也可以把自己的库代码放在那里);jack/包含你的代码main.adbmain.gprjacks_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;

然后,在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

我应该补充一下,我在Mac OS X上使用的是GCC 4.7.0,但这对于任何近期的GNAT都应该能够正常工作。


在以下部分中,我们可以添加多个参数吗: for Source_Dirs use ("../teacher"); - lousycoder
1
@lousycoder,是的,这就是为什么要用括号:("a", "b", "../c") - Simon Wright

6

编译器选项是管理构建源代码位置的方法--定义“搜索路径”的方式,特别是对于基于gcc(如GNAT)和大多数其他编译器的“-I”(包含)选项。

如果您正在从命令行构建,则只需执行以下操作即可:

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

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

如果您正在使用GPS(GNAT编程工具),则打开"项目属性"对话框,选择"源目录"选项卡,并在那里添加搜索路径。(您也可以直接编辑一个"项目属性"文件(".gpr"),但我很少这样做。结果可能因人而异。)编译器设置可以按照每个项目轻松设置,因此不存在需要关注的"全局编译器设置"问题。


很抱歉,我们使用的是一个相当基本的文本编辑器,而不是GPS...我想我可以编写一个bash脚本来处理为我设置命令行选项,或者什么别的吗? - Jack M
如果您可以从命令行调用gnatmake,那么同样可以从脚本中调用它。 - Marc C

4

迄今为止,答案中没有明确提到,所以我要说一下:

在Ada中,withuse子句并不声明使用的单元的位置,只声明它们的存在。

至于如何找到这些单元,完全取决于make脚本、.gpr文件、编译选项或其他你想到的东西。

这就是Ada通过不将代码绑定到目录结构来实现代码可移植性的方式!你只需要正确设置编译选项即可 :)

此外,学习编译器选项几乎永远不是一个坏主意,它会在Ada和许多其他语言中为你服务。


1
是的,使用文件系统作为 GNAT 的库单元实现细节。library units - trashgod

3
扩展@MarcC的答案,GNAT用户指南在第6章中涵盖了gnatmake,属于§6.2 gnatmake的开关:源和库搜索路径开关;此指南应该包含在您的发行版中。

gnatmake命令是make的便捷目标,如此示例所示。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接