Build Engineering is one of the most important functions for any Configuration Management guru and good Build Engineers are always in demand. Sometimes, knowledge of the architecture of the application is required to really setup a good build engineering framework - and often only the developers themselves have enough technical knowledge to make this happen. But good build engineers take the developer's build and make it more reliable and repeatable. I have worked with Ant, Maven 1 and Maven 2 in large scale Java SOA projects. I have also worked with MSBuild to support .net and C# builds. Years ago I worked with Make on HP-UX which was a robust, and often complicated, build environment. Recently, a CTO of a NYC based Hedge Fund was explaining to me that he wanted to use GNU make for C# on .net instead of MSBuild because of GNU Make's power and flexibility. Let's take a gentle peek at how GNU make supports builds using some simple C language programs and, in coming articles, we'll examine some of GNU Make's more advanced features.
It's all in a rule
GNU Make depends upon Rules of the form: target ... : Prerequisites ... command 1 command 2 So a simple Hello World program would look like this: hello : hello.o cc -o hello hello.o hello.o : hello.c cc -c hello.c Let's explain what these two rules are doing. The first rule indicates that the target is the hello program, the prerequisite is the hello.o (which is the output of the compile step) and the actual command to create the hello.o (that you could easily execute at the command line) is cc -o hello hello.c hello : hello.o cc -o hello hello.o The second rule says that the target is the hello and the prerequisite is the hello.c source code (created by our expert C Language programmer) and the command is cc -c hello.c hello.o : hello.c cc -c hello.c Makefiles are elegant in their simplicity and I have also seen them so convoluted that they could make your head spin. You can usually understand even the most complex Makefiles by carefully disecting the rules in the order in which they are executed. Build engineers need to work with the developers to set coding conventions and standards for use within the development team. Make sure that you document these agreed upon "Rules of the Road" in your CM Plan. You can download your copy of GNU Make from http://www.gnu.org/software/make/
This is the command to ascertain the version of make that you have installed. $ make -version GNU Make 3.81 Copyright (C) 2006 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Whatever version of make you download, you can examine the options using the Help command line switch $ make -help Usage: make [options] [target] ... Options: -b, -m Ignored for compatibility. -B, --always-make Unconditionally make all targets. -C DIRECTORY, --directory=DIRECTORY Change to DIRECTORY before doing anything. -d Print lots of debugging information. --debug[=FLAGS] Print various types of debugging information. -e, --environment-overrides Environment variables override makefiles. -f FILE, --file=FILE, --makefile=FILE Read FILE as a makefile. -h, --help Print this message and exit. -i, --ignore-errors Ignore errors from commands. -I DIRECTORY, --include-dir=DIRECTORY Search DIRECTORY for included makefiles. -j [N], --jobs[=N] Allow N jobs at once; infinite jobs with no arg. -k, --keep-going Keep going when some targets can't be made. -l [N], --load-average[=N], --max-load[=N] Don't start multiple jobs unless load is below N. -L, --check-symlink-times Use the latest mtime between symlinks and target. -n, --just-print, --dry-run, --recon Don't actually run any commands; just print them. -o FILE, --old-file=FILE, --assume-old=FILE Consider FILE to be very old and don't remake it. -p, --print-data-base Print make's internal database. -q, --question Run no commands; exit status says if up to date. -r, --no-builtin-rules Disable the built-in implicit rules. -R, --no-builtin-variables Disable the built-in variable settings. -s, --silent, --quiet Don't echo commands. -S, --no-keep-going, --stop Turns off -k. -t, --touch Touch targets instead of remaking them. -v, --version Print the version number of make and exit. -w, --print-directory Print the current directory. --no-print-directory Turn off -w, even if it was turned on implicitly. -W FILE, --what-if=FILE, --new-file=FILE, --assume-new=FILE Consider FILE to be infinitely new. --warn-undefined-variables Warn when an undefined variable is referenced. Here is an example of a working Makefile using our hello.c program. I wrote this C Language program to acknowledge my son who has been helping me edit these articles for CM Crossroads. $ cat hello.c /* First C program */ #include main() { printf("Hi Dovid Aiello\n"); printf("You are an awesome Assistant Editor!"); } Here is the Makefile $ cat Makefile #Makefile #Bob Aiello CM Crossroads hello : hello.o cc -o hello hello.o hello.o : hello.c cc -c hello.c clean : rm hello.exe hello.o The completed Makefile also contains a "clean" target which deletes the executable and object files so that you can be certain to have a clean build. You can execute the clean target as follows: make clean Here is how you would execute the make file to build the hello executable which can then be executed as shown below. $ make cc -c hello.c cc -o hello hello.o bob@Linux007 ~/cc $ ./hello.exe Hi Dovid Aiello You are an awesome Assistant Editor! bob@Linux007 ~/cc Next we'll add some cool functions to swap two numbers and then a print utility. This will give us an easy way to show how we would enhance the Makefile to handle a separate util.c program. Since the functions will be called from the hello.c program we need a common header file to hold the x and y variables that are passed to/from the swap and the print function. Both the hello.c and the util.c program include the common header file - which is considered a prerequisite for both programs. Here is the util.c $ cat util.c /* util.c program */ #include #include "util.h" /* function to swap numbers */ swap(x, y) int *x, *y; { int temp; temp = *x; *x = *y; *y = temp; } /* function to print out numbers */ printxandy (x, y) int x, y; { printf("\n\nfrom printxandy\n"); printf("\nx=%d", x); printf("\ny=%d", y); printf("\n------------------------\n"); } $ cat util.h /* Declare the variables */ static int x,y; Here is how the Makefile would look now to support the hello.c, util.h and util.c programs. $ cat Makefile #Makefile #Bob Aiello CM Crossroads hello : hello.o util.o cc -o hello hello.o util.o hello.o : hello.c cc -c hello.c util.o : util.h util.c cc -c util.c clean : rm hello.exe hello.o util.o Here is how it looks when the new Makefile is executed. $ make cc -c hello.c cc -c util.c cc -o hello hello.o util.o $ ./hello.exe Hi Dovid Aiello You are an awesome Assistant Editor! x=3 y=7 from printxandy x=7 y=3 ------------------------ exiting... This is a pretty simple (and very classic) example of a Makefile. In future articles, we will start to explore more complicated Makefile rules and features. Please send me your input examples and Makefile challenges so that we can all benefit from learning one of the oldest and more powerful build engineering tools used by experienced CM gurus to support large and small projects using many languages such as Java, C and C++. I am also interested in whether or not other teams are considering using GNU to support C# and .net builds. Please drop me a line and tell me about your own build and deploy experiences!!!
Bob Aiello is the Editor-in-Chief for CM Crossroads and a Software Engineer specializing in Software Process Improvement including Software Configuration and Release Management. Mr. Aiello has over 25 years experience as a technical manager in several top NYC Financial Services firms where he had had company-wide responsibility for CM, often providing hands-on technical support for enterprise Source Code Management tools, SOX/Cobit compliance, build engineering, continuous integration and automated application deployment. Bob is a long standing member of the Steering Committee of the NYC Software Process Improvement Network (CitySPIN), where he serves as the chair of the CM SIG. Mr. Aiello holds a Masters in Industrial Psychology from NYU and a B.S. in Computer Science and Math from Hofstra University. You may contact Mr. Aiello at raiello@acm.org or link with him at http://www.linkedin.com/in/bobaiello
Trackback(0)
Comments 
Write comment
 |