CMake是一个跨平台的自动化建构系统,他使用一个名为CMakeLists.txt的文件来描述构建过程,可以产生标准的构建文件,如Unix的Makefile或Windows Visual C++的projects/workspaces。文件CMakeLists.txt需要手工编写,也可以通过编写脚本进行半自动的生成。CMake提供了比autoconfig更简洁的语法。在Linux平台下使用CMake生成Makefile并编译的流程如下:
1、编写CMakeLists.txt
2、执行命令:"cmake PATH"生成Makefile(PATH是CMakeLists.txt所在的目录)。
3、使用Make命令进行编译。
应用
源代码的目录结构
--CMakeSample
|
+--CMakeLists.txt
|
+--cmake
|
+--modules
|
+FindTHREAD_DB.cmake
+--src
|
+--CMakeLists.txt
|
+--hello
|
+--CMakeLists.txt
|
+--hello.h
|
+--hello.cpp
+--sample
|
+--CMakeLists.txt
|
+--main.cpp
在这个例子我模拟以下情况
1、在一个目录下生成一个静态库
2、在另一个目录中生成一个可执行程序,并引用了前一个静态库。
3、查找外部库,(这里例子是在系统的默认路径下查找,这是不必要的,纯粹是为介绍而设的,实际也没有使用)。
首先来编写根目录下的CMakeLists.txt
PROJECT(cmakesample)
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
#Appends the cmake/modules path inside the MAKE_MODULE_PATH variable which stores the
# directories of additional CMake modules
SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/modules ${CMAKE_MODULE_PATH})
ADD_SUBDIRECTORY(src)
1、PROJECT(cmakesample)命名项目的名称。
2、CMAKE_MINIMUM_REQUIRED(VERSION 2.6)声明了CMake的版本要求。
3、SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/modules ${CMAKE_MODULE_PATH})指定了一些自己写的CMake模版所存放的地址,比如FindTHREAD_DB.cmake。其中PROJECT_SOURCE_DIR是代码的根目录,也可以使用cmakesample_SOURCE_DIR来替代,cmakesample就是项目名称。
4、ADD_SUBDIRECTORY(src)指定了代码所在的子目录。
接着来编写src的CMakeLists.txt
INCLUDE_DIRECTORIES(hello)
SUBDIRS(hello sample)
1、INCLUDE_DIRECTORIES(hello)指定了头文件所在的目录,只有src下的子目录中的 CMakeLists.txt可用,假设外面还有一层跟src同一级别的目录,那么这句话对另一个目录下的CMakeLists.txt无效。其实这句话可以放在sample里的CMakeLists.txt里,不过此时需要改成INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/src/hello)。
2、SUBDIRS(hello sample)相当于分别写ADD_SUBDIRECTORY(hello),ADD_SUBDIRECTORY(sample)
接着我们写hello下的CMakeLists.txt
AUX_SOURCE_DIRECTORY(. DIR_HELLO_SRCS)
ADD_LIBRARY(hello STATIC ${DIR_HELLO_SRCS})
1、AUX_SOURCE_DIRECTORY(. DIR_HELLO_SRCS)把当天目录下的所有源码文件名赋给变量DIR_HELLO_SRCS。
2、ADD_LIBRARY(hello STATIC ${DIR_HELLO_SRCS})指定生成一个静态库。那如果要生成一个动态库呢,只要把STATIC改为SHARED就可以了。不过如果我们想同时生成静态库和动态库呢?直接把两句话放在一起?这是不行的,因为在CMake中每个target都必须有一个唯一的命名,于是我们把两个语句放在一起就在命名上冲突了。那么如何解决呢,其实CMake的target名并不一定要和输出文件一致的,于是我们可以通过为静态库和动态库设不同的target名,但把输出文件名设成一样来解决这个问题(其实文件名也是不完全一样的,一个是.a结尾,另一个是.so结尾)。于是我们可以这样来写:
ADD_LIBRARY(hello_static STATIC ${DIR_HELLO_SRCS})
SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME "hello")
SET_TARGET_PROPERTIES(hello_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
ADD_LIBRARY(hello_shared SHARED ${DIR_HELLO_SRCS})
SET_TARGET_PROPERTIES(hello_shared PROPERTIES OUTPUT_NAME "hello")
SET_TARGET_PROPERTIES(hello_shared PROPERTIES CLEAN_DIRECT_OUTPUT 1)
接下来我们来写sample下CMakeLists.txt
SET(DIR_SRCS main.cpp)
ADD_EXECUTABLE(sample ${DIR_SRCS})
TARGET_LINK_LIBRARIES(sample hello)
INSTALL(TARGETS sample RUNTIME DESTINATION bin)
1、SET(DIR_SRCS main.cpp)把变量DIR_SRCS赋值为"main.cpp"。也是通过AUX_SOURCE_DIRECTORY(. DIR_SRCS
)来实现。
2、ADD_EXECUTABLE(sample ${DIR_SRCS})声明要生成一个叫sample的可执行程序。
3、TARGET_LINK_LIBRARIES(sample hello)声明需要链接libhello.a库(因为我上面把hello声明为静态库了)。
4、INSTALL(TARGETS sample RUNTIME DESTINATION bin)声明当运行make insall时把可执行程序安装在${PREFIX}/bin下。其中PREFIX的默认值为/usr/local/,也可以通过在运行cmake时指定-DCMAKE_INSTALL_PREFIX:PATH="${CMAKE_INSTALL_PREFIX}"
最后我们写一下FindTHREAD_DB.cmake
#
# configuration to find DB_CXX library
#
# Include dir
find_path(THREAD_DB_INCLUDE_DIR
NAMES thread_db.h
PATHS /usr/include/ /usr/local/include/
)
# Finally the library itself
find_library(THREAD_DB_LIBRARY
NAMES thread_db
PATHS /usr/lib/ /usr/local/lib/
)
1、find_path(THREAD_DB_INCLUDE_DIR NAMES thread_db.h PATHS /usr/include/ /usr/local/include/)在目录“/usr/include"和"/usr/local/include"下查找thread_db.h,如果找到则把目录名赋给THREAD_DB_INCLUDE_DIR
2、find_library(THREAD_DB_LIBRARY NAMES thread_db PATHS /usr/lib/ /usr/local/lib/)在目录"/usr/lib"和"/usr/local/lib"下查找libthread_db.so,如果找到则把库文件的绝对路径赋给THREAD_DB_LIBRARY
为了纯粹测试,我们就修改./src/sample/CMakeLists.txt为:
FIND_PACKAGE(THREAD_DB REQUIRED)
MARK_AS_ADVANCED(
THREAD_DB_INCLUDE_DIR
THREAD_DB_LIBRARY
)
MESSAGE(STATUS ${THREAD_DB_INCLUDE_DIR}, ${THREAD_DB_LIBRARY})
SET(DIR_SRCS
main.cpp)
ADD_EXECUTABLE(sample ${DIR_SRCS})
TARGET_LINK_LIBRARIES(sample hello)
INSTALL(TARGETS sample RUNTIME DESTINATION bin)
接着我们在项目的根目录下建立一个文件夹build。
进入build运行"cmake .."。有如下输出:
-- The C compiler identification is GNU
-- The CXX compiler identification is GNU
-- Check for working C compiler: /usr/bin/gcc
-- Check for working C compiler: /usr/bin/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- /home/dylan/Public/CMakeSample
-- /usr/include,/usr/lib/libthread_db.so
-- Configuring done
-- Generating done
-- Build files have been written to: /home/dylan/Public/CMakeSample/build
其中"/usr/include,/usr/lib/libthread_db.so"就是MESSAGE(STATUS ${THREAD_DB_INCLUDE_DIR}, ${THREAD_DB_LIBRARY})的输出。
还有一点我要先建立build,然后再运行cmake ..的主要原因是这样就不会污染源代码,如果我不想要这些自动生成的文件时只要简单的删除build文件夹就可以了, 这也是我喜欢cmake的一个原因。
最后我们运行make。这时就会在./build/src/sample下生成一个可执行文件,./build/src/hello下生成一个静态库。
分享到:
相关推荐
例如,下面是一个简单的 `CMakeLists.txt` 示例: ```cmake # 项目名称 PROJECT(test_math) # 头文件路径 INCLUDE_DIRECTORIES(include) # 源文件目录 AUX_SOURCE_DIRECTORY(src DIR_SRCS) # 设置环境变量 SET...
本教程将通过一个简单的CMake例子,帮助初学者快速理解CMake的基本用法。 首先,我们创建一个基本的C++项目,包含两个源文件`main.cpp`和`hello.cpp`。`main.cpp`是主程序,`hello.cpp`包含一个简单的`hello()`函数...
在Ubuntu操作系统中,CMake是一个强大的跨平台构建系统,用于管理C和C++项目的构建过程。CMake并不直接编译代码,而是生成针对特定编译器的“makefile”或项目文件,使得编译和链接过程更加自动化。下面将详细介绍...
一个简单的cmake工程例子,教你你如何使用camek创建一个qt工程.构建CMakeLists的基本工作 通过CMakeLists.txt简单构建了一个项目,说明了构建一个项目要设置的内容,例如确定最低版本、设置项目名字、设置包含路径等...
在上面的例子中,`cmake_minimum_required`指定了CMake的最低版本要求,`project`命令定义了项目名称。`add_executable`用于告诉CMake我们的项目包含哪些源代码文件,而`find_package`则用来查找和添加外部库,如...
这个“cmake使用例子.zip”压缩包显然包含了关于CMake的使用教程和实例,非常适合初学者或者需要深入理解CMake的开发者下载学习。 在CMake中,主要涉及以下几个核心概念: 1. **CMakeLists.txt**:这是CMake项目的...
在本文中,我们将深入探讨CMake的工作原理、基本语法以及如何通过实例来运用它。 首先,CMake不直接编译代码,而是生成针对特定构建系统的配置文件,如Makefile(适用于Unix/Linux系统)或Visual Studio解决方案...
通过实例讲解,使得读者能更好地理解和应用CMake解决实际问题。 **CMake Practice** 《CMake Practice》这本书则着重于实践,强调如何将CMake应用到实际的开发环境中。它包含了一系列的实践案例,覆盖了从简单的单...
一个简单的CMake项目通常包括源代码文件、头文件以及CMakeLists.txt。CMakeLists.txt会列出所有源文件,并指定如何构建。 2. **创建可执行文件** 在CMakeLists.txt中,使用`add_executable`命令指定可执行文件的...
CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程)。它能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性,类似UNIX下的automake。由于CMake易于使用...
通过这个简单的例子,我们可以看到CMake如何帮助我们组织和构建C++项目,而无需关心底层编译器的具体细节。它使得项目在不同平台上保持一致的构建过程,极大地提高了开发效率。同时,随着项目复杂性的增加,CMake也...
通过这个简单的例子,我们了解了如何使用CMake与Mujoco库协同工作,进行动力学计算。在实际开发中,你可能会遇到更多关于编译选项、多平台支持和优化的问题,但有了CMake的帮助,这些问题都可以迎刃而解。继续深入...
在这个例子中,`cmake_minimum_required`指定了CMake的最低版本要求,`project`定义了项目名称,而`add_executable`则告诉CMake如何构建可执行文件。 一旦CMakeLists.txt准备好了,可以通过以下命令来生成构建文件...
这个入门例子通过几个具体的案例,详细介绍了如何使用CMake来构建一个简单的C程序。 案例一中展示了一个简单的C程序如何通过CMake来构建。在这个案例里,首先创建了一个C文件main.c,它仅包含打印"Hello World!"的...
CMake Practice.pdf这个文件很可能是教程的详细内容,包含了更多实例和具体操作步骤。阅读并实践其中的示例,是掌握CMake的最好方式。通过不断练习,你将能够熟练地使用CMake管理复杂的项目构建,无论是在Linux还是...
在这个例子中,我们首先指定了 CMake 的最低版本要求,然后设置了项目名称为 `HelloWorld`。接下来,通过 `add_executable()` 命令定义了一个可执行程序,并指定了源文件。此外,还设置了 C++ 标准版本,并通过 `...
在最小化项目这一章中,作者介绍了如何创建一个最简单的CMake项目,并逐步讲解了其中的关键步骤: - **管理CMake版本**:确保使用兼容的CMake版本。 - **`project()`命令**:用于声明项目名称和其他相关信息。 - **...
通过以上介绍,我们可以看到CMake为开发者提供了强大的功能和支持,从简单的单文件项目到复杂的多模块项目,都能够高效地管理和构建。掌握CMake的基本使用方法对于任何从事C/C++开发的人来说都是必不可少的技能之一...