Makefile與CMake

Makefile

會檢測依賴文件列表中的變動,如果有改動,就重新編譯。否則直接使用編譯後的Object文件。
舉個例子:

//hellomake.c
#include <hellomake.h>

int main(){
	myPrintHelloMake();
	return 0;
	}
//hellomake.h
void myPrintHelloMake();
//hellofunc.c

void myPrintHelloMake(){
printf("Hello makefile\n")
}
##Makefile
CC=gcc
CFLAGS=-I.
hellomake:hellomake.o hellofunc.o
	$(CC) -o hellomake hellomake.o hellofunc.o

hellomake表示冒號後邊表示規則,可以認爲是一種依賴關係,cmake會檢測這些依賴關係的變化,只有有變化的文件才重新build,這個Makefile的缺陷是如果頭文件改動,cmake並不會重新build

CMake

CMake默認變量

  • CMAKE_SOURCE_DIR:cmake命令開始的目錄,也叫source tree 根目錄
  • CMAKE_CURRENT_SOURCE_DIR:目前正在處理的CMakeLists.txt 所在位置。

版本要求命令

設置cmake工具最低版本

CMAKE_MINIMUM_REQUIRED(VERSION 2.8)

PROJECT命令

設置項目名,可以指定編譯語言

project(<PROJECT-NAME> [LANGUAGES] [<language-name>...])

SET命令

設置變量的值

set(<variable> <value>
    [[CACHE <type> <docstring> [FORCE]] | PARENT_SCOPE])

例子:

##設置源碼文件名
set(SRC_LIST helloworld.cpp)
##設置環境變量
set(ENV($PATH) /home/chifred/vcs/bin
#覆蓋Cmake默認編譯選項
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DDEBUG_LOG=1")

若要引用上面的源碼文件名,如下:

${SRC_LIST}

INCLUDE_DIRECTORIES命令

添加include目錄

include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...])

ADD_SUBDIRECTORY命令

常用於添加一個子目錄用於編譯。比如一個目錄包含一個top-level的CMakeLists,該目錄下有不同的子目錄,包含不同模塊的源碼,子目錄又包含自己的CMakeLists,這個時候top-level的CMakelists需要用add_subdirectory命令包含子目錄。

ADD_SUBDIRECTORY

LINK_DIRECTORIES命令

添加鏈接庫目錄

link_directories(directory1 directory2 ...)

TARGET_LINK_LIBRARIES命令

爲某個的target鏈接一個或多個庫,target名在前,庫名在後

target_link_libraries(<target> [item1 [item2 [...]]]
                      [[debug|optimized|general] <item>] ...)

例子:

##把target與libsystemc.a庫鏈接
TARGET_LINK_LIBRARIS(${PROJECT_NAME} systemc)

ADD_EXECUTABLE命令

添加可執行文件

add_executable(<name> [WIN32] [MACOSX_BUNDLE]
               [EXCLUDE_FROM_ALL]
               source1 [source2 ...])

例子

##從源文件生成helloworld的可執行文件
ADD_EXECUTABLE(helloworld helloworld.cpp)

ADD_DEPENDENCIES命令

使top-level的target依賴於其他的target,確保top-level的target編譯前,其他target已經編譯。

add_dependencies(aarch64_toplevel simplecpu)

這個target是通過add_executeable命令或add_library命令指定的。

FIND_FILE命令

查找文件的完整路徑

find_file (
          <VAR>
          name | NAMES name1 [name2 ...]
          [HINTS path1 [path2 ... ENV var]]
          [PATHS path1 [path2 ... ENV var]]
          [PATH_SUFFIXES suffix1 [suffix2 ...]]
          [DOC "cache documentation string"]
          [NO_DEFAULT_PATH]
          [NO_CMAKE_ENVIRONMENT_PATH]
          [NO_CMAKE_PATH]
          [NO_SYSTEM_ENVIRONMENT_PATH]
          [NO_CMAKE_SYSTEM_PATH]
          [CMAKE_FIND_ROOT_PATH_BOTH |
           ONLY_CMAKE_FIND_ROOT_PATH |
           NO_CMAKE_FIND_ROOT_PATH]
         )

例子:

##搜索指定目錄和文件名的文件,返回完整文件路徑
FIND_FILE(FILE_NAME
		  helloworld.cpp
		  PATHS /home/chifred/c++/project
		  )

MESSAGE命令

顯示字符信息,變量和字符串之間要有空格,不然cmake會出warning

條件判斷語法

跟C中宏定義有點相似,注意括號的區別

if  (FPGA_SUPPORT)
	set(FPGA_CFLAS "-DFPGA_SUPPORT=1")
else ()
	set(FPGA_CFLAS "-DFPGA_SUPPORT=0")
endif()

find_package命令

如果需要外部的包,需要cmake在編譯時去找對應的頭文件路徑、庫文件路徑、庫名。find_package命令語法入下:

FIND_PACKAGE( <name> [version] [EXACT] [QUIET] [NO_MODULE] [ [ REQUIRED | COMPONENTS ] [ componets... ] ] )

find_package會去CMAKE_MODULE_PATH指定的目錄中尋找Findname.cmake並執行。所以要修改CMAKE_MODULE_PATH變量,並且自己寫Findename.cmake文件。例子如下

#添加存放.cmake文件的路徑
set(CMAKE_MODULE_PATH $CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake"

find_package(Lua)
if(LUA_FOUND)
	include_directories(${LUA_INCLUDE_DIR})
else()
	message(FATAL_ERROR "LUA library not found")
endif ()

上述會去cmake文件夾下搜索FindLua.cmake文件,並執行。這個.cmake文件會設置搜索頭文件和庫文件的路徑。找到包以後,會自動設置下面的變量。

<name>_FOUND
<name>_INCLUDE_DIRS or <NAME>_INCLUDES
<name>_LIBRARIES or <name>_LIBRARIES or <name>_LIBS
<name>_DEFINITIONS
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章