导航

    蓝鲸ROS机器人论坛

    • 注册
    • 登录
    • 搜索
    • 版块
    • 话题
    • 热门
    ROS交流群
    ROS Group
    产品服务
    Product Service
    开源代码库
    Github
    官网
    Official website
    技术交流
    Technological exchanges
    激光雷达
    LIDAR
    ROS教程
    ROS Tourials
    深度学习
    Deep Learning
    机器视觉
    Computer Vision

    cmake的简单使用

    技术交流
    findpath cmakemodules findpackage cmake
    1
    1
    5575
    正在加载更多帖子
    • 从旧到新
    • 从新到旧
    • 最多赞同
    回复
    • 在新帖中回复
    登录后回复
    此主题已被删除。只有拥有主题管理权限的用户可以查看。
    • weijiz
      weijiz 最后由 编辑

      在用别人写的c或者c++程序的时候。最经常见到的就是cmakelist.txt这个文件了。通常想要编译程序的时候需要执行

      cmake
      make
      make install
      

      这里cmake就是根据cmakelist.txt文件生成编译时使用的makefile文件
      一个程序的编译过程需要经过两个主要的过程。一个是把各个文件编译成机械码,另一个是把编译出的各个文件的机械码链接成一个文件。而cmakelist.txt的作用就是告诉编译软件头文件和链接库在什么地方,以及添加一些编译的特殊参数。下面就简单介绍一下cmakelist.txt应该怎么写。这里只介绍基本的功能,目的是快速上手,所以算是一个 cmakelist.txt quick start guide.

      以下面这个文件为例

      cmake_minimum_required(VERSION 2.8.3)
      
      project(orb_slam2)
      find_package(catkin REQUIRED COMPONENTS
        roscpp
        sensor_msgs
        image_transport
        message_filters
        cv_bridge
        cmake_modules)
      
      set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}  -Wall  -O3 -march=native ")
      set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall  -O3 -march=native")
      
      # Check C++11 or C++0x support
      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")
         add_definitions(-DCOMPILEDWITHC11)
         message(STATUS "Using flag -std=c++11.")
      elseif(COMPILER_SUPPORTS_CXX0X)
         set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
         add_definitions(-DCOMPILEDWITHC0X)
         message(STATUS "Using flag -std=c++0x.")
      else()
         message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
      endif()
      
      LIST(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/../../../cmake_modules)
      
      find_package(OpenCV 2.4.3 REQUIRED)
      find_package(Eigen3 3.1.0 REQUIRED)
      find_package(Pangolin REQUIRED)
      find_package(libmongocxx REQUIRED)
      find_package(libbsoncxx REQUIRED)
      
      
      catkin_package()
      
      include_directories(
      ${PROJECT_SOURCE_DIR}
      ${PROJECT_SOURCE_DIR}/../../../
      ${PROJECT_SOURCE_DIR}/../../../include
      ${Pangolin_INCLUDE_DIRS}
      ${LIBMONGOCXX_INCLUDE_DIRS}
      ${LIBBSONCXX_INCLUDE_DIRS}
      )
      
      set(LIBS
      ${catkin_LIBRARIES}
      ${OpenCV_LIBS}
      ${EIGEN3_LIBS}
      ${Pangolin_LIBRARIES}
      ${PROJECT_SOURCE_DIR}/../../../Thirdparty/DBoW2/lib/libDBoW2.so
      ${PROJECT_SOURCE_DIR}/../../../Thirdparty/g2o/lib/libg2o.so
      ${PROJECT_SOURCE_DIR}/../../../lib/libORB_SLAM2.so
      ${LIBMONGOCXX_LIBRARY_DIRS}/libmongocxx.so
      ${LIBBSONCXX_LIBRARY_DIRS}/libbsoncxx.so
      )
      
      # Node for monocular camera
      add_executable(mono
      src/ros_mono.cc
      )
      
      target_link_libraries(mono
      ${LIBS}
      )
      
      # Node for RGB-D camera
      add_executable(rgbd
      src/ros_rgbd.cc
      )
      
      target_link_libraries(rgbd
      ${LIBS}
      )
      
      # Node for stereo camera
      add_executable(stereo
      src/ros_stereo.cc
      )
      
      target_link_libraries(stereo
      ${LIBS}
      )
      

      首先是指定cmake的版本
      然后是工程的名字
      然后是find_package. 软件一般都是有依赖关系的,如果你依赖别的软件,就可以通过find_package来载入依赖的软件的相关信息,比如软件的头文件,软件的链接库位置。find_package会在特定的目录里去找对应的软件config文件。在cmake的安装路径下里面有各种已安装的软件包的cmake文件。find_package实际上就是在找这些文件,然后执行一遍。有时自己依赖的软件包并不提供这样的文件,这时候就要自己去写。
      alt text

      上图的libbsoncxx-config.cmake就是libbsoncxx这个软件包的cmake文件。在cmake文件中的CMAKE_MODULE_PATH变量就是find_package找的路径。可以在里面添加上自定义的路径。find_package还可以添加上 REQUIRED标记,表明这个软件包是必须的。如果find_package没有找到这个软件包,那么cmake就出报出没有找到这个软件包的错误。
      Set 可以用来设置环境变量的。
      然后在cmake文件里面是有简单的判断分支结构可以用的,简单的语法就是

      If(xxxx)
      elseif(xxxx)
      endif(xxxx)
      

      需要注意的是elseif里面并不是另一种条件,这里要和if里面写的一样。表示当if的条件未被满足时应该执行的语句。如果想要实现更加复杂的判断,就需要嵌套的if语句。
      最后就是 include_directories和 target_link_libraries。这两个的意义很明确,就是设置头文件的地址和链接库的位置。还有就是生成可执行程序的命令 add_executable, 第一个变量是生成的文件名字,之后是对应的源文件。如果不想生成可执行文件,只是想生成一个链接库供别人使用,那么可以用add_library这个命令。使用方法和 add_executable基本一致。下面是一个例子

          add_library(${PROJECT_NAME} SHARED
      src/System.cc
      src/Tracking.cc
      src/LocalMapping.cc
      src/LoopClosing.cc
      src/ORBextractor.cc
      src/ORBmatcher.cc
      src/FrameDrawer.cc
      src/Converter.cc
      src/MapPoint.cc
      src/KeyFrame.cc
      src/Map.cc
      src/MapDrawer.cc
      src/Optimizer.cc
      src/PnPsolver.cc
      src/Frame.cc
      src/KeyFrameDatabase.cc
      src/Sim3Solver.cc
      src/Initializer.cc
      src/Viewer.cc
      )
      

      SHARED是这个库的类型。动态链接库还是静态链接库。
      到这里基本上简单的cmakelist文件已经可以自己写了。下面说说软件库的cmake文件怎么写。就是find_package那个命令会用到的那个文件。

      我们还是以一个例子来做说明。

          # - Find MongoDB
      #  Find the MongoDB includes and client library
      #  This module defines
      #  MongoDB_INCLUDE_DIR, where to find mongo/client/dbclient.h
      #  MongoDB_LIBRARIES, the libraries needed to use MongoDB.
      #  MongoDB_FOUND, If false, do not try to use MongoDB.
      
      if(MongoDB_INCLUDE_DIR AND MongoDB_LIBRARIES)
         set(MongoDB_FOUND TRUE)
      
      else(MongoDB_INCLUDE_DIR AND MongoDB_LIBRARIES)
      
        find_path(MongoDB_INCLUDE_DIR bsoncxx/builder/basic/document.hpp
            /usr/local/include/mongocxx/v_noabi
            /usr/local/include/libbson-1.0
            /usr/local/include/libmongoc-1.0
            /usr/local/include/bsoncxx/v_noabi
            )
      
      if(WIN32)
        find_library(MongoDB_LIBRARIES NAMES mongoclient
            PATHS
            $ENV{ProgramFiles}/Mongo/*/lib
            $ENV{SystemDrive}/Mongo/*/lib
            )
      else(WIN32)
        find_library(MongoDB_LIBRARIES NAMES mongocxx bsoncxx
            PATHS
            /usr/lib
                /usr/lib64
            /usr/lib/mongo
            /usr/lib64/mongo
            /usr/local/lib
            /usr/local/lib64
            /usr/local/lib/mongo
            /usr/local/lib64/mongo
            /opt/mongo/lib
            /opt/mongo/lib64
            )
      endif(WIN32)
      
        if(MongoDB_INCLUDE_DIR AND MongoDB_LIBRARIES)
          set(MongoDB_FOUND TRUE)
          message(STATUS "Found MongoDB: ${MongoDB_INCLUDE_DIR}, ${MongoDB_LIBRARIES}")
        else(MongoDB_INCLUDE_DIR AND MongoDB_LIBRARIES)
          set(MongoDB_FOUND FALSE)
          if (MongoDB_FIND_REQUIRED)
      		message(FATAL_ERROR "MongoDB not found.")
      	else (MongoDB_FIND_REQUIRED)
      		message(STATUS "MongoDB not found.")
      	endif (MongoDB_FIND_REQUIRED)
        endif(MongoDB_INCLUDE_DIR AND MongoDB_LIBRARIES)
      
        mark_as_advanced(MongoDB_INCLUDE_DIR MongoDB_LIBRARIES)
      
      endif(MongoDB_INCLUDE_DIR AND MongoDB_LIBRARIES)
      

      这是一个叫做MongoDB的软件包的cmake文件。
      这个文件会通过设置MongoDB_FOUND变量来告诉cmake这个库有没有找到。这里需要注意的就是find_path这个指令。这个就是用来判断软件是否存在的关键指令。find_path的第一个参数接的是变量名字,之后是文件的名字。后面接一系列这个文件可能存在的路径。也就是软件的可能安装路径。如果在以下路径成功找到这个文件。第一个变量就会被赋值。反之如果找不到,那么这个变量就会被设成False。之后可以用if来判断不同条件下需要执行的语句。大致上就是如此。

      这里只是一些简单的介绍,如果想要更全面的更准确的了解cmake那么可以去看看cmake的官方文档。虽然我觉得那个并不是写出来给人看的。

      1 条回复 最后回复 回复 引用 0
      • 1 / 1
      • First post
        Last post
      Copyright © 2015-2023 BlueWhale community