如何用cmake构建c++项目以及如何引入第三方库

这个项目是我从上clone下来的一个视频播放器,作者提供了Makefile,但是项目结构比较乱,所以我把Makefile删了,并调整了项目结构。

项目重构

项目作者将.cpp文件和.h文件混在一起,但提供了一个Makefile。我直接把Makefile删掉了,在Clion上自己编写CMakeLists.txt来构建项目。

重构后的项目结构如下

│  CMakeLists.txt │ ├─include │      demuxer.h │      display.h │      ffmpeg.h │      format_converter.h │      player.h │      queue.h │      timer.h │      video_decoder.h │ └─src         CMakeLists.txt         demuxer.cpp         display.cpp         ffmpeg.cpp         format_converter.cpp         main.cpp         player.cpp         timer.cpp         video_decoder.cpp 

关于SDL2和FFMPEG等第三方库

SDL2和FFMPEG的介绍后续再补充。

SDL2和FFMPEG库可以到官网下载编译好的版本,需要根据系统环境选择相应的版本。下载后解压,将得到的文件夹放入专门存放第三方库的文件夹中,我是统一放在D:/Code/cpp/third_party_lib目录中。

解压后的文件夹中会包含bin include lib三个目录,bin下存放exe和dll等二进制文件,include下存放头文件,lib下存放静态链接库。

写代码时和编译时,我们需要用到include中的头文件和lib中静态库文件,因此需要在CMakeLists.txt中设置好;而dll则在运行时才会用到,且不用在CMakeLists.txt中指明所需的dll(猜想:程序所需的dll由静态链接库指示)。尽管如此,我们仍需要为操作系统指明dll所在位置(需要将dll所在目录的路径写入PATH环境变量)。可以将所有用到dll放在同一个文件夹中,这样只需要设置一次PATH就可以了。

编写CMakeLists.txt

根目录下的CMakeLists.txt用于管理项目,如:设置头文件的路径,设置第三方库的路径等。

cmake_minimum_required(VERSION 3.5)  # 设置项目名称 project (player)  set(CMAKE_CXX_STANDARD 14) # 设置SDL2头文件与lib的目录,分别命名为SDL2_INCLUDE_DIR和SDL2_LIB_DIR供后续使用 set(SDL2_INCLUDE_DIR D:/Code/cpp/third_party_lib/SDL2-2.0.22/x86_64-w64-mingw32/include) set(SDL2_LIB_DIR D:/Code/cpp/third_party_lib/SDL2-2.0.22/x86_64-w64-mingw32/lib) # 设置ffmpeg头文件与lib的目录 set(FFMPEG_INCLUDE_DIR D:/Code/cpp/third_party_lib/ffmpeg-master-latest-win64-gpl-shared/include) set(FFMPEG_LIB_DIR D:/Code/cpp/third_party_lib/ffmpeg-master-latest-win64-gpl-shared/lib) # 设置输出的可执行文件的目录 set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) # 导入项目内定义的头文件 include_directories(include) # 导入SDL2和FFMPEG的头文件 include_directories(${SDL2_INCLUDE_DIR}) include_directories(${FFMPEG_INCLUDE_DIR}) # 链接SDL2和FFMPEG到项目中 link_directories(${SDL2_LIB_DIR}) link_directories(${FFMPEG_LIB_DIR}) # 添加子文件夹。这样运行当前CMakeLists.txt时,也会运行子文件夹的CMakeLists.txt文件 add_subdirectory(${PROJECT_SOURCE_DIR}/src) 

src文件夹中的CMakeLists.txt,描述生成目标的信息和源文件,并指明要链接哪些库。

# SRC_LIST表示./src目录中的文件 aux_source_directory(${PROJECT_SOURCE_DIR}/src SRC_LIST) # 将SRC_LIST编译成名为player的可执行程序 add_executable(player ${SRC_LIST}) # 指明需要哪些链接库 target_link_libraries(${PROJECT_NAME} SDL2 SDL2main avcodec avformat avutil swresample swscale swscale avfilter ) 

遇到的坑

  • visual studio对cmake的支持好像不是很好,所以我再一次把vs卸载了,换成了Clion。。。

  • 需要在main.cpp文件的#include<SDL.h>之前加上#define SDL_MAIN_HANDLED,否则会报undefined reference to WinMain的错误。

  • 在Clion之外测试生成的player.exe,会提示“找不到libstdc++-6.dll”。可能Clion的debug环境提供了该dll,所以在Clion之外的环境运行player.exe需要单独提供相应的dll。

  • 需要在环境变量PATH中设置好dll的路径,否则Clion运行程序会没有任何反应,直接退出,也不会报错。