Extending GNU Make's Logic
You can set variables to change how GNU Make does what it does, you can define new rules to change what GNU Make can do. The general form of a rule is:
target:prerequisites...commands
The target is typically the name of an executable you want to generate, the prerequisites are typically the .c/.cpp and .h files on which it depends, and the command is one or more shell commands, such as in invocation of g++ or ld.
GNU Make provides a number of “functions” for processing text that allow you to define flexible target and prerequisite lists for your rules. All of these functions take the form:
$(function arguments)
The judicious use of functions combined with consistent habits can keep Makefiles lean and flexible. For example suppose you are developing a program built atop several class libraries. If the project directories for your class libraries are contained within the source directory for your program, you can use a Makefile such as the following to maintain your program's dependency on your class libraries, the sub-projects.
prefix = .. # Each subproject produces lib*name*.a in its obj directory. subprojects = foo bar CPPFLAGS += $(patsubst %, -I$(prefix)/%/include, $(subprojects)) LDFLAGS += $(patsubst %, -L$(prefix)/%/obj, $(subprojects)) LDLIBS += $(patsubst %, -l%, $(subprojects))
You can add new libraries or re-arrange existing ones and change nothing but the names listed in the subprojects variable for the Makefile to properly build your program that depends on these libraries. The GNU Make patsubst command constructs the necessary compiler and link/load options from the library names. If you are careful/consistent in how you organize your directory hierarchy you could define subprojects from the directory structure directly, using patsubst and other functions, and not have to change your Makefile even if you change the names of the libraries on which your project is built.
If all the other GNU Make functions do not satisfy your needs, then the shell function probably will. This function lets you execute arbitrary shell commands to define your targets and prerequisite lists. There is essentially no limit to what GNU Make can accomplish with the help of the shell (e.g., bash). But stepping outside of GNU Make with shell comes with a performance price: each invocation spawns a new shell. If you do that within the definition of a recursively defined variable you will recursively spawn shells, so use shell carefully. Most of your needs will probably be met by the other GNU Make functions and directives (including include).
- Printer-friendly version
- Login to post comments
