Code Libraries ############## .. include:: /header.inc .. vim:filetype=rst spell: Our simulator project is getting pretty big now. Last count, I had these source code files in my development project: .. code-block:: text +- src/ | - main.cpp | -argParse.cpp +- lib/ | - base/ | - Component.cpp | - Pin.cpp | - Wire.cpp | - graphics/ | - ArrowButton.cpp | - Button.cpp | - Graphics.cpp | - gui.cpp | - HexBar.cpp | - hexdisplay.cpp | - keyboard.cpp | - LED.cpp | - LEDmatrix.cpp | - mouse.cpp | - SevenSeg.cpp | - StageBar.cpp | - machine/ | - AVRsim.cpp | - Decode.cpp | - Fetch.cpp | - Store.cpp | - parts/ | - ALU.cpp | - DM.cpp | - IM.cpp | - INC.cpp | - Inverter.cpp | - MUX2.cpp | - PC.cpp +- tests/ - lots! That is a lot of source files, and we need to compile each one of them into an object file, then link everything into the executable. We link almost everything into the test application as well. That is a lot of object files. When we run ``make clean`` we remove all of those object files, meaning if we want to build the application again, we need to recompile everything! But, if we make small changes to out code, we really do not need to specify all those object files on the link step, we can make it very short by using a neat tool included with your compiler. Managing Object Files ********************* Long ago, programmers came up with a way to group object files into a single container called a ``library``. This idea allows a set of object files to be put into a single libray file. The linker can be told to look into a library file for any object files it needs. It will not load the entire thing, only those object files it needs for this particular executable it is building. You use these library files all the time, without even knowing that. They are a part of the standard C++ distribution. Library files are typically named something like ``libavrsim.a``. Inside of that library, we would probably store all of the object files, except for main.o, which should not live in any library (that would confuse the linker badly!) Building a Library ****************** In our GCC compiler tools (where g++ is found), there is a program called simply ``ar`` - short for ``archive``. This tool can be handed a list of object files to store and pack them all into a library. We can add, remove, and list the contents of the ``libraty`` as needed. To do this, we need to tweak our Makefile system a bit. The command we need is this: .. code-block:: bash ar rvs libavrsim.a objectfiles The options do this: ``r`` - replace the files if they are already there ``s`` - create the archive if it does not exist ``v`` - verbose - show what is going on Linking With Libraries ********************** Once you have the library file, we need to modify our build process a bit. Instead of making the target application depend on that huge list of object files, we make it depend on the library we create where all of those files live. For this project, I am going to create a ``libray`` file, and store it in a folder named ``bin``. (I would use ``lib``, which is common, but we are using lib for something else.) Fortunately, Make_ is pretty smart about all of this, so the changes to our ``MAkefile`` system are not that bad! First, add a new target to ``mk/cpp-build.mk``: .. code-block:: makefile $(LIB): $(LOBJS) ar rvs $@ $^ We need to define the name of the library file somewhere. I will do that at the top of ``mk/cpp-project.mk`` .. code-block:: text TARGET := $(PROJNAME)$(EXT) LIB := libavrsim.a LIBDIR := bin Now, we need to update the linker commands: .. code-block:: text $(TARGET)$(EXT): $(UOBJS) $(LIB) @python $(MK)/pyversion.py inc-build g++ -o $@ $^ $(LFLAGS) Now, we will build the library, and use it to link together our application. We should do something similar for the testing code: Make this change in the ``mk/cpp-tests.mk`` file: .. code-block:: text $(TSTTGT): $(TSTOBJS) $(LIB) $(CXX) -o $@ $^ $(LFLAGS) Now your compiler should be faster, even after a ``make clean``. .. note:: It is common to add another clean target, usually named something like ``realclean``, which will delete the library file. I already added a pattern to the ``.gitignore`` file so libraries files do not end up on GitHub_. .. warning:: It would be nice if we could do something similar with all those test object files. Unfortunately, testing that turned up aproblem with Catch_ It would not tun the tests. Not sure why, but I am looking into that.