当前位置: 首页 > Linux

CMake学习1——初出茅庐

时间:2023-04-07 03:14:55 Linux

一、基本概念1.1构造方法CMake的构造方法可以分为内部构造和外部构造两种。应优先使用外部构建,这种方式生成的中间文件和最终文件不会污染原有工程文件。内部构建(in-sourcebuild)是指将生成的中间文件和最终目标输出生成到当前工作目录。由于cmake没有像clean一样清除生成的中间文件的指令,所以需要手动删除。因此,不推荐使用这种方法。OpenWrt以这种方式构建项目。外部构建(out-of-sourcebuild)通过创建一个临时文件夹,在该文件夹中执行构建操作,并将中间文件和最终目标文件生成到该文件夹??中,来消除对原始项目文件的污染。1.2目录树directorytree变量可以方便的引用项目源代码目录路径和构建的二进制文件目录路径。源码树(SourceTree)包含CMake输入文件(CMakeLists.txt)程序源文件(hello.cpp)程序头文件(hello.h)二叉树(BinaryTree)包含本地构建系统文件(Makefiles)在构建过程中生成当文件(库、可执行文件、任何其他构建生成的文件)是源代码构建时,它们指向同一目录。out-of-source构建,两者指向不同的目录。1.3Target对象Target是CMake中一个非常重要的概念,很多高级操作都需要提供一个Target对象。目标对象add_executable创建可执行程序对象add_library创建共享库或静态库对象2.基本规则2.1工程结构一个CMake工程由CMakeLists.txt文件和.h.hpp.c.cpp文件组成。每个目录级别都必须包含一个CMakeLists.txt文件。一级目录结构多层目录结构标准目录结构2.2写法CMake语法支持大写和小写两种方式,建议统一采用命令小写参数大写的编码方式。vscode命令的小写可以智能提示。commandlowercase#所需cmake工具的最低版本cmake_minimum_required(VERSION3.1)#项目名称project(hello-world)#生成可执行程序add_executable(hello-worldmainmain.c)commanduppercase#所需cmake的最低版本toolCMAKE_MINIMUM_REQUIRED(VERSION3.1)#工程名PROJECT(hello-world)#生成可执行程序ADD_EXECUTABLE(hello-worldmainmain.c)3.常用变量3.1系统变量CMAKE_SOURCE_DIR执行cmake命令时运行的目标目录,通常是顶级CMakeLists。txt文件目录。CMAKE_BINARY_DIR是执行cmake命令的执行目录。CMAKE_CURRENT_SOURCE_DIR当前CMakeLists.txt文件所在的目录。3.2项目变量PROJECT_SOURCE_DIR当前项目的顶层源码所在目录,一般为项目所在CMakeLists.txt文件所在目录。PROJECT_BINARY_DIR构建二进制目录下项目对应的目录。3.3构建方法CMAKE_BUILD_TYPE指定项目构建类型,其值包括Debug、Release、RelWithDebInfo、MinSizeRel。BUILD_SHARED_LIBS可以通过将这个全局变量设置为on或off来自动生成共享库或静态库。如果在add_library中明确指定了库类型,则无效。3.4搜索路径CMAKE_MODULE_PATH以“;”分隔的目录列表,指定要加载的CMake模块的find和find_package搜索路径。默认为空,由项目设置。3.5安装变量CMAKE_INSTALL_PREFIX在执行安装操作时,该目录会被预先添加到所有安装目录之前,并拼接成一个新的安装路径。3.5RuntimepathCMAKE_SKIP_BUILD_RPATH执行构建操作时,是否在生成的可执行程序或库中添加'rpath'信息(默认不添加)。CMAKE_BUILD_RPATH如果“CMAKE_SKIP_BUILD_RPATH”为FALSE,则执行构建操作时要附加的“rpath”路径。CMAKE_SKIP_INSTALL_RPATH执行安装操作时,是否在复制的可执行程序或库中添加'rpath'信息(默认不添加)。CMAKE_INSTALL_RPATH如果“CMAKE_SKIP_INSTALL_RPATH”为FALSE,则执行安装操作时要附加的“rpath”路径。4.常用命令4.1项目选项cmake_minimum_required指定项目所需的cmake工具的最低版本语法cmake_minimum_required(VERSION[...][FATAL_ERROR])示例cmake_minimum_required(VERSION3.1)project指定项目name,可传${PROJECT_NAME}为项目名称。项目名称是大写和小写。语法project([VERSION[.[.[.]]]][DESCRIPTION][HOMEPAGE_URL][LANGUAGES...])示例工程(SampleApp)4.2构建可执行程序或标准库add_executable构建可执行程序语法add_executable([WIN32][MACOSX_BUNDLE][EXCLUDE_FROM_ALL][source1][source2...])示例add_executable(${PROJECT_NAME}main.cpputils.cppparse.cpp)add_librarysyntaxadd_library([STATIC|SHARED|MODULE][EXCLUDE_FROM_ALL][source1][source2...])example#Default静态库add_library(${PROJECT_NAME}button.cppedit.cpp)#静态库add_library(${PROJECT_NAMESTATIC}button.cppedit.cpp)#动态库add_library(${PROJECT_NAMESHARED}button.cppedit.cpp)4.3文件包含target_include_directories指定目录集,编译时查找需要的头文件语法target_include_directories([SYSTEM][BEFORE][items1...][[items2...]...])例子/include)表示BEFORE选项可以将当前包含的目录追加到所有包含目录的头文件的前面.........)exampletarget_link_libraries(${PROJECT_NAME}Math#subprojectUi#subprojectpthread#systemlibrary)link_directories指定链接时所需库文件的目录集合语法link_directories([AFTER|BEFORE]directory1[directory2...])来自文件或模块的CMake代码语法include([OPTIONAL][RESULT_VARIABLE][NO_POLICY_SCOPE]Exampleinclude("../macro.cmake")4.4使用pkg-configfind_package使用pkg-config组件查找相关库文件的配置信息,包括头文件路径、库文件路径、版本号等信息。语法find_package([version][EXACT][QUIET][MODULE][REQUIRED][[COMPONENTS][components...]][OPTIONAL_COMPONENTScomponents...][NO_POLICY_SCOPE])示例find_package(PkgConfig)pkg_check_modulesfind验证模块并返回满足验证要求的库信息。语法pkg_check_modules([REQUIRED][QUIET][NO_CMAKE_PATH][NO_CMAKE_ENVIRONMENT_PATH][IMPORTED_TARGET[GLOBAL]][...])示例pkg_check_modules(GSTREQUIREDgstreamer-1.0>=1.8gstreamer-app-1.0>=1.8)returnobjectsyntax#Headerfiledirectory_INCLUDE_DIRS#libraryfiledirectory_LIBRARIESExample$(GST_INCLUDE_DIRS)${GST_LIBRARIES})4.5设置选项add_definitions用于实现编译器中的-D选项编译参数设置语法add_definitions(-DFOO-DBAR...)示例add_definitions(-DRAPIDJSON_HAS_STDSTRING)add_compile_options是add_definitions命令的替代,它支持所有编译参数设置。语法add_compile_options(

][PERMISSIONSpermissions...][CONFIGURATIONS[Debug|Release|...]][COMPONENT][NAMELINK_COMPONENT][OPTIONAL][EXCLUDE_FROM_ALL][NAMELINK_ONLY|NAMELINK_SKIP]][...][INCLUDESDESTINATION[...]])示例#安装可执行程序install(TARGETS${PROJECT_NAME}DESTINATION"/usr/bin")#安装库文件install(TARGETS${PROJECT_NAME}DESTINATION"/usr/lib")安装目录语言法install(DIRECTORYdirs...TYPE|DESTINATION[FILE_PERMISSIONS权限...][DIRECTORY_PERMISSIONS权限...][USE_SOURCE_PERMISSIONS][OPTIONAL][MESSAGE_NEVER][CONFIGURATIONS[Debug|Release|...]][COMPONENT][EXCLUDE_FROM_ALL][FILES_MATCHING][[PATTERN|REGEX][EXCLUDE][PERMISSIONSpermissions...]][...])Example#安装头文件install(DIRECTORY"${PROJECT_SOURCE_DIR}/include/"DESTINATION"/usr/include")表示前面的include/斜线必须包含,否则在/usr/include/include的情况下,如果末尾有斜线,则只复制其下的所有文件和目录,否则将包含当前目录没有斜线。安装文件语法install(files...DESTINATION[PERMISSIONSpermissions...][CONFIGURATIONS[Debug|Release|...]][COMPONENT][RENAME][OPTIONAL])Example#安装资源文件install(FILES"test.mp3"DESTINATION"/usr/bin")五、基本语法5.1注释CMake中用“#”表示注释。#要求的cmake工具最低版本cmake_minimum_required(VERSION3.1)5.2输出消息指令用于输出正常信息、警告信息和错误信息。#正常消息message(STATUS"normalmessage.")#Warningmessagemessage(WARNING"warningmessage.")#Errormessagemessage(FATAL_ERROR"fatalerrormessage.")...5.1可以分别设置变量和${}设置和读取变量。CMake变量还与值复制和引用有关系,这里不展开。#设置变量set(MY_VARIABLE"系统变量或自定义变量")#读取变量message("MY_VARIABLE=${MY_VARIABLE}")#设置环境变量set(ENV{JAVA_HOME}/opt/java/bin)#读取环境变量message("LANG=$ENV{LANG}")#判断环境变量是否存在if(NOTDEFINEDENV{JAVA_HOME})endif5.2listlist可以用来保存多个值#settinglistset(APP_SOURCE)list(APPENDAPP_SOURCEmain.cppmath.cppbutton.cpp)#查看列表message("${APP_SOURCES}")#遍历列表foreach(SOURCE${APP_SOURCES})message("src=${SOURCE}")endforeach5.4Function通过function()和endfunction()定义函数,函数参数列表、参数个数和具体参数用ARGC、ARGV、ARGVN表示。#定义函数function(foo)message("thereare${ARGC}arguments:${ARGV}")message("argument0is${ARGV0}")endfunction()#callfunctionfoo(firstsecondthirdfourth)5.5ConditionCondition用于判断判断方向和循环流程。if()True:1、ON、YES、TRUE、Y、非零值False:0、OFF、NO、FALSE、N、IGNORE、NOTFOUND、空字符串,以-NOTFOUND结尾。if()if(NOT)if(AND)if(OR)if(COMMAND命令名称)if(POLICY策略id)if(TARGET目标名称)if(<变量|字符串>IN_LIST<变量|字符串>)if(DEFINED<名称>|CACHE{<名称>}|ENV{<名称>})if(TEST测试名称)if(EXISTS路径到文件或目录)if(file1IS_NEWER_THANfile2)if(IS_DIRECTORY路径到目录)if(IS_SYMLINK文件名)if(IS_ABSOLUTE路径)if(<变量|字符串>匹配正则表达式)if(<变量|字符串>LESS<变量|字符串>)if(<变量|字符串>GREATER<变量|字符串>)if(<变量|字符串>EQUAL<变量|字符串>)if(<变量|字符串>LESS_EQUAL<变量|字符串>)if(<变量|字符串>GREATER_EQUAL<变量|字符串>)if(<变量|字符串>STRLESS<变量|字符串>)if(<变量|字符串>STRGREATER<变量|字符串>)if(<变量|字符串>|字符串>STREQUAL<变量|字符串>)if(<变量|字符串>STRLESS_EQUAL<变量|字符串>)if(<变量|字符串>STRGREATER_EQUAL<变量|字符串>)if(<变量|字符串>VERSION_LESS<变量|字符串>)if(<变量|字符串>VERSION_GREATER<变量|字符串>)if(<变量|字符串>VERSION_EQUAL<变量|字符串>)if(<变量|字符串>VERSION_LESS_EQUAL<变量|字符串>)if(<变量|字符串>VERSION_GREATER_EQUAL)if((condition)AND(conditionOR(condition)))5.6判断CMake语法中只有if语句,没有switch语句if()elseif()#optionalblock,canberepeatedelse()#optionalblockendif()5.7LoopCMake语法只包含while语句,没有dowhile,whiledo,until等循环语句。while()#跳出循环#进入下一个循环endwhile()参考cmake官网cmake常用变量和常用环境变量查找手册CMakeLists.txt设置编译后的可执行文件程序先调用本地库