-
學習一些關於Makefile的基本知識
-
學習如何自己編譯使用Google Test的程序
# A sample Makefile for building Google Test and using it in user
# tests. Please tweak it to suit your environment and project. You
# may want to move it to your project's root directory.
#
# SYNOPSIS:
#
# make [all] - makes everything.
# make TARGET - makes the given target.
# make clean - removes all files generated by make.
# Please tweak the following variable definitions as needed by your
# project, except GTEST_HEADERS, which you can use in your own targets
# but shouldn't modify.
# Points to the root of Google Test, relative to where this file is.
# Remember to tweak this if you move this file.
GTEST_DIR = ..
# Where to find user code.
USER_DIR = ../samples
# Flags passed to the preprocessor.
# Set Google Test's header directory as a system directory, such that
# the compiler doesn't generate warnings in Google Test headers.
CPPFLAGS += -isystem $(GTEST_DIR)/include
# Flags passed to the C++ compiler.
CXXFLAGS += -g -Wall -Wextra -pthread
# All tests produced by this Makefile. Remember to add new tests you
# created to the list.
TESTS = sample1_unittest
# All Google Test headers. Usually you shouldn't change this
# definition.
GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \
$(GTEST_DIR)/include/gtest/internal/*.h
# House-keeping build targets.
all : $(TESTS)
clean :
rm -f $(TESTS) gtest.a gtest_main.a *.o
# Builds gtest.a and gtest_main.a.
# Usually you shouldn't tweak such internal variables, indicated by a
# trailing _.
GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS)
# For simplicity and to avoid depending on Google Test's
# implementation details, the dependencies specified below are
# conservative and not optimized. This is fine as Google Test
# compiles fast and for ordinary users its source rarely changes.
gtest-all.o : $(GTEST_SRCS_)
$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \
$(GTEST_DIR)/src/gtest-all.cc
gtest_main.o : $(GTEST_SRCS_)
$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \
$(GTEST_DIR)/src/gtest_main.cc
gtest.a : gtest-all.o
$(AR) $(ARFLAGS) $@ $^
######## My Own Test #########
HaloTest.o: HaloTest.cpp $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c HaloTest.cpp
mytest.o: HaloTest.o gtest.a
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@
######### My Own Test #########
gtest_main.a : gtest-all.o gtest_main.o
$(AR) $(ARFLAGS) $@ $^
# Builds a sample test. A test should link with either gtest.a or
# gtest_main.a, depending on whether it defines its own main()
# function.
sample1.o : $(USER_DIR)/sample1.cc $(USER_DIR)/sample1.h $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/sample1.cc
sample1_unittest.o : $(USER_DIR)/sample1_unittest.cc \
$(USER_DIR)/sample1.h $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/sample1_unittest.cc
sample1_unittest : sample1.o sample1_unittest.o gtest_main.a
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@
首先在Makefile中其註釋是使用#,這個從語法的高亮顯示可以窺出。其中,我們要注意,我自己添加的額外代碼是#### My Own Test #####部分。言歸正傳,分析Makefile($(GTEST_DIR)/make下)。
在Makefile文件的前部定義了幾個變量:GTEST_DIR, USR_DIR。Makefile中的變量都是直接定義的,引用的使用$(object)即可。其次是CXXFLAGS(編譯)和CPPFLAGS(預處理),這兩個變量是編譯器隱式規則中的變量,具有一些默認值。使用+=的話,如果變量之前沒有定義,則其類似與定義變量。
接下來是定義的目標:all和clean。這兩個都是僞目標,即他們只是將多個目標放在一起,而不是真正的目標。Makefile的基本規則是:
-
CPPFLAGS::表示包括包含文件的搜索目錄
-
CXXFLAGS:表示編譯的時候的選項,特別要注意 -pthread,gtest需要pthread支持。
-
$^,$@:都是自動化變量,前者表示所有依賴文件,後者表示所有目標文件的集合
-
-isystem:see here -isystem,設置搜索順序,表示其在系統包含目錄之前,-I選項之後搜索。
-
$(CXX), $(AR), $(ARFLAGS):一般情況下表示g++, ar, -rv。
目標:依賴條件
[TAB] 生成目標方法
其中[TAB]必須是TAB鍵,不能是空格代替,否則無法識別命令。如果命令放在同一行,則可以用分號隔開。
通常make文件都至少包含兩個目標:
-
默認第一個目標作爲make文件的最終目標,make程序會去查找依賴以生成這個目標。
-
一般會包含:clean的僞目標,清除所有生成文件,重新生成。
-
此外也有可能會包含:install, all這些僞目標。
綜上,我們看到gtest的Makefile包含了all和clean兩個僞目標。當我們需要生成特定目標時:
make clean; # 生成clean,即清除生成文件
make all; # 從推倒看,這個包括生成測試以及靜態庫文件gtest__main.a
gtest已經稱爲ubuntu的一個庫,你可以通過:sudo apt-get install libgtest-dev
但是注意這個只是下載了程序的必須文件,包括頭文件和源文件,還是需要自己去生成
(/usr/lib/gtest, /usr/src/gtest)。
但是我們最好不要直接編譯源文件,然後生成靜態庫,因爲gtest的編譯選項如何和你要編譯程序的編譯選項不一致的話會導致連接出問題。Google官方說每次自己重新編即可,因爲速度一般是足夠的。如果嫌慢,可以保證選項一致。
這上面的Makefile中,我添加了測試文件的語句,其中主要先生成測試文件的.o文件(未連接,利用-c命令),然後跟gtest.a文件進行連接生成最後的目的程序。