CMakeLists 小学-3

前两篇博客弄明白了cmake的基本command 和variable 。

现在看看别人怎么写CMakeLists.txt 的。

下面是美国德克萨斯大学(奥斯汀分校)的一个研究生写的,源码在github上

cmake_minimum_required(VERSION 2.8)
project(UTAustinVillaBase CXX C)

set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/)

find_package(Threads REQUIRED)
find_package(Boost COMPONENTS system REQUIRED)
find_package(Rcssnet3d REQUIRED)

if(NOT CMAKE_BUILD_TYPE)
  message(STATUS "No build type selected, default to Release")
  set (CMAKE_BUILD_TYPE Release)
endif(NOT CMAKE_BUILD_TYPE)

if(NOT CMAKE_CXX_FLAGS)
  set(CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-unused ")
endif(NOT CMAKE_CXX_FLAGS)


set(CORE_PATH utwalk)

include_directories(
${CORE_PATH}
${RCSSNET3D_INCLUDE_DIR}
)

set(CORE_FILES
  ${CORE_PATH}/MotionCore.cpp
  ${CORE_PATH}/Module.cpp
  ${CORE_PATH}/common/NMatrix.cpp
  ${CORE_PATH}/math/MVTools.cpp
  ${CORE_PATH}/math/RotationMatrix.cpp
  ${CORE_PATH}/memory/Lock.cpp
  ${CORE_PATH}/memory/Logger.cpp
  ${CORE_PATH}/memory/Memory.cpp
  ${CORE_PATH}/memory/MemoryBlock.cpp
  ${CORE_PATH}/memory/PrivateMemory.cpp
  ${CORE_PATH}/memory/SharedMemory.cpp
  ${CORE_PATH}/motion/MotionModule.cpp
  ${CORE_PATH}/motion/UTWalkEngine.cpp
  ${CORE_PATH}/sensor/SensorModule.cpp
  ${CORE_PATH}/sensor/InertialFilter.cpp
  ${CORE_PATH}/kinematics/InverseKinematics.cpp
  ${CORE_PATH}/kinematics/ForwardKinematics.cpp
  ${CORE_PATH}/kinematics/KinematicsModule.cpp
  ${CORE_PATH}/math/Geometry.cpp
  ${CORE_PATH}/common/PIDController.cpp
  ${CORE_PATH}/motion/WalkEngineParameters.cpp
)

set(SRCS
  main.cc
  behaviors/behavior.cc
  behaviors/naobehavior.cc
  behaviors/checkfall.cc
  behaviors/kicking.cc
  behaviors/strategy.cc
  behaviors/pkbehaviors.cc
  behaviors/gazebobehavior.cc
  servercomm/primitives.cc
  parser/parser.cc
  math/hctmatrix.cc
  math/vecposition.cc
  math/Geometry.cc
  worldmodel/worldmodel.cc
  bodymodel/bodymodel.cc
  particlefilter/PFLocalization.cc
  particlefilter/Particle.cc
  skills/skill.cc
  skills/curve3d.cc
  ikfast/ikfast.cpp
  headers/headers.cc
  audio/audio.cc
  rvdraw/rvdraw.cc
  ${CORE_FILES}
  kalman/BallKF.cpp
  kalman/PlayerKF.cpp
  kalman/OrigKalmanFilter.cpp
  optimization/optimizationbehaviors.cc
)

add_executable(agentspark
${SRCS}
)

target_link_libraries(agentspark
${RCSSNET3D_LIBRARY}
${Boost_SYSTEM_LIBRARY}
dl
${CMAKE_THREAD_LIBS_INIT}
rt
)

如果从头读到这,都没有问题。那么,说明你的水平已不是小学水平了,就不用往下看了==#

1. project

project(UTAustinVillaBase CXX C)

这个project和之前我们写的project有点不同,它多了两个参数 CXX 和 C

CXX是语言,表示C/C++,C是语言名 指代前面的CXX

帮助文档的解释:

Set a name, version, and enable languages for the entire project.

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

Optionally you can specify which languages your project supports.
Example languages are ``C``, ``CXX`` (i.e.  C++), ``Fortran``, etc.
By default ``C`` and ``CXX`` are enabled if no language options are

given.

注:默认就是CXX,看来UT Austin大佬多此一举了==

2. CMAKE_MODULE_PATH

set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/)
${CMAKE_SOURCE_DIR}/cmake/ 这个路径就是当前项目 顶层目录下的cmake目录

之所以把这个cmake目录加到CMAKE_MODULE_PATH中,是因为,有一个module(Rcssnet3d)不在cmake自带的Modules路径下(不在默认的CMAKE_MODULE_PATH中)。Rcssnet3d是UT Austin自己写的module,要想让自己写的module能被find_package()找到,必须把它添加到CMAKE_MODULE_PATH

帮助文档

List of directories to search for CMake modules. 说明CMAKE_MODULE_PATH是一个目录列表。
Commands like include() and find_package() search for files indirectories listed by this variable before checking the defaultmodules that come with CMake.

3. find_package()

find_package(Threads REQUIRED)
find_package(Boost COMPONENTS system REQUIRED)
find_package(Rcssnet3d REQUIRED)

这三个find_package(),我们知道是找包(module,第三方库)的,

其中Threads 和Boost 都在/usr/share/cmake-3.5/Modules中,Rcssnet3d<project_path>/cmake中。

那么,REQUIREDCOMPONENTS是什么呢?


帮助文档:
find_package(<package> [version] [EXACT] [QUIET] [MODULE]
              [REQUIRED] [[COMPONENTS] [components...]]
              [OPTIONAL_COMPONENTS components...]
              [NO_POLICY_SCOPE])
Finds and loads settings from an external project.  ``<package>_FOUND``
will be set to indicate whether the package was found.  When the
package is found package-specific information is provided through
variables and :ref:`Imported Targets` documented by the package itself.  The
``QUIET`` option disables messages if the package cannot be found.  The
``MODULE`` option disables the second signature documented below.  The
``REQUIRED`` option stops processing with an error message if the package
cannot be found
.

REQUIRED参数作用:在package 没有找到的情况下,停止处理并报错。

A package-specific list of required components may be listed after the
``COMPONENTS`` option (or after the ``REQUIRED`` option if present).
Additional optional components may be listed after
``OPTIONAL_COMPONENTS``.  Available components and their influence on
whether a package is considered to be found are defined by the target

package.

COMPONENTS参数作用:找 指定包(package-specific)的组件(required components)。不要整个包,要组件。

vim /usr/share/cmake-3.5/Modules/FindBoost.cmake,看看Boost关于system组件的介绍。

Implicit dependencies such as Boost::filesystem 
requiring Boost::system will be automatically detected and satisfied, 
even if system is not specified when using find_package 
and if Boost::system is not added to target_link_libraries.  
If using Boost::thread, then Thread::Thread will also be added automatically.

这里自动检测并满足是什么鬼????身为小白的我,心很累==。。。

有时间再学习Boost库,一样一样学,啊...

4. if(Not CMAKE_BUILD_TYPE)

if(NOT CMAKE_BUILD_TYPE)
  message(STATUS "No build type selected, default to Release")
  set (CMAKE_BUILD_TYPE Release)
endif(NOT CMAKE_BUILD_TYPE)

if 简介:

 if(expression)
   # then section.
   COMMAND1(ARGS ...)
   COMMAND2(ARGS ...)
   ...
 elseif(expression2)
   # elseif section.
   COMMAND1(ARGS ...)
   COMMAND2(ARGS ...)
   ...
 else(expression3)
   # else section.
   COMMAND1(ARGS ...)
   COMMAND2(ARGS ...)
   ...
 endif(expression)

一个if() 必须对应一个 endif() 。if嵌套在if里,也必须要有对应的endif。

elseif() 不需要对应。else() 不需要对应。

帮助文档:

Evaluates the given expression.  If the result is true, the commands
in the THEN section are invoked.  Otherwise, the commands in the else
section are invoked.  The elseif and else sections are optional.  You
may have multiple elseif clauses(从句).  Note that the expression in the

else and endif clause is optional.  

Long expressions can be used and there is a traditional order of precedence(优先权).
Parenthetical expressions(插入的表达式) are evaluated first followed by unary(一元的)
tests such as ``EXISTS``, ``COMMAND``, and ``DEFINED``. 
Then any binary tests such as ``EQUAL``, ``LESS``, ``GREATER``, 
``STRLESS``, ``STRGREATER``, ``STREQUAL``, and ``MATCHES`` will be evaluated. 
Then boolean ``NOT`` operators and finally boolean ``AND`` and 

then ``OR`` operators will be evaluated.

Possible expressions are:
``if(<constant>)``
 True if the constant is ``1``, ``ON``, ``YES``, ``TRUE``, ``Y``,
 or a non-zero number.  False if the constant is ``0``, ``OFF``,
 ``NO``, ``FALSE``, ``N``, ``IGNORE``, ``NOTFOUND``, the empty string,
 or ends in the suffix ``-NOTFOUND``.  Named boolean constants are
 case-insensitive.  If the argument is not one of these specific
 constants, it is treated as a variable or string and the following
 signature is used.

``if(<variable|string>)``
 True if given a variable that is defined to a value that is not a false

 constant(变量被定义了,且定义值为真).  False otherwise.
 (Note macro arguments are not variables.)

``if(NOT <expression>)``

 True if the expression is not true.

if(NOT CMAKE_BUILD_TYPE) 里,CMAKE_BUILD_TYPE是cmake自带的变量,默认为empty。

这里set (CMAKE_BUILD_TYPE Release) 把CMAKE_BUILD_TYPE设置为Release(发布)。

CMAKE_BUILD_TYPE可取的值(了解即可):

empty, ``Debug``, ``Release``, ``RelWithDebInfo`` and ``MinSizeRel``.

再看看这里的message:比之前多了一个STATUS

message([<mode>] "message to display" ...)
The optional ``<mode>`` keyword determines the type of message:
 (none)         = Important information
 STATUS         = Incidental(附带的,次要的) information

多了一个STATUS,在输出效果上看,就多了两个dash(-)。

5. CMAKE_CXX_FLAGS

if(NOT CMAKE_CXX_FLAGS)
  set(CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-unused")
endif(NOT CMAKE_CXX_FLAGS)

 CMAKE_CXX_FLAGS属于CMAKE_<LANG>_FLAGS变量。

CMAKE_CXX_FLAGS 可以取哪些值,我还不清楚,只知道它可以把compiler flags设置为C++。(在网上找了半天,都没找到关于这个变量详细说明)。 

想要在CMakeLists.txt 里设置C++支持C++11标准,可以用以下语句[1]

#只要这一条语句,不用设置CMAKE_CXX_FLAGS
set (CMAKE_CXX_STANDARD 11)
 

奇怪的是,set (CMAKE_CXX_STANDARD 11)加到ut的CMakeLists中,会报关于share_ptr错。

6. include_directories

set(CORE_PATH utwalk)

include_directories(
${CORE_PATH}
${RCSSNET3D_INCLUDE_DIR})

${CORE_PATH}就是顶层目录下的utwalk目录,utwalk目录下是一些关于机器人行走的源码。

${RCSSNET3D_INCLUDE_DIR} 是在module里定义的(<name>_INCLUDE_DIR),

find_package(Rcssnet3d REQUIRED)以后,就可以直接拿来用了。

FindRcssnet3d.cmake里有这样一句说明:
RCSSNET3D_INCLUDE_DIR     - where to find rcssnet include files

7. 其他内容

最后两个长长的set 定义了两个列表,里面都是源文件。

add_executable(agentspark ${SRCS})

target_link_libraries(agentspark
${RCSSNET3D_LIBRARY}
${Boost_SYSTEM_LIBRARY}
dl
${CMAKE_THREAD_LIBS_INIT}
rt
)

${SRCS} 下的所有源文件编译成一个可执行文件agentspark

把五个库链接到agentspark

8. 总结

现在看懂CMakeLists 文件已经没问题了。

下一步该考虑:

  1. 如何自己写module,使用find_package()调用自己写的module
  2. CMakeCache.txt 查看和编辑
  3. cmake 的单元测试部分 ctest


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值