.. _Project_Setup: ************* Project Setup ************* GNAT SAS requires a GNAT project file (a.k.a. GPR project file) to run. If you are using a third party compiler, this chapter starts with :ref:`a quick walk-through` for the creation of an initial gpr file, as well as common configuration for this setup. If you already have a project file that you use to compile with gprbuild, you should look at :ref:`the second section` to ensure that it works well with GNAT SAS. Finally, :ref:`the last section` explains how to configure the GNAT SAS analysis and goes on with describing specific configurations of integrated engines. .. seealso:: Refer to the `GNAT Project Manager `_ section of the GPR Tool's User Guide for general documentation about projects. .. _gnat_setup: Configuration for the GNAT Pro compiler ======================================= GNAT SAS is able to analyze code bases built with any compiler and targeting any architecture/runtime. However, GNAT SAS is easiest to use when analyzing a code base built with a GNAT Pro of the same version. When using GNAT SAS to analyze a cross-target project built with an older GNAT Pro version, the GNAT Warnings and Inspector engines may lose precision and analyze less code. The GNATcheck and Infer engines will however be unaffected. For the analysis of a project that requires building with an older GNAT Pro version (e.g. running an analysis with a GNAT SAS wavefront on a project built with GNAT Pro 21.8), we strongly recommend keeping your project compatible with more recent versions of GNAT Pro. When keeping projects compatible with more recent GNAT Pro versions is not possible, we recommend keeping said projects compatible with an x86_64-linux or x86_64-windows target and runtime instead. .. _no_gnat_setup: Configuration for Third Party Compilers ======================================= This section guides you through the typical steps to setup your project in order to use GNAT SAS when you do not use GNAT to compile your sources. 1. First, you need to :ref:`create a GPR project file`. In order to do so we recommend using `codepeer-gprname` as described :ref:`here`. Indeed, while the resulting project file needs to be updated each time you modify the sources included in the project, `codepeer-gprname` will highlight early problems that the analysis would eventually encounter. At this stage, the project file should contain enough information to identify all the sources of the project (if you used `codeper-gprname`, they are listed in the :file:`prj_source_list.txt` file). By default, GNAT SAS will analyze all of them. However, if there are files that you do not wish to analyze, these should be excluded from the analysis in a second stage (see :ref:`this section`). Indeed, the project should be as "compilable" as possible for the analysis to perform correctly. .. warning:: Your project should not include the sources of your run-time. 2. You should set your target to "gnatsas" with the `Target` attribute: .. code-block:: gpr project is for Target use "gnatsas"; […] You should **not** use the `Runtime` attribute, in particular Section :ref:`Target_Runtime` does not apply since it only works with a runtime from GNAT. 3. You may want to specify a :ref:`Target_Configuration_File` in order to provide target dependent values, such as endianness, type sizes, etc. 4. If you use supported compiler-specific packages, you need to set your project file to :ref:`use them`. Once done, you should be able to confirm that the project is properly set up by running a first analysis with the command: .. code-block:: shell gnatsas analyze -P .gpr You can then look at how to run the tool :ref:`in this section`, and complete your project file by :ref:`Configuring_Analysis`. .. _Creating_Project_File: Creating a Project File ======================= In this section, we present different ways to create a project file if your project does not yet contain one: 1. Create a project file interactively using the Project Wizard in GNAT Studio; 2. Create a project file manually; 3. Use `codepeer-gprname` to automatically generate it. We recommend taking the time to follow either option 1 or 2, as the generated project files in option 3 may be hard to understand, modify and hence maintain. .. _GS_GPR_Creation: Creating a Project File with GNAT Studio ---------------------------------------- Please refer to GNAT Studio's documentation to discover how to generate project files from GNAT Studio using the `Project Wizard `_. .. _Creating_Project_File_Manually: Creating a Project File Manually -------------------------------- If your source code follows the default naming scheme (:file:`.ads`/ :file:`.adb`), then you can create a project file that will look like: .. code-block:: gpr project My_Project is for Source_Dirs use ("./**"); for Target use "gnatsas"; end My_Project; saved in a file called ``my_project.gpr`` located in the root of the project tree. Note that you can specify as many source directories as needed as part of the ``Source_Dirs`` setting. The special syntax ``dir/**`` represents the directory :file:`dir` and all its subdirectories recursively (in the above example, the current directory represented by :file:`.` and all its subdirectories). Specifying ``gnatsas`` for the target will allow the analysis engines to find the Ada runtime bundled with GNAT SAS. .. _Generating_Project_File: Generating a Project File ------------------------- A project file can be generated from an existing directory structure using the ``codepeer-gprname`` utility. Whenever a new source file is added to the project or an existing source file is removed, ``codepeer-gprname`` needs to be re-run to update the project. Here is the typical usage of ``codepeer-gprname``:: codepeer-gprname -Pmy_project "-d./**" "*.ad?" "*.spc" "*.bdy" It will create or update a project file called :file:`my_project.gpr` listing all the Ada source files found under the current directory and all its subdirectories, whose name follow the given patterns (all files ending with ``.ad``, all files ending with ``.spc`` and all files ending with ``.bdy``). Note that ``codepeer-gprname`` requires a writable temporary directory. If the project file generated is empty, you might need to set the environment variable ``TMPDIR`` to a writable directory. See the `gprname documentation`__ in the GNAT User's Guide for more details on how to use ``gprname``. __ https://docs.adacore.com/live/wave/gprbuild/html/gprbuild_ug/gprbuild_ug/companion_tools.html#specifying-a-naming-scheme-with-gprname .. _Project_File_Setup: Ensuring compatibility with GNAT SAS ==================================== .. note:: This section assumes that a project file has been defined for the codebase to analyse. If that is not the case, refer to the instructions in :ref:`Creating_Project_File`. This section describes how to configure the project file so that: * specificities of the code to analyze and of the target are taken into account; * general aspects related to the analysis of Ada packages are considered; * specific aspects related to GNAT SAS analysis engines that rely on the GNAT compiler are taken into account; * ultimately, it can be correctly understood by GNAT SAS. .. warning:: This section *does not* describe the configuration of the GNAT SAS analysis. That is described in :ref:`Configuring_Analysis`. .. _GNAT_SAS_Specific_Project_Settings: Using GNAT SAS-Specific Project Settings ---------------------------------------- If you are using project files also to build with GNAT and need to use e.g. different builder switches between GNAT builds and GNAT SAS analysis, you can then use the predefined ``GPR_TOOL`` variable to differentiate the two modes in your project file: .. code-block:: gpr Tool := External ("GPR_TOOL", ""); package Builder is case Tool is when "gnatsas" => for Global_Compilation_Switches ("Ada") use ("-gnatI"); -- -gnatI is only relevant for GNAT SAS when others => for Global_Compilation_Switches ("Ada") use ("-O", "-g"); -- Switches only relevant when building end case; end Builder; In GNAT SAS 24, ``GPR_TOOL`` is set automatically by GNAT SAS to ``gnatsas``, so you do not need any extra configuration or command line switches to use the above. Support for UTF-8 encoding -------------------------- GNAT SAS is able to analyze source files that have UTF-8 encoding. Simply add the GNAT switch ``-gnatW8`` to the `Compiler` package as below. GNAT SAS will report messages from Infer, GNAT Warnings and GNATcheck with UTF-8 encoding. See the `Wide_Character Encodings `_ section in the GNAT User's Guide for more details. .. code-block:: gpr package Compiler is for Switches ("Ada") use ("-gnatW8"); end Compiler; .. warning:: Concatenation of ``-gnatW8`` with other switches is not supported. Please specify ``-gnatW8`` independently from other switches. E.g. use ``-gnatiw -gnatW8`` instead of ``-gnatiwW8``. .. note:: For Inspector messages, UTF-8 encoding is not fully supported. UTF-8 characters are converted to a different representation and the GNAT SAS output may become hard to read. To be able to use identifiers with characters outside of the Latin-1 character set, typically UTF-8 characters, one may also use the ``-gnatiw`` switch as described below. See the `Character Set Control `_ section in the GNAT User's Guide for more details. .. code-block:: gpr package Compiler is for Switches ("Ada") use ("-gnatW8", "-gnatiw"); end Compiler; .. _Target_Setup: Use of Libraries Installed with GNAT ------------------------------------ If your project uses some of the libraries installed with GNAT (e.g. GNATcoll, XML/Ada, AWS...) and, when launching GNAT SAS, you encounter a message similar to: .. code-block:: none gnatcoll.gpr (4 items) unknown project file: "gpr" Then add the following section to your project file to use the ``"gnatsas"`` runtime packaged with the GNAT SAS installation: .. code-block:: gpr for Target use "gnatsas"; Use of Predefined Ada Packages ------------------------------ The predefined Ada packages (in particular, children of Ada, System, and Interfaces) come packaged with GNAT SAS. Make sure your project file does not include alternative predefined Ada source packages that may be provided by some Ada compilers, since these predefined packages may contain non-portable constructs that GNAT SAS may not recognize. For compiler-specific packages, see :ref:`Compiler_Specific_Packages` for accessing some of these. If this isn't sufficient, you will need to include at least the package specs from your target compiler as part of your project file as for any other source file. .. _Compiler_Specific_Packages: Use of Compiler-Specific Packages --------------------------------- If your Ada code base uses compiler-specific packages, GNAT SAS provides some of these packages pre-installed under :file:`install/share/gpr` and accessible as pre-configured project files. In particular you will find the following project files: * :file:`aa.gpr`: ApexAda specific packages. * :file:`am.gpr`: AdaMulti and AdaMagic specific packages. * :file:`oa.gpr`: ObjectAda specific packages. * :file:`vads.gpr`: VADS specific packages. * :file:`xgc.gpr`: XGC specific packages. To use these project files, add for example the following line to your project file (adjust the name of the imported project as needed): .. code-block:: gpr with "am"; project My_Project is -- other declarations... end My_Project; If some compiler-specific packages are missing, do not hesitate to contact your GNAT SAS support. Using Preprocessing ------------------- In order to enable preprocessing, you can use the ``-gnateD`` and ``-gnatep`` switches, e.g.: .. code-block:: gpr package Compiler is for Switches ("Ada") use ("-gnateDVAR1=xxx", "-gnateDVAR2=yyy"); end Compiler; Note the use of the package `Compiler` here. The ``-gnateD`` switches in the :term:`Analyzer package` are ignored. All the ``-gnateD`` switches are accumulated to find the defined symbols. If ``-gnatep`` is used, it should appear only once and the given file is used to specify the preprocessing data file. See also the section `Form of Input Text for gnatprep`__ in chapter `Preprocessing with gnatprep` for more details on the syntax supported by the preprocessor. __ https://docs.adacore.com/gnat_ugn-docs/html/gnat_ugn/gnat_ugn/the_gnat_compilation_model.html#form-of-input-text-for-gnatprep .. _Arbitrary_Naming_Scheme: Arbitrary Naming Scheme ----------------------- If you are using a different naming scheme than the default :file:`.ads`/ :file:`.adb` for your source files, you can define the naming scheme adding a package ``Naming`` if a single and consistent naming scheme is used for all your source files. For instance: .. code-block:: gpr project My_Project is ... package Naming is for Spec_Suffix ("Ada") use ".1.ada"; for Body_Suffix ("Ada") use ".2.ada"; for Separate_Suffix use ".2.ada"; for Dot_Replacement use "."; end Naming; end My_Project; or: .. code-block:: gpr project My_Project is ... package Naming is for Spec_Suffix ("ada") use "_.ada"; for Body_Suffix ("ada") use ".ada"; for Separate_Suffix use ".ada"; for Dot_Replacement use "__"; end Naming; end My_Project; If more complex naming schemes are used (e.g. files with mixed casing, no automatic mapping between unit names and file names, use of multiple units in a single file, etc...) then you have three options: * In GNAT Studio: use the :menuselection:`File --> Project --> Add Complex File Naming Conventions...` menu and follow the dialog. This will call the underlying command line tool ``codepeer-gprname`` and modify the project file for you. See the `GNAT Studio documentation `_ for more details. * Use the ``codepeer-gprname`` tool to generate the custom naming scheme automatically. See the section :ref:`Generating_Project_File` for more details. * Use the ``codepeer-gnatchop`` tool: Your sources can be preprocessed to generate ``.ads/.adb`` files by running ``codepeer-gnatchop`` on all your Ada sources and use a simple project file on the generated sources, for instance under Linux:: cd mkdir sources find . -name sources -prune -o -name '*.ad?' -exec codepeer-gnatchop {} sources \; This command will take all files ending with ``.ad`` under the current source tree, and generate a corresponding :file:`.ads/.adb` file under a new directory called :file:`sources`. You can then use in your project file: .. code-block:: gpr for Source_Dirs use ("sources"); Ada Language Version -------------------- .. note:: This section only impacts GNAT-based engines (i.e. Inspector and GNAT Warnings), and has no impact on other engines. By default, GNAT Warnings and Inspector assume that sources use the Ada 2012 language. If your sources use an older version of Ada, then you will need to add the following to your project file: .. code-block:: gpr package Builder is for Global_Compilation_Switches ("Ada") use ("-gnat95"); end Builder; The switches corresponding to the various Ada versions are: ``-gnat83``, ``-gnat95``, ``-gnat2005``, ``-gnat2012``, ``-gnat2022``. Note that some Ada 95 compilers support the *overriding* keyword but no other Ada 2005 features. In order to analyze such code, you need to add the ``-gnatd.D`` switch in your project file, in addition to the ``-gnat95`` switch: .. code-block:: gpr package Builder is for Global_Compilation_Switches ("Ada") use ("-gnat95", "-gnatd.D"); end Builder; .. note:: Using ``Global_Compilation_Switches`` in the ``Builder`` package should be preferred over defining the switches in the ``Compiler`` package, since the former applies to the whole project hierarchy, while the latter only applies to the current project and not to subprojects. .. _Representation_Clauses: Representation Clauses ---------------------- .. note:: This section only impacts GNAT-based engines (i.e. Inspector and GNAT Warnings), and has no impact on other engines. If GNAT Warnings or Inspector generate errors related to Ada representation clauses, a simple way to address these errors is to add the ``-gnatI`` compiler switch to your project file: .. code-block:: gpr package Compiler is for Switches ("Ada") use ("-gnatI"); end Compiler; ``-gnatI`` instructs GNAT Warnings and Inspector to ignore representation clauses, as if they had been stripped from the source code. .. _Target_Configuration_File: Target Configuration File ------------------------- .. note:: This section only impacts GNAT-based engines (i.e. Inspector and GNAT Warnings), and has no impact on other engines. Usually, using either the default GNAT SAS settings, the GNAT SAS ``--bits=32`` switch (see :ref:`32-bits_mode`) or the `Compiler` package Ada's ``-gnatI`` switch (see :ref:`Representation_Clauses`), is sufficient to analyze code for most targets. If you need to configure GNAT Warnings and Inspector so that they have a deeper knowledge and understanding of the target compiler, and in particular setting target dependent values such as endianness or sizes and alignments of standard types, then you might need to add the following to your project file: .. code-block:: gpr package Compiler is for Switches ("Ada") use ("-gnateT=" & project'Project_Dir & "/target.atp"); end Compiler; where :file:`target.atp` is a file stored here in the same directory as the project file :file:`my_project.gpr`, which contains the target parametrization. This file can be generated by calling the GNAT compiler for your target with the switch ``-gnatet=target.atp``. The format of this file is described in the GNAT User's Guide as part of the ``-gnateT`` switch description. Here is an example of a configuration file for a bare board PowerPC 750 processor configured as big-endian:: Bits_BE 1 Bits_Per_Unit 8 Bits_Per_Word 32 Bytes_BE 1 Char_Size 8 Double_Float_Alignment 0 Double_Scalar_Alignment 0 Double_Size 64 Float_Size 32 Float_Words_BE 1 Int_Size 32 Long_Double_Size 64 Long_Long_Long_Size 64 Long_Long_Size 64 Long_Size 32 Maximum_Alignment 16 Max_Unaligned_Field 64 Pointer_Size 32 Short_Enums 0 Short_Size 16 Strict_Alignment 1 System_Allocator_Alignment 8 Wchar_T_Size 32 Words_BE 1 float 6 I 32 32 double 15 I 64 64 long double 15 I 64 64 If your target compiler is not GNAT, or an old version of GNAT, then you can also build and run the small utility called ``generate_target`` which can be found under :file:`/share/gnatsas/target`. See comments inside this file for instructions on how to use it. Note that, depending on the Ada constructs you are using and the values specified in the target configuration file, some combinations will not be properly supported and will lead to errors. In this case, consider using the ``-gnatI`` switch instead, or contact GNAT SAS support for alternatives. .. _Target_Runtime: Using the GNAT Target Runtime Directory --------------------------------------- .. note:: This section only impacts GNAT-based engines (i.e. Inspector and GNAT Warnings), and has no impact on other engines. As a general rule, we strongly recommend using ``for Target use "gnatsas";`` in your project file (see :ref:`Target_Setup`). If however you want to use a specific GNAT runtime, you can do so by following the explanations given in this section. .. warning:: The runtime you intend to use *must* come from a version of GNAT identical to GNATSAS' one. A runtime coming from GNAT 22.2 will *not* be compatible with GNAT SAS 24.2. In such a case you will be forced to specify ``for Target use "gnatsas";`` Let's assume you are using GNAT as your target compiler, and explicitly specify a runtime and target to use in your project: .. code-block:: gpr for Target use "arm-eabi"; for Runtime ("Ada") use "ravenscar-sfp-stm32f4"; Inspector and GNAT Warnings will take such setting into account and will use the GNAT runtime directory, as long as your target compiler is found in your PATH environment variable. As mentioned above, you will need to use a matching version of GNAT and GNAT SAS (e.g. GNAT 24.0 and GNAT SAS 24.0). The handling of runtimes of Inspector and GNAT Warnings is in fact unified with that of the GNAT compiler. For details, see "GNAT User's Guide Supplement for Cross Platforms", Section 3. If you specify a target, note that Inspector may use additional configuration, see the section :ref:`Target_Configuration_File`. If for some reason you do not have access to the GNAT compiler on the same machine as GNAT SAS (e.g. the GNAT cross compiler is installed on a different host than GNAT SAS) you will first need to copy the GNAT runtime directory in the GNAT SAS installation, under :file:`/libexec/codepeer/lib/gcc///` where `` is either `x86_64-pc-linux-gnu` or `x86_64-w64-mingw32` and `` is the version of GNAT SAS toolchain. .. note:: This *does not wave aside* the requirement of having matching versions of GNAT SAS and GNAT. For example, assuming you want to use a runtime called :file:`ravenscar-sfp-stm32f4`, then first locate this runtime on the machine with the GNAT installation, e.g.: .. code-block:: sh $ arm-eabi-gnatls -v --RTS=ravenscar-sfp-stm32f4 | grep adalib This command gives the path to :file:`/adalib`. You then need to copy/transfer the ```` directory to the GNAT SAS installation, under :file:`/libexec/codepeer/lib/gcc///`, for example using `bash` syntax: .. code-block:: sh $ scp -pr $(dirname $(arm-eabi-gnatls -v --RTS=ravenscar-sfp-stm32f4 | grep adalib)) \ :/libexec/codepeer/lib/gcc// .. note:: If you don't have access to the GNAT compiler and you copied the GNAT runtime directory in the GNAT SAS installation, you need to use ``for Target use "gnatsas";``. You can then take the specificities of your target into account separately as described in :ref:`Target_Configuration_File`. Working with target-specific configurations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Even when a specific target is used for compilation, we recommend using gnatsas as a target for the analysis when possible. To achieve this, you can either create a dedicated project file for the analysis or use a scenario variable to set different targets for compilation and analysis: .. code-block:: gpr case Enable_GNATSAS is when "True" => for Target use "gnatsas"; when "False" => for Target use "x86_64-pc-linux-gnu"; end case; If a target other than gnatsas is necessary for the analysis, be aware that GNAT SAS takes such a target into account, however, the project's ``Target`` attribute will still be interpreted as having the value ``"gnatsas"`` when processing the project file in the context of GNAT SAS. This means that the project's ``'Target`` attribute should not be directly referenced in other attributes (e.g. ``for Object_Dir use Project'Target``) in parts of the project file that apply to GNAT SAS. If the set of sources to analyze depends on the target, you can use a scenario variable to specify the set of sources for GNAT SAS: .. code-block:: gpr Tool := External ("GPR_TOOL", ""); Target := project'Target; Sources := ("."); case Tool is when "gnatsas" => Sources := Sources & ("src/common/" & "x86_64-pc-linux-gnu"); when others => Sources := Sources & ("src/common/" & Target); end case; for Source_Dirs use Sources; If you want to analyze a codebase with different targets and each target has specific sources, you can define a scenario variable defining such targets and use it instead of using ``Target`` directly. In this case, ``--subdirs`` or ``for Subdirs`` should be used to separate each target-specific analysis by creating a separate :term:`gnatsas directory` for it. For example: .. code-block:: gpr Tool := External ("GPR_TOOL", ""); type Gnatsas_Target_Type is ("x86_64-pc-linux-gnu", "aarch64-linux-gnu"); Gnatsas_Target : Gnatsas_Target_Type := external("GNATSAS_TARGET", "x86_64-pc-linux-gnu"); Target := project'Target; Sources := ("."); case Tool is when "gnatsas" => Sources := Sources & ("src/common/" & Gnatsas_Target); when others => Sources := Sources & ("src/common/" & Target); end case; for Source_Dirs use Sources; package Analyzer is for Subdirs use Gnatsas_Target; -- will result in a gnatsas directory -- located in -- "//gnatsas" end Analyzer; .. _Configuration_of_System: Configuration of System Package (system.ads) -------------------------------------------- .. note:: This section only impacts GNAT-based engines (i.e. Inspector and GNAT Warnings), and has no impact on other engines. Some Ada compilers provide additional, non-portable definitions in the predefined package ``System`` which might lead to errors when running Inspector and GNAT Warnings analyses. A solution to address this issue automatically is to use the ``pragma Extend_System`` in a pragma configuration file, either using one of the predefined GNAT extensions (e.g. ``Aux_Dec`` for the DEC Ada compiler or ``VADS`` for the VADS compiler, available via the project file :file:`vads.gpr` as described in :ref:`Compiler_Specific_Packages`), or by providing a customized :file:`s-auxcom.ads` file. For example, you can create a file called :file:`gnatsas.adc` located under the same directory where your project file is, which will contain: .. code-block:: ada pragma Extend_System (Aux_Dec); or alternatively: .. code-block:: ada pragma Extend_System (Aux_VADS); And configure your project file to take this file into account: .. code-block:: gpr package Builder is for Global_Configuration_Pragmas use "gnatsas.adc"; end Builder; or if using ``Aux_VADS``: .. code-block:: gpr with "vads"; project My_Project is package Builder is for Global_Configuration_Pragmas use "gnatsas.adc"; end Builder; end My_Project; Similarly, if your target compiler provides additional definitions, you can manually create a :file:`s-auxcom.ads` file containing these additional definitions, e.g.: .. code-block:: ada package System.Aux_Compiler is pragma Preelaborate; function To_Integer (Addr : Address) return Integer; function To_Address (Int : Integer) return Address; No_Addr : constant Address := Null_Address; Address_Zero : constant Address := Null_Address; Assertion_Error : exception; ... end System.Aux_Compiler; and then specify: .. code-block:: ada pragma Extend_System (Aux_Compiler); in :file:`gnatsas.adc`. See the `GNAT Reference Manual `_ for more details on ``Pragma Extend_System``. Also note that you should never include the compiler System package in your project file (either in your source file list or even in your source directories), as Inspector needs to use its own version of :file:`system.ads`. Ignoring Pragmas ---------------- .. note:: This section only impacts GNAT-based engines (i.e. Inspector and GNAT Warnings), and has no impact on other engines. In some cases, non-portable pragmas are used across Ada technologies in an incompatible way, generating some spurious error messages when Inspector or GNAT Warnings analyze these files. In order to address these issues, you can configure your project file to ignore a set of pragmas via the ``Ignore_Pragma`` pragma that you should place in a :file:`gnatsas.adc` file as explained in :ref:`Configuration_of_System`. For example, if you want to ignore pragmas called ``Import_Procedure`` and ``Import_Function`` you can put in your :file:`gnatsas.adc`: .. code-block:: ada pragma Ignore_Pragma (Import_Procedure); pragma Ignore_Pragma (Import_Function); Similarly if you want to ignore pragma ``Global``: .. code-block:: ada pragma Ignore_Pragma (Global); If not already done, you need to configure your project file to take this file into account: .. code-block:: gpr package Builder is for Global_Configuration_Pragmas use "gnatsas.adc"; end Builder; Providing Stubs for Missing Generic Bodies ------------------------------------------ .. note:: This section only impacts GNAT-based engines (i.e. Inspector and GNAT Warnings), and has no impact on other engines. GNAT Warnings and Inspector will ignore missing bodies and will make reasonable presumptions about calls to such unknown subprograms (see :ref:`Inspector_Presumptions`). However they will generate an error when they encounter a generic package whose body is missing at instantiation time. In order to work around this error, you can provide a skeleton for the generic package via the ``codepeer-gnatstub`` utility, e.g.:: codepeer-gnatstub -Pmy_project generic_package.ads will generate a file :file:`generic_package.adb` which can be used by GNAT Warnings and Inspector. .. _Configuring_Analysis: Configuring the Analysis ======================== .. note:: This section assumes that a project file has been defined for the codebase to analyse and configured to be compatible with GNAT SAS. If that is not the case, refer to the instructions in :ref:`Creating_Project_File` and :ref:`Project_File_Setup`. This section describes how the GNAT SAS analysis can be configured by users to adjust the scope of the analysis, its precision, control where files are generated, etc. It also explains the available configuration for each integrated analysis engine. All analysis engines are enabled by default. It is possible to individually enable or disable any engine (see :ref:`gnatsas analyze switches `). .. _Analyzer_Package_Attributes: `Analyzer` package attributes ----------------------------- In addition to the project attributes described in the GPRbuild and GPR Companion Tools User's Guide and described in :ref:`Project_Setup` (e.g. ``Source_Dirs``, ``Object_Dir`` attributes, `Naming` and `IDE` packages, ...), the optional project attributes described below are available in the :term:`Analyzer package`. * ``Subdirs`` Specify the relative path from the :term:`object directory` (if specified, project directory otherwise) to the :term:`gnatsas directory`. See :term:`subdirs`. * ``Output_Dir`` Specify the :term:`output directory` to use for this project. If you specify a relative directory, that directory is interpreted as relative to the directory that contains the project file. * ``Review_File`` The :term:`review file` to use for this project. If you specify a relative path, that path is interpreted as relative to the directory that contains the project file. * ``Excluded_Source_Files`` List of project source files (as base names) which should be excluded from GNAT SAS' analyses. See :ref:`Excluding_Files` for more info. * ``Excluded_Source_Dirs`` List of project source directories which should be excluded from GNAT SAS' analyses. See :ref:`Excluding_Dirs` for more info. * ``Switches`` An associative array representing the additional switches that should be used for each GNAT SAS subcommand and analysis engines. Possible keys are: - ``"analyze"`` - ``"inspector"``, ``"infer"``, (and discouraged ``"gnat"`` and ``"gnatcheck"``, see below) - ``"report X"``, where X can be any format supported by the ``gnatsas report`` command (e.g. ``"report text"`` or ``"report csv"``). Note that switches specified for a given format will not apply to other formats. - ``"baseline"`` .. warning:: Using the ``Switches`` attribute in the :term:`Analyzer package` is **not recommended** for configuring the analysis of GNATcheck and GNAT Warnings. Indeed, such configuration is not recognized by the corresponding tool when it is run standalone (i.e., not through GNAT SAS). The preferred workflow is to always configure GNATcheck through the `Check` package, and GNAT Warnings through the `Compiler` or `Builder` packages. Refer to :ref:`Configuring_GNATcheck` and :ref:`Configuring_GNAT_Warnings` for more details about the configuration of those tools. .. code-block:: gpr project Prj is package Analyzer is for Switches ("analyze") use ("--mode=deep"); -- This is NOT recommended: -- for Switches ("gnatcheck") use ("-rules", "+RLocal_Packages"); end Analyzer; -- Use the Check package instead: package Check is for Default_Switches ("ada") use ("-rules", "+RLocal_Packages"); end Check; end Prj; * ``Pending_Status``, ``Not_A_Bug_Status``, ``Bug_Status`` Lists of custom review status definitions, see :ref:`Custom_Review_Status`. .. seealso:: Refer to the :ref:`GNAT SAS CLI Reference ` for more information on supported switches. .. _32-bits_mode: 32-bits mode ^^^^^^^^^^^^ By default GNAT SAS assumes that the compilation target is the same as the host on which it is run. This is often a sufficient default, although one typical case where this is not sufficient is when using GNAT SAS in 64-bits mode and analyzing code designed for 32-bits architectures. In this case, you can run GNAT SAS with the ``--bits=32`` switch so that GNAT SAS will analyze the code assuming the same architecture, but in 32-bits mode instead of 64-bits. You can use this switch either from the command line, or specify it in the project file: .. code-block:: gpr package Analyzer is for Switches ("analyze") use ("--bits=32"); end Analyzer; See also :ref:`Target_Configuration_File` for advanced configuration of the target. .. warning:: This is currently not supported for Infer and GNATcheck. .. _Partial_Analysis: Partial Analysis ---------------- This section describes how to perform a partial analysis, and in particular, how to exclude entities (projects, directories, files, packages, subprograms) from analysis. Selecting the Analysis Scope ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ GNAT SAS provides several switches allowing users to control the analysis scope, by passing them to the ``gnatsas analyze`` command line or specifying them in the project file: * The default behavior when none of the switches below are specified is to analyze the closure of the main units specified in the project file for the full project tree, except externally built units. * ``-U``: analyze all files in the full project tree, except externally built ones. * ``-U FILE``: analyze files contained in the closure of the FILE unit. * ``--no-subprojects``: analyze all files in the root project only, ignoring all subprojects and also ignoring main units defined in the root project. * ``--file FILE``: analyze a single file FILE. * ``--files-from FILE``: analyze files listed in FILE. .. seealso:: Refer to :ref:`CLI_Reference` for more information about GNAT SAS command-line usage. In addition, it is possible to exclude entities from the analysis as explained in the following sections. .. _Excluding_Subprograms_or_Packages_From_Analysis: Excluding Subprograms or Packages from Analysis ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. note:: This section only applies to Infer and Inspector engines. To selectively disable the analysis of a particular subprogram or set of subprograms for Infer and Inspector, you can add in your Ada source code a pragma Annotate of the form: .. code-block:: ada pragma Annotate (GNATSAS, Skip_Analysis); When used in this way, an Annotate pragma takes exactly these two arguments. The pragma may be placed at the beginning (possibly preceded only by different Annotate pragmas) of the declaration list of a subprogram body, a package body, or package visible part. In the case of a subprogram body, Infer and Inspector's analysis of that subprogram body (and anything declared therein, including nested subprograms) will not be performed. In the case of a package body, Infer and Inspector's analysis of any subprogram body occurring (directly or indirectly) within the package body will not be performed. In the case of a package visible part, analysis of subprogram bodies occurring in the package specification (as well as the package body) will not be performed; note that a subprogram body can occur in a package specification as part of an instantiation of a generic unit. The subprogram or package in question may be a generic unit or may occur within a generic unit; in this case, the pragma will be replicated (as described in Ada RM 12.3(13)) when an instance of the generic unit is declared and will affect Inspector's analysis of the instance as described in this section. When an Annotate pragma is used in this way to prevent Inspector and Infer's analysis of a subprogram body, the analysis of clients of the subprogram will be affected in the same way as if the body of the subprogram were unavailable for some other reason (e.g. a missing .adb file). Here is an example of usage to disable analysis of a specific subprogram: .. code-block:: ada procedure Complex_Subprogram (...) is pragma Annotate (GNATSAS, Skip_Analysis); begin ... end Complex_Subprogram; And similarly for a package: .. code-block:: ada package Complex_Package is pragma Annotate (GNATSAS, Skip_Analysis); ... end Complex_Package; .. _Excluding_Files: Excluding Files from Analysis ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ If you want to exclude some files from the analysis (because e.g. GNAT SAS is taking lots of time analyzing them, and these files do not contain useful subprograms for GNAT SAS to analyze), you can use the ``Excluded_Source_Files`` project attribute in the :term:`Analyzer package`, for example: .. code-block:: gpr package Analyzer is for Excluded_Source_Files use ("xxx.adb"); -- Analysis of xxx.adb generates lots of timeouts, skip it for now end Analyzer; For the values, ensure to **always specify the basename** of the excluded files, with no path information. The path information is computed automatically by GNAT SAS based on other project properties. .. warning:: Project attributes in the :term:`Analyzer package` (in particular ``Excluded_Source_Dirs`` and ``Excluded_Source_Files``) are ignored when executing **GNATcheck or GNAT Warnings as standalone tools**. .. note:: Note that excluding a specification file from the analysis also excludes the corresponding body file, if present. On the contrary, excluding a body file does not exclude the corresponding specification file. .. _Inspector_Specific_Handling: Inspector-specific handling """"""""""""""""""""""""""" The Inspector engine has some limitations when it comes to excluding files from the analysis. In the general case, exclusion can be done using the `Analyzer` package as previously described. However, in some specific cases file exclusion needs to be done differently. This section describes such cases and their impact. .. rubric:: Excluding a file containing a generic When a file excluded from the analysis contains a generic, the generic will still be analyzed by Inspector if it is instantiated in at least one file that is not excluded. This is because Inspector doesn't analyze generics per se, but analyzes each instantiation of the generic as explained in :ref:`Handling_of_Generic_Units`. In such case, it is possible to exclude all instantiations of a generic package from the analysis as described in :ref:`Excluding_Subprograms_or_Packages_From_Analysis`. Inspector will no longer attempt to analyze the excluded file (note, however, that it will still compile it and generate a SCIL for it; if that is not desirable, see the next paragraph). .. rubric:: Excluding a file from compilation and SCIL generation If you want to not only exclude files from the analysis, but go further and also exclude it from compilation and SCIL generation; and if these files are not in the transitive closure of other files (e.g. a body file, as opposed to a specification file used by other Ada units); then the project-level ``Excluded_Source_Files`` attribute can be used instead of the `Analyzer` attribute: .. code-block:: gpr project My_Project is for Excluded_Source_Files use ("xxx.adb"); end My_Project; .. warning:: * Unlike excluding a body file, excluding a specification file at the project level **may cause compilation errors** on the files depending on this spec and as a result prevent the analysis of those files. * If a specification or a body file of a module is excluded at the project level, Inspector will not be able to perform an incremental analysis of the modules depending on that module. This means that **those modules will be fully re-analyzed** by Inspector (even in fast mode). Those effects do not occur if files are excluded using the `Analyzer` package. .. seealso:: This mechanism may also be used to address some compilation errors as explained in :ref:`Compilation_Errors`. .. _Excluding_Dirs: Excluding Directories from Analysis ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ If you want to exclude from analysis all source files from a given set of directories, you can use the ``Excluded_Source_Dirs`` project attribute in the :term:`Analyzer package`, for example: .. code-block:: gpr package Analyzer is for Excluded_Source_Dirs use ("directory1", "directory2"); end Analyzer; .. warning:: Project attributes in the :term:`Analyzer package` (in particular ``Excluded_Source_Dirs`` and ``Excluded_Source_Files``) are ignored when executing **GNATcheck or GNAT Warnings as standalone tools**. You can specify absolute directories or directories relative to the location of the project file (same as for source directories). As explained in the section :ref:`Excluding_Files`, generic instantiations made in files not excluded from the analysis will be still analyzed. Note that it is possible to exclude all instantiations of a generic package from the analysis as described in :ref:`Excluding_Subprograms_or_Packages_From_Analysis`. .. _Excluding_Projects: Excluding Projects from Analysis ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ If you have a tree of project files (:file:`.gpr`) and want to exclude some entire projects (aka subsystems) from GNAT SAS analysis, you can do it by adding the following project attributes to each of the projects involved: .. code-block:: gpr for Externally_Built use "True"; This attribute tells GNAT SAS to disable analysis on all source files for this project. Projects using files (e.g. spec) from this project will still be analyzed, as well as generic instantiations made in other projects. .. _Configuring_GNATcheck: Configuring GNATcheck --------------------- GNAT SAS uses a small selection of GNATcheck rules by default as listed in :ref:`GNATcheck_Messages`. GNATcheck is enabled by default and can be disabled with the ``--no-gnatcheck`` switch. More rules can be checked by configuring the `Check` package of the project file. .. note:: The default rules will not be enabled by GNAT SAS if any of the following is true: * an LKQL rule file is specified in the `Check` package (through the ``Rule_File`` attribute) * at least one rule is specified in the `Check` package (through the ``Rule`` attribute or the ``-rules`` switch) * a default ``rules.lkql`` file exists in the directory of the project file. .. seealso:: For more detailed information about configuring GNATcheck, see the `GNATcheck Reference Manual `_. The recommended workflow when using the GNATcheck engine in GNAT SAS is to configure the `Check` package of the project file. This ensures that the GNATcheck configuration defined for the project is consistently taken into account both by GNAT SAS and by GNATcheck when used as a standalone tool. Some examples of configuration are provided below. Differences with standalone GNATcheck tool ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ There exist noteworthy differences between using GNATcheck integrated in GNAT SAS and using GNATcheck as a standalone tool. .. note:: In GNAT Studio, GNAT SAS with GNATcheck is available from the top-menu :menuselection:`GNATSAS -> Analyze...` (see :ref:`Invocation_from_GNAT_Studio`), while GNATcheck standalone is available from the menu :menuselection:`Analyze -> Check Coding Standard`. In particular: - GNAT SAS runs five GNATcheck rules by default (see :ref:`GNATcheck_Messages`), while standalone GNATcheck runs none. - **The output of both tools is not stored and displayed in the same manner**: - Standalone GNATcheck's default output directory is the directory specified by the ``Object_Dir`` of the project, or the current directory if no ``Object_Dir`` is specified. GNATcheck will generate a text report :file:`gnatcheck.out` and other files under that directory. This behavior can be overridden with multiple switches defined in the `Check` package, such as ``--subdirs`` or ``-o``. See the `GNATcheck Reference Manual `_. for more details. - However, the results of the GNATcheck analysis integrated in GNAT SAS will be generated in the :term:`output directory` with the same format as messages from other engines (:ref:`Sam_Files`) and can be displayed in multiple ways (see :ref:`How_To_View_GNAT_SAS_Output`). Internal GNATcheck output is also available under the :file:`gnatsas/.gnatcheck` directory. Other settings from the `Check` package will be ignored. - **The set of sources analyzed by GNATcheck may differ** (specified as ``"analyze"`` key switches in the :term:`Analyzer package` or GNAT SAS command-line: ``-U``, ``--file``, ``--files-from``, ``--no-subprojects``or ``for Source_Files``; and specified as values of ``for Default_Switches ("ada")``: ``-U``, ``-files=``, ``--no-subprojects`` in the `Check` package). - When running standalone GNATcheck, above settings from the :term:`Analyzer package` will be ignored. - When running GNATcheck integrated in GNAT SAS, above settings from the `Check` package will be ignored. - Projects marked as externally built with the ``Externally_Built`` project attribute will not be analyzed when GNATcheck is ran through GNAT SAS. - The ``Annotate`` pragmas for GNAT SAS will only be taken into account when running GNATcheck through GNAT SAS. See :ref:`Improve_Your_Code_Specification`. - The ``-j`` switch for controlling the number of jobs, can be specified through ``for Switches ("analyze")`` in the :term:`Analyzer package`, which will override the settings set through ``for Default_Switches ("ada")`` in the `Check` package. .. _Configuring_Infer: Configuring Infer ----------------- GNAT SAS runs some analyses based on Infer by default. Enabled by default, can be disabled with ``--no-infer``. Some Infer analyses can be activated and/or parameterized using Infer-specific switches. These switches can be specified using the index `"infer"` of the project attribute `Switches` in the :term:`Analyzer package`: .. code-block:: gpr project My_Project is package Analyzer is for Switches ("infer") use ("--side-effects"); end Analyzer; end My_Project; This example will enable emitting a warning when a function has side effects. The section :ref:`Infer_messages` contains a list of all Infer messages, with their description and detailed configuration parameters. .. _Configuring_GNAT_Warnings: Configuring GNAT Warnings ------------------------- The GNAT front-end warnings. Enabled by default, can be disabled with ``--no-gnat``. Specifying warnings to check ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ When enabled, GNAT SAS calls the GNAT front-end with the switches you enabled through the `Default_Switches ("Ada")` attribute of the Compiler package of your GPR file and a default selection of checks chosen by GNATSAS itself (see the :ref:`table listing GNAT Warnings ` for an exact list). To disable or enable additional checks, add the relevant switches to the :term:`Analyzer package` in your project file. Disabling warnings can be achieved by using the same mechanism as GNAT, i.e. specifying the warning switch using capital letters. For example: .. code-block:: gpr project prj is package Analyzer is for Switches ("gnat") use ("-gnatwbz.a"); -- equivalent to: -- for Switches ("gnat") use ("-gnatwb", "-gnatwz", "-gnatw.a"); -- disabled with: -- for Switches ("gnat") use ("-gnatwBZ.A"); end Compiler; end prj; .. _Minimal_Recompilation: Ignoring Source File Timestamp Mismatch ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ If your environment changes the timestamps of your source files between GNAT SAS runs (with no actual changes in source files contents), then in order to minimize the regeneration of Inspector SCIL files or recomputation of GNAT Warnings, you can specify the ``--incrementality-method=checksums`` switch in the :term:`Analyzer package` of your project file, so that checksums rather than timestamps should be used for determining whether source files have changed since the previous run: .. code-block:: gpr package Analyzer is for Switches ("analyze") use ("--incrementality-method=checksums"); end Analyzer; .. note:: This switch only impacts GNAT based engines, i.e., Inspector and GNAT Warnings. .. warning:: When incrementality is based on checksums, some messages may end up referring to wrong source locations. Indeed: Incrementality based on checksums internally relies on GPRbuild checksum computation. GPRbuild ignores comments when computing the checksum of a file. Hence, a file were only comments are modified between two gnatsas runs is not re-analyzed. While the messages on the file are still valid, they refer to source locations prior to the comments modifications. .. _Configuring_Inspector: Configuring Inspector --------------------- Inspector is the historical analysis engine of GNAT SAS. Enabled by default, can be disabled with ``--no-inspector``. .. seealso:: See :ref:`Inspector_Reference` for more advanced Inspector configuration. .. rubric:: Example project file Here is an example of a project file using some of the Inspector attributes described in the following sections: .. code-block:: gpr project Prj1 is ... package Analyzer is for Excluded_Source_Files use ("file1.ads", "file2.adb"); for Output_Dir use "/work/project1.outputs"; for Switches ("analyze") use ("--keep-going"); for Switches ("report text") use ("--show-backtraces"); for Additional_Patterns use "ExtraMessagePatterns.xml"; end Analyzer; end Prj1; `Analyzer` package attributes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * ``Message_Patterns`` Alternate :file:`MessagePatterns.xml` file that Inspector should use for this project. * ``Additional_Patterns`` Extra :file:`MessagePatterns.xml` file that Inspector should use in addition to the default patterns file. This can be either a path relative to the project's directory, or an absolute path. Ignoring Source File Timestamp Mismatch ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ See :ref:`Minimal_Recompilation`. Ignoring Exception Handlers ^^^^^^^^^^^^^^^^^^^^^^^^^^^ By default Inspector tries to take exception handlers into account in its analysis, although by doing so this can lead to a loss of precision in the detection of possible (or certain) run-time errors. If you want Inspector to analyze the code by completely ignoring exception handlers (behave as if the exception handlers were stripped from the code) then you can add the ``-gnatd.x`` switch, e.g.: .. code-block:: ada package Analyzer is for Switches ("inspector") use ("-gnatd.x"); end Analyzer; Handling Enumeration Representation Clauses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Even without ``-gnatI``, Inspector by default ignores enumeration representation clauses, to reduce the various implicit representation transformations required by such clauses, which can produce confusing output. If your application uses Enum_Rep, Enum_Val, or Unchecked_Conversion to manipulate the underlying codes specified by an enumeration representation clause, then you may want to override this Inspector default by using the compiler switch ``-gnatd.I``. This will cause Inspector to obey the enumeration representation clause and ensure that Enum_Rep, Enum_Val, and Unchecked_Conversion are interpreted correctly for this enumeration type. This switch can be added to your project file, as follows: .. code-block:: ada package Analyzer is for Switches ("inspector") use ("-gnatd.I"); end Analyzer; .. _FPO_Detection: Detection of Floating Point Overflow ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Inspector assumes that floating point operations are carried out in single precision (binary32) or double precision (binary64) as defined in the IEEE-754 standard for floating point arithmetic. You should make sure that this is the case on your platform. For example, on x86 platforms, by default some intermediate computations may be carried out in extended precision, leading to unexpected results. With GNAT, you can specify the use of SSE arithmetic by using the compilation switches "-msse2 -mfpmath=sse" which cause all arithmetic to be done using the SSE instruction set which only provides 32-bit and 64-bit IEEE types, and does not provide extended precision. SSE arithmetic is also more efficient. Note that the ABI allows free mixing of units using the two types of floating-point, so it is not necessary to force all units in a program to use SSE arithmetic. Inspector considers the floating point values which represent positive, negative infinity or NaN as invalid, and it checks that such values cannot occur. By default, Inspector will only detect potential overflows on floating point operations on constrained floating point types (user floating point types with explicit ranges) and not on unconstrained types (e.g. predefined float types). You can ask Inspector to check for possible floating point overflows on unconstrained types (which will then lead to infinite values) via the ``-gnateF`` compiler switch, e.g.: .. code-block:: gpr package Compiler is for Switches ("Ada") use ("-gnateF"); end Compiler;