Ubuntu下使用cmake生成可执行文件

时间:2024-02-15 16:46:03

1.单个CPP文件的cmake

首先编写一个简单的程序(main.cpp):

#include <iostream>
using namespace std;
int main()
{
  cout<<"hello cmake"<<endl;
  return 0;
}

编写 CMakeLists.txt,并与main.cpp 放在同一个目录。

project(hello)
add_executable(hello main.cpp)

进入CMakeLists.txt所在目录,在CMakeLists.txt 所在的目录下创建一个 build目录,进入build目录输入:

cmake ..
make

执行完毕后,在 build 目录下会有很多编译出来的文件,但是只需要其中的可执行文件,如果要把可执行文件放到与 build 目录同级的 bin 文件夹下,那么在CMakeLists.txt 的最后加上下面这两句话:

set( CMAKE_INSTALL_PREFIX "${CMAKE_SOURCE_DIR}/bin/")
install(TARGETS hello RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX})

将 make 指令改为make install,执行完毕后,就可以在 bin 文件夹中看到可执行文件 hello。

注意:上述语句不能直接写成:

install(TARGETS hello RUNTIME DESTINATION bin)

会产生错误:

CMake Error at cmake_install.cmake:42 (FILE):
  file INSTALL cannot copy file “XXXX” to "XXXX"

因为默认路径前缀为/usr/local/

若不手动改路径前缀则会出现将项目install到/usr/local/bin而没有权限的情况。

2.引入data文件夹

如果可执行文件需要调用一些文件,假设文件在 data 文件夹中,且 data 与CMakeLists.txt 在同级目录,则可以通过如下语句将 data 文件夹也放入 bin 文件夹

install(DIRECTORY data DESTINATION ${CMAKE_INSTALL_PREFIX})

3.多个CPP和H文件的cmake

如果 main.cpp 中用到了另一个文件的内容,文件目录如下图,应该怎么办呢?


其中 hello.h 为类的声明,hello.cpp 为类函数的定义。
这时可以把 CMakeLists.txt 改为下面这样:

project(hello)
set(SRCS main.cpp hello.cpp)
add_executable(hello ${SRCS})

上述代码等价于:

project(hello)
add_executable(hello main.cpp hello.cpp)

如果 hello.cpp 与 main.cpp 不在同一个文件夹呢?如下所示


这时候每个文件夹下都要有一个 CMakeLists.txt。
其中 main.cpp 同级目录下的 CMakeLists.txt 如下:

project(hello)
add_executable(hello main.cpp)
target_link_libraries(hello header)

Hello 目录下的 CMakeLists.txt 如下:

add_library(header STATIC hello.cpp)

说明:第一个 CMakeLists.txt 中的 add_subdirectory(Hello)表示在编译时要包含Hello这个目录,而 target_link_libraries(hello header)表示在生成 hello 时要调用静态链接库 header ,而 header 是在 Hello 目录下的 CMakeLists.txt 中的add_library(header STATIC hello.cpp)中产生的。

同理,如果 hello.cpp 中使用了其它链接库里的东西,则在其 CMakeLists.txt 也要加入 target_link_libraries(header xxx)。
注意:在写 target_link_libraries 语句时,括号里面的第一名称必须是当前所需要生成文件的名称,比如上面的 hello 和 header。但是,这样写在引用头文件时要写成 #include “Hello/hello.h”, 显得过长,这时,可以在 CMakeLists.txt 中加入下面这句话:

include_directories(./Hello)

这样引用头文件就可以写成 #include “hello.h”
更多使用方法自行百度。