Created
April 4, 2014 16:36
-
-
Save Mithrandir0x/9978359 to your computer and use it in GitHub Desktop.
Part of the Makefile from http://c.learncodethehardway.org/book/ex28.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
CFLAGS=-g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG $(OPTFLAGS) | |
# These are the usual CFLAGS that you set in all of your projects, but with a few others | |
# that may be needed to build libraries. You may need to adjust these for different | |
# platforms. Notice the OPTFLAGS variable at the end which lets people augment the build | |
# options as needed. | |
LIBS=-ldl $(OPTLIBS) | |
# Options used when linking a library, and allows someone else to augment the linking | |
# options using the OPTLIBS variable. | |
PREFIX?=/usr/local | |
# Setting an optional variable called PREFIX that will only have this value if the | |
# person running the Makefile didn't already give a PREFIX setting. That's what the ?= does. | |
SOURCES=$(wildcard src/**/*.c src/*.c) | |
# This fancy line of awesome dynamically creates the SOURCES variable by doing a wildcard | |
# search for all *.c files in the src/ directory. You have to give both src/**/*.c and | |
# src/*.c so that GNU make will include the files in src and also the ones below it. | |
OBJECTS=$(patsubst %.c,%.o,$(SOURCES)) | |
# Once you have the list of source files, you can then use the patsubst to take the SOURCES | |
# list of *.c files and make a new list of all the object files. You do this by telling | |
# patsubst to change all %.c extensions to %.o and then those are assigned to OBJECTS. | |
TEST_SRC=$(wildcard tests/*_tests.c) | |
# Using the wildcard again to find all the test source files for the unit tests. These are | |
# separate from the library's source files. | |
TESTS=$(patsubst %.c,%,$(TEST_SRC)) | |
# Then using the same patsubst trick to dynamically get all the TEST targets. In this case | |
# I'm stripping away the .c extension so that a full program will be made with the same name. | |
# Previously I had replaced the .c with {.o} so an object file is created. | |
TARGET=build/libYOUR_LIBRARY.a | |
SO_TARGET=$(patsubst %.a,%.so,$(TARGET)) | |
# Finally, we say the ultimate target is build/libYOUR_LIBRARY.a, which you will change to | |
# be whatever library you are actually trying to build. | |
# The Target Build | |
all: $(TARGET) $(SO_TARGET) tests | |
# Remember that the first target is what make will run by default when no target is given. | |
# In this case it's called all: and it gives $(TARGET) tests as the targets to build. Look | |
# up at the TARGET variable and you see that's the library, so all: will first build the | |
# library. The tests target is then further down in the Makefile and builds the unit tests. | |
dev: CFLAGS=-g -Wall -Isrc -Wall -Wextra $(OPTFLAGS) | |
dev: all | |
# Another target for making "developer builds" that introduces a technique for changing | |
# options for just one target. If I do a "dev build" I want the CFLAGS to include options | |
# like -Wextra that are useful for finding bugs. If you place them on the target line as | |
# options like this, then give another line that says the original target (in this case all) | |
# then it will change the options you set. I use this for setting different flags on | |
# different platforms that need it. | |
$(TARGET): CFLAGS += -fPIC | |
# Builds the TARGET library, whatever that is, and also uses the same trick from line 15 of | |
# giving a target with just options changes to alter them for this run. In this case I'm | |
# adding -fPIC just for the library build using the += syntax to add it on. | |
$(TARGET): build $(OBJECTS) | |
# Now the real target where I say first make the build directory, then compile all the OBJECTS. | |
ar rcs $@ $(OBJECTS) | |
# Runs the ar command which actually makes the TARGET. The syntax $@ $(OBJECTS) is a way | |
# of saying, "put the target for this Makefile source here and all the OBJECTS after | |
# that". In this case the $@ maps back to the $(TARGET) on line 19, which maps to | |
# build/libYOUR_LIBRARY.a. It seems like a lot to keep track of this indirection, and it | |
# can be, but once you get it working this means you just change TARGET at the top and | |
# build a whole new library. | |
ranlib $@ | |
# Finally, to make the library you run ranlib on the TARGET and it's built. | |
$(SO_TARGET): $(TARGET) $(OBJECTS) | |
$(CC) -shared -o $@ $(OBJECTS) | |
build: | |
@mkdir -p build | |
@mkdir -p bin | |
# This just makes the build/ or bin/ directories if they don't exist. This is then | |
# referenced from line 19 when it gives the build target to make sure the build/ | |
# directory is made. | |
# The Unit Tests | |
.PHONY: tests | |
tests: CFLAGS += $(TARGET) | |
tests: $(TESTS) | |
sh ./tests/runtests.sh | |
valgrind: | |
VALGRIND="valgrind --log-file=/tmp/valgrind-%p.log" $(MAKE) | |
# The Cleaner | |
clean: | |
rm -rf build $(OBJECTS) $(TESTS) | |
rm -f tests/tests.log | |
find . -name "*.gc*" -exec rm {} \; | |
rm -rf `find . -name "*.dSYM" -print` | |
# The Install | |
install: all | |
install -d $(DESTDIR)/$(PREFIX)/lib/ | |
install $(TARGET) $(DESTDIR)/$(PREFIX)/lib/ | |
# The Checker | |
BADFUNCS='[^_.>a-zA-Z0-9](str(n?cpy|n?cat|xfrm|n?dup|str|pbrk|tok|_)|stpn?cpy|a?sn?printf|byte_)' | |
check: | |
@echo Files with potentially dangerous functions. | |
@egrep $(BADFUNCS) $(SOURCES) || true |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment