diff --git a/clang.md b/clang.md index 212081a1af51ffdd45b0fedfb422f54753e19a9e..0dd735519d858a133ad9b49caaf46968a5b9296d 100644 --- a/clang.md +++ b/clang.md @@ -651,3 +651,174 @@ warnings can save you hours of debugging!_) - `-pedantic`: issue warnings demanded by strict conformance to the stardard - `-D_FORTIFY_SOURCE=2`: detect runtime buffer overflow - `-fpie -Wl,-pie`: enable full ASLR(address space layout randomization) for better security + +## Build Automation + +Build automation involves automating the process of compiling code into libraries and executables. This can be a very complex process for large projects. + +For large programs, recompiling all the pieces of the program can be very time consuming. If we only recompile the files that have changed, we can save a lot of time. + +`Make` is such a build automation tool that solves those problems for us. `Make` and its variants are available on Linux, MacOS and Windows. + +### Makefile + +`Make` uses a file called `Makefile` which contains declarative rules. We can use this language to to tell `Make` what we want. + +You can invoke the `Make` program via the executable named `make`. + +### Rules in a Makefile + +A typical rule in a `Makefile` has the form: + +``` +target: prerequisite1 prerequisite2 prerequisite3 ... + command1 + command2 + command3 + ... +``` + +`target` can be the name of a file that needs to created or a "phony" name that can be used to specify a certain action. + +`prerequisites` are those files that must exist before the target can be successfully created. + +And the `commands` are those shell commands that will create the target from the prerequisites. Each command must be indented with a tab. + +For example, here is a rule for compiling a C file into a object file: + +```makefile +foo.o: foo.c foo.h + gcc -c foo.c +``` + +#### Automatic Variables + +These are the variables that allow you to refer to the same name defined in `target` or `prerequisite`: + +```makefile +hello: p1 p2 + # Outputs "hello", since this is the target name + echo $@ + + # Outputs all prerequisites newer than the target + echo $? + + # Outputs all prerequisites + echo $^ + + # Outputs the first prerequisite + echo $< + + touch hello + +p1: + touch p1 + +p2: + touch p2 + +clean: + rm -f hello p1 p2 +``` + +#### Marcos/Variables + +`Make` allows you to use macros, also called variables. These are defined using `=` pairs. It is traditional to use upper case letters in variable names: + +```makefile +CFLAGS = -O2 -Wall +CC = gcc +``` + +There is a bunch of built-in variables, but you can overwrite them to suit your needs. + +#### Implicit Rules + +Implicit rules tell `Make` how to use customary techniques so that you do not have to specify them in detail when you want to use them. + +For example, there is an implicit rule for C compilation: + +- `filename.o` is made automatically from `filename.c` with a command of the form `$(CC) -c $(CPPFLAGS) $(CFLAGS) $^ -o $@` +- The executable `filaname` is made automatically from `filename.o` with the command `$(CC) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@` + +The built-in implicit rules use several variables in their recipes so that, by changing the values of the variables, you can change the way the implicit rule works. + +Here is an example of using the implicit rules: + +```makefile +CC = gcc # Flag for implicit rules +CFLAGS = -g # Flag for implicit rules. Turn on debug info + +# Implicit rule #1: blah is built via the C linker implicit rule +# Implicit rule #2: blah.o is built via the C compilation implicit rule, because blah.c exists +blah: blah.o + +blah.c: + echo "int main() { return 0; }" > blah.c + +clean: + rm -f blah* +``` + +#### Pattern Rules + +It's quite verbose to write for each file a specific rules. We can use pattern rules to specify a rules for a series of files that fall into the same category: + +```makefile +# Define a pattern rule that compiles every .c file into a .o file +%.o: %.c + $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ +``` + +Pattern rules contain a `%` in the target. This `%` matches any nonempty string, and the other characters match themselves. + +### Run make + +Then you can invoke `make [target]` to generate the specified target described in `makefile`. The default command `make` will use the first target in the `makefile` if the target is not specified. + +### Makefile example + +A simple and typical `Makfile` looks like this: + +```makefile +# Define required macros here +PROG = main +OBJS = main.o +CFLAG = -Wall -g +CC = gcc +INCLUDE = -I. + +# binary target +$(PROG): $(OBJS) + $(CC) $(CFLAGS) $(INCLUDES) -o $@ $(OBJS) + +# implicit rule for building .o from .c +%.o: %.c + $(CC) -c -o $@ $< $(CFLAGS) $(INCLUDES) + +.PHONY: clean +# clean all the .o and executable files +clean: + rm -rf *.o core *.core $(PROG) +``` + +### Learning Materials + +`Make` has lots of other useful rules which allows you to write a more generic `makefile` for your projects. + +We won't cover those details in this document, but here are some useful materials if you are interested in learning more about `Make`: + +- https://cs.colby.edu/maxwell/courses/tutorials/maketutor/ +- https://makefiletutorial.com/#getting-started +- https://www.gnu.org/software/make/manual/make.html +- https://www.oreilly.com/library/view/managing-projects-with/0596006101/ + +## Debugging, Testing and Analysis + +TBD + +## References + +- https://www.gnu.org/software/gnu-c-manual/gnu-c-manual.html +- https://en.wikibooks.org/wiki/C_Programming +- http://cs.boisestate.edu/~amit/teaching/253/cs253.html