blob: cf28b1ec1da4a9dd8cb815905cbf75e306726edd [file] [log] [blame]
------------------------------------------------------------------------------
-- --
-- GNAT COMPILER COMPONENTS --
-- --
-- M A K E U T L --
-- --
-- S p e c --
-- --
-- Copyright (C) 2004-2014, 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 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 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. --
-- --
------------------------------------------------------------------------------
-- This package contains various subprograms used by the builders, in
-- particular those subprograms related to project management and build
-- queue management.
with ALI;
with Namet; use Namet;
with Opt;
with Osint;
with Prj; use Prj;
with Prj.Tree;
with Snames; use Snames;
with Table;
with Types; use Types;
with GNAT.OS_Lib; use GNAT.OS_Lib;
package Makeutl is
type Fail_Proc is access procedure (S : String);
-- Pointer to procedure which outputs a failure message
Root_Environment : Prj.Tree.Environment;
-- The environment coming from environment variables and command line
-- switches. When we do not have an aggregate project, this is used for
-- parsing the project tree. When we have an aggregate project, this is
-- used to parse the aggregate project; the latter then generates another
-- environment (with additional external values and project path) to parse
-- the aggregated projects.
Default_Config_Name : constant String := "default.cgpr";
-- Name of the configuration file used by gprbuild and generated by
-- gprconfig by default.
On_Windows : constant Boolean := Directory_Separator = '\';
-- True when on Windows
Source_Info_Option : constant String := "--source-info=";
-- Switch to indicate the source info file
Subdirs_Option : constant String := "--subdirs=";
-- Switch used to indicate that the real directories (object, exec,
-- library, ...) are subdirectories of those in the project file.
Unchecked_Shared_Lib_Imports : constant String :=
"--unchecked-shared-lib-imports";
-- Command line switch to allow shared library projects to import projects
-- that are not shared library projects.
Single_Compile_Per_Obj_Dir_Switch : constant String :=
"--single-compile-per-obj-dir";
-- Switch to forbid simultaneous compilations for the same object directory
-- when project files are used.
Create_Map_File_Switch : constant String := "--create-map-file";
-- Switch to create a map file when an executable is linked
No_Exit_Message_Option : constant String := "--no-exit-message";
-- Switch to suppress exit error message when there are compilation
-- failures. This is useful when a tool, such as gnatprove, silently calls
-- the builder and does not want to pollute its output with error messages
-- coming from the builder. This is an internal switch.
Keep_Temp_Files_Option : constant String := "--keep-temp-files";
-- Switch to suppress deletion of temp files created by the builder.
-- Note that debug switch -gnatdn also has this effect.
Load_Standard_Base : Boolean := True;
-- False when gprbuild is called with --db-
package Db_Switch_Args is new Table.Table
(Table_Component_Type => Name_Id,
Table_Index_Type => Integer,
Table_Low_Bound => 1,
Table_Initial => 200,
Table_Increment => 100,
Table_Name => "Makegpr.Db_Switch_Args");
-- Table of all the arguments of --db switches of gprbuild
package Directories is new Table.Table
(Table_Component_Type => Path_Name_Type,
Table_Index_Type => Integer,
Table_Low_Bound => 1,
Table_Initial => 200,
Table_Increment => 100,
Table_Name => "Makegpr.Directories");
-- Table of all the source or object directories, filled up by
-- Get_Directories.
procedure Add
(Option : String_Access;
To : in out String_List_Access;
Last : in out Natural);
procedure Add
(Option : String;
To : in out String_List_Access;
Last : in out Natural);
-- Add a string to a list of strings
function Absolute_Path
(Path : Path_Name_Type;
Project : Project_Id) return String;
-- Returns an absolute path for a configuration pragmas file
function Create_Binder_Mapping_File
(Project_Tree : Project_Tree_Ref) return Path_Name_Type;
-- Create a binder mapping file and returns its path name
function Create_Name (Name : String) return File_Name_Type;
function Create_Name (Name : String) return Name_Id;
function Create_Name (Name : String) return Path_Name_Type;
-- Get an id for a name
function Base_Name_Index_For
(Main : String;
Main_Index : Int;
Index_Separator : Character) return File_Name_Type;
-- Returns the base name of Main, without the extension, followed by the
-- Index_Separator followed by the Main_Index if it is non-zero.
function Executable_Prefix_Path return String;
-- Return the absolute path parent directory of the directory where the
-- current executable resides, if its directory is named "bin", otherwise
-- return an empty string. When a directory is returned, it is guaranteed
-- to end with a directory separator.
procedure Inform (N : Name_Id := No_Name; Msg : String);
procedure Inform (N : File_Name_Type; Msg : String);
-- Prints out the program name followed by a colon, N and S
function File_Not_A_Source_Of
(Project_Tree : Project_Tree_Ref;
Uname : Name_Id;
Sfile : File_Name_Type) return Boolean;
-- Check that file name Sfile is one of the source of unit Uname. Returns
-- True if the unit is in one of the project file, but the file name is not
-- one of its source. Returns False otherwise.
function Check_Source_Info_In_ALI
(The_ALI : ALI.ALI_Id;
Tree : Project_Tree_Ref) return Name_Id;
-- Check whether all file references in ALI are still valid (i.e. the
-- source files are still associated with the same units). Return the name
-- of the unit if everything is still valid. Return No_Name otherwise.
procedure Ensure_Absolute_Path
(Switch : in out String_Access;
Parent : String;
Do_Fail : Fail_Proc;
For_Gnatbind : Boolean := False;
Including_Non_Switch : Boolean := True;
Including_RTS : Boolean := False);
-- Do nothing if Switch is an absolute path switch. If relative, fail if
-- Parent is the empty string, otherwise prepend the path with Parent. This
-- subprogram is only used when using project files. If For_Gnatbind is
-- True, consider gnatbind specific syntax for -L (not a path, left
-- unchanged) and -A (path is optional, preceded with "=" if present).
-- If Including_RTS is True, process also switches --RTS=. Do_Fail is
-- called in case of error. Using Osint.Fail might be appropriate.
function Is_Subunit (Source : Source_Id) return Boolean;
-- Return True if source is a subunit
procedure Initialize_Source_Record (Source : Source_Id);
-- Get information either about the source file, or the object and
-- dependency file, as well as their timestamps.
function Is_External_Assignment
(Env : Prj.Tree.Environment;
Argv : String) return Boolean;
-- Verify that an external assignment switch is syntactically correct
--
-- Correct forms are:
--
-- -Xname=value
-- -X"name=other value"
--
-- Assumptions: 'First = 1, Argv (1 .. 2) = "-X"
--
-- When this function returns True, the external assignment has been
-- entered by a call to Prj.Ext.Add, so that in a project file, External
-- ("name") will return "value".
type Name_Ids is array (Positive range <>) of Name_Id;
No_Names : constant Name_Ids := (1 .. 0 => No_Name);
-- Name_Ids is used for list of language names in procedure Get_Directories
-- below.
Ada_Only : constant Name_Ids := (1 => Name_Ada);
-- Used to invoke Get_Directories in gnatmake
type Activity_Type is (Compilation, Executable_Binding, SAL_Binding);
procedure Get_Directories
(Project_Tree : Project_Tree_Ref;
For_Project : Project_Id;
Activity : Activity_Type;
Languages : Name_Ids);
-- Put in table Directories the source (when Sources is True) or
-- object/library (when Sources is False) directories of project
-- For_Project and of all the project it imports directly or indirectly.
-- The source directories of imported projects are only included if one
-- of the declared languages is in the list Languages.
function Aggregate_Libraries_In (Tree : Project_Tree_Ref) return Boolean;
-- Return True iff there is one or more aggregate library projects in
-- the project tree Tree.
procedure Write_Path_File (FD : File_Descriptor);
-- Write in the specified open path file the directories in table
-- Directories, then closed the path file.
procedure Get_Switches
(Source : Source_Id;
Pkg_Name : Name_Id;
Project_Tree : Project_Tree_Ref;
Value : out Variable_Value;
Is_Default : out Boolean);
procedure Get_Switches
(Source_File : File_Name_Type;
Source_Lang : Name_Id;
Source_Prj : Project_Id;
Pkg_Name : Name_Id;
Project_Tree : Project_Tree_Ref;
Value : out Variable_Value;
Is_Default : out Boolean;
Test_Without_Suffix : Boolean := False;
Check_ALI_Suffix : Boolean := False);
-- Compute the switches (Compilation switches for instance) for the given
-- file. This checks various attributes to see if there are file specific
-- switches, or else defaults on the switches for the corresponding
-- language. Is_Default is set to False if there were file-specific
-- switches. Source_File can be set to No_File to force retrieval of the
-- default switches. If Test_Without_Suffix is True, and there is no "for
-- Switches(Source_File) use", then this procedure also tests without the
-- extension of the filename. If Test_Without_Suffix is True and
-- Check_ALI_Suffix is True, then we also replace the file extension with
-- ".ali" when testing.
function Linker_Options_Switches
(Project : Project_Id;
Do_Fail : Fail_Proc;
In_Tree : Project_Tree_Ref) return String_List;
-- Collect the options specified in the Linker'Linker_Options attributes
-- of project Project, in project tree In_Tree, and in the projects that
-- it imports directly or indirectly, and returns the result.
function Path_Or_File_Name (Path : Path_Name_Type) return String;
-- Returns a file name if -df is used, otherwise return a path name
function Unit_Index_Of (ALI_File : File_Name_Type) return Int;
-- Find the index of a unit in a source file. Return zero if the file is
-- not a multi-unit source file.
procedure Verbose_Msg
(N1 : Name_Id;
S1 : String;
N2 : Name_Id := No_Name;
S2 : String := "";
Prefix : String := " -> ";
Minimum_Verbosity : Opt.Verbosity_Level_Type := Opt.Low);
procedure Verbose_Msg
(N1 : File_Name_Type;
S1 : String;
N2 : File_Name_Type := No_File;
S2 : String := "";
Prefix : String := " -> ";
Minimum_Verbosity : Opt.Verbosity_Level_Type := Opt.Low);
-- If the verbose flag (Verbose_Mode) is set and the verbosity level is at
-- least equal to Minimum_Verbosity, then print Prefix to standard output
-- followed by N1 and S1. If N2 /= No_Name then N2 is printed after S1. S2
-- is printed last. Both N1 and N2 are printed in quotation marks. The two
-- forms differ only in taking Name_Id or File_name_Type arguments.
-------------------------
-- Program termination --
-------------------------
procedure Fail_Program
(Project_Tree : Project_Tree_Ref;
S : String;
Flush_Messages : Boolean := True);
-- Terminate program with a message and a fatal status code
procedure Finish_Program
(Project_Tree : Project_Tree_Ref;
Exit_Code : Osint.Exit_Code_Type := Osint.E_Success;
S : String := "");
-- Terminate program, with or without a message, setting the status code
-- according to Fatal. This properly removes all temporary files.
--------------
-- Switches --
--------------
generic
with function Add_Switch
(Switch : String;
For_Lang : Name_Id;
For_Builder : Boolean;
Has_Global_Compilation_Switches : Boolean) return Boolean;
-- For_Builder is true if we have a builder switch. This function
-- should return True in case of success (the switch is valid),
-- False otherwise. The error message will be displayed by
-- Compute_Builder_Switches itself.
--
-- Has_Global_Compilation_Switches is True if the attribute
-- Global_Compilation_Switches is defined in the project.
procedure Compute_Builder_Switches
(Project_Tree : Project_Tree_Ref;
Env : in out Prj.Tree.Environment;
Main_Project : Project_Id;
Only_For_Lang : Name_Id := No_Name);
-- Compute the builder switches and global compilation switches. Every time
-- a switch is found in the project, it is passed to Add_Switch. You can
-- provide a value for Only_For_Lang so that we only look for this language
-- when parsing the global compilation switches.
-----------------------
-- Project_Tree data --
-----------------------
-- The following types are specific to builders, and associated with each
-- of the loaded project trees.
type Binding_Data_Record;
type Binding_Data is access Binding_Data_Record;
type Binding_Data_Record is record
Language : Language_Ptr;
Language_Name : Name_Id;
Binder_Driver_Name : File_Name_Type;
Binder_Driver_Path : String_Access;
Binder_Prefix : Name_Id;
Next : Binding_Data;
end record;
-- Data for a language that have a binder driver
type Builder_Project_Tree_Data is new Project_Tree_Appdata with record
Binding : Binding_Data;
There_Are_Binder_Drivers : Boolean := False;
-- True when there is a binder driver. Set by Get_Configuration when
-- an attribute Language_Processing'Binder_Driver is declared.
-- Reset to False if there are no sources of the languages with binder
-- drivers.
Number_Of_Mains : Natural := 0;
-- Number of main units in this project tree
Closure_Needed : Boolean := False;
-- If True, we need to add the closure of the file we just compiled to
-- the queue. If False, it is assumed that all files are already on the
-- queue so we do not waste time computing the closure.
Need_Compilation : Boolean := True;
Need_Binding : Boolean := True;
Need_Linking : Boolean := True;
-- Which of the compilation phases are needed for this project tree
end record;
type Builder_Data_Access is access all Builder_Project_Tree_Data;
procedure Free (Data : in out Builder_Project_Tree_Data);
-- Free all memory allocated for Data
function Builder_Data (Tree : Project_Tree_Ref) return Builder_Data_Access;
-- Return (allocate if needed) tree-specific data
procedure Compute_Compilation_Phases
(Tree : Project_Tree_Ref;
Root_Project : Project_Id;
Option_Unique_Compile : Boolean := False; -- Was "-u" specified ?
Option_Compile_Only : Boolean := False; -- Was "-c" specified ?
Option_Bind_Only : Boolean := False;
Option_Link_Only : Boolean := False);
-- Compute which compilation phases will be needed for Tree. This also does
-- the computation for aggregated trees. This also check whether we'll need
-- to check the closure of the files we have just compiled to add them to
-- the queue.
-----------
-- Mains --
-----------
-- Package Mains is used to store the mains specified on the command line
-- and to retrieve them when a project file is used, to verify that the
-- files exist and that they belong to a project file.
-- Mains are stored in a table. An index is used to retrieve the mains
-- from the table.
type Main_Info is record
File : File_Name_Type; -- Always canonical casing
Index : Int := 0;
Location : Source_Ptr := No_Location;
Source : Prj.Source_Id := No_Source;
Project : Project_Id;
Tree : Project_Tree_Ref;
end record;
No_Main_Info : constant Main_Info :=
(No_File, 0, No_Location, No_Source, No_Project, null);
package Mains is
procedure Add_Main
(Name : String;
Index : Int := 0;
Location : Source_Ptr := No_Location;
Project : Project_Id := No_Project;
Tree : Project_Tree_Ref := null);
-- Add one main to the table. This is in general used to add the main
-- files specified on the command line. Index is used for multi-unit
-- source files, and indicates which unit in the source is concerned.
-- Location is the location within the project file (if a project file
-- is used). Project and Tree indicate to which project the main should
-- belong. In particular, for aggregate projects, this isn't necessarily
-- the main project tree. These can be set to No_Project and null when
-- not using projects.
procedure Delete;
-- Empty the table
procedure Reset;
-- Reset the cursor to the beginning of the table
procedure Set_Multi_Unit_Index
(Project_Tree : Project_Tree_Ref := null;
Index : Int := 0);
-- If a single main file was defined, this subprogram indicates which
-- unit inside it is the main (case of a multi-unit source files).
-- Errors are raised if zero or more than one main file was defined,
-- and Index is non-zaero. This subprogram is used for the handling
-- of the command line switch.
function Next_Main return String;
function Next_Main return Main_Info;
-- Moves the cursor forward and returns the new current entry. Returns
-- No_Main_Info there are no more mains in the table.
function Number_Of_Mains (Tree : Project_Tree_Ref) return Natural;
-- Returns the number of mains in this project tree (if Tree is null, it
-- returns the total number of project trees)
procedure Fill_From_Project
(Root_Project : Project_Id;
Project_Tree : Project_Tree_Ref);
-- If no main was already added (presumably from the command line), add
-- the main units from root_project (or in the case of an aggregate
-- project from all the aggregated projects).
procedure Complete_Mains
(Flags : Processing_Flags;
Root_Project : Project_Id;
Project_Tree : Project_Tree_Ref);
-- If some main units were already added from the command line, check
-- that they all belong to the root project, and that they are full
-- paths rather than (partial) base names (e.g. no body suffix was
-- specified).
end Mains;
-----------
-- Queue --
-----------
type Source_Info_Format is (Format_Gprbuild, Format_Gnatmake);
package Queue is
-- The queue of sources to be checked for compilation. There can be a
-- single such queue per application.
type Source_Info (Format : Source_Info_Format := Format_Gprbuild) is
record
case Format is
when Format_Gprbuild =>
Tree : Project_Tree_Ref := No_Project_Tree;
Id : Source_Id := No_Source;
Closure : Boolean := False;
when Format_Gnatmake =>
File : File_Name_Type := No_File;
Unit : Unit_Name_Type := No_Unit_Name;
Index : Int := 0;
Project : Project_Id := No_Project;
Sid : Source_Id := No_Source;
end case;
end record;
-- Information about files stored in the queue. The exact information
-- depends on the builder, and in particular whether it only supports
-- project-based files (in which case we have a full Source_Id record).
No_Source_Info : constant Source_Info :=
(Format_Gprbuild, null, null, False);
procedure Initialize
(Queue_Per_Obj_Dir : Boolean;
Force : Boolean := False);
-- Initialize the queue
--
-- Queue_Per_Obj_Dir matches the --single-compile-per-obj-dir switch:
-- when True, there cannot be simultaneous compilations with the object
-- files in the same object directory when project files are used.
--
-- Nothing is done if Force is False and the queue was already
-- initialized.
procedure Remove_Marks;
-- Remove all marks set for the files. This means that the files will be
-- handed to the compiler if they are added to the queue, and is mostly
-- useful when recompiling several executables in non-project mode, as
-- the switches may be different and -s may be in use.
function Is_Empty return Boolean;
-- Returns True if the queue is empty
function Is_Virtually_Empty return Boolean;
-- Returns True if queue is empty or if all object directories are busy
procedure Insert (Source : Source_Info; With_Roots : Boolean := False);
function Insert
(Source : Source_Info; With_Roots : Boolean := False) return Boolean;
-- Insert source in the queue. The second version returns False if the
-- Source was already marked in the queue. If With_Roots is True and the
-- source is in Format_Gprbuild mode (ie with a project), this procedure
-- also includes the "Roots" for this main, ie all the other files that
-- must be included in the library or binary (in particular to combine
-- Ada and C files connected through pragma Export/Import). When the
-- roots are computed, they are also stored in the corresponding
-- Source_Id for later reuse by the binder.
procedure Insert_Project_Sources
(Project : Project_Id;
Project_Tree : Project_Tree_Ref;
All_Projects : Boolean;
Unique_Compile : Boolean);
-- Insert all the compilable sources of the project in the queue. If
-- All_Project is true, then all sources from imported projects are also
-- inserted. Unique_Compile should be true if "-u" was specified on the
-- command line: if True and some files were given on the command line),
-- only those files will be compiled (so Insert_Project_Sources will do
-- nothing). If True and no file was specified on the command line, all
-- files of the project(s) will be compiled. This procedure also
-- processed aggregated projects.
procedure Insert_Withed_Sources_For
(The_ALI : ALI.ALI_Id;
Project_Tree : Project_Tree_Ref;
Excluding_Shared_SALs : Boolean := False);
-- Insert in the queue those sources withed by The_ALI, if there are not
-- already in the queue and Only_Interfaces is False or they are part of
-- the interfaces of their project.
procedure Extract
(Found : out Boolean;
Source : out Source_Info);
-- Get the first source that can be compiled from the queue. If no
-- source may be compiled, sets Found to False. In this case, the value
-- for Source is undefined.
function Size return Natural;
-- Return the total size of the queue, including the sources already
-- extracted.
function Processed return Natural;
-- Return the number of source in the queue that have aready been
-- processed.
procedure Set_Obj_Dir_Busy (Obj_Dir : Path_Name_Type);
procedure Set_Obj_Dir_Free (Obj_Dir : Path_Name_Type);
-- Mark Obj_Dir as busy or free (see the parameter to Initialize)
function Element (Rank : Positive) return File_Name_Type;
-- Get the file name for element of index Rank in the queue
end Queue;
end Makeutl;