zoukankan      html  css  js  c++  java
  • c++ cmakelist 详解

    基本元素

    首先cmaklist必须包括以下几个部分:

    #工程名

    project(study_case)

    #cmake最低版本需求

    cmake_minimum_required(VERSION 2.8.3)

     

    #添加添加需要的库

    set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "/usr/local/share/OpenCV")

    find_package(OpenCV 3.2.0 REQUIRED)

     

    #确定需要的头文件

    include_directories(

        include

    )

     

    #确定编译语言

    #1

    set(CMAKE_CXX_STANDARD 11)

    #2. or

    add_definitions(-std=c++11)

     

    #设置二进制文件目录

    SET(BIN_DESTINATION ${PROJECT_SOURCE_DIR}/bin)

    SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${BIN_DESTINATION})

     

    #如果多个文件相关,则添加源代码(可选)

    set(SRC 

        ${PROJECT_SOURCE_DIR}/src/detector.cpp

        ${PROJECT_SOURCE_DIR}/src/demo.cpp

        ${PROJECT_SOURCE_DIR}/src/test.cpp

    )

    #如果需要编译动态库并链接库文件(可选)

    link_directories(${PROJECT_SOURCE_DIR})

    add_library(overload SHARED ${SRC})

    target_link_libraries(overload -llianghao  -lpthread -lm -lstdc++)

     

    #生成可执行文件

    link_directories(${PROJECT_SOURCE_DIR})

    #添加可执行文件

    #1. 如果文件之间没有关联

    add_executable(overload src/overload.cpp)

    #2. or 如果多个文件相关

    add_executable(overload src/overload.cpp ${SRC})

     

    #如果有依赖外部库则需要添加以下命令(可选)

    target_link_libraries(overload -llianghao  -lpthread -lm -lstdc++)

    其他功能

    1. 使其包含c++11特性-std=c++11如何写进cmakeList.txt

    #1

    set(CMAKE_CXX_STANDARD 11)

    #2. or

    add_definitions(-std=c++11)

    #3. or

    include(CheckCXXCompilerFlag)

    CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)

    CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)

    if(COMPILER_SUPPORTS_CXX11)

            set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

    elseif(COMPILER_SUPPORTS_CXX0X)

            set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")

    else()

         message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")

    endif()

    2. 设定可执行文件的输出目录

    SET(BIN_DESTINATION ${PROJECT_SOURCE_DIR}/bin)

    SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${BIN_DESTINATION})

    3. 生成so

    3.1 想生成多个so

    # 设置构建本地库所需的最小版本的cbuild。

    cmake_minimum_required(VERSION 3.4.1)

    # 创建并命名一个库,将其设置为静态

    #  或者共享,并提供其源代码的相对路径。

    # 您可以定义多个库,而cbuild为您构建它们。

    #  Gradle自动将共享库与你的APK打包。

    add_library( hello-lib  #设置库的名称。即SO文件的名称,生产的so文件为“libhello-lib.so”,在加载的时候“System.loadLibrary("hello-lib");”

                    SHARED  # 将库设置为共享库。

                    src/main/jni/hello.cpp    # 提供一个源文件的相对路径

                    src/main/jni/helloJni.cpp    # 提供同一个SO文件中的另一个源文件的相对路径

                  )

    #搜索指定的预构建库,并将该路径存储为一个变量。因为cbuild默认包含了搜索路径中的系统库,所以您只需要指定您想要添加的公共NDK库的名称。cbuild在完成构建之前验证这个库是否存在。

    find_library(log-lib  # 设置path变量的名称。

                  log   #  指定NDK库的名称 你想让CMake来定位。

                   )

    #指定库的库应该链接到你的目标库。您可以链接多个库,比如在这个构建脚本中定义的库、预构建的第三方库或系统库。

    target_link_libraries( hello-lib     #指定目标库中。与 add_library的库名称一定要相同

                           ${log-lib}    # 将目标库链接到日志库包含在NDK。

                            )

    #如果需要生产多个SO文件的话,写法如下

    add_library( natave-lib  #设置库的名称。另一个so文件的名称

                    SHARED  # 将库设置为共享库。

                    src/main/jni/nataveJni.cpp    # 提供一个源文件的相对路径

                  )

    target_link_libraries( natave-lib     #指定目标库中。与 add_library的库名称一定要相同

                           ${log-lib}    # 将目标库链接到日志库包含在NDK。

                            )

    这里还有一个坑在里面,就是如果你的库的名字起得不是叫xx-lib的话,编译是通不过的,亲测,比如起个so库名叫test,cpp文件叫做test.cpp,这样是编译不过的,不会生成多个so库。

    3.1 生成一个so库,多个cpp文件

    # 查找cpp目录下的所有源文件

    # 并将名称保存到 DIR_LIB_SRCS 变量

    aux_source_directory(src/main/cpp/ DIR_LIB_SRCS)

    # 生成链接库

    add_library (native-lib SHARED ${DIR_LIB_SRCS})

     

    # 导入cpp目录下的所有头文件

    include_directories(src/main/cpp/)

    替换原有的add_library命令就可以了,其实就是生成一个变量,指定cpp的文件路径

    4. 设置编译类型

    #set release

    if (NOT CMAKE_BUILD_TYPE)

        message("not defined Build Type:auto define it to Debug" )

        set (CMAKE_BUILD_TYPE Debug)

    endif (NOT CMAKE_BUILD_TYPE)

     

    if (CMAKE_BUILD_TYPE MATCHES "Debug" )

        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g ")

        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g ")

    elseif (CMAKE_BUILD_TYPE MATCHES "Release" )

        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 ")

        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2 ")

    elseif (CMAKE_BUILD_TYPE MATCHES "RelWithDebInfo")

        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O2 ")

        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O2 ")

    else()

        message("unkown defined Build Type:same handle with Debug" )

        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g ")

        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g ")

    endif (CMAKE_BUILD_TYPE MATCHES "Debug")

    5. 外部库FIND_PACKAGE

    格式: 

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

    5.1 查找*.cmake的顺序

    1 find_package(<Name>)命令首先会在模块路径中寻找Find<name>.cmake

    这是查找库的一个典型方式,具体查找路径依次为CMake: 

    变量${CMAKE_MODULE_PATH}中的所有目录。

    如果没有, 然后再查看它自己的模块目录: /share/cmake-x.y/Modules/ 。

    这称为模块模式。

    2如果没找到这样的文件:

    find_package()会在:

    ~/.cmake/packages/

    或/usr/local/share/

    中的各个包目录中查找,寻找:

    <库名字的大写>Config.cmake 

    或 <库名字的小写>-config.cmake

    (比如库Opencv,它会查找/usr/local/share/OpenCV中的OpenCVConfig.cmake或opencv-config.cmake)。**这称为配置模式。

    不管使用哪一种模式,只要找到.cmake.cmake里面都会定义下面这些变量:

    例子<NAME>: OpenCVConfig.cmake

    <NAME>_FOUND

    <NAME>_INCLUDE_DIRS or <NAME>_INCLUDES

    <NAME>_LIBRARIES or <NAME>_LIBRARIES or <NAME>_LIBS

    <NAME>_DEFINITIONS

    注意大部分包的这些变量中的包名是全大写的,如 LIBFOO_FOUND ,有些包则使用包的实际大小写,如 LibFoo_FOUND

      如果找到这个包,则可以通过在工程的顶层目录中的CMakeLists.txt 文件添加 include_directories(_INCLUDE_DIRS) 来包含库的头文件,添加target_link_libraries(源文件 _LIBRARIES)命令将源文件与库文件链接起来。

    5.2 使用外部库的方式

    为了能支持各种常见的库和包,CMake自带了很多模块。可以通过命令cmake --help-module-list得到你的CMake支持的模块的列表,或者直接查看模块路径。比如Ubuntu上,模块的路径是: 

    /usr/share/cmake/Modules/

    让我们以bzip2库为例。CMake中有个FindBZip2.cmake 模块。只要使用 find_package(BZip2) 调用这个模块,cmake会自动给一些变量赋值,然后就可以在CMakelists.txt中使用它们了。变量的列表可以查看cmake模块文件,或者使用命令 cmake –help-module FindBZip2 。

    比如一个使用bzip2的简单程序,编译器需要知道 bzlib.h 的位置,链接器需要找到bzip2库(动态链接的话,Unix上是 libbz2.so 类似的文件,Windows上是 libbz2.dll )。

    cmake_minimum_required(VERSION 2.8)

    project(helloworld)

    add_executable(helloworld hello.c)

    find_package(BZip2)

    if (BZIP2_FOUND)

      include_directories(${BZIP_INCLUDE_DIRS})

      target_link_libraries (helloworld ${BZIP2_LIBRARIES})

    endif (BZIP2_FOUND)

    5.3 find_package中的参数定义

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

    1 version参数 

    需要一个版本号,它是正在查找的包应该兼容的版本号。 

    eg: 

    find_package(Boost ${boost_version})

    2 EXACT选项 

    要求版本号必须精确匹配。如果在find-module内部对该命令的递归调用没有给定[version]参数,那么[version]和EXACT选项会自动地从外部调用前向继承。对版本的支持目前只存在于包和包之间。 

    eg: 

    find_package(Boost ${boost_version} EXACT REQUIRED)

    3 QUIET 参数: 

    会禁掉包没有被发现时的警告信息。对应于Find.cmake模块中的 NAME_FIND_QUIETLY。 

    eg: 

    find_package(Boost ${boost_version} EXACT QUIET)

    4 REQUIRED 参数 

    其含义是指是工程必须的,表示如果报没有找到的话,cmake的过程会终止,并输出警告信息。对应于Find.cmake模块中的 NAME_FIND_REQUIRED 变量。 

    eg: 

    find_package(Boost REQUIRED COMPONENTS system)

    COMPONENTS参数 

    在REQUIRED选项之后,或者如果没有指定REQUIRED选项但是指定了COMPONENTS选项,在它们的后面可以列出一些与包相关(依赖)的部件清单(components list) 

    eg: 

    find_package(Boost REQUIRED COMPONENTS system)

    6. 其他

    cmake中一些预定义变量

    • PROJECT_SOURCE_DIR 工程的根目录
    • PROJECT_BINARY_DIR 运行cmake命令的目录,通常是${PROJECT_SOURCE_DIR}/build
    • CMAKE_INCLUDE_PATH 环境变量,非cmake变量
    • CMAKE_LIBRARY_PATH 环境变量
    • CMAKE_CURRENT_SOURCE_DIR 当前处理的CMakeLists.txt所在的路径
    • CMAKE_CURRENT_BINARY_DIR target编译目录 
    • 使用ADD_SURDIRECTORY(src bin)可以更改此变量的值 
    • SET(EXECUTABLE_OUTPUT_PATH <新路径>)并不会对此变量有影响,只是改变了最终目标文件的存储路径
    • CMAKE_CURRENT_LIST_FILE 输出调用这个变量的CMakeLists.txt的完整路径
    • CMAKE_CURRENT_LIST_LINE 输出这个变量所在的行
    • CMAKE_MODULE_PATH 定义自己的cmake模块所在的路径 
    • SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake),然后可以用INCLUDE命令来调用自己的模块
    • EXECUTABLE_OUTPUT_PATH 重新定义目标二进制可执行文件的存放位置
    • LIBRARY_OUTPUT_PATH 重新定义目标链接库文件的存放位置
    • PROJECT_NAME 返回通过PROJECT指令定义的项目名称
    • CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS 用来控制IF ELSE语句的书写方式

    系统信息

    • CMAKE_MAJOR_VERSION cmake主版本号,如2.8.6中的2
    • CMAKE_MINOR_VERSION cmake次版本号,如2.8.6中的8
    • CMAKE_PATCH_VERSION cmake补丁等级,如2.8.6中的6
    • CMAKE_SYSTEM 系统名称,例如Linux-2.6.22
    • CAMKE_SYSTEM_NAME 不包含版本的系统名,如Linux
    • CMAKE_SYSTEM_VERSION 系统版本,如2.6.22
    • CMAKE_SYSTEM_PROCESSOR 处理器名称,如i686
    • UNIX 在所有的类UNIX平台为TRUE,包括OS X和cygwin
    • WIN32 在所有的win32平台为TRUE,包括cygwin

    开关选项

    • BUILD_SHARED_LIBS 控制默认的库编译方式。如果未进行设置,使用ADD_LIBRARY时又没有指定库类型,默认编译生成的库都是静态库 (可在t3中稍加修改进行验证)
    • CMAKE_C_FLAGS 设置C编译选项
    • CMAKE_CXX_FLAGS 设置C++编译选项

    运行

    cmake .

    make

  • 相关阅读:
    如何实现浏览器内多个标签页之间的通信?
    vue组件库的基本开发步骤(源代码)
    vue组件库的基本开发步骤
    Websocket原理
    TCP和UDP的区别
    一句话概括 tcp三次握手
    简单说一下你对http和https的理解
    .Ajax(async异步与sync同步)
    get和post请求方式的区别
    面试易忽略状态码
  • 原文地址:https://www.cnblogs.com/navysummer/p/10251537.html
Copyright © 2011-2022 走看看