If you want to share code for several binaries you would normally organize this code as a shared or static library. This is usually how I do it, but recently I came across a situation where this actually became a clumsy way of doing it.
The real life scenario is the following. We have a binary that make a lot of syntactical and type checks for a configuration file format. If the configuration file is ok the binary starts to generate system configuration files. We will label this binary as tool. Additional to the tool binary we want a binary that only do the checks and is not able to generate files and that binary is labeled tool-simple. The code base is a huge directory tree with many Makefiles, like this:
|-Makefile |-pkg/ |-src/ | |-proj1/ | | |-Makefile | | |-main.c | | | |-proj2/ | | |-Makefile . . . . . . . . .
In this case proj1 contains the source code for the binary called tool. However, proj1 needs to be built in two binary different flavors from the exact same source files but with different define arguments to gcc. This could have easily been done by running make twice (traverse the build tree twice) in the normal case. However, because the binaries will be packaged in the same tgz file we can only traverse the build tree once if we want to make a sane build environment. The solution is to create a structure for project q that look like this:
|-src/ | |-proj1/ | | |-Makefile | | |-tool/ | | | |-Makefile | | | |-cmd.c | | | |-cmd.h | | | |-common.inc | | | |-main.c | | | | | |-tool-simple/ | | | |-Makefile
Lets consentrate on the files in the project1 dirextory tree.
There is nothing special about this Makefile and that is the nice thing about it. Lets keep things simple and clean where we can and all the special cases isolated.
The only thing interesting in these 3 C files (main.c, cmd.c and cmd.h) are the ifdefs and ifndefs that are used to include and exclude code depending on the build. From the real scenario the shared code for the binaries are rather 80% than the few percent that are used in these files.
The file common.inc mainly contains the list of all object files that should be produced. In this case we have also included the common definition of CC.
The Makefile in the tool directory is a very normal Makefile with the include of common.inc as the only deviation.
The interesting stuff is found in the Makefile contained in the tool-simple
directory In this Makefile we also include the common.inc file from the tools
directory. The tools-simple directory does not contain any C files that can be
compiled to the object files declared in common.inc though. We will compile the
.c and .h files from the tools directory in to the tools-simple directory
with the help of the
vpath directive. Note the lower case of the
are two different directives.
VPATH specifies a list of directories
that make should search. Similar to the
VPATH directive, but more
selective, is the
vpath directive , which allows you to specify a
search path for a particular class of file names: those that match a particular
pattern. Also note that we define SIMPLE in this Makefile with the argument
-DSIMPLE when we build our object files for tool-simple By defining SIMPLE we
will not compile some code as you can see from the C files above.
Go and have fun with some Makefiles!