-- --
-- B o d y --
-- --
--- Copyright (C) 2004-2005 Free Software Foundation, Inc. --
+-- Copyright (C) 2004-2008, Free Software Foundation, Inc. --
-- --
-- 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- --
+-- ware Foundation; either version 3, 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, 59 Temple Place - Suite 330, Boston, --
--- MA 02111-1307, USA. --
+-- Public License distributed with GNAT; see file COPYING3. If not, go to --
+-- http://www.gnu.org/licenses for a complete copy of the license. --
-- --
-- GNAT was originally developed by the GNAT team at New York University. --
-- Extensive contributions were provided by Ada Core Technologies Inc. --
-- --
------------------------------------------------------------------------------
-with Ada.Command_Line; use Ada.Command_Line;
-with Ada.Strings.Fixed; use Ada.Strings.Fixed;
-with Ada.Text_IO; use Ada.Text_IO;
-with Ada.Unchecked_Deallocation;
-
with Csets;
with Gnatvsn;
+with Hostparm; use Hostparm;
+with Makeutl; use Makeutl;
+with MLib.Tgt; use MLib.Tgt;
+with Namet; use Namet;
+with Output; use Output;
+with Opt; use Opt;
+with Osint; use Osint;
+with Prj; use Prj;
+with Prj.Ext; use Prj.Ext;
+with Prj.Pars;
+with Prj.Util; use Prj.Util;
+with Snames; use Snames;
+with Table;
+with Types; use Types;
-with GNAT.Directory_Operations; use GNAT.Directory_Operations;
+with Ada.Command_Line; use Ada.Command_Line;
+with Ada.Strings.Fixed; use Ada.Strings.Fixed;
+with Ada.Text_IO; use Ada.Text_IO;
+with Ada.Unchecked_Deallocation;
+
+with GNAT.Directory_Operations; use GNAT.Directory_Operations;
with GNAT.Dynamic_Tables;
-with GNAT.Expect; use GNAT.Expect;
+with GNAT.Expect; use GNAT.Expect;
with GNAT.HTable;
-with GNAT.OS_Lib; use GNAT.OS_Lib;
-with GNAT.Regpat; use GNAT.Regpat;
-
-with Makeutl; use Makeutl;
-with MLib.Tgt; use MLib.Tgt;
-with Namet; use Namet;
-with Output; use Output;
-with Opt; use Opt;
-with Osint; use Osint;
-with Prj; use Prj;
-with Prj.Pars;
-with Prj.Util; use Prj.Util;
-with Snames; use Snames;
+with GNAT.OS_Lib; use GNAT.OS_Lib;
+with GNAT.Regpat; use GNAT.Regpat;
+
with System;
-with System.Case_Util; use System.Case_Util;
-with Table;
-with Types; use Types;
+with System.Case_Util; use System.Case_Util;
package body Makegpr is
+ On_Windows : constant Boolean := Directory_Separator = '\';
+ -- True when on Windows. Used in Check_Compilation_Needed when processing
+ -- C/C++ dependency files for backslash handling.
+
Max_In_Archives : constant := 50;
-- The maximum number of arguments for a single invocation of the
-- Archive Indexer (ar).
- Cpp_Linker : constant String := "c++linker";
- -- The name of a linking script, built one the fly, when there are C++
- -- sources and the C++ compiler is not g++.
-
No_Argument : aliased Argument_List := (1 .. 0 => null);
-- Null argument list representing case of no arguments
-- ar commands.
Archive_Indexer_Path : String_Access := null;
- -- The path name of the archive indexer (ranlib), if it exists.
+ -- The path name of the archive indexer (ranlib), if it exists
Copyright_Output : Boolean := False;
Usage_Output : Boolean := False;
(Header_Num => Header_Num,
Element => Boolean,
No_Element => False,
- Key => Name_Id,
+ Key => File_Name_Type,
Hash => Hash,
Equal => "=");
- package X_Switches is new Table.Table
+ package Saved_Switches is new Table.Table
(Table_Component_Type => String_Access,
Table_Index_Type => Integer,
Table_Low_Bound => 1,
- Table_Initial => 2,
+ Table_Initial => 10,
Table_Increment => 100,
- Table_Name => "Makegpr.X_Switches");
- -- Table to store the -X switches to be passed to gnatmake
+ Table_Name => "Makegpr.Saved_Switches");
+ -- Table to store the switches to be passed to gnatmake
Initial_Argument_Count : constant Positive := 20;
type Boolean_Array is array (Positive range <>) of Boolean;
Table_Index_Type => Integer,
Table_Low_Bound => 1,
Table_Initial => 200,
- Table_Increment => 50,
+ Table_Increment => 100,
Table_Name => "Makegpr.Cache_Args");
-- A table to cache arguments, to avoid multiple allocation of the same
-- strings. It is not possible to use a hash table, because String is
Dash_cargs : constant String_Access := Dash_cargs_String'Access;
Dash_d_String : aliased String := "-d";
Dash_d : constant String_Access := Dash_d_String'Access;
+ Dash_eL_String : aliased String := "-eL";
+ Dash_eL : constant String_Access := Dash_eL_String'Access;
Dash_f_String : aliased String := "-f";
Dash_f : constant String_Access := Dash_f_String'Access;
Dash_k_String : aliased String := "-k";
Path_Option : String_Access;
-- The path option switch, when supported
+ Project_Of_Current_Object_Directory : Project_Id := No_Project;
+ -- The object directory of the project for the last compilation. Avoid
+ -- calling Change_Dir if the current working directory is already this
+ -- directory.
+
package Lib_Path is new Table.Table
(Table_Component_Type => Character,
Table_Index_Type => Integer,
Table_Low_Bound => 1,
Table_Initial => 200,
- Table_Increment => 50,
+ Table_Increment => 100,
Table_Name => "Makegpr.Lib_Path");
-- A table to compute the path to put in the path option switch, when it
-- is supported.
procedure Add_Argument (Arg : String_Access; Display : Boolean);
procedure Add_Argument (Arg : String; Display : Boolean);
- -- Add an argument to Arguments. Reallocate if necessary.
+ -- Add an argument to Arguments. Reallocate if necessary
procedure Add_Arguments (Args : Argument_List; Display : Boolean);
-- Add a list of arguments to Arguments. Reallocate if necessary
(Data : Project_Data;
Proc : Processor;
Language : Language_Index;
- File_Name : Name_Id);
+ File_Name : File_Name_Type);
-- Add to Arguments the switches, if any, for a source (attribute Switches)
-- or language (attribute Default_Switches), coming from package Compiler
-- or Linker (depending on Proc) of a specified project file.
-- 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
+ -- Create the archive dependency file for the main project
procedure Display_Command
- (Name : String;
- Path : String_Access;
- CPATH : String_Access := null);
- -- Display the command for a spawned process, if in Verbose_Mode or
- -- not in Quiet_Output.
+ (Name : String;
+ Path : String_Access;
+ CPATH : String_Access := null;
+ Ellipse : Boolean := False);
+ -- Display the command for a spawned process, if in Verbose_Mode or not in
+ -- Quiet_Output. In non verbose mode, when Ellipse is True, display "..."
+ -- in place of the first argument that has Display set to False.
procedure Get_Compiler (For_Language : First_Language_Indexes);
-- Find the compiler name and path name for a specified programming
- -- language, if not already done. Results are in the corresponding
- -- elements of arrays Compiler_Names and Compiler_Paths. Name of compiler
- -- is found in package IDE of the main project, or defaulted.
- -- Fail if compiler cannot be found on the path. For the Ada language,
- -- gnatmake, rather than the Ada compiler is returned.
+ -- language, if not already done. Results are in the corresponding elements
+ -- of arrays Compiler_Names and Compiler_Paths. Name of compiler is found
+ -- in package IDE of the main project, or defaulted. Fail if compiler
+ -- cannot be found on the path. For the Ada language, gnatmake, rather than
+ -- the Ada compiler is returned.
procedure Get_Imported_Directories
(Project : Project_Id;
Data : in out Project_Data);
- -- Find the necessary switches -I to be used when compiling sources
- -- of languages other than Ada, in a specified project file. Cache the
- -- result in component Imported_Directories_Switches of the project data.
- -- For gcc/g++ compilers, get the value of the C*_INCLUDE_PATH, instead.
+ -- Find the necessary switches -I to be used when compiling sources of
+ -- languages other than Ada, in a specified project file. Cache the result
+ -- in component Imported_Directories_Switches of the project data. For
+ -- gcc/g++ compilers, get the value of the C*_INCLUDE_PATH, instead.
procedure Initialize;
-- Do the necessary package initialization and process the command line
-- arguments.
function Is_Included_In_Global_Archive
- (Object_Name : Name_Id;
+ (Object_Name : File_Name_Type;
Project : Project_Id) return Boolean;
-- Return True if the object Object_Name is not overridden by a source
-- in a project extending project Project.
-- Link executables
procedure Report_Error (S1 : String; S2 : String := ""; S3 : String := "");
- -- Report an error. If Keep_Going is False, just call Osint.Fail.
- -- If Keep_Going is True, display the error and increase the total number
- -- of errors.
+ -- Report an error. If Keep_Going is False, just call Osint.Fail. If
+ -- Keep_Going is True, display the error and increase the total number of
+ -- errors.
procedure Report_Total_Errors (Kind : String);
-- If Total_Number_Of_Errors is not zero, report it, and fail
procedure Add_Archives (For_Gnatmake : Boolean) is
Last_Arg : constant Natural := Last_Argument;
- -- The position of the last argument before adding the archives.
- -- Used to reverse the order of the arguments added when processing
- -- the archives.
+ -- The position of the last argument before adding the archives. Used to
+ -- reverse the order of the arguments added when processing the
+ -- archives.
procedure Recursive_Add_Archives (Project : Project_Id);
-- Recursive procedure to add the archive of a project file, if any,
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 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) &
+ (Get_Name_String (Data.Display_Library_Dir) &
Directory_Separator &
"lib" & Get_Name_String (Data.Library_Name) &
'.' & Archive_Ext,
("-l" & Get_Name_String (Data.Library_Name),
Verbose_Mode);
- Get_Name_String (Data.Library_Dir);
+ Get_Name_String (Data.Display_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 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 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;
end if;
end if;
- -- For a non-library project, the only archive needed
- -- is the one for the main project, if there is one.
+ -- For a non-library project, the only archive needed is the one
+ -- for the main project, if there is one.
elsif Project = Main_Project and then Global_Archive_Exists then
Add_Argument
- (Get_Name_String (Data.Object_Directory) &
+ (Get_Name_String (Data.Display_Object_Dir) &
Directory_Separator &
- "lib" & Get_Name_String (Data.Name) &
- '.' & Archive_Ext,
+ "lib" & Get_Name_String (Data.Display_Name)
+ & '.' & Archive_Ext,
Verbose_Mode);
end if;
end Add_Archive_Path;
-- And reverse the order
declare
- First : Positive := Last_Arg + 1;
- Last : Natural := Last_Argument;
+ First : Positive;
+ Last : Natural;
Temp : String_Access;
begin
+ First := Last_Arg + 1;
+ Last := Last_Argument;
while First < Last loop
Temp := Arguments (First);
Arguments (First) := Arguments (Last);
-- Nothing to do if argument is empty
if Arg'Length > 0 then
+
-- Check if the argument is already in the Cache_Args table.
-- If it is already there, reuse the allocated value.
(Data : Project_Data;
Proc : Processor;
Language : Language_Index;
- File_Name : Name_Id)
+ File_Name : File_Name_Type)
is
Switches : Variable_Value;
-- The switches, if any, for the file/language
end case;
if Pkg /= No_Package then
+
-- Get the Switches ("file name"), if they exist
Switches_Array := Prj.Util.Value_Of
Switches :=
Prj.Util.Value_Of
- (Index => File_Name,
+ (Index => Name_Id (File_Name),
Src_Index => 0,
In_Array => Switches_Array,
In_Tree => Project_Tree);
--------------------------
procedure Build_Global_Archive is
- Data : Project_Data :=
- Project_Tree.Projects.Table (Main_Project);
+ Data : Project_Data := Project_Tree.Projects.Table (Main_Project);
Source_Id : Other_Source_Id;
+ S_Id : Other_Source_Id;
Source : Other_Source;
Success : Boolean;
Archive_Name : constant String :=
- "lib" & Get_Name_String (Data.Name) & '.' & Archive_Ext;
+ "lib"
+ & Get_Name_String (Data.Display_Name)
+ & '.'
+ & Archive_Ext;
-- The name of the archive file for this project
Archive_Dep_Name : constant String :=
- "lib" & Get_Name_String (Data.Name) & ".deps";
+ "lib"
+ & Get_Name_String (Data.Display_Name)
+ & ".deps";
-- The name of the archive dependency file for this project
Need_To_Rebuild : Boolean := Need_To_Rebuild_Global_Archive;
-- When True, archive will be rebuilt
- File : Prj.Util.Text_File;
-
- Object_Path : Name_Id;
- Time_Stamp : Time_Stamp_Type;
-
+ File : Prj.Util.Text_File;
+ Object_Path : Path_Name_Type;
+ Time_Stamp : Time_Stamp_Type;
Saved_Last_Argument : Natural;
First_Object : Natural;
Discard : Boolean;
+ pragma Warnings (Off, Discard);
begin
Check_Archive_Builder;
- Change_Dir (Get_Name_String (Data.Object_Directory));
+ if Project_Of_Current_Object_Directory /= Main_Project then
+ Project_Of_Current_Object_Directory := Main_Project;
+ Change_Dir (Get_Name_String (Data.Object_Directory));
+
+ if Verbose_Mode then
+ Write_Str ("Changing to object directory of """);
+ Write_Name (Data.Display_Name);
+ Write_Str (""": """);
+ Write_Name (Data.Display_Object_Dir);
+ Write_Line ("""");
+ end if;
+ end if;
if not Need_To_Rebuild then
if Verbose_Mode then
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.
+ -- rebuild the archive and to create its dependency file.
if not Is_Valid (File) then
Need_To_Rebuild := True;
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
- for Proj in Project_Table.First ..
- Project_Table.Last (Project_Tree.Projects)
- loop
- Data := Project_Tree.Projects.Table (Proj);
+ declare
+ Local_Data : Project_Data;
- if not Data.Library then
- Last_Source := 0;
- Source_Id := Data.First_Other_Source;
+ begin
+ Last_Source := 0;
- while Source_Id /= No_Other_Source loop
- Add_Source_Id (Proj, Source_Id);
- Source_Id := Project_Tree.Other_Sources.Table
- (Source_Id).Next;
- end loop;
- end if;
- end loop;
+ for Proj in Project_Table.First ..
+ Project_Table.Last (Project_Tree.Projects)
+ loop
+ Local_Data := Project_Tree.Projects.Table (Proj);
+
+ if not Local_Data.Library then
+ Source_Id := Local_Data.First_Other_Source;
+ while Source_Id /= No_Other_Source loop
+ Add_Source_Id (Proj, Source_Id);
+ Source_Id := Project_Tree.Other_Sources.Table
+ (Source_Id).Next;
+ end loop;
+ end if;
+ end loop;
+ end;
-- Read the dependency file, line by line
-- 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 := Project_Tree.Other_Sources.Table
- (Source_Id);
+ S_Id := Source_Indexes (S).Id;
+ Source := Project_Tree.Other_Sources.Table (S_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.
+ -- We have found the object file: get the source data,
+ -- and mark it as found.
+ Source_Id := S_Id;
Source_Indexes (S).Found := True;
exit;
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
+ -- 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
if not Data.Library then
Source_Id := Data.First_Other_Source;
-
while Source_Id /= No_Other_Source loop
Source :=
Project_Tree.Other_Sources.Table (Source_Id);
-- Only include object file name that have not been
- -- overriden in extending projects.
+ -- overridden in extending projects.
if Is_Included_In_Global_Archive
(Source.Object_Name, Proj)
then
Add_Argument
- (Get_Name_String (Source.Object_Path), Verbose_Mode);
+ (Get_Name_String (Source.Object_Path),
+ Verbose_Mode or (First_Object = Last_Argument));
end if;
Source_Id := Source.Next;
Last_Argument := Saved_Last_Argument;
end if;
- Display_Command (Archive_Builder, Archive_Builder_Path);
+ Display_Command
+ (Archive_Builder,
+ Archive_Builder_Path,
+ Ellipse => True);
Spawn
(Archive_Builder_Path.all,
Arguments (1 .. Last_Argument),
Success);
- exit when not Success;
-
- exit when Last_Argument = Saved_Last_Argument;
+ exit when not Success
+ or else Last_Argument = Saved_Last_Argument;
Arguments (1) := r;
Arguments (3 .. Saved_Last_Argument - Last_Argument + 2) :=
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);
Report_Error
("running" & Archive_Indexer & " for project """,
- Get_Name_String (Data.Name),
+ Get_Name_String (Data.Display_Name),
""" failed");
return;
end if;
Report_Error
("building archive for project """,
- Get_Name_String (Data.Name),
+ Get_Name_String (Data.Display_Name),
""" failed");
end if;
end if;
Source : Other_Source;
Archive_Name : constant String :=
- "lib" & Get_Name_String (Data.Name) & '.' & Archive_Ext;
+ "lib" & Get_Name_String (Data.Library_Name)
+ & '.' & Archive_Ext;
-- The name of the archive file for this project
Archive_Dep_Name : constant String :=
- "lib" & Get_Name_String (Data.Name) & ".deps";
+ "lib" & Get_Name_String (Data.Library_Name)
+ & ".deps";
-- The name of the archive dependency file for this project
Need_To_Rebuild : Boolean := Unconditionally;
File : Prj.Util.Text_File;
- Object_Name : Name_Id;
+ Object_Name : File_Name_Type;
Time_Stamp : Time_Stamp_Type;
Driver_Name : Name_Id := No_Name;
- Lib_Opts : Argument_List_Access := No_Argument'Access;
+ Lib_Opts : Argument_List_Access := No_Argument'Access;
+
begin
+ -- Nothing to do if the project is externally built
+
+ if Data.Externally_Built then
+ return;
+ end if;
+
Check_Archive_Builder;
-- If Unconditionally is False, check if the archive need to be built
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.
+ -- rebuild the archive and to create its dependency file.
if not Is_Valid (File) then
Need_To_Rebuild := True;
-- Put all sources of language other than Ada in Source_Indexes
Last_Source := 0;
- Source_Id := Data.First_Other_Source;
+ Source_Id := Data.First_Other_Source;
while Source_Id /= No_Other_Source loop
Add_Source_Id (Project, Source_Id);
- Source_Id := Project_Tree.Other_Sources.Table
- (Source_Id).Next;
+ Source_Id :=
+ Project_Tree.Other_Sources.Table (Source_Id).Next;
end loop;
-- Read the dependency file, line by line
Last_Argument := 0;
- -- If there are sources in Ada, then gnatmake will build the
- -- library, so nothing to do.
+ -- If there are sources in Ada, then gnatmake will build the library,
+ -- so nothing to do.
- if not Data.Languages (Ada_Language_Index) then
+ if not Data.Langs (Ada_Language_Index) then
-- Get all the object files of the project
Source_Id := Data.First_Other_Source;
-
while Source_Id /= No_Other_Source loop
Source := Project_Tree.Other_Sources.Table (Source_Id);
Add_Argument
Source_Id := Source.Next;
end loop;
- -- If it is a library, it need to be built it the same way
- -- Ada libraries are built.
+ -- If it is a library, it need to be built it the same way Ada
+ -- libraries are built.
if Data.Library_Kind = Static then
MLib.Build_Library
(Ofiles => Arguments (1 .. Last_Argument),
- Afiles => No_Argument,
Output_File => Get_Name_String (Data.Library_Name),
- Output_Dir => Get_Name_String (Data.Library_Dir));
+ Output_Dir => Get_Name_String (Data.Display_Library_Dir));
else
-- Link with g++ if C++ is one of the languages, otherwise
begin
if not Library_Options.Default then
declare
- Current : String_List_Id := Library_Options.Values;
+ Current : String_List_Id;
Element : String_Element;
begin
+ Current := Library_Options.Values;
while Current /= Nil_String loop
- Element := Project_Tree.String_Elements.
- Table (Current);
+ Element :=
+ Project_Tree.String_Elements.Table (Current);
Get_Name_String (Element.Value);
if Name_Len /= 0 then
MLib.Tgt.Build_Dynamic_Library
(Ofiles => Arguments (1 .. Last_Argument),
- Foreign => Arguments (1 .. Last_Argument),
- Afiles => No_Argument,
- Options => No_Argument,
- Options_2 => Lib_Opts.all,
+ Options => Lib_Opts.all,
Interfaces => No_Argument,
Lib_Filename => Get_Name_String (Data.Library_Name),
Lib_Dir => Get_Name_String (Data.Library_Dir),
declare
Archive : Ada.Text_IO.File_Type;
- use Ada.Text_IO;
begin
Create (Archive, Out_File, Archive_Name);
Close (Archive);
(Source : Other_Source;
Need_To_Compile : out Boolean)
is
- Source_Name : constant String := Get_Name_String (Source.File_Name);
- Source_Path : constant String := Get_Name_String (Source.Path_Name);
- Object_Name : constant String := Get_Name_String (Source.Object_Name);
- Dep_Name : constant String := Get_Name_String (Source.Dep_Name);
+ Source_Name : constant String := Get_Name_String (Source.File_Name);
+ Source_Path : constant String := Get_Name_String (Source.Path_Name);
+ Object_Name : constant String := Get_Name_String (Source.Object_Name);
+ C_Object_Name : String := Object_Name;
+ Dep_Name : constant String := Get_Name_String (Source.Dep_Name);
+ C_Source_Path : constant String :=
+ Normalize_Pathname
+ (Name => Source_Path,
+ Resolve_Links => False,
+ Case_Sensitive => False);
Source_In_Dependencies : Boolean := False;
-- Set True if source was found in dependency file of its object file
Start : Natural;
Finish : Natural;
+ Looping : Boolean := False;
+ -- Set to True at the end of the first Big_Loop
+
begin
+ Canonical_Case_File_Name (C_Object_Name);
+
-- Assume the worst, so that statement "return;" may be used if there
-- is any problem.
return;
end if;
- declare
- End_Of_File_Reached : Boolean := False;
+ -- Loop Big_Loop is executed several times only when the dependency file
+ -- contains several times
+ -- <object file>: <source1> ...
+ -- When there is only one of such occurrence, Big_Loop is exited
+ -- successfully at the beginning of the second loop.
- begin
- loop
- if End_Of_File (Dep_File) then
- End_Of_File_Reached := True;
- exit;
+ Big_Loop :
+ loop
+ declare
+ End_Of_File_Reached : Boolean := False;
+
+ begin
+ loop
+ if End_Of_File (Dep_File) then
+ End_Of_File_Reached := True;
+ exit;
+ end if;
+
+ Get_Line (Dep_File, Name_Buffer, Name_Len);
+
+ exit when Name_Len > 0 and then Name_Buffer (1) /= '#';
+ end loop;
+
+ -- If dependency file contains only empty lines or comments, then
+ -- dependencies are unknown, and the source needs to be
+ -- recompiled.
+
+ if End_Of_File_Reached then
+ -- If we have reached the end of file after the first loop,
+ -- there is nothing else to do.
+
+ exit Big_Loop when Looping;
+
+ if Verbose_Mode then
+ Write_Str (" -> dependency file ");
+ Write_Str (Dep_Name);
+ Write_Line (" is empty");
+ end if;
+
+ Close (Dep_File);
+ return;
end if;
+ end;
- Get_Line (Dep_File, Name_Buffer, Name_Len);
+ Start := 1;
+ Finish := Index (Name_Buffer (1 .. Name_Len), ": ");
- exit when Name_Len > 0 and then Name_Buffer (1) /= '#';
- end loop;
+ if Finish /= 0 then
+ Canonical_Case_File_Name (Name_Buffer (1 .. Finish - 1));
+ end if;
- -- If dependency file contains only empty lines or comments, then
- -- dependencies are unknown, and the source needs to be recompiled.
+ -- First line must start with name of object file, followed by colon
- if End_Of_File_Reached then
+ if Finish = 0 or else
+ Name_Buffer (1 .. Finish - 1) /= C_Object_Name
+ then
if Verbose_Mode then
Write_Str (" -> dependency file ");
Write_Str (Dep_Name);
- Write_Line (" is empty");
+ Write_Line (" has wrong format");
end if;
Close (Dep_File);
return;
- end if;
- end;
- Start := 1;
- Finish := Index (Name_Buffer (1 .. Name_Len), ": ");
+ else
+ Start := Finish + 2;
- -- First line must start with name of object file, followed by colon
+ -- Process each line
- if Finish = 0 or else Name_Buffer (1 .. Finish - 1) /= Object_Name then
- if Verbose_Mode then
- Write_Str (" -> dependency file ");
- Write_Str (Dep_Name);
- Write_Line (" has wrong format");
- end if;
-
- Close (Dep_File);
- return;
+ Line_Loop : loop
+ declare
+ Line : String := Name_Buffer (1 .. Name_Len);
+ Last : Natural := Name_Len;
- else
- Start := Finish + 2;
+ begin
+ Name_Loop : loop
- -- Process each line
+ -- Find the beginning of the next source path name
- Line_Loop : loop
- declare
- Line : constant String := Name_Buffer (1 .. Name_Len);
- Last : constant Natural := Name_Len;
+ while Start < Last and then Line (Start) = ' ' loop
+ Start := Start + 1;
+ end loop;
- begin
- Name_Loop : loop
+ -- Go to next line when there is a continuation character
+ -- \ at the end of the line.
- -- Find the beginning of the next source path name
+ exit Name_Loop when Start = Last
+ and then Line (Start) = '\';
- while Start < Last and then Line (Start) = ' ' loop
- Start := Start + 1;
- end loop;
+ -- We should not be at the end of the line, without
+ -- a continuation character \.
- -- Go to next line when there is a continuation character \
- -- at the end of the line.
+ if Start = Last then
+ if Verbose_Mode then
+ Write_Str (" -> dependency file ");
+ Write_Str (Dep_Name);
+ Write_Line (" has wrong format");
+ end if;
- exit Name_Loop when Start = Last
- and then Line (Start) = '\';
+ Close (Dep_File);
+ return;
+ end if;
- -- We should not be at the end of the line, without
- -- a continuation character \.
+ -- Look for the end of the source path name
+
+ Finish := Start;
+ while Finish < Last loop
+ if Line (Finish) = '\' then
+
+ -- On Windows, a '\' is part of the path name,
+ -- except when it is followed by another '\' or by
+ -- a space. On other platforms, when we are getting
+ -- a '\' that is not the last character of the
+ -- line, the next character is part of the path
+ -- name, even if it is a space.
+
+ if On_Windows
+ and then Line (Finish + 1) /= '\'
+ and then Line (Finish + 1) /= ' '
+ then
+ Finish := Finish + 1;
+
+ else
+ Line (Finish .. Last - 1) :=
+ Line (Finish + 1 .. Last);
+ Last := Last - 1;
+ end if;
- if Start = Last then
- if Verbose_Mode then
- Write_Str (" -> dependency file ");
- Write_Str (Dep_Name);
- Write_Line (" has wrong format");
- end if;
+ else
+ -- A space that is not preceded by '\' indicates
+ -- the end of the path name.
- Close (Dep_File);
- return;
- end if;
+ exit when Line (Finish + 1) = ' ';
- -- Look for the end of the source path name
+ Finish := Finish + 1;
+ end if;
+ end loop;
- Finish := Start;
- while Finish < Last and then Line (Finish + 1) /= ' ' loop
- Finish := Finish + 1;
- end loop;
+ -- Check this source
- -- Check this source
+ declare
+ Src_Name : constant String :=
+ Normalize_Pathname
+ (Name =>
+ Line (Start .. Finish),
+ Resolve_Links => False,
+ Case_Sensitive => False);
+ Src_TS : Time_Stamp_Type;
- declare
- Src_Name : constant String :=
- Normalize_Pathname
- (Name => Line (Start .. Finish),
- Case_Sensitive => False);
- Src_TS : Time_Stamp_Type;
+ begin
+ -- If it is original source, set
+ -- Source_In_Dependencies.
- begin
- -- If it is original source, set Source_In_Dependencies
+ if Src_Name = C_Source_Path then
+ Source_In_Dependencies := True;
+ end if;
- if Src_Name = Source_Path then
- Source_In_Dependencies := True;
- end if;
+ Name_Len := 0;
+ Add_Str_To_Name_Buffer (Src_Name);
+ Src_TS := File_Stamp (File_Name_Type'(Name_Find));
- Name_Len := 0;
- Add_Str_To_Name_Buffer (Src_Name);
- Src_TS := File_Stamp (Name_Find);
+ -- If the source does not exist, we need to recompile
- -- If the source does not exist, we need to recompile
+ if Src_TS = Empty_Time_Stamp then
+ if Verbose_Mode then
+ Write_Str (" -> source ");
+ Write_Str (Src_Name);
+ Write_Line (" does not exist");
+ end if;
- if Src_TS = Empty_Time_Stamp then
- if Verbose_Mode then
- Write_Str (" -> source ");
- Write_Str (Src_Name);
- Write_Line (" does not exist");
- end if;
+ Close (Dep_File);
+ return;
- Close (Dep_File);
- return;
+ -- If the source has been modified after the object
+ -- file, we need to recompile.
- -- If the source has been modified after the object file,
- -- we need to recompile.
+ elsif Src_TS > Source.Object_TS then
+ if Verbose_Mode then
+ Write_Str (" -> source ");
+ Write_Str (Src_Name);
+ Write_Line
+ (" has time stamp later than object file");
+ end if;
- elsif Src_TS > Source.Object_TS then
- if Verbose_Mode then
- Write_Str (" -> source ");
- Write_Str (Src_Name);
- Write_Line
- (" has time stamp later than object file");
+ Close (Dep_File);
+ return;
end if;
+ end;
- Close (Dep_File);
- return;
- end if;
- end;
+ -- If the source path name ends the line, we are done
- -- If the source path name ends the line, we are done.
+ exit Line_Loop when Finish = Last;
- exit Line_Loop when Finish = Last;
+ -- Go get the next source on the line
- -- Go get the next source on the line
+ Start := Finish + 1;
+ end loop Name_Loop;
+ end;
- Start := Finish + 1;
- end loop Name_Loop;
- end;
+ -- If we are here, we had a continuation character \ at the end
+ -- of the line, so we continue with the next line.
- -- If we are here, we had a continuation character \ at the end
- -- of the line, so we continue with the next line.
+ Get_Line (Dep_File, Name_Buffer, Name_Len);
+ Start := 1;
+ end loop Line_Loop;
+ end if;
- Get_Line (Dep_File, Name_Buffer, Name_Len);
- Start := 1;
- end loop Line_Loop;
- end if;
+ -- Set Looping at the end of the first loop
+ Looping := True;
+ end loop Big_Loop;
Close (Dep_File);
return;
end if;
- -- If we are here, then everything is OK, and we don't need
- -- to recompile.
+ -- If we are here, then everything is OK, no need to recompile
if Verbose_Mode then
Write_Line (" -> up to date");
Project_Table.Last (Project_Tree.Projects)
loop
if
- Project_Tree.Projects.Table (Project).Languages
+ Project_Tree.Projects.Table (Project).Langs
(C_Plus_Plus_Language_Index)
then
C_Plus_Plus_Is_Used := True;
procedure Compile
(Source_Id : Other_Source_Id;
- Data : in Project_Data;
+ Data : Project_Data;
Local_Errors : in out Boolean)
is
Source : Other_Source :=
- Project_Tree.Other_Sources.Table (Source_Id);
+ Project_Tree.Other_Sources.Table (Source_Id);
Success : Boolean;
CPATH : String_Access := null;
declare
Dep_File : Ada.Text_IO.File_Type;
Result : Expect_Match;
- Status : Integer;
+
+ Status : Integer;
+ pragma Warnings (Off, Status);
begin
-- Create the dependency file
Delete_File (Get_Name_String (Source.Dep_Name), Success);
exception
- when Process_Died =>
+ when Process_Died =>
-- This is the normal outcome. Just close the file
Close (FD, Status);
Close (Dep_File);
- when others =>
+ when others =>
-- Something wrong happened. It is safer to delete the
-- dependency file, otherwise the dependencies may be wrong.
Add_Argument (Dash_c, True);
- -- Add the compiling switches for this source found in
- -- package Compiler of the project file, if they exist.
+ -- Add the compiling switches for this source found in package Compiler
+ -- of the project file, if they exist.
Add_Switches
(Data, Compiler, Source.Language, Source.File_Name);
Add_Argument (Get_Name_String (Source.Path_Name), True);
-- If non static library project, compile with the PIC option if there
- -- is one (when there is no PIC option, function MLib.Tgt.PIC_Option
- -- returns an empty string, and Add_Argument with an empty string has
- -- no effect).
+ -- is one (when there is no PIC option, MLib.Tgt.PIC_Option returns an
+ -- empty string, and Add_Argument with an empty string has no effect).
if Data.Library and then Data.Library_Kind /= Static then
Add_Argument (PIC_Option, True);
Add_Argument (Dash_o, True);
Add_Argument (Get_Name_String (Source.Object_Name), True);
- -- When compiler is GCC, use the magic switch that creates
- -- the dependency file in the correct format.
+ -- When compiler is GCC, use the magic switch that creates the
+ -- dependency file in the correct format.
if Compiler_Is_Gcc (Source.Language) then
Add_Argument
Verbose_Mode);
end if;
- -- Add the compiling switches for the language specified
- -- on the command line, if any.
+ -- 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
Add_Argument (Options (Source.Language).Table (J), True);
end loop;
- -- Finally, add the imported directory switches for this
- -- project file (or, for gcc compilers, set up the CPATH env var
- -- if needed).
+ -- Finally, add the imported directory switches for this project file
+ -- (or, for gcc compilers, set up the CPATH env var if needed).
Add_Search_Directories (Data, Source.Language);
Project_Tree.Projects.Table (Main_Project);
Source_Id : Other_Source_Id;
Source : Other_Source;
- Source_Name : Name_Id;
+ Source_Name : File_Name_Type;
Project_Name : String := Get_Name_String (Data.Name);
Dummy : Boolean := False;
Ada_Is_A_Language : constant Boolean :=
- Data.Languages (Ada_Language_Index);
+ Data.Langs (Ada_Language_Index);
begin
Ada_Mains.Init;
-- Compilation will occur in the object directory
- Change_Dir (Get_Name_String (Data.Object_Directory));
+ if Project_Of_Current_Object_Directory /= Main_Project then
+ Project_Of_Current_Object_Directory := Main_Project;
+ Change_Dir (Get_Name_String (Data.Object_Directory));
+
+ if Verbose_Mode then
+ Write_Str ("Changing to object directory of """);
+ Write_Name (Data.Name);
+ Write_Str (""": """);
+ Write_Name (Data.Display_Object_Dir);
+ Write_Line ("""");
+ end if;
+ end if;
if not Data.Other_Sources_Present then
if Ada_Is_A_Language then
end loop;
else
- Osint.Fail
- ("project ", Project_Name, " contains no source");
+ Osint.Fail ("project ", Project_Name, " contains no source");
end if;
else
if not Sources_Compiled.Get (Source_Name) then
Sources_Compiled.Set (Source_Name, True);
- Source_Id := Data.First_Other_Source;
+ Source_Id := Data.First_Other_Source;
while Source_Id /= No_Other_Source loop
- Source :=
- Project_Tree.Other_Sources.Table (Source_Id);
+ Source := Project_Tree.Other_Sources.Table (Source_Id);
exit when Source.File_Name = Source_Name;
Source_Id := Source.Next;
end loop;
-- Specify the project file
Add_Argument (Dash_P, True);
- Add_Argument (Get_Name_String (Data.Path_Name), True);
+ Add_Argument (Get_Name_String (Data.Display_Path_Name), True);
- -- Add the -X switches, if any
+ -- Add the saved switches, if any
- for Index in 1 .. X_Switches.Last loop
- Add_Argument (X_Switches.Table (Index), True);
+ for Index in 1 .. Saved_Switches.Last loop
+ Add_Argument (Saved_Switches.Table (Index), True);
end loop;
-- If Mains_Specified is True, find the mains in package Mains
Add_Argument (Dash_d, True);
end if;
+ -- -eL
+
+ if Follow_Links_For_Files then
+ Add_Argument (Dash_eL, True);
+ end if;
+
-- -k
if Keep_Going then
Compiler_Names (Ada_Language_Index).all,
" failed");
end if;
-
end Compile_Link_With_Gnatmake;
---------------------
-- Keep_Going is True, to inhibit the building of the archive.
Need_To_Compile : Boolean;
- -- Set to True when a source needs to be compiled/recompiled.
+ -- Set to True when a source needs to be compiled/recompiled
Need_To_Rebuild_Archive : Boolean := Force_Compilations;
-- True when the archive needs to be built/rebuilt unconditionally
loop
Data := Project_Tree.Projects.Table (Project);
- if (not Data.Virtual) and then Data.Other_Sources_Present then
+ if not Data.Virtual and then Data.Other_Sources_Present then
Source_Id := Data.First_Other_Source;
while Source_Id /= No_Other_Source loop
Source := Project_Tree.Other_Sources.Table (Source_Id);
-- Compilation will occur in the object directory
- Change_Dir (Get_Name_String (Data.Object_Directory));
+ if Project_Of_Current_Object_Directory /= Project then
+ Project_Of_Current_Object_Directory := Project;
+ Change_Dir (Get_Name_String (Data.Object_Directory));
- Source_Id := Data.First_Other_Source;
+ if Verbose_Mode then
+ Write_Str ("Changing to object directory of """);
+ Write_Name (Data.Display_Name);
+ Write_Str (""": """);
+ Write_Name (Data.Display_Object_Dir);
+ Write_Line ("""");
+ end if;
+ end if;
-- Process each source one by one
+ Source_Id := Data.First_Other_Source;
while Source_Id /= No_Other_Source loop
-
Source := Project_Tree.Other_Sources.Table (Source_Id);
Current_Source_Number := Current_Source_Number + 1;
Need_To_Compile := Force_Compilations;
if not Local_Errors
and then Data.Library
- and then not Data.Languages (Ada_Language_Index)
+ and then not Data.Langs (Ada_Language_Index)
and then not Compile_Only
then
Build_Library (Project, Need_To_Rebuild_Archive);
Write_Eol;
Write_Str ("GPRMAKE ");
Write_Str (Gnatvsn.Gnat_Version_String);
- Write_Str (" Copyright 2004 Free Software Foundation, Inc.");
+ Write_Str (" Copyright 2004-");
+ Write_Str (Gnatvsn.Current_Year);
+ Write_Str (" Free Software Foundation, Inc.");
Write_Eol;
end if;
end Copyright;
(Name : String;
First_Source : Other_Source_Id)
is
- Source_Id : Other_Source_Id := First_Source;
+ 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
Create (Dep_File, Append_File, Name);
+ Source_Id := First_Source;
while Source_Id /= No_Other_Source loop
Source := Project_Tree.Other_Sources.Table (Source_Id);
Put_Line (Dep_File, Get_Name_String (Source.Object_Name));
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.
if not Project_Tree.Projects.Table (Project).Library then
Source_Id :=
Project_Tree.Projects.Table (Project).First_Other_Source;
-
while Source_Id /= No_Other_Source loop
Source := Project_Tree.Other_Sources.Table (Source_Id);
---------------------
procedure Display_Command
- (Name : String;
- Path : String_Access;
- CPATH : String_Access := null)
+ (Name : String;
+ Path : String_Access;
+ CPATH : String_Access := null;
+ Ellipse : Boolean := False)
is
+ Display_Ellipse : Boolean := Ellipse;
+
begin
-- Only display the command in Verbose Mode (-v) or when
-- not in Quiet Output (no -q).
if Arguments_Displayed (Arg) then
Write_Char (' ');
Write_Str (Arguments (Arg).all);
+
+ elsif Display_Ellipse then
+ Write_Str (" ...");
+ Display_Ellipse := False;
end if;
end loop;
else
Osint.Fail
- ("unknow compiler name for language """,
+ ("unknown compiler name for language """,
Get_Name_String (Language_Names.Table (For_Language)),
"""");
end if;
---------
procedure Add (Source_Dirs : String_List_Id) is
- Element_Id : String_List_Id := Source_Dirs;
+ Element_Id : String_List_Id;
Element : String_Element;
Add_Arg : Boolean := True;
begin
-- Add each source directory path name, preceded by "-I" to Arguments
+ Element_Id := Source_Dirs;
while Element_Id /= Nil_String loop
Element := Project_Tree.String_Elements.Table (Element_Id);
if Element.Value /= No_Name then
- Get_Name_String (Element.Value);
+ Get_Name_String (Element.Display_Value);
if Name_Len > 0 then
+
-- Remove a trailing directory separator: this may cause
-- problems on Windows.
Arg : constant String :=
"-I" & Name_Buffer (1 .. Name_Len);
begin
- -- Check if directory is already in the list.
- -- If it is, no need to put it again.
+ -- Check if directory is already in the list. If it is,
+ -- no need to put it there again.
+
+ Add_Arg := True;
for Index in 1 .. Last_Argument loop
if Arguments (Index).all = Arg then
Recursive_Get_Dirs (Data.Extends);
- Imported := Data.Imported_Projects;
-
-- Call itself for all imported projects, if any
+ Imported := Data.Imported_Projects;
while Imported /= Empty_Project_List loop
Recursive_Get_Dirs
- (Project_Tree.Project_Lists.Table
- (Imported).Project);
+ (Project_Tree.Project_Lists.Table (Imported).Project);
Imported :=
Project_Tree.Project_Lists.Table (Imported).Next;
end loop;
if Verbose_Mode then
Write_Eol;
- Write_Str ("Parsing Project File """);
+ Write_Str ("Parsing project file """);
Write_Str (Project_File_Name.all);
Write_Str (""".");
Write_Eol;
if Verbose_Mode then
Write_Eol;
- Write_Str ("Parsing of Project File """);
+ Write_Str ("Parsing of project file """);
Write_Str (Project_File_Name.all);
Write_Str (""" is finished.");
Write_Eol;
-- If -c was not specified, link the executables,
-- if there are any.
- if not Compile_Only and then not Data.Library then
+ if not Compile_Only
+ and then not Data.Library
+ and then Data.Object_Directory /= No_Path
+ then
Build_Global_Archive;
Link_Executables;
end if;
procedure Initialize is
begin
+ Set_Mode (Ada_Only);
+
-- Do some necessary package initializations
Csets.Initialize;
Prj.Initialize (Project_Tree);
Mains.Delete;
+ -- Add the directory where gprmake is invoked in front of the path,
+ -- if gprmake is invoked from a bin directory or with directory
+ -- information. Only do this if the platform is not VMS, where the
+ -- notion of path does not really exist.
+
+ -- Below code shares nasty code duplication with make.adb code???
+
+ if not OpenVMS then
+ declare
+ Prefix : constant String := Executable_Prefix_Path;
+ Command : constant String := Command_Name;
+
+ begin
+ if Prefix'Length > 0 then
+ declare
+ PATH : constant String :=
+ Prefix & Directory_Separator & "bin" &
+ Path_Separator &
+ Getenv ("PATH").all;
+ begin
+ Setenv ("PATH", PATH);
+ end;
+
+ else
+ for Index in reverse Command'Range loop
+ if Command (Index) = Directory_Separator then
+ declare
+ Absolute_Dir : constant String :=
+ Normalize_Pathname
+ (Command (Command'First .. Index));
+ PATH : constant String :=
+ Absolute_Dir &
+ Path_Separator &
+ Getenv ("PATH").all;
+ begin
+ Setenv ("PATH", PATH);
+ end;
+
+ exit;
+ end if;
+ end loop;
+ end if;
+ end;
+ end if;
+
-- Set Name_Ide and Name_Compiler_Command
Name_Len := 0;
Add_Str_To_Name_Buffer ("compiler_command");
Name_Compiler_Command := Name_Find;
- -- Make sure the -X switch table is empty
+ -- Make sure the Saved_Switches table is empty
- X_Switches.Set_Last (0);
+ Saved_Switches.Set_Last (0);
-- Get the command line arguments
-----------------------------------
function Is_Included_In_Global_Archive
- (Object_Name : Name_Id;
+ (Object_Name : File_Name_Type;
Project : Project_Id) return Boolean
is
Data : Project_Data := Project_Tree.Projects.Table (Project);
Mains_Specified : constant Boolean := Mains.Number_Of_Mains /= 0;
-- True if main sources were specified on the command line
- Object_Dir : constant String := Get_Name_String (Data.Object_Directory);
+ Object_Dir : constant String :=
+ Get_Name_String (Data.Display_Object_Dir);
-- Path of the object directory of the main project
Source_Id : Other_Source_Id;
procedure Link_Foreign
(Main : String;
- Main_Id : Name_Id;
+ Main_Id : File_Name_Type;
Source : Other_Source);
-- Link a non-Ada main, when there is no Ada code
procedure Add_C_Plus_Plus_Link_For_Gnatmake is
begin
- if Compiler_Is_Gcc (C_Plus_Plus_Language_Index) then
- Add_Argument
- ("--LINK=" & Compiler_Names (C_Plus_Plus_Language_Index).all,
- Verbose_Mode);
-
- else
- Add_Argument
- ("--LINK=" &
- Object_Dir & Directory_Separator &
- Cpp_Linker,
- Verbose_Mode);
- end if;
+ Add_Argument
+ ("--LINK=" & Compiler_Names (C_Plus_Plus_Language_Index).all,
+ Verbose_Mode);
end Add_C_Plus_Plus_Link_For_Gnatmake;
-----------------------
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_Path : constant String := Get_Name_String
+ (Prj_Data.Display_Object_Dir) & Directory_Separator
+ & "lib" & Get_Name_String (Prj_Data.Display_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);
+ Add_Str_To_Name_Buffer (Archive_Path);
+ Archive_TS := File_Stamp (File_Name_Type'(Name_Find));
-- If the archive is later than the
-- executable, we need to relink.
if Compiler_Names (C_Plus_Plus_Language_Index) = null then
Get_Compiler (C_Plus_Plus_Language_Index);
end if;
-
- if not Compiler_Is_Gcc (C_Plus_Plus_Language_Index) then
- Change_Dir (Object_Dir);
-
- declare
- File : Ada.Text_IO.File_Type;
- use Ada.Text_IO;
-
- begin
- Create (File, Out_File, Cpp_Linker);
-
- Put_Line (File, "#!/bin/sh");
-
- Put_Line (File, "LIBGCC=`gcc -print-libgcc-file-name`");
- Put_Line
- (File,
- Compiler_Names (C_Plus_Plus_Language_Index).all &
- " $* ${LIBGCC}");
-
- Close (File);
- Set_Executable (Cpp_Linker);
- end;
- end if;
end Choose_C_Plus_Plus_Link_Process;
------------------
procedure Link_Foreign
(Main : String;
- Main_Id : Name_Id;
+ Main_Id : File_Name_Type;
Source : Other_Source)
is
Executable_Name : constant String :=
Executable_Path : constant String :=
Get_Name_String
- (Data.Exec_Directory) &
- Directory_Separator &
- Executable_Name;
+ (Data.Display_Exec_Dir) &
+ Directory_Separator & Executable_Name;
-- Path name of the executable
Exec_Time_Stamp : Time_Stamp_Type;
Name_Len := 0;
Add_Str_To_Name_Buffer (Executable_Path);
- Exec_Time_Stamp := File_Stamp (Name_Find);
+ Exec_Time_Stamp := File_Stamp (File_Name_Type'(Name_Find));
if Verbose_Mode then
Write_Str (" Checking executable ");
Add_Argument (Dash_o, True);
Add_Argument
- (Get_Name_String (Data.Exec_Directory) &
+ (Get_Name_String (Data.Display_Exec_Dir) &
Directory_Separator &
Get_Name_String
(Executable_Of
-- Add the linking options specified on the
-- command line.
- for Arg in 1 .. Linker_Options.Last loop
+ for Arg in 1 .. Linker_Options.Last loop
Add_Argument (Linker_Options.Table (Arg), True);
end loop;
if not Mains_Specified then
declare
- Element_Id : String_List_Id := Data.Mains;
+ Element_Id : String_List_Id;
Element : String_Element;
begin
+ Element_Id := Data.Mains;
while Element_Id /= Nil_String loop
- Element := Project_Tree.String_Elements.Table
- (Element_Id);
+ Element := Project_Tree.String_Elements.Table (Element_Id);
if Element.Value /= No_Name then
Mains.Add_Main (Get_Name_String (Element.Value));
-- Only Ada sources in the main project, and even maybe not
- if not Data.Languages (Ada_Language_Index) then
-
+ if Data.Extends = No_Project and then
+ not Data.Langs (Ada_Language_Index)
+ then
-- Fail if the main project has no source of any language
Osint.Fail
-- There are other language sources. First check if there are also
-- sources in Ada.
- if Data.Languages (Ada_Language_Index) then
+ if Data.Langs (Ada_Language_Index) 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.
+ -- Find the mains of the other languages and the Ada mains
Mains.Reset;
Ada_Mains.Set_Last (0);
loop
declare
Main : constant String := Mains.Next_Main;
- Main_Id : Name_Id;
+ Main_Id : File_Name_Type;
begin
exit when Main'Length = 0;
Add_Str_To_Name_Buffer (Main);
Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
Main_Id := Name_Find;
- Source_Id := Data.First_Other_Source;
-- Check if it is a source of a language other than Ada
+ Source_Id := Data.First_Other_Source;
while Source_Id /= No_Other_Source loop
Source :=
Project_Tree.Other_Sources.Table (Source_Id);
-- If C++ is one of the languages, add the --LINK switch to
-- the linking switches.
- if Data.Languages (C_Plus_Plus_Language_Index) then
+ if Data.Langs (C_Plus_Plus_Language_Index) then
Add_Argument (Dash_largs, Verbose_Mode);
Add_C_Plus_Plus_Link_For_Gnatmake;
Add_Argument (Dash_margs, Verbose_Mode);
-- First, get the linker to invoke
- if Data.Languages (C_Plus_Plus_Language_Index) then
+ if Data.Langs (C_Plus_Plus_Language_Index) then
Get_Compiler (C_Plus_Plus_Language_Index);
Linker_Name := Compiler_Names (C_Plus_Plus_Language_Index);
Linker_Path := Compiler_Paths (C_Plus_Plus_Language_Index);
loop
declare
- Main : constant String := Mains.Next_Main;
- Main_Id : Name_Id;
+ Main : constant String := Mains.Next_Main;
+ Main_Id : File_Name_Type;
+
begin
exit when Main'Length = 0;
Add_Str_To_Name_Buffer (Main);
Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
Main_Id := Name_Find;
- Source_Id := Data.First_Other_Source;
-- Check if it is a source of the main project file
+ Source_Id := Data.First_Other_Source;
while Source_Id /= No_Other_Source loop
Source :=
Project_Tree.Other_Sources.Table (Source_Id);
declare
Main : constant String := Mains.Next_Main;
- Main_Id : Name_Id;
+ Main_Id : File_Name_Type;
begin
Name_Len := 0;
Add_Str_To_Name_Buffer (Main);
-- Switches start with '-'
elsif Arg (1) = '-' then
- if Arg = "-c" then
+ if Arg'Length > 3 and then Arg (1 .. 3) = "-aP" then
+ Add_Search_Project_Directory (Arg (4 .. Arg'Last));
+
+ -- Record the switch, so that it is passed to gnatmake, if
+ -- gnatmake is called.
+
+ Saved_Switches.Append (new String'(Arg));
+
+ elsif Arg = "-c" then
Compile_Only := True;
-- Make sure that when a main is specified and switch -c is used,
elsif Arg = "-d" then
Display_Compilation_Progress := True;
+ elsif Arg = "-eL" then
+ Follow_Links_For_Files := True;
+
elsif Arg = "-f" then
Force_Compilations := True;
Project_File_Name := new String'(Arg (3 .. Arg'Last));
end if;
+ elsif Arg = "-p" or else Arg = "--create-missing-dirs" then
+ Setup_Projects := True;
+
elsif Arg = "-q" then
Quiet_Output := True;
then
-- Is_External_Assignment has side effects when it returns True
- -- Record the -X switch, so that they can be passed to gnatmake,
+ -- Record the -X switch, so that it will be passed to gnatmake,
-- if gnatmake is called.
- X_Switches.Increment_Last;
- X_Switches.Table (X_Switches.Last) := new String'(Arg);
+ Saved_Switches.Append (new String'(Arg));
else
Osint.Fail ("illegal option """, Arg, """");
Write_Str ("Usage: ");
Osint.Write_Program_Name;
Write_Str (" -P<project file> [opts] [name] {");
-
- for Lang in First_Language_Indexes loop
- Write_Str ("[-cargs:lang opts] ");
- end loop;
-
+ Write_Str ("[-cargs:lang opts] ");
Write_Str ("[-largs opts] [-gargs opts]}");
Write_Eol;
Write_Eol;
Write_Str ("gprmake switches:");
Write_Eol;
+ -- Line for -aP
+
+ Write_Str (" -aPdir Add directory dir to project search path");
+ Write_Eol;
+
-- Line for -c
Write_Str (" -c Compile only");
Write_Eol;
+ -- Line for -eL
+
+ Write_Str (" -eL Follow symbolic links when processing " &
+ "project files");
+ Write_Eol;
+
-- Line for -f
Write_Str (" -f Force recompilations");
Write_Str (" -o name Choose an alternate executable name");
Write_Eol;
+ -- Line for -p
+
+ Write_Str (" -p Create missing obj, lib and exec dirs");
+ Write_Eol;
+
-- Line for -P
Write_Str (" -Pproj Use GNAT Project File proj");