IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发工具 -> 在Windows上使用VS Code(CMake Tools、clangd)和CMake编译测试OpenGL(glad、glfw)代码 -> 正文阅读

[开发工具]在Windows上使用VS Code(CMake Tools、clangd)和CMake编译测试OpenGL(glad、glfw)代码

?1.前言?

? ? ? ? 本来之前发文用的是CodeBlocks和cmake进行结合使用的,无奈在Mac上CodeBlocks竟然不更新了,纠结了许久是否继续使用CodeBlocks,但是想到在mac上不能使用CodeBlocks愉快地学习了。本文所有内容在Windows10上实践,所以Mac和Ubuntu得有空跑通再另说。

2.安装环境

? ? ? ? 此文章所用环境及版本为:

? ? ? ? (1) MinGW? ?v8.1.0

? ? ? ? (2) CMake? ?v3.21.2? ?

? ? ? ? (3) VS Code? ?v1.62.1 (系统安装模式)

? ? ? ? ? ? ? (插件:C/C++ v1.7.1,CMake v0.0.17,CMake Tools v1.9.1,clangd v0.1.13)

? ? ? ? (4) glad v3.3 (core)? ? ? ?

? ? ? ? (5) glfw v3.3.5

2.1安装MinGW

? 在Windows上安装mingw推荐安装32位和64位兼容的版本,因为你可能需要同时编译32位和64位的,如果只装其中一个版本,那就比较头疼。在这个下面网址下载MinGW-W64-install.exe进行在线安装,Version我这里选择8.1.0,Architecture因为我的是64位系统所以选择x86_64,Threads选择posix (通常我希望不只是编译win的,还可以Android的,所以选了这个),Exception选择sjlj(这个支持32位和64位的,seh是新的不支持32位,如果只编译64位你可以选择seh),然后安装就可以了。你也可以在页面直接选择下载解压,不过要自己配置环境变量。


MinGW-w64 - for 32 and 64 bit Windows - Browse /mingw-w64 at SourceForge.nethttps://sourceforge.net/projects/mingw-w64/files/mingw-w64/

? ? ? ? 我的安装路径在C:\mingw64,环境变量的Path配置如下:

2.2安装CMake

? ? ? ? 在cmake官网下载cmake-3.21.2-windows-x86_64.msi(可以根据最新版本自己选择),安装下一步到完成就好了(记得选择配置环境变量或者自己配置一下路径,跟上图C:\Program Files\CMake\bin一样指定到bin路径就可以)。Download | CMakehttps://cmake.org/download/

2.3安装VS Code及插件

? ? ? ? 我在这里选择了Windows->System installer->64bit下载安装。

? ? ? ? ?在VS Code左侧点选图中第四个(如果你的不是第四个请选择同样的图标进行点击),然后依次安装图中四个插件。特别注意的是在安装clangd插件的时候会弹出Download clangd server进行安装依赖,这里大概率会失败,请重试几次或者按照提示进行自己下载。这里自动下载安装的话会在settings.json自动配置clangd.path这个参数,如果自己下载的请自行添加指定到具体路径。

? ? ? ? ?另外需要特别的配置是勾选cmake-tools的导出compile_commands.json这个文件,这个文件用在clangd寻找依赖的时候用到的。通过CMake Tools右侧设置按钮点出的菜单选择Extension Settings,在弹出的界面上方输入export compile进行搜索,然后勾选第二张图所示。

? ? ? ? ?最后,附上我这里目前的配置和进行一些必要说明就可以了,有一些是我自己摸索出来的。这里需要特别说明的几个是:

(1)cmake.buildDirectory这个配置是我希望不同的编译选项编译到不同的路径,比如build/x86/Debug和build/X64/Release这些,在后面的cmake-variants.json中会配置后面的两个参数,如果你不是跟我一样用请自行修改一下。

(2)cmake.copyCompileCommands这个配置的是cmake配置完成后会在build/x86/Debug这样的路径下生成compile_commands.json这个文件,但是在后面的clangd.arguments?--compile-commands-dir这里我想要配置${workspaceFolder}/build/${variant:buildTarget}/${buildType}这种动态的参数是无效的,最终clangd解析出来的还是原样的字符串,所以这里只能写死到build文件夹了,所以cmake配置项目完成后拷贝这个文件到build文件夹即可,特别注意的是cmake.copyCompileCommands这个配置的值必须要指定到文件名称,就是路径/compile_commands.json这种格式才行。

(3)C_Cpp.intelliSenseEngine这个参数需要写死为Disable,因为我这里使用clangd进行代码提示,所以C/C++原本的提示功能需要禁止不然会有冲突。如果后面你要用回默认的那个代码提示,请删掉这个配置和删除clangd这个插件(吐槽一下,自带的代码提示啥玩意,垃圾!)。

(4)因为clangd在新版本移除了--clang-tidy的支持,所以我们需要自己在clangd的配置路径下创建config.yaml进行开启代码静态检查,你不需要可以不设置。比如路径为C:\Users\你的用户名\AppData\Local\clangd\config.yaml,内容为:

Diagnostics:
  ClangTidy:
    Add:
      [
        cppcoreguidelines*,
        performance*,
        bugprone*,
        portabilit-*,
        modernize*,
        google*
      ]
    Remove:
      [
        modernize-use-trailing-return-type
      ]
  Index:
    Background: Build

????????以下配置在settings.json进行设置,ctrl+shift+p后输入Open Settings进行查找,点击如下选项即可进行编辑。

{
   // clangd路径,如果通过工具安装会配置,通过手动安装请修改这个的值
  "clangd.path": "c:\\Users\\用户名\\AppData\\Roaming\\Code\\User\\globalStorage\\llvm-vs-code-extensions.vscode-clangd\\install\\13.0.0\\clangd_13.0.0\\bin\\clangd.exe",

  // 开启自动配置
  "cmake.configureOnOpen": true,
  // cmake 编译生成文件的路劲
  "cmake.buildDirectory": "${workspaceFolder}/build/${variant:buildTarget}/${buildType}",
  // 拷贝cmake生成compile_commands.json到这个路径下的同名文件
  "cmake.copyCompileCommands": "${workspaceFolder}/build/compile_commands.json",

   /**********
   * Clangd *
   **********/
  // 关闭 C/C++ 提供的 IntelliSenseEngine
  "C_Cpp.intelliSenseEngine": "Disabled",
  // Clangd 运行参数(在终端/命令行输入 clangd --help-list-hidden 可查看更多)
  "clangd.onConfigChanged": "restart",
  "clangd.arguments": [
    // 全局补全(输入时弹出的建议将会提供 CMakeLists.txt 里配置的所有文件中可能的符号,会自动补充头文件)
    "--all-scopes-completion",
    // 启用 Clang-Tidy 以提供「静态检查」
    "--clang-tidy",
    // compelie_commands.json 文件的目录位置(相对于工作区,由于 CMake 生成的该文件默认在 build 文件夹中,故设置为 build)
    "--compile-commands-dir=build",
    // 建议风格:打包(bundled重载函数只会给出一个建议);反可以设置为detailed
    "--completion-style=bundled",
    /**
     * Read user and project configuration from YAML files.
     * Project config is from a .clangd file in the project directory.
     * User config is from clangd/config.yaml in the following directories:
     *     Windows: %USERPROFILE%\AppData\Local
     *     Mac OS: ~/Library/Preferences/
     *     Others: $XDG_CONFIG_HOME, usually ~/.config
     *
     * 我所使用的配置:
     * Diagnostics:
     *  ClangTidy:
     *    Add:
     *      [
     *        cppcoreguidelines*,
     *        performance*,
     *        bugprone*,
     *        portabilit-*,
     *        modernize*,
     *        google*
     *      ]
     *  Index:
     *  Background: Build
     */
    "--enable-config",
    // 默认格式化风格: 谷歌开源项目代码指南(可用的有 LLVM, Google, Chromium, Mozilla, Webkit, Microsoft, GNU 等)
    "--fallback-style=Google",
    // 启用这项时,补全函数时,将会给参数提供占位符,键入后按 Tab 可以切换到下一占位符,乃至函数末
    "--function-arg-placeholders=true",
    // 输入建议中,已包含头文件的项与还未包含头文件的项会以圆点加以区分
    "--header-insertion-decorators",
    // 允许补充头文件
    "--header-insertion=iwyu",
    // 让 Clangd 生成更详细的日志
    "--log=verbose",
    // pch优化的位置(memory 或 disk,选择memory会增加内存开销,但会提升性能)
    "--pch-storage=memory",
    // 输出的 JSON 文件更美观
    "--pretty",
    // 同时开启的任务数量
    "-j=12"
  ],
  // 自动检测 clangd 更新
  "clangd.checkUpdates": true,
  // clangd的snippets有很多的跳转点,不用这个就必须手动触发Intellisense了
  "editor.suggest.snippetsPreventQuickSuggestions": false,

  /********
   * LLDB *
   ********/
  // LLDB 指令自动补全
  "lldb.commandCompletions": true,
  // LLDB 指针显示解引用内容
  "lldb.dereferencePointers": true,
  // LLDB 鼠标悬停在变量上时预览变量值
  "lldb.evaluateForHovers": true,
  // LLDB 监视表达式的默认类型
  "lldb.launch.expressions": "simple",
  // LLDB 不显示汇编代码
  "lldb.showDisassembly": "never",
  // LLDB 生成更详细的日志
  "lldb.verboseLogging": true,
}

3.编译搞起

? ? ? ? 在上面的配置和编译摸索了很久以后,终于在编译这一块有自己满意的一套了。这里附上我的github项目代码,这里主要以Test目录下的进行解释,后续这个项目会更新更多关于我个人学习opengl相关的学习代码。pananfly/OpenGLLearn: OpenGL learning codes. Base on glad and glfw, compile with cmake and gcc, edit on vscode ide. (github.com)https://github.com/pananfly/OpenGLLearn????????首先先解释下外面的libs文件夹的东西,我分出来是为了在后面的所有子模块如Test和Triangle等所使用的OpenGL或者其他库都是一样的,不用在自己子模块的文件夹下各自拷贝一份这个依赖。你可以下载后在VS Code进行open folder找到下载代码后的Test文件夹进行打开,打开后我们就可以看到如下的文件树,.vscode里配置的cmake编译的VS code配置信息,launch.json配置的是运行的一些参数,CMakeLists.txt是配置编译项目的设置,test.cpp是源代码。

? ? ? ? ?这里的cmake-variants.json是我自己新建的文件,没看到在哪里可以快速创建。launch.json可以通过Run->Add Configuration->选择(gdb) Launch进行添加,添加后修改program的值为${command:cmake.launchTargetPath},我觉得配置这个就够了,因为我们后面配置编译x64/x86、Debug/Release这么多不同的组合是不同的路径,我看了这个launchTargetPath是可以找到当前的编译路径的。cwd改为${workspaceFolder},这个好像不改也行,最后删除miDebuggerPath这个配置,我看Windows这里好像自动去找了(因为我配置了mingw的环境),Mac和Linux等我跑起来看看再补充有什么不同。

? ? ? ? ?最终的launch.json如下(提示一下,这里或者其他json配置文件,比如你敲"na"这个会自动提示出来name或者其他匹配的选项,或者你敲双引号开始就有提示了,这个挺nice):

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(gdb) Launch",
            "type": "cppdbg",
            "request": "launch",
            "program": "${command:cmake.launchTargetPath}",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "setupCommands": [
                {
                    "description": "Enable pretty-printing for gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ]
        }
    ]
}

? ? ? ? cmake-variants.json配置如下,这里的buildType就是Cmake Tool默认的,我自己加了buildTarget这个配置可以选择编译32位或者64位

{
  "buildType": {
    "default": "debug",
    "description": "The build type.",
    "choices": {
      "debug": {
        "short": "Debug",
        "long": "Disable optimizations - include debug information.",
        "buildType": "Debug"
      },
      "release": {
        "short": "Release",
        "long": "Optimize for speed - exclude debug information.",
        "buildType": "Release"
      }
    }
  },
  "buildTarget": {
    "default": "x64",
    "description": "abi for 64 bit target build",
    "choices": {
      "x64": {
        "short": "x64",
        "long": "abi for 64 bit",
        "settings": {
          "CAMKE_BUILD_GENERATOR": "x64"
        }
      },
      "x86": {
        "short": "x86",
        "long": "abi for 32 bit target build",
        "settings": {
          "CAMKE_BUILD_GENERATOR": "x86"
        }
      }
    }
  }
}

? ? ? ? 然后我们就可以在VS Code底下这个选项点击后弹出这些选项来选择编译哪个。这里说一个个人绕的坑,我在没有配置cmake-variants.json之前走了一大段弯路,我找到了tasks.json这个配置方式来进行编译模式的选择,但是最终都不是完美的,所以这个方式才是我觉得完美的终极方式,具体tasks.json你们可以在github上的Triangle/.vscode下查看,蹩脚又有很多限制,想知道的可以私聊我,也许你私聊我的时候过太久也许我已经不太记得了。

?接下来是CMakeLists.txt的内容,这里面都写了比较详细的注释,要说明的一点是我自定义了CAMKE_BUILD_GENERATOR这个变量是cmake-variants.json中配置的,在你选择哪个模式后会最终传到这里。

cmake_minimum_required(VERSION 3.10) # 设置支持最低Cmake版本

set(PROJECT_NAME_STR Test) # 设置项目名称为Test
project(${PROJECT_NAME_STR}) # set project name

if (Apple)
  set (CMAKE_OSX_ARCHITECTURES i386)
  set (CUDA_64_BIT_DEVICE_CODE OFF)
endif (Apple)

if (CMAKE_HOST_WIN32)
    set(WINDOWS 1)
elseif(CMAKE_HOST_APPLE)
    set(MACOS 1)
elseif(CMAKE_HOST_UNIX)
    set(LINUX 1)
endif()


message("-- CMAKE_BUILD_TYPE : ${CMAKE_BUILD_TYPE}") # 输出从cmake运行传过来的buildType参数是什么,如Debug和Release等
message("-- CAMKE_BUILD_GENERATOR : ${CAMKE_BUILD_GENERATOR}") #输出从cmake运行传过来的buildGenerator参数是什么,如x86和x64等,这个参数是自定义的,如果不传默认编译64位(我当前系统64位)

if("${CAMKE_BUILD_GENERATOR}" MATCHES "^.*x86.*$") # 判断编译的版本
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32") # -m32 32bit 指定为编译32位
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32")
    if (CMAKE_HOST_WIN32)
        set(GLFW_LINK_DIR ${PROJECT_SOURCE_DIR}/../libs/opengl/glfw/windows/static-ucrt) # 设置GLFW_LINK_DIR值为libs文件夹下windows平台对应的32位glfw依赖的库路径
    elseif(CMAKE_HOST_APPLE)
        set(GLFW_LINK_DIR ${PROJECT_SOURCE_DIR}/../libs/opengl/glfw/osx/lib-x86_64)
    elseif(CMAKE_HOST_UNIX)
    endif()
else() # default to link 64 bit lib
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m64") # -m64 64bit
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m64")
    if (CMAKE_HOST_WIN32)
        set(GLFW_LINK_DIR ${PROJECT_SOURCE_DIR}/../libs/opengl/glfw/windows/static-ucrt-w64)# 设置GLFW_LINK_DIR值为libs文件夹下windows平台对应的64位glfw依赖的库路径
    elseif(CMAKE_HOST_APPLE)
        set(GLFW_LINK_DIR ${PROJECT_SOURCE_DIR}/../libs/opengl/glfw/osx/lib-x86_64)
    elseif(CMAKE_HOST_UNIX)
    endif()
endif()

link_directories(${GLFW_LINK_DIR}) # 指定glfw3的链接路径
add_executable(${PROJECT_NAME_STR} test.cpp ${PROJECT_SOURCE_DIR}/../libs/opengl/glad/src/glad.c) # set source files 添加编译源文件

# 指定依赖的头文件路径
include_directories(
${PROJECT_SOURCE_DIR}/../libs/opengl/glfw/include
${PROJECT_SOURCE_DIR}/../libs/opengl/glad/include
)

target_link_libraries(${PROJECT_NAME_STR} glfw3) # 链接程序和glfw库

# copy lib 如果是windows,则拷贝依赖的glfw3.dll库到编译出来的工程exe同路径下,免得运行的时候找不到依赖的库
if(CMAKE_HOST_WIN32)
    add_custom_command(TARGET ${PROJECT_NAME_STR}
        POST_BUILD
        COMMAND echo "copy dll files after make"
        COMMAND ${CMAKE_COMMAND} -E copy_if_different
        "${GLFW_LINK_DIR}/glfw3.dll"
        $<TARGET_FILE_DIR:${PROJECT_NAME_STR}>)

endif()
#add_library(testlib SHARED test.cpp)
#add_library(testa STATIC test.cpp)

? ? ? ? 接下来是运行的源码了,这里就是用了别人的代码进行测试开启一个窗口画了一个底色。

#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <stdlib.h>
// 设置窗口尺寸
const unsigned int SCR_WIDTH = 400;
const unsigned int SCR_HEIGHT = 300;

static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
        glfwSetWindowShouldClose(window, GLFW_TRUE);
}

// glfw: whenever the window size changed (by OS or user resize) this callback function executes
// ---------------------------------------------------------------------------------------------
static void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
    // make sure the viewport matches the new window dimensions; note that width and 
    // height will be significantly larger than specified on retina displays.
    glViewport(0, 0, width, height);
}

int main()
{
    // glfw: 初始化
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
    // uncomment this statement to fix compilation on OS X
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); 
#endif
    // glfw 创建窗口
    GLFWwindow *window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "Test<GLFW+GLAD>", NULL, NULL);
    if (window == NULL)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }
    glfwSetKeyCallback(window, key_callback);
    glfwMakeContextCurrent(window);
    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
    // glad: load all OpenGL function pointers
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }
    // render loop
    while (!glfwWindowShouldClose(window))
    {
        glClearColor(0.0f, 1.f, 0.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);
        // glfw: swap buffers and poll IO events (keyspressed/released, mouse moved etc.)
        glfwSwapBuffers(window);
        // glfwPollEvents();
        glfwWaitEvents();
    }
    // glfw: terminate, clearing all previously allocated GLFWresources.
    glfwTerminate();
    return 0;
}

? ? ? ? 关于CMake kits,因为我们配置了mingw的环境变量,所以会自动检测到GCC 8.1.0 x86_64-w64-mingw32这个选项,选这一个就好了,这个选项可以默认编译适合cmake的编译的东西因为它自动加了MinGW Makefiles这个配置,其他的我装了VS会生成VS项目相关的东西,这里不做讲解。点击底下如果所示位置就可以弹出所有的kits了,如果没有东西请选择一下Scan for kits跑一次查找。如果你自己要编辑这个kits的配置,ctrl+shift+p后搜索Edit User Local Kits进行修改,对应的文件路径为C:\Users\你的用户名\AppData\Local\CMakeTools\cmake-tools-kits.json。

? ? ? ? ?最后我们终于可以开始编译代码运行了。确认如下图1处选择了编译的选项后,确认图2处选择了GCC的kit后,点击图3处的build,再点击图4的三角形进行运行。

? ? ? ? ?好了,我们的程序跑起来了,结果如下:

?4.后记

? ? ? ? 这个VS Code自定义摸索挺折腾人的,不过经过一番折腾后,这些配置在登录微软账号的情况下是可以同步的,应该可以愉快地在Ubuntu和Mac上愉快地学习了。看到最后一个引用了没,后面试试通过VS Code CMake来搞NDK编译,希望简单的NDK项目可以不用开Android Studio那么麻烦了,搞起!

参考文章如下:

VSCode 配置 C/C++:VSCode + Clang + Clangd + LLDB + CMake + Git_tyKuGengty的博客-CSDN博客

VS Code + Cmake Tools, 搭建C/C++跨平台(NDK、iOS)开发环境 - 知乎 (zhihu.com)

  开发工具 最新文章
Postman接口测试之Mock快速入门
ASCII码空格替换查表_最全ASCII码对照表0-2
如何使用 ssh 建立 socks 代理
Typora配合PicGo阿里云图床配置
SoapUI、Jmeter、Postman三种接口测试工具的
github用相对路径显示图片_GitHub 中 readm
Windows编译g2o及其g2o viewer
解决jupyter notebook无法连接/ jupyter连接
Git恢复到之前版本
VScode常用快捷键
上一篇文章      下一篇文章      查看所有文章
加:2021-11-12 19:48:05  更:2021-11-12 19:50:33 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 20:59:39-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码