From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-0.8 required=5.0 tests=BAYES_00,INVALID_DATE autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,91a8e5a9a6030be9,start X-Google-Attributes: gid103376,public X-Google-ArrivalTime: 1995-01-07 18:14:21 PST Path: nntp.gmd.de!newsserver.jvnc.net!howland.reston.ans.net!pipex!uunet!zib-berlin.de!informatik.tu-muenchen.de!news.muc.de!waporo.muc.de!waporo!re From: re@waporo.muc.de (Rolf Ebert) Newsgroups: comp.lang.ada Subject: Finally there is a real gnatmake Followup-To: comp.lang.ada Date: 8 Jan 1995 03:14:21 +0100 Organization: Rolf Ebert Distribution: world Message-ID: Date: 1995-01-08T03:14:21+01:00 List-Id: The discussion about Makefiles when using GNAT keeps popping up in this newsgroup. After getting tired to maintain my Makefiles by hand (every time gnatbind complained about out of date files, I had to modify the Makefile accordingly), I finaly wrote this perl script. Robert Dewar told us several times, how a real gnatmake should work using the .ali files, but nobody ever wrote one. Even gnat-2.0 did not contain one. Here you get it. I threw this together in not even two hours in the middle of the night. There was only some limited testing. Don't be astonished, if you find a bug. Kill it and tell me about it. Rolf #!/usr/bin/perl # -*- Mode: Perl -*- # Filename : gnatmake # Description : faciliate make with GNAT # Author : Rolf Ebert # Created On : Sun Jan 8 00:25:31 1995 # Last Modified By: Rolf Ebert # Last Modified On: Sun Jan 8 02:21:02 1995 # Update Count : 20 # Status : Unknown, Use with caution! # # Copyright (C) 1995 Rolf Ebert (Rolf.Ebert@waporo.muc.de) # # $Revision: 1.1 $ # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # # USAGE # ===== # # gnatmake [-v] [-n] [gcc-opts] main # -v : verbose # -n : no action # -k : continue on error # gcc-opts : other options passed to gcc # main : name of the main program # # With the '-v' option, GNATMAKE tells you where it currently searches # for out of date dependencies. It furthermore tells you, why a given # file is going to be recompiled. # # '-n' and '-k' correspond to the standard make options. Analysis is # done, but no action is taken with '-n'. Compilation continues # despite a failed compilation with '-k'. # # All other options are passed on to 'gcc'. The 'gcc' option '-v' is # hidden by the gnatmake '-v'. # # As the last parameter give the name of the main unit. This must be # the filename without an extension. # # # PURPOSE # ======= # # GNATMAKE replaces the hard to maintain parts of a Makefile, if you # use it together with the GNU Ada compiler GNAT. GNAT generates at # each compilation a supplementary file with the extension .ali (see # the GNAT documentation for more details). This file contains # information, on which other files the just compiled unit depends. # GNATMAKE uses this information to traverse the whole closure of the # main unit. # # GNATMAKE does not replace the need for a Makefile. GNATMAKE does # not do the final binding, nor can it compile files of another # programming language. # # # PROBLEMS # ======== # # How do I avoid attempts to compile "separates" ? # # There is no way to tell from the filename if a given dependency is a # child unit or a "separate"d part of the body. GNATMAKE assumes it is # a child, and tries to compile it. GNAT will tell you that it # could not generate code for that unit, if is was a "separate". # # There is no .ali for generic units. If this unit depends on other # units, which are not mentioned anywhere else, your project will stay # incomplete. # # GNATMAKE will try to compile the bodyfile, if there is one. # If there is a body file for a package, that must not have one, you # will get an error. # # # CODE # # some constants and start values $gnat = "gcc"; $ali = ".ali"; $obj = ".o"; $specext = ".ads"; $bodyext = ".adb"; # # these are the files I cannot catch with a regexp # $gnatlibfiles = "ada.ads system.ads system.adb unchdeal.ads unchdeal.adb"; $gnatlibfiles .= "unchconv.ads interfac.ads text_io.ads sequenio.ads gnat.ads"; $gnatlibfiles .= "ioexcept.ads calendar.ads directio.ads"; # # options handling # $exclude_glib = 1; while (@ARGV && $ARGV[0] =~ /^-(.)/) { if ($1 eq 'v') { $opt_v = 1; } elsif ($1 eq 'n') { $opt_n = 1; } elsif ($1 eq 'k') { $opt_k = 1; } else { $opt_gcc .= $ARGV[0]; } shift(@ARGV); } if ($#ARGV < 0) { print "$0 [-v] [-n] [gcc-opts] main\n"; print " -v : verbose\n"; print " -n : no action\n"; print " -k : continue on error\n"; print " gcc-opts : other options passed to gcc\n"; print " main : name of the main program\n"; exit (1); } sub COMPILE { local ($source) = pop (@_); $commandline = $gnat . " -c " . $opt_gcc . " " . $source; print $commandline, "\n"; if (! $opt_n) { $err = system ($commandline) / 256; if (! $opt_k && $err) { exit ($err); } } } sub UPDATE { local ($main) = pop (@_); local (@deps); $level++; # print "DEBUG: level = $level\n"; if ($updated{$main}) { # print "DEBUG: avoided branch $main.\n"; } else { if ($opt_v) { print "analyzing \"$main\".\n"; } # # get system information about the files # # take the date of the object file instead of the ALI. There is not # necessarily an ALI for generic packages ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime_ali,$blksize,$blocks) = stat($main . $obj); ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime_bdy,$blksize,$blocks) = stat($main . $bodyext); ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime_spc,$blksize,$blocks) = stat($main . $specext); # print "DEBUG: $main ctime ALI = $ctime_ali\n"; # print "DEBUG: $main ctime BODY = $ctime_bdy\n"; # print "DEBUG: $main ctime SPEC = $ctime_spc\n"; # # recompile, if SPEC or BODY are more recent than ALI. # $recompile = 1; if ($ctime_bdy > $ctime_ali || $ctime_spc > $ctime_ali) { if ($ctime_bdy < 1) { # there is no BODY &COMPILE ($main . $specext); } else { &COMPILE ($main . $bodyext); } $recompile = 0; } # # now we can be sure an ALI exists. # open (ALI, $main . $ali); while () { chop; ($flag, $file, $time) = split; if ($flag eq "D") { # gnatlib files are supposed to be up to date if ($exclude_glib && ($file =~ m/^(s|a|i|g)-/ || index ($gnatlibfiles,$file) >= 0)) { # print "DEBUG: gnatlib file excluded.\n"; } else { # print "DEBUG: \"$main\" depends on \"$file\"\n"; push (@deps, $file); } } } close (ALI); # # is any of the DEPS files more recent than the ALI? # if ($recompile) { $recompile = 0; foreach $file (@deps) { ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime_file,$blksize,$blocks) = stat($file); if ($ctime_file > $ctime_ali) { $recompile = 1; if ($opt_v) { print "GNATMAKE: "; print "\"$main\" must be recompiled because of "; print "\"$file\".\n"; } } } } if ($recompile) { if ($ctime_bdy < 1) { # there is no BODY &COMPILE ($main . $specext); } else { &COMPILE ($main . $bodyext); } } $updated{$main} = 1; foreach $file (@deps) { $file = substr ($file, 0, rindex ($file, ".")); &UPDATE ($file); } } $level--; } # end UPDATE &UPDATE ($ARGV[0]); 1; # gnatmake ends here -- Rolf Ebert Beratung fuer Energiesysteme und Informatik Erich Kaestner Str. 17 Conseil en Energetique et Informatique D - 80796 Muenchen (Team Ada) Tel.: +49-89-30.77.88.00 Germany Fax.: +49-89-30.77.91.00