Contents -------- 1. What is gnatelim 2. How it works? 3. Eliminate pragma 4. gnatelim options 5. Preparing tree and bind files for gnatelim 6. Creating a list of Eliminate pragmas with gnatelim 7. Minimizing your executables 8. Manual correction of the list of Eliminate pragmas creating by gnatelim 9. Processing precompiled Ada libraries and GNAT RTL 10. gnatelim usage cycle: summary 11. Related information 12. Submitting bug reports 1. What is gnatelim ---------------- When you are working with a program which shares some set of Ada packages with other programs, it may happen, that your program uses only a part of subprogram defined in these packages, whereas the code created for unused subprograms increases the size of the executable your program. gnatelim is a utility tracking unused subprograms in an Ada program. Its output consists of a list of Eliminate pragmas marking all the subprograms that are declared, but never called in a given program. Eliminate is a GNAT-specific pragma, see section 3 for more details. By placing the list of Eliminate pragmas in the GNAT configuration file gnat.adc and recompiling your program, you may decrease the size of its executable, because the compiler will not create the code for unused subprograms. 2. How it works? ------------ gnatelim is an ASIS application developed on top of the ASIS implementation for GNAT. It needs a set of tree files representing a program to analyze and the bind file for its main subprogram to be created in the current directory (see sections 5 and 9). For the current version, it is a gnatelim user's responsibility to maintain the consistency of the set of tree files processed by gnatelim, if the user also changes the sources of the Ada program to be processed. To produce a list of Eliminate pragmas, gnatelim has to do an extensive analysis and it may take some time. For example, to process itself, gnatelim takes 4 minutes of CPU time on a Pentium 200. 3. Eliminate pragma ---------------- The following description is talen "as is" from the GNAT Reference Manual, version 3.11 Syntax: pragma Eliminate ( [Unit_Name =>] IDENTIFIER | SELECTED_COMPONENT [,[Entity =>] IDENTIFIER | SELECTED_COMPONENT | STRING_LITERAL] [,[Parameter_Types =>] PARAMETER_TYPES] [,[Result_Type =>] result_SUBTYPE_MARK]); PARAMETER_TYPES ::= null | SUBTYPE_MARK {, SUBTYPE_MARK} This pragma indicates that the given entity is unused in a program. The entity may be either a subprogram or a variable. If the entity to be eliminated is a library level subprogram, then only the first argument, specifying the corresponding unit name, is required. If the item is an entity of a library package, then the first argument specifies the unit name, and the second argument specifies the particular entity. If the second argument is in string form, it must correspond to the internal manner in which GNAT stores entity names (see compilation unit Namet in the compiler sources for details). The third and fourth parameters are optionally used to distinguish between overloaded subprograms, in the same manner as is used for pragma Import_Procedure. The effect of the pragma is to allow the compiler to optionally eliminate the code or data associated with the named entity. If the declaration of the entity would have resulted in side effects, these side effects may or may not occur in the resulting program. Any reference to an eliminated entity may cause a compile time error, link time error, or incorrect results at runtime. The intention of pragma Eliminate is to allow a program to be compiled in a system independent manner, with unused entities eliminated, without the requirement of modifying the source text. Normally the required set of Eliminate pragmas is constructed automatically using the gnatelim tool. 4. gnatelim options ---------------- The current version of gnatelim has the following command-line interface: gnatelim [options] name 'name' should be a full expanded Ada name of a main subprogram of a program (partition). gnatelim options: -v verbose mode: - gnatelim version information is printed (in the form of Ada comments) in stdout; - the names of the files being processed are printed to standard-error; -vf same as -v, but in addition various debugging information and information reflecting some details of the analysis done by gnatelim are printed to standard-error; -a process RTL components: by default, gnatelim does not analyze the units which are the components of the GNAT Run-Time Library (RTL), and it does not generate Eliminate pragmas for subprograms declared in RTL. If '-a' option is set, RTL components are also analyzed (except some units, which contains subprograms implicitly called by the compiler); -m check missed units: if this option is set, gnatelim checks, that all the units which (according to the bind file) has to be analyzed by gnatelim are really represented by the set of tree files processed by gnatelim (depending on whether or not '-a' option is set). By default (that is, if '-m' option is not set), gnatelim analyzes a set of units represented by a given set of tree files "as is" (excluding library packages which require bodies, but for which bodies are not available). 5. Preparing tree and bind files for gnatelim ------------------------------------------ As an ASIS application built on top of ASIS-for-GNAT, gnatelim needs a proper set of tree files to be created in the directory from which gnatelim is called. It also needs a bind file for the program for which it is called to be placed into this directory. Suppose that Main_Prog is the name of a main subprogram, and this subprogram is in file main_prog.ads or main_prog.adb (names of child units are also allowed in this position.) To create a minimal set of tree files covering the whole program, you may call gnatmake for this program with -gnatc -gnatt compiler options: gnatmake -c [-f] -gnatc -gnatt Main_Prog -c gnatmake option turns off the bind and link phases, which are impossible anyway, because sources are compiled with -gnatc option, which turns off generating object files. If you have already done some compilations in your current directory, you should use -f gnatmake option, which forces recompilation of all the needed sources, even if they are up-to-date with the existing ALI files. To create a bind file for gnatelim, run gnatbind for the main subprogram. gnatelim can work with either Ada or C bind file, if both are present, it works with the Ada bind file. If you run gnatbind just after calling gnatmake for creating the tree files, or if there is some inconsistency between the existing object and source files, gnatbind will produce an error message, and you will have to reapply gnatmake, but without -gnatc -gnatt compiler options. To avoid problems with creating a consistent data for gnatelim, you may use the following procedure. It creates all the data needed by gnatelim from scratch and therefore guarantees their consistency: 1. creating a bind file: gnatmake -c Main_Prog gnatbind main_prog.ali (if you would like to get an Ada bind file, use -A option for gnatbind: gnatbind -A main_prog.ali ) 2. creating a set of tree files: gnatmake -f -c -gnatc -gnatt Main_Prog Note, that gnatelim needs neither object nor ALI files, so you may delete them at this stage. Note also, that creating the right set of tree files is an important part of using gnatelim. When successfully called at "empty" place (or when called with -f' option), gnatmake create a set of tree files representing all units needed by the main subprogram to make up a partition, and it is exactly what gnatelim needs to perform its analysis. By default, gnatelim does not check the completeness of a set of tree files it processes, but it assumes, that this completeness has already been ensured by the preceding call to gnatmake. The '-m' option is intended to be used as some kind of debugging means in case if gnatelim generates wrong Eliminate pragmas. (See also section 9 concerning processing precompiled Ada libraries). 6. Creating a list of Eliminate pragmas with gnatelim -------------------------------------------------- To create the list of Eliminate pragmas for your program, call gnatelim with the name of its main subprogram as a command-line parameter. Note, that gnatelim produces its output in stdout, so use the output redirection to put these pragmas in the gnat.adc configuration file: gnatelim Main_Prog > gnat.adc If you already have the configuration file for you program in the current directory and if you would like to keep its existing content, use another form of output redirection to append the gnatelim output to the existing gnat.adc file: gnatelim Main_Prog >> gnat.adc 7. Minimizing your executables --------------------------- Suppose that you have already got the list of Eliminate pragmas for your program, and you have put these pragmas into gnat.adc file (Note, that gnat.adc may contain also some other configuration pragmas, for example Source_File_Name). To get a smaller executable for your program, you have to recompile the program completely, having this gnat.adc file in your current directory. To continue our example from sections 5 and 6, and supposing, that we have everything in the current directory, the next step is gnatmake -f Main_Prog (you will need '-f' option for gnatmake to recompile everything with the set of pragmas Eliminate you have got from gnatelim). Be aware, that a set of Eliminate pragmas is individual for every program. Therefore, you should never merge sets of Eliminate pragmas created for different programs in one gnat.adc file. 8. Manual correction of the list of Eliminate pragmas creating by gnatelim ----------------------------------------------------------------------- In a very rare case gnatelim may try to eliminate subprograms which cannot really be eliminated because they are actually called in the program. (It is a very rare case for the current gnatelim version, but it still happens). In this case, you will get an error message from the compiler of the form: file.adb:106:07: cannot call eliminated subprogram "My_Prog" You have to correct the gnat.adc file manually by suppressing the faulty Eliminate pragmas. It is advised to recompile from scratch when this happens, because you need a consistent gnat.adc file during the complete compilation in order to get an meaningful result. NOTE: generating erroneous Eliminate pragmas is a bug; we will appreciate your letting us know about it by submitting a bug report (see chapter 12). 9. Processing precompiled Ada libraries and GNAT RTL ------------------------------------------------- The GNAT Run-Time Library exists as a precompiled set of Ada sources. For a user Ada program which makes use of some RTL components (e.g., input-output packages), these components are not recompiled when the program is (re)compiled, but the specs of RTL components are processed when the user's components depended on these specs are compiled. As a result, a set of tree files created for gnatelim by using gnatmake (as it is described above in section 5), will contain only specs, but not bodies of RTL components. Some other precompiled Ada libraries may exist as a part of a particular GNAT installation. Technically, in case of GNAT a precompiled library is a set of source, object and ALI (Ada library information) files, where ALI files are locked (made read-only), and these sources normally are not recompiled when applying gnatmake to a user program which uses the library. Therefore, for such a user program, a set of tree files created by gnatmake will contain only specs, but not bodies of library components. If a user wishes to apply gnatelim to some program which uses precompiled Ada libraries, he has three possibilities: (1) not to analyze any component of any library (Eliminate pragmas will not be generated for subprograms declared in Ada libraries); (2) to analyze all used precompiled Ada libraries except GNAT RTL; (3) to analyze all used precompiled Ada libraries including GNAT RTL; To take the first approach, the user has to follow the procedure described above in section 5: the bodies for components of precompiled libraries will not be presented by a set of tree files created for gnatelim, and gnatelim excludes the specs of library components from the analysis. To take the second approach, the user has to call gnatmake with '-a' option when creating a set of tree files for gnatelim and when recompiling his program with the set of Eliminate pragmas created by gnatelim. '-a' option forces the recompilation of all the precompiled library components (and all the results of such recompilations, that is, object and tree files are put in the current directory). Note, that gnatelim should be called without '-a' option, if GNAT RTL components should not be analyzed. In this case gnatelim will generate Eliminate pragmas for subprograms declared in precompiled Ada libraries (except GNAT RTL), and when the user will create an exectutable for his program, library components will be recompiled again with these pragmas. To take the third approach, the user has to call both gnatmake and gnatelim with '-a' options. The difference between this and the previous case is that in this case gnatelim will analyze also the GNAT RTL components and it will generate Eliminate pragmas for them. Note that for gnatmake '-f' and '-a' options act independently and none of them implies the other one. 10. gnatelim usage cycle: summary ----------------------------- Here is a summary of the steps you have to do to reduce the size of your executables with gnatelim. Note, that this is only an example, which creates all the data for gnatelim from scratch. You may try to reuse the tree file and the bind file when running gnatelim several times for the same program (but we would not advise you to do this, you can lose more time if running into a problem of the consistency of the gnatelim input data then you need to create everything needed by gnatelim from scratch). You may also use other GNAT options (you may to control the optimization level, produce the debugging information, set search path etc). -- producing a set of tree files and a bind file: gnatmake -c Main_Prog gnatbind [-A] main_prog.ali gnatmake -f -c [-a] -gnatc -gnatt Main_Prog -- generating a list of Eliminate pragmas gnatelim [-a] Main_Prog >[>] gnat.adc -- recompiling everything with gnat.adc file to create a smaller -- executable (manual correction of gnat.adc may be needed): gnatmake -f [-a] Main_Prog 11. Related information ------------------- See GNAT User's Guide for more details about GNAT options. See ASIS-for-GNAT User's Guide for more details concerning tree files. 12. Submitting bug reports ---------------------- All bug reports, as well as any comments concerning the gnatelim functionality and options, which are very welcome, should be sent to asis-report@gnat.com. For bug reports, as usual don't forget to supply the Ada partition necessary to reproduce the problem.