Advanced Makefile ################# .. include:: /references.inc I use Make_ to build many programs from the command line. There are more advanced tools around, but I feel that beginning programming students need to be exposed to Make_ so they can see how powerful such build tools are, and be able to use them in their programming projects. Make_ has been around so long, and it is part of so many projects, they just have to learn a bit about it. I usually start students off in exploring Make_ with very simple patterns, but eventually they need to see the real power of such a tool. So, in developing a Graphics library for students to use in my programming class, I decided to add a few more powerful features of Make_ to the project ``Makefile``. In this note, I will develop a Makefile suitable to use in a :term:`test driven development` based C++ project. As part of this development, we will design a project directory structure suitable for building a library, intended to be used in other C++ projects. The ``Makefile`` will build, test, and install that library code on all major development systems: Windows, Linux, and Mac. Finding Source Files ******************** Simple student ``Makefile`` setups begin with a list of the course files in a project. These files are usually collected into a common project directory, along side of other directories for testing, building and documentation. Here is a starting point for a good project directory layout: .. code-block:: text project_directory\ | +- src\ - holds main project code | +- include\ library header files | +- lib\ holds library code files | +- bin\ - holds all files generated by building the project | +- bin\prod - holds all files generated for production | +- bin\debug - holds all files generated for testing | +- test\ - holds project test code | +- docs\ documentation for the project ( sphinx based for me!) The first part of the project ``Makefile`` lists the two programs this file will build. One is the main application, and the second is a test program that runs a set of tests we will use to make sure the code works properly. More on that later .. literalinclude:: code/casm/Makefile :lines: 1-4 Next, we name the major directories we use in this project. Creating names makes it easy to modify this file for another project later: .. literalinclude:: code/casm/Makefile :lines: 6-10 In the next section, we set up a few names that will hold options we use on various commands later. Botice that "+=" operator. You can add things to a name in a later step using this trick. .. literalinclude:: code/casm/Makefile :lines: 12-14 This next section tries to deal with building the application on different operating systems. This code will check the operating system and set a few names differently depending on what system we are running on. The big difference here is that programs on WIndows need to be named ``something.exe`, but on Mac/Linus, they are just named ``something``. We set up a name called ``EXT`` and set it to ``.exe`` on windows, and nothing on other systems. You will see this at work later. .. literalinclude:: code/casm/Makefile :lines: 16-34 Now, we can have Make_ search the project directories for any source files that will need to be processed: .. literalinclude:: code/casm/Makefile :lines: 36-44 In this section we have set up something that makes projects esier to manage. The ``g++`` compiler can be told to read all the source files and figure out what each one depends on. It does this by looking at the ``include`` lines. The output of this step is a file called ``something.d`` (for depends). We will use these files to make sure Make can build your code in the most efficient manner. The last part of the Makefile sets up the rules needed to build all the project components. These rules are similar to thse we went over earlier, and should be easy enough to figure out. Exactly what options are used for each build tool is somehting we can worry about later for this example. .. literalinclude:: code/casm/Makefile :lines: 46-87 Learning More ************* This gives you a sense of what Make can do. You can learn a lot by scanning projects on Github_ and looking to see how they use Makefiles to build their programs.