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 theres
- create the archive if it does not existv
- 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.