aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/makegpr.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/makegpr.adb')
-rw-r--r--gcc/ada/makegpr.adb1415
1 files changed, 926 insertions, 489 deletions
diff --git a/gcc/ada/makegpr.adb b/gcc/ada/makegpr.adb
index 5947f19..d818ff2 100644
--- a/gcc/ada/makegpr.adb
+++ b/gcc/ada/makegpr.adb
@@ -66,15 +66,14 @@ package body Makegpr is
-- sources and the C++ compiler is not g++.
No_Argument : constant Argument_List := (1 .. 0 => null);
+ -- Null argument list representing case of no arguments
FD : Process_Descriptor;
-- The process descriptor used when invoking a non GNU compiler with -M
-- and getting the output with GNAT.Expect.
- Line_Matcher : constant Pattern_Matcher :=
- Compile ("^.*?\n", Single_Line);
- -- The pattern when using GNAT.Expect for the invocation of a non GNU
- -- compiler with -M.
+ Line_Matcher : constant Pattern_Matcher := Compile ("^.*?\n", Single_Line);
+ -- Pattern for GNAT.Expect for the invocation of a non GNU compiler with -M
Name_Ide : Name_Id;
Name_Compiler_Command : Name_Id;
@@ -85,11 +84,11 @@ package body Makegpr is
-- True when switch -u is used on the command line
type Source_Index_Rec is record
- Id : Other_Source_Id;
- Found : Boolean := False;
+ Project : Project_Id;
+ Id : Other_Source_Id;
+ Found : Boolean := False;
end record;
- -- Used as component of Source_Indexes, to check if an archive need to
- -- be rebuilt.
+ -- Used as Source_Indexes component to check if archive needs to be rebuilt
type Source_Index_Array is array (Positive range <>) of Source_Index_Rec;
type Source_Indexes_Ref is access Source_Index_Array;
@@ -127,8 +126,7 @@ package body Makegpr is
Copyright_Output : Boolean := False;
Usage_Output : Boolean := False;
- -- Flags to avoid multiple displays of the Copyright notice and of the
- -- Usage.
+ -- Flags to avoid multiple displays of Copyright notice and of Usage
Output_File_Name : String_Access := null;
-- The name given after a switch -o
@@ -156,8 +154,7 @@ package body Makegpr is
Binder_String 'Access,
Linker_String 'Access);
Packages_To_Check : constant String_List_Access := List_Of_Packages'Access;
- -- List of the packages to be checked when parsing/processing project
- -- files.
+ -- List of the packages to be checked when parsing/processing project files
Main_Project : Project_Id;
-- The project id of the main project
@@ -300,6 +297,8 @@ package body Makegpr is
-- Used when Keep_Going is True (switch -k) to keep the total number
-- of compilation/linking errors, to report at the end of execution.
+ Need_To_Rebuild_Global_Archive : Boolean := False;
+
Error_Header : constant String := "*** ERROR: ";
-- The beginning of error message, when Keep_Going is True
@@ -335,12 +334,13 @@ package body Makegpr is
-- Current_Processor and Current_Language.
procedure Add_Search_Directories
- (Data : Project_Data; Language : Programming_Language);
+ (Data : Project_Data;
+ Language : Programming_Language);
-- Either add to the Arguments the necessary -I switches needed to
-- compile, or, when compiler is gcc/g++, set up the C*INCLUDE_PATH
-- environment variable, if necessary.
- procedure Add_Source_Id (Id : Other_Source_Id);
+ procedure Add_Source_Id (Project : Project_Id; Id : Other_Source_Id);
-- Add a source id to Source_Indexes, with Found set to False
procedure Add_Switches
@@ -352,11 +352,21 @@ package body Makegpr is
-- or language (attribute Default_Switches), coming from package Compiler
-- or Linker (depending on Proc) of a specified project file.
- procedure Build_Archive (Project : Project_Id; Unconditionally : Boolean);
- -- Build the archive for a specified project. If Unconditionally is
- -- False, first check if the archive is up to date, and build it only
+ procedure Build_Global_Archive;
+ -- Build the archive for the main project
+
+ procedure Build_Library (Project : Project_Id; Unconditionally : Boolean);
+ -- Build the library for a library project. If Unconditionally is
+ -- False, first check if the library is up to date, and build it only
-- if it is not.
+ procedure Check (Option : String);
+ -- Check that a switch coming from a project file is not the concatenation
+ -- of several valid switch, for example "-g -v". If it is, issue a warning.
+
+ procedure Check_Archive_Builder;
+ -- Check if the archive builder (ar) is there
+
procedure Check_Compilation_Needed
(Source : Other_Source;
Need_To_Compile : out Boolean);
@@ -370,6 +380,7 @@ package body Makegpr is
(Source_Id : Other_Source_Id;
Data : Project_Data;
Local_Errors : in out Boolean);
+ -- Compile one non-Ada source
procedure Compile_Individual_Sources;
-- Compile the sources specified on the command line, when in
@@ -390,7 +401,10 @@ package body Makegpr is
procedure Create_Archive_Dependency_File
(Name : String;
First_Source : Other_Source_Id);
- -- ??? needs comment
+ -- Create the archive dependency file for a library project
+
+ procedure Create_Global_Archive_Dependency_File (Name : String);
+ -- Create the archive depenency file for the main project
procedure Display_Command
(Name : String;
@@ -419,6 +433,12 @@ package body Makegpr is
-- Do the necessary package initialization and process the command line
-- arguments.
+ function Is_Included_In_Global_Archive
+ (Object_Name : Name_Id;
+ Project : Project_Id) return Boolean;
+ -- Return True if the object Object_Name is not overridden by a source
+ -- in a project extending project Project.
+
procedure Link_Executables;
-- Link executables
@@ -434,7 +454,7 @@ package body Makegpr is
-- Process one command line argument
function Strip_CR_LF (Text : String) return String;
- -- Needs comment ???
+ -- Remove characters ASCII.CR and ASCII.LF from a String
procedure Usage;
-- Display the usage
@@ -462,6 +482,103 @@ package body Makegpr is
Imported : Project_List;
Prj : Project_Id;
+ procedure Add_Archive_Path;
+ -- For a library project or the main project, add the archive
+ -- path to the arguments.
+
+ ----------------------
+ -- Add_Archive_Path --
+ ----------------------
+
+ procedure Add_Archive_Path is
+ Increment : Positive;
+ Prev_Last : Positive;
+
+ begin
+ if Data.Library then
+
+ -- If it is a library project file, nothing to do if
+ -- gnatmake will be invoked, because gnatmake will take
+ -- care of it, even if the library is not an Ada library.
+
+ if not For_Gnatmake then
+ if Data.Library_Kind = Static then
+ Add_Argument
+ (Get_Name_String (Data.Library_Dir) &
+ Directory_Separator &
+ "lib" & Get_Name_String (Data.Library_Name) &
+ '.' & Archive_Ext,
+ Verbose_Mode);
+
+ else
+ -- As we first insert in the reverse order,
+ -- -L<dir> is put after -l<lib>
+
+ Add_Argument
+ ("-l" & Get_Name_String (Data.Library_Name),
+ Verbose_Mode);
+
+ Get_Name_String (Data.Library_Dir);
+
+ Add_Argument
+ ("-L" & Name_Buffer (1 .. Name_Len),
+ Verbose_Mode);
+
+ -- If there is a run path option, prepend this
+ -- directory to the library path. It is probable
+ -- that the order of the directories in the path
+ -- option is not important, but just in case
+ -- put the directories in the same order as the
+ -- libraries.
+
+ if Path_Option /= null then
+
+ -- If it is not the first directory, make room
+ -- at the beginning of the table, including
+ -- for a path separator.
+
+ if Lib_Path.Last > 0 then
+ Increment := Name_Len + 1;
+ Prev_Last := Lib_Path.Last;
+ Lib_Path.Set_Last (Prev_Last + Increment);
+
+ for Index in reverse 1 .. Prev_Last loop
+ Lib_Path.Table (Index + Increment) :=
+ Lib_Path.Table (Index);
+ end loop;
+
+ Lib_Path.Table (Increment) := Path_Separator;
+
+ else
+ -- If it is the first directory, just set
+ -- Last to the length of the directory.
+
+ Lib_Path.Set_Last (Name_Len);
+ end if;
+
+ -- Put the directory at the beginning of the
+ -- table.
+
+ for Index in 1 .. Name_Len loop
+ Lib_Path.Table (Index) := Name_Buffer (Index);
+ end loop;
+ end if;
+ end if;
+ end if;
+
+ -- For a non-library project, the only archive needed
+ -- is the one for the main project.
+
+ elsif Project = Main_Project then
+ Add_Argument
+ (Get_Name_String (Data.Object_Directory) &
+ Directory_Separator &
+ "lib" & Get_Name_String (Data.Name) &
+ '.' & Archive_Ext,
+ Verbose_Mode);
+ end if;
+ end Add_Archive_Path;
+
begin
-- Nothing to do when there is no project specified
@@ -499,100 +616,17 @@ package body Makegpr is
-- If there is sources of language other than Ada in this
-- project, add the path of the archive to Arguments.
- if Data.Sources_Present then
- if Data.Library then
-
- -- If it is a library project file, nothing to do if
- -- gnatmake will be invoked, because gnatmake will take
- -- care of it, even if the library is not an Ada library.
-
- if not For_Gnatmake then
- if Data.Library_Kind = Static then
- Add_Argument
- (Get_Name_String (Data.Library_Dir) &
- Directory_Separator &
- "lib" & Get_Name_String (Data.Library_Name) &
- '.' & Archive_Ext,
- Verbose_Mode);
-
- else
- -- As we first insert in the reverse order,
- -- -L<dir> is put after -l<lib>
-
- Add_Argument
- ("-l" & Get_Name_String (Data.Library_Name),
- Verbose_Mode);
-
- Get_Name_String (Data.Library_Dir);
-
- Add_Argument
- ("-L" & Name_Buffer (1 .. Name_Len),
- Verbose_Mode);
-
- -- If there is a run path option, prepend this
- -- directory to the library path. It is probable
- -- that the order of the directories in the path
- -- option is not important, but just in case
- -- put the directories in the same order as the
- -- libraries.
-
- if Path_Option /= null then
- -- If it is not the first directory, make room
- -- at the beginning of the table, including
- -- for a path separator.
-
- if Lib_Path.Last > 0 then
- declare
- Increment : constant Positive :=
- Name_Len + 1;
- Prev_Last : constant Positive :=
- Lib_Path.Last;
-
- begin
- Lib_Path.Set_Last (Prev_Last + Increment);
-
- for Index in reverse 1 .. Prev_Last loop
- Lib_Path.Table (Index + Increment) :=
- Lib_Path.Table (Index);
- end loop;
-
- Lib_Path.Table (Increment) :=
- Path_Separator;
- end;
-
- else
- -- If it is the first directory, just set
- -- Last to the length of the directory.
-
- Lib_Path.Set_Last (Name_Len);
- end if;
-
- -- Put the directory at the beginning of the
- -- table.
-
- for Index in 1 .. Name_Len loop
- Lib_Path.Table (Index) := Name_Buffer (Index);
- end loop;
- end if;
- end if;
- end if;
-
- else
- -- For a non library project, just add the path name of
- -- the archive.
-
- Add_Argument
- (Get_Name_String (Data.Object_Directory) &
- Directory_Separator &
- "lib" & Get_Name_String (Data.Name) &
- '.' & Archive_Ext,
- Verbose_Mode);
- end if;
+ if Project = Main_Project
+ or else Data.Other_Sources_Present
+ then
+ Add_Archive_Path;
end if;
end if;
end if;
end Recursive_Add_Archives;
+ -- Start of processing for Add_Archives
+
begin
-- First, mark all projects as not processed
@@ -723,11 +757,15 @@ package body Makegpr is
if Last_Argument + Args'Length > Arguments'Last then
declare
New_Arguments : constant Argument_List_Access :=
- new Argument_List
- (1 .. Last_Argument + Args'Length + Initial_Argument_Count);
+ new Argument_List
+ (1 .. Last_Argument + Args'Length +
+ Initial_Argument_Count);
+
New_Arguments_Displayed : constant Booleans :=
- new Boolean_Array
- (1 .. Last_Argument + Args'Length + Initial_Argument_Count);
+ new Boolean_Array
+ (1 .. Last_Argument +
+ Args'Length +
+ Initial_Argument_Count);
begin
New_Arguments (1 .. Last_Argument) :=
@@ -790,7 +828,7 @@ package body Makegpr is
-- Add_Source_Id --
-------------------
- procedure Add_Source_Id (Id : Other_Source_Id) is
+ procedure Add_Source_Id (Project : Project_Id; Id : Other_Source_Id) is
begin
-- Reallocate the array, if necessary
@@ -808,7 +846,7 @@ package body Makegpr is
end if;
Last_Source := Last_Source + 1;
- Source_Indexes (Last_Source) := (Id, False);
+ Source_Indexes (Last_Source) := (Project, Id, False);
end Add_Source_Id;
----------------------------
@@ -902,12 +940,22 @@ package body Makegpr is
if Switches /= Nil_Variable_Value then
Element_Id := Switches.Values;
-
while Element_Id /= Nil_String loop
Element := String_Elements.Table (Element_Id);
if Element.Value /= No_Name then
- Add_Argument (Get_Name_String (Element.Value), True);
+ Get_Name_String (Element.Value);
+
+ if not Quiet_Output then
+
+ -- When not in quiet output (no -q), check that the switch
+ -- is not the concatenation of several valid switches,
+ -- such as "-g -v". If it is, issue a warning.
+
+ Check (Option => Name_Buffer (1 .. Name_Len));
+ end if;
+
+ Add_Argument (Name_Buffer (1 .. Name_Len), True);
end if;
Element_Id := Element.Next;
@@ -915,12 +963,12 @@ package body Makegpr is
end if;
end Add_Switches;
- -------------------
- -- Build_Archive --
- -------------------
+ --------------------------
+ -- Build_Global_Archive --
+ --------------------------
- procedure Build_Archive (Project : Project_Id; Unconditionally : Boolean) is
- Data : constant Project_Data := Projects.Table (Project);
+ procedure Build_Global_Archive is
+ Data : Project_Data := Projects.Table (Main_Project);
Source_Id : Other_Source_Id;
Source : Other_Source;
Success : Boolean;
@@ -933,36 +981,344 @@ package body Makegpr is
"lib" & Get_Name_String (Data.Name) & ".deps";
-- The name of the archive dependency file for this project
- Need_To_Rebuild : Boolean := Unconditionally;
+ Need_To_Rebuild : Boolean := Need_To_Rebuild_Global_Archive;
-- When True, archive will be rebuilt
File : Prj.Util.Text_File;
- Object_Name : Name_Id;
- Time_Stamp : Time_Stamp_Type;
+ Object_Path : Name_Id;
+ Time_Stamp : Time_Stamp_Type;
Saved_Last_Argument : Natural;
+ First_Object : Natural;
+
+ Discard : Boolean;
begin
- -- First, make sure that the archive builder (ar) is on the path
+ Check_Archive_Builder;
- if Archive_Builder_Path = null then
- Archive_Builder_Path := Locate_Exec_On_Path (Archive_Builder);
+ Change_Dir (Get_Name_String (Data.Object_Directory));
- if Archive_Builder_Path = null then
- Osint.Fail
- ("unable to locate archive builder """,
- Archive_Builder,
- """");
+ if not Need_To_Rebuild then
+ if Verbose_Mode then
+ Write_Str (" Checking ");
+ Write_Line (Archive_Name);
end if;
- -- If there is an archive indexer (ranlib), try to locate it on the
- -- path. Don't fail if it is not found.
+ -- If the archive does not exist, of course it needs to be built
- if Archive_Indexer /= "" then
- Archive_Indexer_Path := Locate_Exec_On_Path (Archive_Indexer);
+ if not Is_Regular_File (Archive_Name) then
+ Need_To_Rebuild := True;
+
+ if Verbose_Mode then
+ Write_Line (" -> archive does not exist");
+ end if;
+
+ -- Archive does exist
+
+ else
+ -- Check the archive dependency file
+
+ Open (File, Archive_Dep_Name);
+
+ -- If the archive dependency file does not exist, we need to
+ -- to rebuild the archive and to create its dependency file.
+
+ if not Is_Valid (File) then
+ Need_To_Rebuild := True;
+
+ if Verbose_Mode then
+ Write_Str (" -> archive dependency file ");
+ Write_Str (Archive_Dep_Name);
+ Write_Line (" does not exist");
+ end if;
+
+ else
+ -- Put all sources of language other than Ada in
+ -- Source_Indexes.
+
+ for Proj in 1 .. Projects.Last loop
+ Data := Projects.Table (Proj);
+
+ if not Data.Library then
+ Last_Source := 0;
+ Source_Id := Data.First_Other_Source;
+
+ while Source_Id /= No_Other_Source loop
+ Add_Source_Id (Proj, Source_Id);
+ Source_Id := Other_Sources.Table (Source_Id).Next;
+ end loop;
+ end if;
+ end loop;
+
+ -- Read the dependency file, line by line
+
+ while not End_Of_File (File) loop
+ Get_Line (File, Name_Buffer, Name_Len);
+
+ -- First line is the path of the object file
+
+ Object_Path := Name_Find;
+ Source_Id := No_Other_Source;
+
+ -- Check if this object file is for a source of this project
+
+ for S in 1 .. Last_Source loop
+ Source_Id := Source_Indexes (S).Id;
+ Source := Other_Sources.Table (Source_Id);
+
+ if (not Source_Indexes (S).Found)
+ and then Source.Object_Path = Object_Path
+ then
+ -- We have found the object file: get the source
+ -- data, and mark it as found.
+
+ Source_Indexes (S).Found := True;
+ exit;
+ end if;
+ end loop;
+
+ -- If it is not for a source of this project, then the
+ -- archive needs to be rebuilt.
+
+ if Source_Id = No_Other_Source then
+ Need_To_Rebuild := True;
+ if Verbose_Mode then
+ Write_Str (" -> ");
+ Write_Str (Get_Name_String (Object_Path));
+ Write_Line (" is not an object of any project");
+ end if;
+
+ exit;
+ end if;
+
+ -- The second line is the time stamp of the object file.
+ -- If there is no next line, then the dependency file is
+ -- truncated, and the archive need to be rebuilt.
+
+ if End_Of_File (File) then
+ Need_To_Rebuild := True;
+
+ if Verbose_Mode then
+ Write_Str (" -> archive dependency file ");
+ Write_Line (" is truncated");
+ end if;
+
+ exit;
+ end if;
+
+ Get_Line (File, Name_Buffer, Name_Len);
+
+ -- If the line has the wrong number of characters, then
+ -- the dependency file is incorrectly formatted, and the
+ -- archive needs to be rebuilt.
+
+ if Name_Len /= Time_Stamp_Length then
+ Need_To_Rebuild := True;
+
+ if Verbose_Mode then
+ Write_Str (" -> archive dependency file ");
+ Write_Line (" is incorrectly formatted (time stamp)");
+ end if;
+
+ exit;
+ end if;
+
+ Time_Stamp := Time_Stamp_Type (Name_Buffer (1 .. Name_Len));
+
+ -- If the time stamp in the dependency file is different
+ -- from the time stamp of the object file, then the archive
+ -- needs to be rebuilt.
+
+ if Time_Stamp /= Source.Object_TS then
+ Need_To_Rebuild := True;
+
+ if Verbose_Mode then
+ Write_Str (" -> time stamp of ");
+ Write_Str (Get_Name_String (Object_Path));
+ Write_Str (" is incorrect in the archive");
+ Write_Line (" dependency file");
+ end if;
+
+ exit;
+ end if;
+ end loop;
+
+ Close (File);
+ end if;
+ end if;
+ end if;
+
+ if not Need_To_Rebuild then
+ if Verbose_Mode then
+ Write_Line (" -> up to date");
+ end if;
+
+ -- Archive needs to be rebuilt
+
+ else
+ -- If the archive is built, then linking will need to occur
+ -- unconditionally.
+
+ Need_To_Relink := True;
+
+ -- If archive already exists, first delete it
+
+ -- Comment needed on why we discard result???
+
+ if Is_Regular_File (Archive_Name) then
+ Delete_File (Archive_Name, Discard);
+ end if;
+
+ Last_Argument := 0;
+
+ -- Start with the options found in MLib.Tgt (usually just "rc")
+
+ Add_Arguments (Archive_Builder_Options.all, True);
+
+ -- Followed by the archive name
+
+ Add_Argument (Archive_Name, True);
+
+ First_Object := Last_Argument;
+
+ -- Followed by all the object files of the non library projects
+
+ for Proj in 1 .. Projects.Last loop
+ Data := Projects.Table (Proj);
+
+ if not Data.Library then
+ Source_Id := Data.First_Other_Source;
+
+ while Source_Id /= No_Other_Source loop
+ Source := Other_Sources.Table (Source_Id);
+
+ -- Only include object file name that have not been
+ -- overriden in extending projects.
+
+ if Is_Included_In_Global_Archive
+ (Source.Object_Name, Proj)
+ then
+ Add_Argument
+ (Get_Name_String (Source.Object_Path), Verbose_Mode);
+ end if;
+
+ Source_Id := Source.Next;
+ end loop;
+ end if;
+ end loop;
+
+ -- Spawn the archive builder (ar)
+
+ Saved_Last_Argument := Last_Argument;
+
+ Last_Argument := First_Object + Max_In_Archives;
+
+ loop
+ if Last_Argument > Saved_Last_Argument then
+ Last_Argument := Saved_Last_Argument;
+ end if;
+
+ Display_Command (Archive_Builder, Archive_Builder_Path);
+
+ Spawn
+ (Archive_Builder_Path.all,
+ Arguments (1 .. Last_Argument),
+ Success);
+
+ exit when not Success;
+
+ exit when Last_Argument = Saved_Last_Argument;
+
+ Arguments (1) := r;
+ Arguments (3 .. Saved_Last_Argument - Last_Argument + 2) :=
+ Arguments (Last_Argument + 1 .. Saved_Last_Argument);
+ Saved_Last_Argument := Saved_Last_Argument - Last_Argument + 2;
+ end loop;
+
+ -- If the archive was built, run the archive indexer (ranlib)
+ -- if there is one.
+
+ if Success then
+
+ -- If the archive was built, run the archive indexer (ranlib),
+ -- if there is one.
+
+ if Archive_Indexer_Path /= null then
+ Last_Argument := 0;
+ Add_Argument (Archive_Name, True);
+
+ Display_Command (Archive_Indexer, Archive_Indexer_Path);
+
+ Spawn (Archive_Indexer_Path.all, Arguments (1 .. 1), Success);
+
+ if not Success then
+
+ -- Running ranlib failed, delete the dependency file,
+ -- if it exists.
+
+ if Is_Regular_File (Archive_Dep_Name) then
+ Delete_File (Archive_Dep_Name, Success);
+ end if;
+
+ -- And report the error
+
+ Report_Error
+ ("running" & Archive_Indexer & " for project """,
+ Get_Name_String (Data.Name),
+ """ failed");
+ return;
+ end if;
+ end if;
+
+ -- The archive was correctly built, create its dependency file
+
+ Create_Global_Archive_Dependency_File (Archive_Dep_Name);
+
+ -- Building the archive failed, delete dependency file if one exists
+
+ else
+ if Is_Regular_File (Archive_Dep_Name) then
+ Delete_File (Archive_Dep_Name, Success);
+ end if;
+
+ -- And report the error
+
+ Report_Error
+ ("building archive for project """,
+ Get_Name_String (Data.Name),
+ """ failed");
end if;
end if;
+ end Build_Global_Archive;
+
+ -------------------
+ -- Build_Library --
+ -------------------
+
+ procedure Build_Library (Project : Project_Id; Unconditionally : Boolean) is
+ Data : constant Project_Data := Projects.Table (Project);
+ Source_Id : Other_Source_Id;
+ Source : Other_Source;
+
+ Archive_Name : constant String :=
+ "lib" & Get_Name_String (Data.Name) & '.' & Archive_Ext;
+ -- The name of the archive file for this project
+
+ Archive_Dep_Name : constant String :=
+ "lib" & Get_Name_String (Data.Name) & ".deps";
+ -- The name of the archive dependency file for this project
+
+ Need_To_Rebuild : Boolean := Unconditionally;
+ -- When True, archive will be rebuilt
+
+ File : Prj.Util.Text_File;
+
+ Object_Name : Name_Id;
+ Time_Stamp : Time_Stamp_Type;
+
+ begin
+ Check_Archive_Builder;
-- If Unconditionally is False, check if the archive need to be built
@@ -1001,14 +1357,13 @@ package body Makegpr is
end if;
else
- -- Put all sources of language other than Ada in
- -- Source_Indexes.
+ -- Put all sources of language other than Ada in Source_Indexes
Last_Source := 0;
Source_Id := Data.First_Other_Source;
while Source_Id /= No_Other_Source loop
- Add_Source_Id (Source_Id);
+ Add_Source_Id (Project, Source_Id);
Source_Id := Other_Sources.Table (Source_Id).Next;
end loop;
@@ -1045,6 +1400,7 @@ package body Makegpr is
if Source_Id = No_Other_Source then
Need_To_Rebuild := True;
+
if Verbose_Mode then
Write_Str (" -> ");
Write_Str (Get_Name_String (Object_Name));
@@ -1139,22 +1495,17 @@ package body Makegpr is
end if;
end if;
- -- Build the archive if necessary
+ -- Build the library if necessary
if Need_To_Rebuild then
- -- If an archive is built, then linking will need to occur
+ -- If a library is built, then linking will need to occur
-- unconditionally.
Need_To_Relink := True;
Last_Argument := 0;
- -- If it is a library project file, we need to build the library
- -- in the library directory.
-
- if Data.Library then
-
-- If there are sources in Ada, then gnatmake will build the
-- library, so nothing to do.
@@ -1192,9 +1543,7 @@ package body Makegpr is
Lib_Dir => Get_Name_String (Data.Library_Dir),
Symbol_Data => No_Symbols,
Driver_Name => No_Name,
- Lib_Address => "",
Lib_Version => "",
- Relocatable => Data.Library_Kind = Relocatable,
Auto_Init => False);
end if;
end if;
@@ -1212,109 +1561,88 @@ package body Makegpr is
Create_Archive_Dependency_File
(Archive_Dep_Name, Data.First_Other_Source);
- return;
- end if;
-
- -- Start with the options found in MLib.Tgt (usually just "rc")
-
- Add_Arguments (Archive_Builder_Options.all, True);
-
- -- Followed by the archive name
-
- Add_Argument (Archive_Name, True);
-
- -- Followed by all the object files of the project
-
- Source_Id := Data.First_Other_Source;
-
- while Source_Id /= No_Other_Source loop
- Source := Other_Sources.Table (Source_Id);
- Add_Argument (Get_Name_String (Source.Object_Name), Verbose_Mode);
- Source_Id := Source.Next;
- end loop;
-
- -- Spawn the archive builder (ar)
-
- Saved_Last_Argument := Last_Argument;
-
- Last_Argument := Max_In_Archives;
-
- loop
- if Last_Argument > Saved_Last_Argument then
- Last_Argument := Saved_Last_Argument;
- end if;
-
- Display_Command (Archive_Builder, Archive_Builder_Path);
-
- Spawn
- (Archive_Builder_Path.all,
- Arguments (1 .. Last_Argument),
- Success);
-
- exit when not Success;
-
- exit when Last_Argument = Saved_Last_Argument;
-
- Arguments (1) := r;
- Arguments (3 .. Saved_Last_Argument - Last_Argument + 2) :=
- Arguments (Last_Argument + 1 .. Saved_Last_Argument);
- Saved_Last_Argument := Saved_Last_Argument - Last_Argument + 2;
- end loop;
+ end if;
+ end Build_Library;
- if Success then
+ -----------
+ -- Check --
+ -----------
- -- If the archive was built, run the archive indexer (ranlib),
- -- if there is one.
+ procedure Check (Option : String) is
+ First : Positive := Option'First;
+ Last : Natural;
- if Archive_Indexer_Path /= null then
- Last_Argument := 0;
- Add_Argument (Archive_Name, True);
+ begin
+ for Index in Option'First + 1 .. Option'Last - 1 loop
+ if Option (Index) = ' ' and then Option (Index + 1) = '-' then
+ Write_Str ("warning: switch """);
+ Write_Str (Option);
+ Write_Str (""" is suspicious; consider using ");
+
+ Last := First;
+ while Last <= Option'Last loop
+ if Option (Last) = ' ' then
+ if First /= Option'First then
+ Write_Str (", ");
+ end if;
- Display_Command (Archive_Indexer, Archive_Indexer_Path);
+ Write_Char ('"');
+ Write_Str (Option (First .. Last - 1));
+ Write_Char ('"');
- Spawn (Archive_Indexer_Path.all, Arguments (1 .. 1), Success);
+ while Last <= Option'Last and then Option (Last) = ' ' loop
+ Last := Last + 1;
+ end loop;
- if not Success then
+ First := Last;
- -- Running ranlib failed, delete the dependency file,
- -- if it exists.
+ else
+ if Last = Option'Last then
+ if First /= Option'First then
+ Write_Str (", ");
+ end if;
- if Is_Regular_File (Archive_Dep_Name) then
- Delete_File (Archive_Dep_Name, Success);
+ Write_Char ('"');
+ Write_Str (Option (First .. Last));
+ Write_Char ('"');
end if;
- -- And report the error
-
- Report_Error
- ("running" & Archive_Indexer & " for project """,
- Get_Name_String (Data.Name),
- """ failed");
- return;
+ Last := Last + 1;
end if;
- end if;
+ end loop;
- -- The archive was correctly built, create its dependency file
+ Write_Line (" instead");
+ exit;
+ end if;
+ end loop;
+ end Check;
- Create_Archive_Dependency_File
- (Archive_Dep_Name, Data.First_Other_Source);
+ ---------------------------
+ -- Check_Archive_Builder --
+ ---------------------------
- else
- -- Building the archive failed, delete the dependency file, if
- -- one exists.
+ procedure Check_Archive_Builder is
+ begin
+ -- First, make sure that the archive builder (ar) is on the path
- if Is_Regular_File (Archive_Dep_Name) then
- Delete_File (Archive_Dep_Name, Success);
- end if;
+ if Archive_Builder_Path = null then
+ Archive_Builder_Path := Locate_Exec_On_Path (Archive_Builder);
- -- And report the error
+ if Archive_Builder_Path = null then
+ Osint.Fail
+ ("unable to locate archive builder """,
+ Archive_Builder,
+ """");
+ end if;
- Report_Error
- ("building archive for project """,
- Get_Name_String (Data.Name),
- """ failed");
+ -- If there is an archive indexer (ranlib), try to locate it on the
+ -- path. Don't fail if it is not found.
+
+ if Archive_Indexer /= "" then
+ Archive_Indexer_Path := Locate_Exec_On_Path (Archive_Indexer);
end if;
end if;
- end Build_Archive;
+ end Check_Archive_Builder;
------------------------------
-- Check_Compilation_Needed --
@@ -1330,8 +1658,7 @@ package body Makegpr is
Dep_Name : constant String := Get_Name_String (Source.Dep_Name);
Source_In_Dependencies : Boolean := False;
- -- Set to True if the source was find in the dependency file of its
- -- object file.
+ -- Set True if source was found in dependency file of its object file
Dep_File : Prj.Util.Text_File;
Start : Natural;
@@ -1349,8 +1676,7 @@ package body Makegpr is
Write_Line (" ... ");
end if;
- -- If the object file does not exist, of course the source need to be
- -- compiled.
+ -- If object file does not exist, of course source need to be compiled
if Source.Object_TS = Empty_Time_Stamp then
if Verbose_Mode then
@@ -1432,8 +1758,7 @@ package body Makegpr is
end loop;
-- If dependency file contains only empty lines or comments, then
- -- the dependencies are unknown, and the source needs to be
- -- recompiled.
+ -- dependencies are unknown, and the source needs to be recompiled.
if End_Of_File_Reached then
if Verbose_Mode then
@@ -1450,8 +1775,7 @@ package body Makegpr is
Start := 1;
Finish := Index (Name_Buffer (1 .. Name_Len), ": ");
- -- The first line must start with the name of the object file, followed
- -- by a colon (:).
+ -- First line must start with name of object file, followed by colon
if Finish = 0 or else Name_Buffer (1 .. Finish - 1) /= Object_Name then
if Verbose_Mode then
@@ -1470,7 +1794,7 @@ package body Makegpr is
Line_Loop : loop
declare
- Line : constant String := Name_Buffer (1 .. Name_Len);
+ Line : constant String := Name_Buffer (1 .. Name_Len);
Last : constant Natural := Name_Len;
begin
@@ -1631,13 +1955,13 @@ package body Makegpr is
CPATH : String_Access := null;
begin
- -- If the compiler is not know yet, get its path name
+ -- If the compiler is not known yet, get its path name
if Compiler_Names (Source.Language) = null then
Get_Compiler (Source.Language);
end if;
- -- For non GCC compilers, get the dependency file, calling first the
+ -- For non GCC compilers, get the dependency file, first calling the
-- compiler with the switch -M.
if not Compiler_Is_Gcc (Source.Language) then
@@ -1663,8 +1987,7 @@ package body Makegpr is
Add_Argument (Options (Source.Language).Table (J), True);
end loop;
- -- Finally, add the imported directory switches for this
- -- project file.
+ -- Finally, add imported directory switches for this project file
Add_Search_Directories (Data, Source.Language);
@@ -1800,9 +2123,7 @@ package body Makegpr is
-- Add the compiling switches for the language specified
-- on the command line, if any.
- for
- J in 1 .. Comp_Opts.Last (Options (Source.Language))
- loop
+ for J in 1 .. Comp_Opts.Last (Options (Source.Language)) loop
Add_Argument (Options (Source.Language).Table (J), True);
end loop;
@@ -1830,10 +2151,11 @@ package body Makegpr is
Arguments (1 .. Last_Argument),
Success);
+ -- Case of successful compilation
+
if Success then
- -- Compilation was successful, update the time stamp
- -- of the object file.
+ -- Update the time stamp of the object file
Source.Object_TS := File_Stamp (Source.Object_Name);
@@ -1859,6 +2181,8 @@ package body Makegpr is
Other_Sources.Table (Source_Id) := Source;
end if;
+ -- Compilation failed
+
else
Local_Errors := True;
Report_Error
@@ -1884,9 +2208,7 @@ package body Makegpr is
begin
Ada_Mains.Init;
-
To_Mixed (Project_Name);
-
Compile_Only := True;
Get_Imported_Directories (Main_Project, Data);
@@ -1896,7 +2218,7 @@ package body Makegpr is
Change_Dir (Get_Name_String (Data.Object_Directory));
- if not Data.Sources_Present then
+ if not Data.Other_Sources_Present then
if Ada_Is_A_Language then
Mains.Reset;
@@ -1930,7 +2252,6 @@ package body Makegpr is
if not Sources_Compiled.Get (Source_Name) then
Sources_Compiled.Set (Source_Name, True);
-
Source_Id := Data.First_Other_Source;
while Source_Id /= No_Other_Source loop
@@ -1942,8 +2263,7 @@ package body Makegpr is
if Source_Id = No_Other_Source then
if Ada_Is_A_Language then
Ada_Mains.Increment_Last;
- Ada_Mains.Table (Ada_Mains.Last) :=
- new String'(Main);
+ Ada_Mains.Table (Ada_Mains.Last) := new String'(Main);
else
Report_Error
@@ -1962,10 +2282,9 @@ package body Makegpr is
if Ada_Mains.Last > 0 then
- -- Invoke gnatmake for all sources that are not of a non Ada language
+ -- Invoke gnatmake for all Ada sources
Last_Argument := 0;
-
Add_Argument (Dash_u, True);
for Index in 1 .. Ada_Mains.Last loop
@@ -2019,7 +2338,7 @@ package body Makegpr is
Add_Argument (Output_File_Name, True);
end if;
- -- Transmit to gnatmake some switches
+ -- Transmit some switches to gnatmake
-- -c
@@ -2075,8 +2394,9 @@ package body Makegpr is
end if;
if not Compile_Only then
- -- If there are linking options from the command line, transmit them
- -- to gnatmake.
+
+ -- If there are linking options from the command line,
+ -- transmit them to gnatmake.
if Linker_Options.Last /= 0 then
Add_Argument (Dash_largs, True);
@@ -2133,7 +2453,7 @@ package body Makegpr is
-- True when the archive needs to be built/rebuilt unconditionally
begin
- -- For each project file
+ -- Loop through project files
for Project in 1 .. Projects.Last loop
Local_Errors := False;
@@ -2141,7 +2461,7 @@ package body Makegpr is
-- Nothing to do when no sources of language other than Ada
- if (not Data.Virtual) and then Data.Sources_Present then
+ if (not Data.Virtual) and then Data.Other_Sources_Present then
-- If the imported directory switches are unknown, compute them
@@ -2187,11 +2507,18 @@ package body Makegpr is
Source_Id := Source.Next;
end loop;
+ if Need_To_Rebuild_Archive and then (not Data.Library) then
+ Need_To_Rebuild_Global_Archive := True;
+ end if;
+
-- If there was no compilation error, build/rebuild the archive
-- if necessary.
- if not Local_Errors then
- Build_Archive (Project, Need_To_Rebuild_Archive);
+ if not Local_Errors
+ and then Data.Library
+ and then not Data.Languages (Lang_Ada)
+ then
+ Build_Library (Project, Need_To_Rebuild_Archive);
end if;
end if;
end loop;
@@ -2229,7 +2556,10 @@ package body Makegpr is
use Ada.Text_IO;
begin
- Create (Dep_File, Out_File, Name);
+ -- Create the file in Append mode, to avoid automatic insertion of
+ -- an end of line if file is empty.
+
+ Create (Dep_File, Append_File, Name);
while Source_Id /= No_Other_Source loop
Source := Other_Sources.Table (Source_Id);
@@ -2247,6 +2577,55 @@ package body Makegpr is
end if;
end Create_Archive_Dependency_File;
+ -------------------------------------------
+ -- Create_Global_Archive_Dependency_File --
+ -------------------------------------------
+
+ procedure Create_Global_Archive_Dependency_File (Name : String) is
+ Source_Id : Other_Source_Id;
+ Source : Other_Source;
+ Dep_File : Ada.Text_IO.File_Type;
+
+ use Ada.Text_IO;
+
+ begin
+ -- Create the file in Append mode, to avoid automatic insertion of
+ -- an end of line if file is empty.
+
+ Create (Dep_File, Append_File, Name);
+
+ -- Get all the object files of non-Ada sources in non-library projects
+
+ for Project in 1 .. Projects.Last loop
+ if not Projects.Table (Project).Library then
+ Source_Id := Projects.Table (Project).First_Other_Source;
+
+ while Source_Id /= No_Other_Source loop
+ Source := Other_Sources.Table (Source_Id);
+
+ -- Put only those object files that are in the global archive
+
+ if Is_Included_In_Global_Archive
+ (Source.Object_Name, Project)
+ then
+ Put_Line (Dep_File, Get_Name_String (Source.Object_Path));
+ Put_Line (Dep_File, String (Source.Object_TS));
+ end if;
+
+ Source_Id := Source.Next;
+ end loop;
+ end if;
+ end loop;
+
+ Close (Dep_File);
+
+ exception
+ when others =>
+ if Is_Open (Dep_File) then
+ Close (Dep_File);
+ end if;
+ end Create_Global_Archive_Dependency_File;
+
---------------------
-- Display_Command --
---------------------
@@ -2261,6 +2640,7 @@ package body Makegpr is
-- not in Quiet Output (no -q).
if Verbose_Mode or (not Quiet_Output) then
+
-- In Verbose Mode output the full path of the spawned process
if Verbose_Mode then
@@ -2391,9 +2771,9 @@ package body Makegpr is
Element_Id : String_List_Id := Source_Dirs;
Element : String_Element;
Add_Arg : Boolean := True;
+
begin
- -- Add each source directory path name, preceded by "-I" to
- -- Arguments.
+ -- Add each source directory path name, preceded by "-I" to Arguments
while Element_Id /= Nil_String loop
Element := String_Elements.Table (Element_Id);
@@ -2476,6 +2856,8 @@ package body Makegpr is
end if;
end Recursive_Get_Dirs;
+ -- Start of processing for Get_Imported_Directories
+
begin
-- First, mark all project as not processed
@@ -2538,8 +2920,7 @@ package body Makegpr is
Write_Eol;
end if;
- -- Parse and process the project files for other languages
- -- (not for Ada).
+ -- Parse and process project files for other languages (not for Ada)
Prj.Pars.Parse
(Project => Main_Project,
@@ -2570,14 +2951,14 @@ package body Makegpr is
if Mains.Number_Of_Mains = 0 then
Osint.Fail
("No source specified to compile in 'unique compile' mode");
-
else
Compile_Individual_Sources;
Report_Total_Errors ("compilation");
end if;
else
- -- First compile sources and build archives, if necessary
+ -- First compile sources and build archives for library project,
+ -- if necessary.
Compile_Sources;
@@ -2590,6 +2971,7 @@ package body Makegpr is
-- If -c was not specified, link the executables, if there are any.
if not Compile_Only then
+ Build_Global_Archive;
Check_For_C_Plus_Plus;
Link_Executables;
end if;
@@ -2655,6 +3037,34 @@ package body Makegpr is
Osint.Add_Default_Search_Dirs;
end Initialize;
+ -----------------------------------
+ -- Is_Included_In_Global_Archive --
+ -----------------------------------
+
+ function Is_Included_In_Global_Archive
+ (Object_Name : Name_Id;
+ Project : Project_Id) return Boolean
+ is
+ Data : Project_Data := Projects.Table (Project);
+ Source : Other_Source_Id;
+
+ begin
+ while Data.Extended_By /= No_Project loop
+ Data := Projects.Table (Data.Extended_By);
+ Source := Data.First_Other_Source;
+
+ while Source /= No_Other_Source loop
+ if Other_Sources.Table (Source).Object_Name = Object_Name then
+ return False;
+ else
+ Source := Other_Sources.Table (Source).Next;
+ end if;
+ end loop;
+ end loop;
+
+ return True;
+ end Is_Included_In_Global_Archive;
+
----------------------
-- Link_Executables --
----------------------
@@ -2684,9 +3094,19 @@ package body Makegpr is
procedure Add_C_Plus_Plus_Link_For_Gnatmake;
-- Add the --LINK= switch for gnatlink, depending on the C++ compiler
+ procedure Check_Time_Stamps (Exec_Time_Stamp : Time_Stamp_Type);
+ -- Check if there is an archive that is more recent than the executable
+ -- to decide if we need to relink.
+
procedure Choose_C_Plus_Plus_Link_Process;
-- If the C++ compiler is not g++, create the correct script to link
+ procedure Link_Foreign
+ (Main : String;
+ Main_Id : Name_Id;
+ Source : Other_Source);
+ -- Link a non-Ada main, when there is no Ada code
+
---------------------------------------
-- Add_C_Plus_Plus_Link_For_Gnatmake --
---------------------------------------
@@ -2707,6 +3127,61 @@ package body Makegpr is
end if;
end Add_C_Plus_Plus_Link_For_Gnatmake;
+ -----------------------
+ -- Check_Time_Stamps --
+ -----------------------
+
+ procedure Check_Time_Stamps (Exec_Time_Stamp : Time_Stamp_Type) is
+ Prj_Data : Project_Data;
+
+ begin
+ for Prj in 1 .. Projects.Last loop
+ Prj_Data := Projects.Table (Prj);
+
+ -- There is an archive only in project
+ -- files with sources other than Ada
+ -- sources.
+
+ if Data.Other_Sources_Present then
+ declare
+ Archive_Path : constant String :=
+ Get_Name_String
+ (Prj_Data.Object_Directory) &
+ Directory_Separator &
+ "lib" &
+ Get_Name_String (Prj_Data.Name) &
+ '.' & Archive_Ext;
+ Archive_TS : Time_Stamp_Type;
+ begin
+ Name_Len := 0;
+ Add_Str_To_Name_Buffer
+ (Archive_Path);
+ Archive_TS := File_Stamp (Name_Find);
+
+ -- If the archive is later than the
+ -- executable, we need to relink.
+
+ if Archive_TS /= Empty_Time_Stamp
+ and then
+ Exec_Time_Stamp < Archive_TS
+ then
+ Need_To_Relink := True;
+
+ if Verbose_Mode then
+ Write_Str (" -> ");
+ Write_Str (Archive_Path);
+ Write_Str (" has time stamp ");
+ Write_Str ("later than ");
+ Write_Line ("executable");
+ end if;
+
+ exit;
+ end if;
+ end;
+ end if;
+ end loop;
+ end Check_Time_Stamps;
+
-------------------------------------
-- Choose_C_Plus_Plus_Link_Process --
-------------------------------------
@@ -2747,6 +3222,159 @@ package body Makegpr is
end if;
end Choose_C_Plus_Plus_Link_Process;
+ ------------------
+ -- Link_Foreign --
+ ------------------
+
+ procedure Link_Foreign
+ (Main : String;
+ Main_Id : Name_Id;
+ Source : Other_Source)
+ is
+ Executable_Name : constant String :=
+ Get_Name_String
+ (Executable_Of
+ (Project => Main_Project,
+ Main => Main_Id,
+ Index => 0,
+ Ada_Main => False));
+ -- File name of the executable
+
+ Executable_Path : constant String :=
+ Get_Name_String
+ (Data.Exec_Directory) &
+ Directory_Separator &
+ Executable_Name;
+ -- Path name of the executable
+
+ Exec_Time_Stamp : Time_Stamp_Type;
+
+ begin
+ -- Now, check if the executable is up to date. It is considered
+ -- up to date if its time stamp is not earlier that the time stamp
+ -- of any archive. Only do that if we don't know if we need to link.
+
+ if not Need_To_Relink then
+
+ -- Get the time stamp of the executable
+
+ Name_Len := 0;
+ Add_Str_To_Name_Buffer (Executable_Path);
+ Exec_Time_Stamp := File_Stamp (Name_Find);
+
+ if Verbose_Mode then
+ Write_Str (" Checking executable ");
+ Write_Line (Executable_Name);
+ end if;
+
+ -- If executable does not exist, we need to link
+
+ if Exec_Time_Stamp = Empty_Time_Stamp then
+ Need_To_Relink := True;
+
+ if Verbose_Mode then
+ Write_Line (" -> not found");
+ end if;
+
+ -- Otherwise, get the time stamps of each archive. If one of
+ -- them is found later than the executable, we need to relink.
+
+ else
+ Check_Time_Stamps (Exec_Time_Stamp);
+ end if;
+
+ -- If Need_To_Relink is False, we are done
+
+ if Verbose_Mode and (not Need_To_Relink) then
+ Write_Line (" -> up to date");
+ end if;
+ end if;
+
+ -- Prepare to link
+
+ if Need_To_Relink then
+ Link_Done := True;
+
+ Last_Argument := 0;
+
+ -- Specify the executable path name
+
+ Add_Argument (Dash_o, True);
+ Add_Argument
+ (Get_Name_String (Data.Exec_Directory) &
+ Directory_Separator &
+ Get_Name_String
+ (Executable_Of
+ (Project => Main_Project,
+ Main => Main_Id,
+ Index => 0,
+ Ada_Main => False)),
+ True);
+
+ -- Specify the object file of the main source
+
+ Add_Argument
+ (Object_Dir & Directory_Separator &
+ Get_Name_String (Source.Object_Name),
+ True);
+
+ -- Add the switches specified in package Linker of
+ -- the main project.
+
+ Add_Switches
+ (Data => Data,
+ Proc => Linker,
+ Language => Source.Language,
+ File_Name => Main_Id);
+
+ -- Add the switches specified in attribute
+ -- Linker_Options of packages Linker.
+
+ if Link_Options_Switches = null then
+ Link_Options_Switches :=
+ new Argument_List'
+ (Linker_Options_Switches (Main_Project));
+ end if;
+
+ Add_Arguments (Link_Options_Switches.all, True);
+
+ -- Add the linking options specified on the
+ -- command line.
+
+ for Arg in 1 .. Linker_Options.Last loop
+ Add_Argument (Linker_Options.Table (Arg), True);
+ end loop;
+
+ -- Add all the archives, in a correct order
+
+ Add_Archives (For_Gnatmake => False);
+
+ -- If there are shared libraries and the run path
+ -- option is supported, add the run path switch.
+
+ if Lib_Path.Last > 0 then
+ Add_Argument
+ (Path_Option.all &
+ String (Lib_Path.Table (1 .. Lib_Path.Last)),
+ Verbose_Mode);
+ end if;
+
+ -- And invoke the linker
+
+ Display_Command (Linker_Name.all, Linker_Path);
+ Spawn
+ (Linker_Path.all,
+ Arguments (1 .. Last_Argument),
+ Success);
+
+ if not Success then
+ Report_Error ("could not link ", Main);
+ end if;
+ end if;
+ end Link_Foreign;
+
+ -- Start of processing of Link_Executables
+
begin
-- If no mains specified, get mains from attribute Main, if it exists
@@ -2769,6 +3397,7 @@ package body Makegpr is
end if;
if Mains.Number_Of_Mains = 0 then
+
-- If the attribute Main is an empty list or not specified,
-- there is nothing to do.
@@ -2786,10 +3415,12 @@ package body Makegpr is
-- Check how we are going to do the link
- if not Data.Sources_Present then
+ if not Data.Other_Sources_Present then
+
-- Only Ada sources in the main project, and even maybe not
if not Data.Languages (Lang_Ada) then
+
-- Fail if the main project has no source of any language
Osint.Fail
@@ -2802,8 +3433,7 @@ package body Makegpr is
Last_Argument := 0;
- -- Choose the correct linker if there is C++ code in other
- -- projects.
+ -- Choose correct linker if there is C++ code in other projects
if C_Plus_Plus_Is_Used then
Choose_C_Plus_Plus_Link_Process;
@@ -2820,10 +3450,11 @@ package body Makegpr is
-- sources in Ada.
if Data.Languages (Lang_Ada) then
+
-- There is a mix of Ada and other language sources in the main
-- project. Any main that is not a source of the other languages
-- will be deemed to be an Ada main.
- --
+
-- Find the mains of the other languages and the Ada mains.
Mains.Reset;
@@ -2834,8 +3465,9 @@ package body Makegpr is
loop
declare
- Main : constant String := Mains.Next_Main;
+ Main : constant String := Mains.Next_Main;
Main_Id : Name_Id;
+
begin
exit when Main'Length = 0;
@@ -2883,6 +3515,7 @@ package body Makegpr is
for Main in 1 .. Other_Mains.Last loop
declare
Source : constant Other_Source := Other_Mains.Table (Main);
+
begin
Last_Argument := 0;
@@ -3007,200 +3640,7 @@ package body Makegpr is
Get_Name_String (Data.Name));
else
- declare
- Executable_Name : constant String :=
- Get_Name_String
- (Executable_Of
- (Project => Main_Project,
- Main => Main_Id,
- Index => 0,
- Ada_Main => False));
- -- File name of the executable
-
- Executable_Path : constant String :=
- Get_Name_String
- (Data.Exec_Directory) &
- Directory_Separator &
- Executable_Name;
- -- Path name of the executable
-
- Exec_Time_Stamp : Time_Stamp_Type;
-
- begin
- -- Now, check if the executable is up to date.
- -- It is considered up to date if its time stamp is
- -- not earlier that the time stamp of any archive.
- -- Only do that if we don't know if we need to link.
-
- if not Need_To_Relink then
-
- -- Get the time stamp of the executable
-
- Name_Len := 0;
- Add_Str_To_Name_Buffer (Executable_Path);
- Exec_Time_Stamp := File_Stamp (Name_Find);
-
- if Verbose_Mode then
- Write_Str (" Checking executable ");
- Write_Line (Executable_Name);
- end if;
-
- -- If executable does not exist, we need to link
-
- if Exec_Time_Stamp = Empty_Time_Stamp then
- Need_To_Relink := True;
-
- if Verbose_Mode then
- Write_Line (" -> not found");
- end if;
-
- else
- -- Otherwise, get the time stamps of each
- -- archive. If one of them is found later than
- -- the executable, we need to relink.
-
- declare
- Prj_Data : Project_Data;
-
- begin
- for Prj in 1 .. Projects.Last loop
- Prj_Data := Projects.Table (Prj);
-
- -- There is an archive only in project
- -- files with sources other than Ada
- -- sources.
-
- if Data.Sources_Present then
- declare
- Archive_Path : constant String :=
- Get_Name_String
- (Prj_Data.Object_Directory) &
- Directory_Separator &
- "lib" &
- Get_Name_String (Prj_Data.Name) &
- '.' & Archive_Ext;
- Archive_TS : Time_Stamp_Type;
- begin
- Name_Len := 0;
- Add_Str_To_Name_Buffer
- (Archive_Path);
- Archive_TS := File_Stamp (Name_Find);
-
- -- If the archive is later than the
- -- executable, we need to relink.
-
- if Archive_TS /= Empty_Time_Stamp
- and then
- Exec_Time_Stamp < Archive_TS
- then
- Need_To_Relink := True;
-
- if Verbose_Mode then
- Write_Str (" -> ");
- Write_Str (Archive_Path);
- Write_Str (" has time stamp ");
- Write_Str ("later than ");
- Write_Line ("executable");
- end if;
-
- exit;
- end if;
- end;
- end if;
- end loop;
- end;
- end if;
-
- -- If Need_To_Relink is False, we are done
-
- if Verbose_Mode and (not Need_To_Relink) then
- Write_Line (" -> up to date");
- end if;
-
- end if;
-
- -- Prepare to link
-
- if Need_To_Relink then
- Link_Done := True;
-
- Last_Argument := 0;
-
- -- Specify the executable path name
-
- Add_Argument (Dash_o, True);
- Add_Argument
- (Get_Name_String (Data.Exec_Directory) &
- Directory_Separator &
- Get_Name_String
- (Executable_Of
- (Project => Main_Project,
- Main => Main_Id,
- Index => 0,
- Ada_Main => False)),
- True);
-
- -- Specify the object file of the main source
-
- Add_Argument
- (Object_Dir & Directory_Separator &
- Get_Name_String (Source.Object_Name),
- True);
-
- -- Add the switches specified in package Linker of
- -- the main project.
-
- Add_Switches
- (Data => Data,
- Proc => Linker,
- Language => Source.Language,
- File_Name => Main_Id);
-
- -- Add the switches specified in attribute
- -- Linker_Options of packages Linker.
-
- if Link_Options_Switches = null then
- Link_Options_Switches :=
- new Argument_List'
- (Linker_Options_Switches (Main_Project));
- end if;
-
- Add_Arguments (Link_Options_Switches.all, True);
-
- -- Add the linking options specified on the
- -- command line.
-
- for Arg in 1 .. Linker_Options.Last loop
- Add_Argument (Linker_Options.Table (Arg), True);
- end loop;
-
- -- Add all the archives, in a correct order
-
- Add_Archives (For_Gnatmake => False);
-
- -- If there are shared libraries and the run path
- -- option is supported, add the run path switch.
-
- if Lib_Path.Last > 0 then
- Add_Argument
- (Path_Option.all &
- String (Lib_Path.Table (1 .. Lib_Path.Last)),
- Verbose_Mode);
- end if;
-
- -- And invoke the linker
-
- Display_Command (Linker_Name.all, Linker_Path);
- Spawn
- (Linker_Path.all,
- Arguments (1 .. Last_Argument),
- Success);
-
- if not Success then
- Report_Error ("could not link ", Main);
- end if;
- end if;
- end;
+ Link_Foreign (Main, Main_Id, Source);
end if;
end;
end loop;
@@ -3211,13 +3651,14 @@ package body Makegpr is
Osint.Write_Program_Name;
if Mains.Number_Of_Mains = 1 then
+
-- If there is only one executable, report its name too
Write_Str (": """);
Mains.Reset;
declare
- Main : constant String := Mains.Next_Main;
+ Main : constant String := Mains.Next_Main;
Main_Id : Name_Id;
begin
Name_Len := 0;
@@ -3251,8 +3692,7 @@ package body Makegpr is
S3 : String := "")
is
begin
- -- If Keep_Going is True, output the error message, preceded by the
- -- error header.
+ -- If Keep_Going is True, output error message preceded by error header
if Keep_Going then
Total_Number_Of_Errors := Total_Number_Of_Errors + 1;
@@ -3262,9 +3702,9 @@ package body Makegpr is
Write_Str (S3);
Write_Eol;
- else
- -- Otherwise, just fail
+ -- Otherwise just fail
+ else
Osint.Fail (S1, S2, S3);
end if;
end Report_Error;
@@ -3300,8 +3740,8 @@ package body Makegpr is
return;
end if;
- -- If preceding switch was -P, a project file name need to be specified,
- -- not a switch.
+ -- If preceding switch was -P, a project file name need to be
+ -- specified, not a switch.
if Project_File_Name_Expected then
if Arg (1) = '-' then
@@ -3311,8 +3751,8 @@ package body Makegpr is
Project_File_Name := new String'(Arg);
end if;
- -- If preceding switch was -o, an executable name need to be specidied,
- -- not a switch.
+ -- If preceding switch was -o, an executable name need to be
+ -- specified, not a switch.
elsif Output_File_Name_Expected then
if Arg (1) = '-' then
@@ -3326,10 +3766,9 @@ package body Makegpr is
-- -c???args: Compiler arguments
- elsif Arg'Length >= 6 and then
- Arg (Arg'First .. Arg'First + 1) = "-c" and then
- Arg (Arg'Last - 3 .. Arg'Last) = "args"
-
+ elsif Arg'Length >= 6
+ and then Arg (Arg'First .. Arg'First + 1) = "-c"
+ and then Arg (Arg'Last - 3 .. Arg'Last) = "args"
then
declare
OK : Boolean := False;
@@ -3347,7 +3786,6 @@ package body Makegpr is
if OK then
Current_Processor := Compiler;
-
else
Osint.Fail ("illegal option """, Arg, """");
end if;
@@ -3417,6 +3855,7 @@ package body Makegpr is
elsif Arg = "-v" then
Verbose_Mode := True;
+ Copyright;
elsif Arg'Length = 4 and then Arg (1 .. 3) = "-vP"
and then Arg (4) in '0' .. '2'
@@ -3435,8 +3874,7 @@ package body Makegpr is
elsif Arg'Length >= 3 and then Arg (2) = 'X'
and then Is_External_Assignment (Arg)
then
- -- Is_External_Assignment has side effects
- -- when it returns True;
+ -- Is_External_Assignment has side effects when it returns True
null;
@@ -3456,8 +3894,7 @@ package body Makegpr is
-----------------
function Strip_CR_LF (Text : String) return String is
-
- To : String (1 .. Text'Length);
+ To : String (1 .. Text'Length);
Index_To : Natural := 0;
begin