home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Geek Gadgets 1
/
ADE-1.bin
/
ade-dist
/
gnat-2.06-src.tgz
/
tar.out
/
fsf
/
gnat
/
ada
/
gnatmake.adb
< prev
next >
Wrap
Text File
|
1996-09-28
|
31KB
|
1,016 lines
------------------------------------------------------------------------------
-- --
-- GNAT COMPILER COMPONENTS --
-- --
-- G N A T M A K E --
-- --
-- B o d y --
-- --
-- $Revision: 1.14 $ --
-- --
-- Copyright (c) 1992,1993,1994,1995 NYU, All Rights Reserved --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
-- ware Foundation; either version 2, or (at your option) any later ver- --
-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
-- for more details. You should have received a copy of the GNU General --
-- Public License distributed with GNAT; see file COPYING. If not, write --
-- to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. --
-- --
------------------------------------------------------------------------------
-- Contents
-- --------
-- Gnatmake usage: summary
-- Smart gnatmake
-- Gnatmake algorithm
-- Gnat flags used in gnatmake
--
--
-- Gnatmake usage: summary (consult gnat documentation for more info)
-- ------------------------------------------------------------------
--
-- gnatmake [-c] [-f] [-g] [-n] [-q] [-s] [-v] [-search dir]
-- unit_or_file_name
-- {[-cargs options] [-bargs options] [-largs options]}
--
-- Automatically (re)compiles the ada sources needed by some ada compilation
-- unit, Unit. Bind and link steps are performed by default.
-- There are two ways to specify the actual compilation unit:
--
-- * By giving the name of the compilation unit ("gnatmake unit")
--
-- * By giving the name of the source containing it
-- ("gnatmake file.adb" or "gnatmake file.ads")
--
-- All gnatmake output is to stderr.
--
-- [-a]
-- Consider all files. Considers all files in the make process, even
-- the GNAT internal system files.
--
-- [-c]
-- Compile only. Do not perform the bind and link steps.
--
-- [-f]
-- Force recompilations. Recompile sources even though some object
-- files may be up to date but don't recompile predifined units if up
-- to date.
--
-- [-g]
-- Compile with debugging information. Same effect as -cargs -g -largs -g.
-- See below for meaning of -cargs & -largs.
--
-- [-n]
-- Don't compile, bind or link. Issue a (maybe innacurate) list of
-- commands without actually executing them by guessing from the old
-- ali (ada library information). If, during the process, any ali file
-- is missing, gnatmake is halted and an error message is emitted.
--
-- [-q]
-- Quiet. Without this flag set the commands carried out by gnatmake
-- are displayed. If -q is set, they are not.
--
-- [-s]
-- Smart. Performs smart recompilations.
-- See section on smart gnatmake below.
--
-- [-v]
-- Verbose. Motivates all (re)compilations (ie gives the reason why it
-- is (re)compiling a source file).
--
-- [-cargs options]
-- Compiler arguments. Without -cargs, gnatmake simply uses "gcc -c"
-- to perform compilations. Otherwise gnatmake uses "gcc -c options".
-- Note that by default "gnatmake -a" (see flag -a above) compiles all
-- GNAT internal files with "gcc -c -gnatg" rather than just "gcc -c".
--
-- [-bargs options]
-- Binder arguments. Without -bargs, gnatmake simply uses
-- "gnatbind unit.ali" to bind. Otherwise gnatmake uses
-- "gnatbind options unit.ali".
--
-- [-largs options]
-- Linker arguments. Without -largs, gnatmake simply uses
-- "gnatbl -linkony unit.ali" to link. Otherwise gnatmake uses
-- "gnatbl -linkonly options unit.ali".
--
-- Smart gnatmake
-- --------------
--
-- Not implemented yet.
--
--
-- gnatmake ALGORITHM
-- ------------------
--
-- gnatmake file.adb
--
-- 1. Insert file.adb in the Queue (Q) and mark it.
--
-- 2. Let unit be the file at the head of the Q. Look at the files under the
-- D (dependency) section of unit.ali. If unit.ali does not exist or some
-- of the time stamps do not match, (re)compile unit.
--
-- 3. Look into the W section of unit.ali (the with section) and insert
-- into the Q all mentioned source files that are not marked.
-- Specifically, assuming that the W section looks like
--
-- W types%s types.adb types.ali
-- W unchecked_deallocation%s
-- W xref_tab%s xref_tab.adb xref_tab.ali
--
-- Then xref_tab.adb and types.adb are inserted in the Q if they are not
-- already marked.
-- Note that there is no file listed under W unchecked_deallocation%s
-- so no generic body should ever be explicitely compiled (unless the
-- file.adb at the start was a generic body).
--
-- 4. Repeat steps 2 and 3 above until the Q is empty
--
-- Note that the above algorithm works because the units withed in subnits
-- are transitively included in the W section (with section) of the main unit.
-- Likewise the withed units in a generic body needed during a compilation
-- are also transitively included in the W section of the originally compiled
-- file.
--
-- Flag Usage in Gnatmake
-- ----------------------
--
-- The flags defined in package Opt, set in package Switch or Initialize
-- and used by Gnatmake are the following:
--
-- * Check_Internal_Files: True when -a present
-- * Compile_Only: True when -c present
-- * Force_Compilations: True when -f present
-- * Dont_Execute: True when -n present
-- * Quiet_Output: True when -q present
-- * Smart_Compilations: True when -s present
-- * Generate_Debug: True when -g present
-- * Verbose_Mode: True when -v present
--
-- The following flags defined in Opt are set explicitely in gnatmake to
-- affect the behavior of routines in ALI, specifically Set_Source_Tables.
--
-- * All_Sources: set to True to require all source files to be present.
-- * Check_Source_Files: set to True to get the actual time stamp of sources.
with ALI; use ALI;
with Binderr; use Binderr;
with Fname; use Fname;
with Gnatvsn; use Gnatvsn;
with Namet; use Namet;
with Opt; use Opt;
with Osint; use Osint;
with GNAT.OS_Lib; use GNAT.OS_Lib;
with Output; use Output;
with Table;
with Types; use Types;
procedure Gnatmake is
-------------------------------------
-- Queue (Q) Manipulation Routines --
-------------------------------------
procedure Init_Q;
-- Must be called to initialize the Q.
procedure Insert_Q (Source_File : File_Name_Type);
-- Inserts Source_File at the end of Q.
function Empty_Q return Boolean;
-- Returns True if Q is empty.
function Extract_From_Q return File_Name_Type;
-- Extracts the first element from the Q.
----------------------
-- Marking Routines --
----------------------
procedure Mark (Ali_File : File_Name_Type);
-- Used to mark an Ali_File. Marking is used to signal that a given source
-- has already been inserted in the Q. Because of the way things are set
-- up in package ALI, we cannot directly mark source files, but have to
-- mark their corresponding Ali_File.
function Is_Marked (Ali_File : File_Name_Type) return Boolean;
-- Returns True if Ali_File was previously marked.
-----------------------------------------
-- Compiler, Binder & Linker Interface --
-----------------------------------------
function Compile (Source_File : File_Name_Type) return Exit_Code_Type;
-- Compiles Source_File and returns the compilation exit code.
function Bind (Ali_File : File_Name_Type) return Exit_Code_Type;
-- Invokes the binder on Ali_File and returns the binder exit code.
function Link (Ali_File : File_Name_Type) return Exit_Code_Type;
-- Invokes the linker on Ali_File and returns the linker exit code.
----------------------------
-- Miscellaneous Routines --
----------------------------
function First_New_Spec (A : ALI_Id) return File_Name_Type;
-- Looks in the with table entries of A and returns the spec file name of
-- the first withed unit (subprogram) for which no spec existed when A was
-- generated but for which there exists one now, implying that A is now
-- obsolete. If no such unit is found No_File is returned. Otherwise the
-- spec file name of the unit is returned.
--
-- **WARNING** in the event of Uname format modifications, one *MUST* make
-- sure this function is also updated.
--
-- This function should really be in ali.adb and use Uname services, but
-- this causes the whole compiler to be dragged along from gnatbind and
-- gnatmake.
function Full_Name (N : File_Name_Type) return Name_Id;
-- Returns the full name of the file whose simple name is N. If the file
-- cannot be located N is returned. The full name includes the appropriate
-- directory information.
procedure Makeusg;
-- Outputs gnatmake usage information.
--------------------------------------
-- Queue (Q) Variables and Routines --
--------------------------------------
-- Our Q implementation uses the GNAT generic table package Table.
-- We basically implement the Q as an array and explicitely keep a
-- pointer (Q_Front below), to indicate the front of the Q. The rear of
-- the Q is implicitly ket by the Table package and accessible through
-- subprogram Last.
--
-- Note that this implementation of the Q can actually use as much as
-- twice the amount of space as the number of elements inserted in the Q.
-- Given the amounts involved it is not worth loosing too much sleep over
-- this.
Q_First : Natural := 0;
-- Points to the first valid element of the Q.
package Queue is new Table (
Table_Component_Type => File_Name_Type,
Table_Index_Type => Natural,
Table_Low_Bound => Q_First,
Table_Initial => 100,
Table_Increment => 100,
Table_Name => "gnatmake.Queue");
-- This is the actual Q.
------------
-- Init_Q --
------------
procedure Init_Q is
begin
Queue.Init;
Queue.Set_Last (Q_First);
end Init_Q;
--------------
-- Insert_Q --
--------------
procedure Insert_Q (Source_File : File_Name_Type) is
begin
Queue.Increment_Last;
Queue.Table (Queue.Last) := Source_File;
end Insert_Q;
-------------
-- Empty_Q --
-------------
function Empty_Q return Boolean is
begin
return Q_First >= Queue.Last;
end Empty_Q;
--------------------
-- Extract_From_Q --
--------------------
function Extract_From_Q return File_Name_Type is
begin
pragma Assert (not Empty_Q);
Q_First := Q_First + 1;
return Queue.Table (Q_First);
end Extract_From_Q;
---------------
-- Is_Marked --
---------------
function Is_Marked (Ali_File : File_Name_Type) return Boolean is
begin
return Get_Name_Table_Info (Ali_File) /= 0;
end Is_Marked;
----------
-- Mark --
----------
procedure Mark (Ali_File : File_Name_Type) is
begin
Set_Name_Table_Info (Ali_File, Int (No_Unit_Id));
end Mark;
----------------------------------------------------
-- Compiler, Binder & Linker Variables & Routines --
----------------------------------------------------
Path : constant String_Access := Getenv ("PATH");
Gcc : constant String_Access :=
GNAT.OS_Lib.Locate_Regular_File ("gcc", Path.all);
Gnatbind : constant String_Access :=
GNAT.OS_Lib.Locate_Regular_File ("gnatbind", Path.all);
Gnatbl : constant String_Access :=
GNAT.OS_Lib.Locate_Regular_File ("gnatbl", Path.all);
function Execute (P : String_Access; Args : Argument_List) return Boolean;
-- Executes a program. P is the full pathname of the executable.
-- Args contains the arguments to be passed to the program P.
-- If the program is executed successfully True is returned.
-------------
-- Execute --
-------------
function Execute (P : String_Access; Args : Argument_List) return Boolean is
Success : Boolean := True;
begin
if not Quiet_Output then
Write_Str (P.all);
for J in Args'Range loop
Write_Str (" ");
Write_Str (Args (J).all);
end loop;
Write_Eol;
end if;
if not Dont_Execute then
GNAT.OS_Lib.Spawn (P.all, Args, Success);
end if;
return Success;
end Execute;
----------
-- Bind --
----------
function Bind (Ali_File : File_Name_Type) return Exit_Code_Type is
Success_Of_Bind : Boolean := False;
Simple_Args : Argument_List (1 .. 1);
Afile : String_Access;
begin
Get_Name_String (Ali_File);
Afile := new String'(Name_Buffer (1 .. Name_Len));
if Binder_Switches.Last < Binder_Switches.First then
Simple_Args (1) := Afile;
Success_Of_Bind := Execute (Gnatbind, Simple_Args);
else
declare
Complex_Args : Argument_List
(Binder_Switches.First .. Binder_Switches.Last + 1);
begin
for I in Binder_Switches.First .. Binder_Switches.Last loop
Complex_Args (I) := Binder_Switches.Table (I);
end loop;
Complex_Args (Binder_Switches.Last + 1) := Afile;
Success_Of_Bind := Execute (Gnatbind, Complex_Args);
end;
end if;
if not Success_Of_Bind then
Osint.Write_Program_Name;
Write_Str (": *** bind failed.");
Write_Eol;
return E_Errors;
else
return E_Success;
end if;
end Bind;
-------------
-- Compile --
-------------
function Compile (Source_File : File_Name_Type) return Exit_Code_Type is
Success_Of_Compilation : Boolean := False;
Sfile : String_Access;
Arg_Count : Positive := 2;
begin
Get_Name_String (Full_Name (Source_File));
Sfile := new String'(Name_Buffer (1 .. Name_Len));
if Gcc_Switches.Last < Gcc_Switches.First then
Arg_Count := 2;
else
Arg_Count :=
2 + Positive (1 + Gcc_Switches.Last - Gcc_Switches.First);
end if;
if Generate_Debug then
Arg_Count := Arg_Count + 1;
end if;
if Is_Language_Defined_Unit (Source_File) then
Arg_Count := Arg_Count + 1;
end if;
declare
Args : Argument_List (1 .. Arg_Count);
Next_Arg : Positive := 2;
begin
Args (1) := new String'("-c");
if Generate_Debug then
Args (Next_Arg) := new String'("-g");
Next_Arg := Next_Arg + 1;
end if;
if Is_Language_Defined_Unit (Source_File) then
Args (Next_Arg) := new String'("-gnatg");
Next_Arg := Next_Arg + 1;
end if;
for J in Gcc_Switches.First .. Gcc_Switches.Last loop
Args (Next_Arg) := Gcc_Switches.Table (J);
Next_Arg := Next_Arg + 1;
end loop;
Args (Next_Arg) := Sfile;
Success_Of_Compilation := Execute (Gcc, Args);
end;
if not Success_Of_Compilation then
Osint.Write_Program_Name;
Write_Str (": *** compilation failed.");
Write_Eol;
return E_Errors;
else
return E_Success;
end if;
end Compile;
----------
-- Link --
----------
function Link (Ali_File : File_Name_Type) return Exit_Code_Type is
Success_Of_Link : Boolean := False;
Afile : String_Access;
Arg_Count : Positive := 2;
begin
Get_Name_String (Ali_File);
Afile := new String'(Name_Buffer (1 .. Name_Len));
if Linker_Switches.Last < Linker_Switches.First then
Arg_Count := 2;
else
Arg_Count :=
2 + Natural (1 + Linker_Switches.Last - Linker_Switches.First);
end if;
if Generate_Debug then
Arg_Count := Arg_Count + 1;
end if;
declare
Args : Argument_List (1 .. Arg_Count);
Next_Arg : Positive := 2;
begin
Args (1) := new String'("-linkonly");
if Generate_Debug then
Args (Next_Arg) := new String'("-g");
Next_Arg := Next_Arg + 1;
end if;
for J in Linker_Switches.First .. Linker_Switches.Last loop
Args (Next_Arg) := Linker_Switches.Table (J);
Next_Arg := Next_Arg + 1;
end loop;
Args (Next_Arg) := Afile;
Success_Of_Link := Execute (Gnatbl, Args);
end;
if not Success_Of_Link then
Osint.Write_Program_Name;
Write_Str (": *** link failed.");
Write_Eol;
return E_Errors;
else
return E_Success;
end if;
end Link;
--------------------
-- First_New_Spec --
--------------------
function First_New_Spec (A : ALI_Id) return File_Name_Type is
Spec_File_Name : File_Name_Type := No_File;
function New_Spec (Uname : Unit_Name_Type) return Boolean;
-- Uname is the name of the spec or body of some ada unit.
-- This function returns True if the Uname is the name of a body
-- which has a spec not mentioned in ali file A. If True is returned
-- Spec_File_Name above is set to the name of this spec file.
function New_Spec (Uname : Unit_Name_Type) return Boolean is
Spec_Name : Unit_Name_Type;
File_Name : File_Name_Type;
begin
-- Test whether Uname is the name of a body unit (ie ends with %b)
Get_Name_String (Uname);
pragma
Assert (Name_Len > 2 and then Name_Buffer (Name_Len - 1) = '%');
if Name_Buffer (Name_Len) /= 'b' then
return False;
end if;
-- Convert unit name into spec name
Name_Buffer (Name_Len) := 's';
Spec_Name := Name_Find;
File_Name := Get_File_Name (Spec_Name);
-- Look if File_Name is mentioned in A's sdep list.
-- If not look if the file exists. If it does return True.
for D in
ALIs.Table (A).First_Sdep .. ALIs.Table (A).Last_Sdep
loop
if Sdep.Table (D).Sfile = File_Name then
return False;
end if;
end loop;
if Full_Source_Name (File_Name) /= No_File then
Spec_File_Name := File_Name;
return True;
end if;
return False;
end New_Spec;
-- Start of processing for First_New_Spec
begin
U_Chk : for U in
ALIs.Table (A).First_Unit .. ALIs.Table (A).Last_Unit
loop
exit U_Chk when New_Spec (Unit.Table (U).Uname);
for W in Unit.Table (U).First_With .. Unit.Table (U).Last_With loop
exit U_Chk when
Withs.Table (W).Afile /= No_File
and then New_Spec (Withs.Table (W).Uname);
end loop;
end loop U_Chk;
return Spec_File_Name;
end First_New_Spec;
---------------
-- Full_Name --
---------------
function Full_Name (N : File_Name_Type) return Name_Id is
Name : constant Name_Id := Full_Source_Name (N);
begin
if Name = No_Name then
return N;
else
return Name;
end if;
end Full_Name;
-------------
-- Makeusg --
-------------
procedure Makeusg is
procedure Write_Switch_Char;
-- Write two spaces followed by appropriate switch character
procedure Write_Switch_Char is
begin
Write_Str (" ");
Write_Char (Switch_Character);
end Write_Switch_Char;
begin
-- Usage line
Write_Str ("Usage: ");
Osint.Write_Program_Name;
Write_Char (' ');
Write_Str ("switches unit[.adb] ");
Write_Str ("{[-cargs opts] [-bargs opts] [-largs opts]}");
Write_Eol;
Write_Eol;
-- Line for -a
Write_Switch_Char;
Write_Str ("a Consider all files, even GNAT internal files");
Write_Eol;
-- Line for -c
Write_Switch_Char;
Write_Str ("c Compile only, do not bind and link");
Write_Eol;
-- Line for -f
Write_Switch_Char;
Write_Str ("f Force recompilations of non predefined units");
Write_Eol;
-- Line for -g
Write_Switch_Char;
Write_Str ("g Compile with debugging information");
Write_Eol;
-- Line for -n
Write_Switch_Char;
Write_Str ("n Just output the commands, don't execute them");
Write_Eol;
-- Line for -q
Write_Switch_Char;
Write_Str ("q Be quiet, do not display the executed commands");
Write_Eol;
-- Line for -s
Write_Switch_Char;
Write_Str ("s Perform smart recompilations");
Write_Eol;
-- Line for -v
Write_Switch_Char;
Write_Str ("v Motivate all (re)compilations");
Write_Eol;
Write_Eol;
-- Line for unit[.adb]
Write_Str (" unit[.adb] Compilation unit name or source file");
Write_Eol;
Write_Eol;
-- Line for -cargs
Write_Switch_Char;
Write_Str ("cargs opts Arguments to be passed to the compiler");
Write_Eol;
-- Line for -bargs
Write_Switch_Char;
Write_Str ("bargs opts Arguments to be passed to the binder");
Write_Eol;
-- Line for -largs
Write_Switch_Char;
Write_Str ("largs opts Arguments to be passed to the linker");
Write_Eol;
Write_Eol;
end Makeusg;
------------------------
-- Gnatmake Variables --
------------------------
Main_Unit_Or_File_Name : Name_Id;
-- The name of the main compilation unit or of the source containing it
Main_Ali_File : File_Name_Type;
-- The ali file corresponding to the unit input to gnatmake
Source_File : File_Name_Type;
-- Current source file
Lib_File : File_Name_Type;
-- Current library file
Afile : File_Name_Type;
-- Contains, in turn, the ali file of the units withed by Source_File
Sfile : File_Name_Type;
-- Contains, in turn, the source file of the units withed by Source_File
Modified_Source : File_Name_Type;
-- The first source in Lib_File whose current time stamp differs
-- from that stored in Lib_File.
New_Spec : File_Name_Type;
-- If Lib_File contains in its W (with) section a body (for a subprogram)
-- for which there exists a spec and the spec did not appear in the Sdep
-- section of Lib_File, New_Spec contains the file name of this new spec.
Objects_Up_To_Date : Boolean := True;
Need_To_Compile : Boolean := False;
Exit_Code : Exit_Code_Type := E_Success;
Text : Text_Buffer_Ptr;
Ali : ALI_Id;
--------------------------------------
-- Start of Processing for Gnatmake --
--------------------------------------
begin
-- Package and Queue initializations. The order of calls is important here.
Output.Set_Standard_Error;
Osint.Initialize (Make);
Namet.Initialize;
Binderr.Initialize_Binderr;
Initialize_ALI;
Init_Q;
-- The following two flags affects the behavior of Set_Source_Table. We set
-- Check_Source_Files to True to ensure that source file time stamps are
-- checked, and we set All_Sources to False to avoid checking the presence
-- of the source files listed in the source dependency section of an ali
-- file (which would be a mistake since the ali file may be obsolete).
Check_Source_Files := True;
All_Sources := False;
if Verbose_Mode then
Write_Eol;
Write_Str ("NYU GNAT Make Version ");
Write_Str (Gnat_Version_String);
Write_Str (" (C) NYU, 1995 All Rights Reserved");
Write_Eol;
end if;
-- Output usage information if more than one file or compile unit
if Number_Of_Files = 0 then
Makeusg;
Exit_Program (E_Fatal);
elsif Number_Of_Files > 1 then
Osint.Write_Program_Name;
Write_Str (": error, only one source or compilation unit allowed.");
Write_Eol;
Exit_Program (E_Fatal);
end if;
-- ??? get rid of the following when smart compilation is implemented
if Smart_Compilations then
Osint.Write_Program_Name;
Write_Str (": WARNING smart recompilation not yet implemented.");
Write_Eol;
end if;
-- If check only warn the user the list of files to recompile is tentative
if Dont_Execute then
Osint.Write_Program_Name;
Write_Str (": providing a *tentative* list of commands");
Write_Eol;
end if;
-- Now check if the user input a file or compilation unit name. If it is a
-- compilation unit name first check the existence of the source file for
-- the compilation unit body. If the file for the body of the compilation
-- unit does not exist try the spec.
Main_Unit_Or_File_Name := Next_Main_Source;
if Is_File_Name (Main_Unit_Or_File_Name) then
Source_File := Main_Unit_Or_File_Name;
else
Source_File := File_Name_Of_Body (Main_Unit_Or_File_Name);
if Full_Source_Name (Source_File) = No_Name then
Source_File := File_Name_Of_Spec (Main_Unit_Or_File_Name);
if Full_Source_Name (Source_File) = No_Name then
Osint.Write_Program_Name;
Write_Str (": no file found for body or spec of """);
Write_Name (Main_Unit_Or_File_Name);
Write_Char ('"');
Write_Eol;
Exit_Program (E_Fatal);
end if;
end if;
end if;
-- Consider GNAT predefined files only if -a switch is set.
if Is_Language_Defined_Unit (Source_File)
and then not Check_Internal_Files
then
Osint.Write_Program_Name;
Write_Str (": use the -a switch to compile GNAT predefined files");
Write_Eol;
Exit_Program (E_Fatal);
end if;
-- The gnatmake algorithm starts here.
Main_Ali_File := Osint.Lib_File_Name (Source_File);
Insert_Q (Source_File);
Mark (Main_Ali_File);
Make_Loop : while not Empty_Q loop
Need_To_Compile := False;
Source_File := Extract_From_Q;
Lib_File := Lib_File_Name (Source_File);
if Verbose_Mode then
Write_Str ("Checking --> ");
Write_Name (Full_Name (Source_File));
Write_Eol;
end if;
Text := Read_Library_Info (Lib_File, Fatal_Err => False);
if Dont_Execute and then Text = null then
Osint.Write_Program_Name;
Write_Str (" -n: cannot find """);
Write_Name (Lib_File);
Write_Str (""" *tentative* check aborted.");
Write_Eol;
Exit_Program (E_Fatal);
end if;
if Text = null then
Need_To_Compile := True;
if Verbose_Mode then
Write_Str (" """);
Write_Name (Lib_File);
Write_Str (""" not found. **Recompile**");
Write_Eol;
end if;
else
Ali := Scan_ALI (Lib_File, Text);
Set_Source_Table (Ali);
-- get the source files and their time stamps. Note that some sources
-- may be missing is Ali is out-of-date.
Modified_Source := Time_Stamp_Mismatch (Ali);
if Modified_Source /= No_File then
Need_To_Compile := True;
if Verbose_Mode then
Write_Str (" """);
Write_Name (Full_Name (Modified_Source));
Write_Str (""" time stamp mismatch. **Recompile**");
Write_Eol;
end if;
else
New_Spec := First_New_Spec (Ali);
if New_Spec /= No_File then
Need_To_Compile := True;
if Verbose_Mode then
Write_Str (" """);
Write_Name (Full_Name (New_Spec));
Write_Str (""" new spec. **Recompile**");
Write_Eol;
end if;
end if;
end if;
end if;
if Need_To_Compile or Force_Compilations then
Objects_Up_To_Date := False;
Exit_Code := Compile (Source_File);
if Exit_Code /= E_Success then
exit Make_Loop;
end if;
-- Re-read the updated library file
Text := Read_Library_Info (Lib_File, Fatal_Err => False);
if Text /= null then
Ali := Scan_ALI (Lib_File, Text);
end if;
end if;
-- Now insert in the Queue the unmarked source files (i.e. those which
-- have neever been inserted in the Queue and hance never considered).
if Text /= null then
for J in
ALIs.Table (Ali).First_Unit .. ALIs.Table (Ali).Last_Unit
loop
for K in Unit.Table (J).First_With .. Unit.Table (J).Last_With loop
Afile := Withs.Table (K).Afile;
Sfile := Withs.Table (K).Sfile;
-- Never consider generics (Afile /= No_File).
-- Consider GNAT internal files only if -a switch is set.
if Afile /= No_File
and then not Is_Marked (Afile)
and then (not Is_Language_Defined_Unit (Sfile)
or else Check_Internal_Files)
then
Insert_Q (Sfile);
Mark (Afile);
end if;
end loop;
end loop;
end if;
end loop Make_Loop;
if Objects_Up_To_Date
and then Exit_Code = E_Success
then
Osint.Write_Program_Name;
Write_Str (": sources up to date. No recompilations needed.");
Write_Eol;
end if;
if Exit_Code = E_Success and then not Compile_Only then
Exit_Code := Bind (Main_Ali_File);
if Exit_Code = E_Success then
Exit_Code := Link (Main_Ali_File);
end if;
end if;
Finalize_Binderr;
Namet.Finalize;
if Exit_Code /= E_Success then
Osint.Write_Program_Name;
Write_Str (": *** make failed.");
Write_Eol;
end if;
Exit_Program (Exit_Code);
exception
when others =>
Osint.Write_Program_Name;
Write_Str (": internal error. Please report to gnat-report@cs.nyu.edu");
Write_Eol;
Osint.Write_Program_Name;
Write_Str (": *** make failed.");
Write_Eol;
Exit_Program (E_Fatal);
end Gnatmake;