Code Libraries

Read time: 13 minutes (3257 words)

Our simulator project is getting pretty big now. Last count, I had these source code files in my development project:

+- 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:

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:


$(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

TARGET  := $(PROJNAME)$(EXT)
LIB     := libavrsim.a
LIBDIR  := bin

Now, we need to update the linker commands:

$(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:

$(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.