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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章