在下面的三個練習中你會創(chuàng)建一個項目的目錄框架,用于構(gòu)建之后的C程序。這個目錄框架會在這本書中剩余的章節(jié)中使用,并且這個練習中我會涉及到Makefile便于你理解它。
這個結(jié)構(gòu)的目的是,在不憑借配置工具的情況下,使構(gòu)建中等規(guī)模的程序變得容易。如果完成了它,你會學到很多GNU make和一些小型shell腳本方面的東西。
首先要做的事情是創(chuàng)建一個C的目錄狂阿基,并且放置一些多續(xù)項目都擁有的,基本的文件和目錄。這是我的目錄:
$ mkdir c-skeleton
$ cd c-skeleton/
$ touch LICENSE README.md Makefile
$ mkdir bin src tests
$ cp dbg.h src/ # this is from Ex20
$ ls -l
total 8
-rw-r--r-- 1 zedshaw staff 0 Mar 31 16:38 LICENSE
-rw-r--r-- 1 zedshaw staff 1168 Apr 1 17:00 Makefile
-rw-r--r-- 1 zedshaw staff 0 Mar 31 16:38 README.md
drwxr-xr-x 2 zedshaw staff 68 Mar 31 16:38 bin
drwxr-xr-x 2 zedshaw staff 68 Apr 1 10:07 build
drwxr-xr-x 3 zedshaw staff 102 Apr 3 16:28 src
drwxr-xr-x 2 zedshaw staff 68 Mar 31 16:38 tests
$ ls -l src
total 8
-rw-r--r-- 1 zedshaw staff 982 Apr 3 16:28 dbg.h
$
之后你會看到我執(zhí)行了ls -l,所以你會看到最終結(jié)果。
下面是每個文件所做的事情:
LICENSE
如果你在項目中發(fā)布源碼,你會希望包含一份協(xié)議。如果你不這么多,雖然你有代碼的版權(quán),但是通常沒有人有權(quán)使用。
README.md
對你項目的簡要說明。它以.md結(jié)尾,所以應(yīng)該作為Markdown來解析。
Makefile
這個項目的主要構(gòu)建文件。
bin/
放置可運行程序的地方。這里通常是空的,Makefile會在這里生成程序。
build/
當值庫和其它構(gòu)建組件的地方。通常也是空的,Makefile會在這里生成這些東西。
src/
放置源碼的地方,通常是.c和.h文件。
tests/
放置自動化測試的地方。
src/dbg.h
我將練習20的dbg.h復制到了這里。
我剛才分解了這個項目框架的每個組件,所以你應(yīng)該明白它們怎么工作。
我要講到的第一件事情就是Makefile,因為你可以從中了解其它東西的情況。這個練習的Makeile比之前更加詳細,所以我會在你輸入它之后做詳細的分解。
CFLAGS=-g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG $(OPTFLAGS)
LIBS=-ldl $(OPTLIBS)
PREFIX?=/usr/local
SOURCES=$(wildcard src/**/*.c src/*.c)
OBJECTS=$(patsubst %.c,%.o,$(SOURCES))
TEST_SRC=$(wildcard tests/*_tests.c)
TESTS=$(patsubst %.c,%,$(TEST_SRC))
TARGET=build/libYOUR_LIBRARY.a
SO_TARGET=$(patsubst %.a,%.so,$(TARGET))
# The Target Build
all: $(TARGET) $(SO_TARGET) tests
dev: CFLAGS=-g -Wall -Isrc -Wall -Wextra $(OPTFLAGS)
dev: all
$(TARGET): CFLAGS += -fPIC
$(TARGET): build $(OBJECTS)
ar rcs $@ $(OBJECTS)
ranlib $@
$(SO_TARGET): $(TARGET) $(OBJECTS)
$(CC) -shared -o $@ $(OBJECTS)
build:
@mkdir -p build
@mkdir -p bin
# 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
要記住你應(yīng)該使用一致的Tab字符來縮進Makefile。你的編輯器應(yīng)該知道怎么做,但是如果不是這樣你可以換個編輯器。沒有程序員會使用一個連如此簡單的事情都做不好的編輯器。