AIPS++ NOTE 178: How to Minimize Executable Compilation Times and Sizes for cfront Compilers. ======================================================================= J. E. Horstkotte 14 March 1995 NOTE: The following only applies to Sun computers. These tricks may not even be necessary on other computers, with their C++ compilers. In any case, due to C++ compiler differences, particularly those having to do with template instantiation, the following instructions cannot be expected to work on non-Sun computers. Eventually, these tricks will be built into the gmake rules. The thing which will speed your program builds the most is to put template instantiations into the library. There are a number of ways to do this. Which one you use depends upon your situation. The way to make your executables small is to use optimized versions of the object modules, both "regular" and template instantiations, of everything which you do not need to debug. The following methods pay reasonable attention to this. One may need to adjust the details depending upon one's debugging needs. In general, specifying "OPT=1" on the gmake command line compiles optimized, and links against the optimized versions of the installation libraries and template instantiation repositories. The default is to compile debug, and link against the debug versions of the installation libraries and template instantiation repositories. The following descriptions always assume that you are starting with a clean workspace, i.e. no libraries, no .o's, nothing in the template repositories, no executables, and no dependency files. This translates to the directories "arch"/{aux,bin,lib,ptrepository} being empty. All of these descriptions talk about the files xyz.cc and xyz.h, which are library source files, and txyz.cc, which is the source for a test program testing xyz.cc and xyz.h . The following instructions use the following variable names. They are not defined; you must define them yourself. NOTE: You can use gmake to define them for yourself. In a workspace directory which contains a makefile, and with the environment variable AIPSPATH defined, issue the following command to define the variables in "var_list": % eval `gmake VARS='var_list' show_vars 2>/dev/null | awk '/\=/'` Example: define PTROPTD and PGMRLIBD, while currently in the code/aips/implement/Arrays directory of your workspace. % eval `gmake VARS='PTROPTD PGMRLIBD' show_vars 2>/dev/null | awk '/\=/'` AIPSROOT : the root directory of your AIPS++ installation PTROPTD : the directory where your installation optimized template instantiations are located. It will be: $AIPSROOT/"arch"/lib/ptrepository PTRDBGD : the directory where your installation debug template instantiations are located. It will be: $AIPSROOT/"arch"/libdbg/ptrepository PGMRROOT : the root directory of your workspace PGMRLIBD : the directory where your workspace library is located. It will probably be one of: $PGMRROOT/"arch"/lib $PGMRROOT/code/aips/implement PGMRBIND : the directory where your workspace executables are located. It will probably be one of: $PGMRROOT/"arch"/bin the directory where the source for the executable is located. PGMRPTRD : the directory where your workspace template instantiations are located. It will probably be one of: $PGMRROOT/"arch"/ptrepository $PGMRROOT/ptrepository Situation 1. The workspace files xyz.cc and xyz.h are new to the installation, i.e. they do not exist in the installation. In this case, nothing in the installation libraries or repositories depends on these files in your workspace. -- Use "do_ar_cpadd". This will copy the installation library to your local workspace, and add to it the contents of the installation repository. By default, you will get the optimized versions of these. A flag allows you to get the debug versions, but I recommend against this strongly; the debug versions are too big. -- Copy the system template instantiation defmap to your repository. % cp $PTROPTD/defmap $PGMRPTRD : use $PTRDBGD if you used the debug : installation libraries and repository -- Then add xyz.o to this library. There are several commands to do this (which are issued in the workspace directory containing xyz.cc): "gmake" or "gmake all" add everything in the directory to the library. Since xyz is the only thing there, this is equivalent to: "gmake xyz update_mylib" which just adds xyz.o to the library. -- Build txyz % gmake txyz : in the workspace test directory containing txyx.cc This will get most of its template instantiations from the library, treating them as regular library object modules. The template instantiation mechanism will never know about them. Any instantiations which are not in the library will be created in the normal way. These additional instantiations could be necessary for two reasons: 1. xyz.cc and xyz.h define templates, which are used by txyz. 2. txyz requires instantiations from the code in the installation which were not pre-instantiated by ReposFiller. If you have situation 2), you may want to add these instantiations to the library. If you have situation 1), you almost certainly do not want to add these instantiations to the library, since that will prevent the instantiations from being recompiled when you change xyz.cc or xyz.h . There are two methods to add all of the instantiations in your workspace repository to your library. If you have situation 1), you then need to remove those instantiations from the library. Both of these methods assume that you have already instantiated into your workspace, by performing the procedure above. The syntax is for sh or bash shells; they will need to be modified for csh to use csh syntax. I recommend Method 2. It will be faster. Method 1: Rebuild the workspace library from scratch. -- Copy the installation library, adding both the installation and workspace instantiations. % rm $PGMRLIBD/libaips.a % do_ar_cpadd -l : the "-l" flag tells it to add the workspace : instantiations as well -- Add the workspace regular object modules (xyz.o). % gmake all : as above -- If necessary, remove the instantiations from xyz. % del_list=`libinstdepend -s "xyz.cc xyz.h" -ptr $PGMRPTRD $PGMRLIBD/libaips.a` % if [ `echo "$del_list" | wc -w` -gt 0 ] then mar dv $PGMRLIBD/libaips.a $del_list fi Method 2: Just add the workspace instantiations to the library. -- Add the workspace instantiations to the library. % mar rv $PGMRLIBD/libaips.a $PGMRPTRD/*.o -- If necessary, remove the instantiations from xyz. % del_list=`libinstdepend -s "xyz.cc xyz.h" -ptr $PGMRPTRD $PGMRLIBD/libaips.a` % if [ `echo "$del_list" | wc -w` -gt 0 ] then mar dv $PGMRLIBD/libaips.a $del_list fi Situation 2. You are working on xyz.cc, which exists in the installation. You are *not* modifying xyz.h (and therefore do not have it in your workspace). -- If xyz.cc does not contain template source, then proceed as in Situation 1) above. -- If xyz.cc does contain template source, then proceed as in Situation 1) above, making sure to remove to remove from the library the instantiations which depend upon xyz.cc : % del_list=`libinstdepend -s "xyz.cc" -ptr $PGMRPTRD $PGMRLIBD/libaips.a` % if [ `echo "$del_list" | wc -w` -gt 0 ] then mar dv $PGMRLIBD/libaips.a $del_list fi Situation 3. You are working on xyz.cc and xyz.h, both of which exist in the installation. This situation is fundamentally different, since object modules other than xyz.o in the installation library and in the installation repository could depend on xyz.h . Method 1. Do not copy anything down from the installation, but build it all in your workspace. -- Build the entire library. % cd %PGMRROOT/code/aips/implement % gmake OPT=1 mylibs : build the library optimized -- Optionally, rebuild xyz.o debug. % ar -dv $PGMRLIBD/libaips.a xyz.o % gmake xyz update_mylib -- Build txyz % gmake OPT=1 txyz : in the workspace test directory containing txyx.cc : again, this builds optimized, so that one gets : optimized template instantiations -- Add the workspace template instantiations to your library. % mar rv $PGMRLIBD/libaips.a $PGMRPTRD/*.o -- If necessary, remove the instantiations from xyz. % del_list=`libinstdepend -s "xyz.cc xyz.h" -ptr $PGMRPTRD $PGMRLIBD/libaips.a` % if [ `echo "$del_list" | wc -w` -gt 0 ] then mar dv $PGMRLIBD/libaips.a $del_list fi -- Optionally, rebuild txyz debug: % rm $PGMRBIND/txyz.o % gmake txyz Method 2. Copy the installation stuff down to your workspace, delete the "regular" object modules in the library which depend upon xyz.h and the template instantiation object modules which depend upon xyz.h and xyz.cc, and rebuild those parts. I have not built tools which can use the dependency information for the "regular" object modules in the library. Therefore, we cannot yet use this method. However, it would be straightforward to build the tools. I may do so in the near future.