[笔记]基于VSCode使用cmake配置使用第三方库文件(SFML等)的项目

前言

本文主要实现的是在windows10下使用VSCode编辑器以及cmake工具来构建一个包含第三方库文件(此处为SFML)的项目的配置和调试。(因为SFML库文件的cmake比较难搞,,所以我自认为重点是其cmakelists.txt的编写)。
首先要保证VSCode可以正常使用MinGW编译器来编译运行C++程序、已经安装并能使用cmake。

构建基础项目结构

首先贴一下项目的大致结构:[笔记]基于VSCode使用cmake配置使用第三方库文件(SFML等)的项目_第1张图片
其中:

  • build 一般按照项目的习惯是作为整个项目编译后的文件所在的文件夹,可以理解为变异的得到的可执行程序以及需要的资源的文件夹(即main.exe)
  • CMakeFiles 这个是cmake执行时自动生成的一些文件,不用管
  • external 这个一般就是我们项目引入第三方库文件的所在的文件夹,这里的文件一般要去你所需的库文件的官网下载 适合自己平台 的编译好的文件。(这里后面再说)
  • include 这个一般是包含在编写代码时为了自动补全等需要的头文件等等内容。
  • res 一般是一些项目的资源文件,如图片、视频、音频、纹理、模型等等。
  • src 即我们项目自己编写的源码文件夹。
  • CMakeLists.txt 这个文件是项目的一个配置文件,对于不同平台环境的使用者,都可以使用 cmake 命令来解释此文件来生成适合自己环境的项目编译等的 Makefile 文件。比如,我们win下完成的项目,只要编写一个合适的 CMakeLists.txt ,使用 cmake 命令就可以生成 win下的一个编译项目的方式(包括 Makefile 和资源文件、依赖文件等等的内容,一般就在 build 文件夹中) 。而另一个 unix 用户,也可以通过其 cmake 命令来生成自己平台下的 build 文件夹。这样无论是什么平台下的用户,都可以使用本平台的 make 命令来编译运行我们的项目。这也是使用 cmakemake 命令来管理项目的一个原因吧。
  • 其他几个文件示项目不同。
  • 此外,一般还包含单元测试 test 文件夹等内容。

关于 external 文件夹、SFML以及cmake命令:

对于 SFML 来说,需要去 SFML Downloads 下载适合本平台的版本,(比如我,设备安装的是MinGW64,所以我下载的就是GCC 7.3.0 MinGW (SEH) - 64-bit这个版本的)然后将其解压并复制到 external 文件夹下就行了,

其实就是相当于引入第三方库的 头文件 以及 需要链接的.a 文件,至于一些 .dll 文件,我们可以直接复制到编译好的程序的同级目录下即可,

解释

对于前面两个引入,我们可以通过 g++ main.cpp -IIncludePath -LLibsPath -o main.exe 来搞定,当然为了简化输入命令的过程,可以通过编写 Makefile 文件来简化,,这样通过 make 命令就可以编译、运行、清理环境等等。

对于最后一个引入,我们可以通过编写 cmake 的 CMakeLists.txt 来实现将确定位置的 .dll 文件拷贝的操作。

整理一下这个流程:

  • 我们需要简化 main.cpp 等源文件和第三方文件的编译、链接操作,可以通过 make 命令对 Makefile 文件解释来实现;
  • 我们需要简化对整个项目中的第三方文件以及不同平台上的项目的配置操作,所以通过 cmake 来解释 CMakeLists.txt 文件来生成适合本平台下的 Makefile 文件。

(对于java系,引入第三方包,直接将jar包拖到IDE就能配置好,,当然C++下的IDE也可以实现这样的操作,,仅仅是IDE实现了 CMakeLists.txt 的一些功能,将其集成到一个按钮上)

接下来进入到具体到 使用SFML库CMakeLists.txt 的编写。

CMakeLists.txt 的编写

首先贴一下我当前 SFML 在项目中的位置:(上文提到的下载位置、解压、将
[笔记]基于VSCode使用cmake配置使用第三方库文件(SFML等)的项目_第2张图片
然后在项目的根目录中添加一个 项目名Config.h.in 文件,其中的内容如下(否则可能后续cmake会报错):

#define 项目名_VERSION_MAJOR @项目名_VERSION_MAJOR@
#define 项目名_VERSION_MINOR @项目名_VERSION_MINOR@

接着,在根目录中添加 CMakeLists.txt 文件,文件的内容如下(参考):

# cmake最低版本号要求
cmake_minimum_required (VERSION 3.0)

# 设置项目名
set(PROJECT_NAME sfml_learning_project)
project (${PROJECT_NAME})
set (${PROJECT_NAME}_VERSION_MAJOR 1)
set (${PROJECT_NAME}_VERSION_MINOR 0)

# 设置编译器参数,可以自己更改
set (CMAKE_CXX_STAND 11)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

# 配置一个头文件来传递一个cmake设置到源代码
configure_file (
    "${PROJECT_SOURCE_DIR}/${PROJECT_NAME}Config.h.in"
    "${PROJECT_SOURCE_DIR}/${PROJECT_NAME}Config.h"
)

# 设置引入的外部第三方库的路径
set (EXTERNAL_DIR ${PROJECT_SOURCE_DIR}/external)
# set(CMAKE_MODULE_PATH ${EXTERNAL_DIR})


# sfml
# SFML库的路径,要精确到官方下载的文件/lib/cmake/SFML
set (SFML_DIR ${EXTERNAL_DIR}/SFML-2.5.1/lib/cmake/SFML)
# set(SFML_STATIC_LIBRARIES TRUE)
# 输出路径,检查是否正确
message(${SFML_DIR})
# 调用需要的模块,此项命令依赖于上面那个路径的设置,对于SFML,项目用到啥 调用啥
find_package(SFML 2.5 COMPONENTS system window graphics network audio REQUIRED)

# 查找当前目录下的所有源文件并存入DIR_SRCS变量
aux_source_directory(src SRC_DIR)

# 递归列出所有源文件
file (GLOB_RECURSE SOURCE_FILES main.cpp)

# 添加一个可编译的目标到工程
add_executable (${PROJECT_NAME} ${SOURCE_FILES})

# 设置工作目录
set_property(TARGET ${PROJECT_NAME} PROPERTY VS_DEBUGGER_WORKING_DIRECTORY 
    ${CMAKE_SOURCE_DIR}/res
)

# 添加链接库,项目需要啥,调用啥
target_link_libraries (${PROJECT_NAME} sfml-window sfml-graphics sfml-audio)

# target_compile_definitions(${PROJECT_NAME} PRIVATE SFML_INCLUDE_NONE)

# 将SFML/bin下的所有*.dll复制到 /build文件下,保证编译程序正常运行,不报缺少dll错误
file(GLOB_RECURSE PROJECT_DLL ${EXTERNAL_DIR}/*.dll)
message(${PROJECT_DLL})
# 复制库到工作目录
# POST_BUILD 在编译后操作
# copy命令拷贝单个文件,下面的 copy_directory是拷贝目录
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy
    ${PROJECT_DLL}
    $
)

# 复制资源文件到工作目录
# 当项目中有用到素材时需要
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_directory
    ${CMAKE_SOURCE_DIR}/res
    $/res
)

# 针对苹果系统,未测试
if(APPLE)
    add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
        COMMAND install_name_tool -change /usr/local/lib/libirrklang.dylib @executable_path/libirrklang.dylib ${PROJECT_NAME}
    )
endif()

对于SFML,重要的是路径的配置(即 .hpp等头文件以及 .a链接文件):

# sfml
# SFML库的路径,要精确到官方下载的文件/lib/cmake/SFML
set (SFML_DIR ${EXTERNAL_DIR}/SFML-2.5.1/lib/cmake/SFML)
# set(SFML_STATIC_LIBRARIES TRUE)
# 输出路径,检查是否正确
message(${SFML_DIR})
# 调用需要的模块,此项命令依赖于上面那个路径的设置,对于SFML,项目用到啥 调用啥
find_package(SFML 2.5 COMPONENTS system window graphics network audio REQUIRED)

以及对 .dll 文件的拷贝:

# 将SFML/bin下的所有*.dll复制到 /build文件下,保证编译程序正常运行,不报缺少dll错误
file(GLOB_RECURSE PROJECT_DLL ${EXTERNAL_DIR}/*.dll)
message(${PROJECT_DLL})
# 复制库到工作目录
# POST_BUILD 在编译后操作
# copy命令拷贝单个文件,下面的 copy_directory是拷贝目录
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy
    ${PROJECT_DLL}
    $
)

当编辑完毕 CMakeLists.txt 后,打开 cmake-gui ,选择项目的路径,以及编译后的路径,点击 Configure 没有错误后点击 Generate 即可在 build 文件夹生成适合本平台的整个项目:
[笔记]基于VSCode使用cmake配置使用第三方库文件(SFML等)的项目_第3张图片
[笔记]基于VSCode使用cmake配置使用第三方库文件(SFML等)的项目_第4张图片
此时,,我们可以在 build 文件夹中看到生成的文件(主要是 Makefile
[笔记]基于VSCode使用cmake配置使用第三方库文件(SFML等)的项目_第5张图片
到这一步就相当于是我们在IDE中配置好了整个项目的环境,如项目的名称、路径、引入的第三方库文件的路径等等内容,所以 只要build不删,我们只需执行一次cmake命令

之后我们就可以在 src 中编写项目的代码,测试时就到 build 文件夹下,(因为我们已经通过 cmake 生成了项目的 Makefile 文件,所以直接 make就行了),执行 mingw32-make.exe -j8 V=1 即可完成编译(MinGW把自带的make更名了,其中 -j8 表示并行调用8和核心编译, V=1 表示显示中间信息):

[笔记]基于VSCode使用cmake配置使用第三方库文件(SFML等)的项目_第6张图片
build 文件夹下可以看到编译后的程序所需的文件:
[笔记]基于VSCode使用cmake配置使用第三方库文件(SFML等)的项目_第7张图片
其中有源码编译后的程序、有所需的资源文件夹、有所需的 .dll 文件等等。

这里使用的源程序为:


#include 
#include 
#include 

using namespace std;

sf::RenderWindow window(sf::VideoMode(1920,1080), "Tree");

void start(float inix, float iniy, float degree, float length)
{
	if (length < 1.0f) return;
	
	else
	{
		float newlength=0.67f * length;
		
		float finx = inix + (newlength * (float)cos(degree * (3.14 / 180.0f)));
		float finy = iniy + (newlength * (float)sin(degree * (3.14 / 180.0f)));
		
		sf::Vertex line[]= {
				sf::Vertex(sf::Vector2f(inix, iniy)),
				sf::Vertex(sf::Vector2f(finx, finy))
		};
		start(finx, finy, degree+60.0f, newlength);
		start(finx, finy, degree-30.0f, newlength);
		
		window.draw(line, 2, sf::Lines);
		//line.setFillColor(sf::Color::Blue);
		//window.display(); // Uncomment for animation
	}
}

int main()
{
	window.clear();
	start(1000, 799, -90, 350);
	window.display();
	
	sf::Event event;
	while (window.isOpen())
	{
		while (window.pollEvent(event))
		{
			if (event.type == sf::Event::Closed) window.close();
		}
	}
	
	return 0;
}

进入 build 文件后运行即可:

[笔记]基于VSCode使用cmake配置使用第三方库文件(SFML等)的项目_第8张图片
后台会不断的输出 Failed to set DirectInput device axis mode: 1 这个可以貌似是官方的一个bug,,,不影响测试我就没管。

参考

  • 一个详细讲cmake的 cmakelists.txt编写方法的博客
  • 官方给出的一个 SFML 的CMakeLists.txt 例子和讨论
  • 同上,只是这种配置SFML已经失效,对于最后的其他库的引用给出了一种方式
  • 在学习CMakeLists.txt中很大一部分参考的项目配置
  • 一个很不错的项目结构
  • 最后的测试代码的来源

整个配置操作应该就结束了,如果有错误欢迎指出交流!(author: 31415926535x)

你可能感兴趣的:(笔记,环境配置,工具,cmake,SFML,配置,CMakeLists.txt,VSCode)