├── .gitignore ├── .vscode ├── launch.json ├── settings.json └── tasks.json ├── CMakeLists.txt ├── README.md ├── conanfile.txt └── src └── main.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | ##### Generated files 2 | build/ 3 | 4 | ##### MacOS 5 | .DS_Store 6 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "C++ GNU Debug", 6 | "type": "cppdbg", 7 | "request": "launch", 8 | "program": "${command:cmake.launchTargetPath}", 9 | "args": [], 10 | "cwd": "${command:cmake.launchTargetDirectory}", 11 | "envFile": "${command:cmake.buildDirectory}/.conan/conanrun.env", 12 | "MIMode": "gdb", 13 | "osx": { 14 | "MIMode": "lldb" 15 | } 16 | }, 17 | { 18 | "name": "C++ MSVC Debug", 19 | "type": "cppvsdbg", 20 | "request": "launch", 21 | "program": "${command:cmake.launchTargetPath}", 22 | "args": [], 23 | "cwd": "${command:cmake.launchTargetDirectory}", 24 | "envFile": "${command:cmake.buildDirectory}/.conan/conanrun.env" 25 | } 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "C_Cpp.intelliSenseEngine": "disabled", 3 | "clangd.arguments": [ 4 | "--compile-commands-dir=${workspaceFolder}/build/.clangd" 5 | ], 6 | "cmake.buildDirectory": "${workspaceFolder}/build/${buildKit}/${buildType}", 7 | "cmake.configureArgs": [ 8 | "-DCMAKE_TOOLCHAIN_FILE=${workspaceFolder}/build/${buildKit}/${buildType}/.conan/conan_toolchain.cmake" 9 | ], 10 | "cmake.copyCompileCommands": "${workspaceFolder}/build/.clangd/compile_commands.json", 11 | "cmake.exportCompileCommandsFile": true, 12 | "cmake.preferredGenerators": [ 13 | "Ninja" 14 | ], 15 | "cmake.useCMakePresets": "never" 16 | } 17 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "label": "conan initialize", 6 | "type": "shell", 7 | "command": "conanrunsh=${command:cmake.buildDirectory}/.conan/conanrun.sh; conanrunenv=${command:cmake.buildDirectory}/.conan/conanrun.env; if [ -f $conanrunsh ]; then grep \"^export \" $(cat $conanrunsh | cut -d \"\\\"\" -f2) | cut -c 8- > $conanrunenv; else echo -n \"\" > $conanrunenv; fi", 8 | "windows": { 9 | "command": "$conanrunbat = '${command:cmake.buildDirectory}/.conan/conanrun.bat'; $conanrunenv = '${command:cmake.buildDirectory}/.conan/conanrun.env'; If (Test-Path $conanrunbat -PathType Leaf) {$fileread = $(Select-String -Path $conanrunbat -Pattern '^call ').Line; Get-Content -Path $($fileread.Substring(6,$fileread.Length-7)) | Select-String -Pattern '^set ' | foreach-object {$_ -replace '^set ','' -replace '(^\\\"|\\\"$)',''} | out-file $conanrunenv} Else {New-Item $conanrunenv -ItemType File -Value '' -Force | Out-Null}" 10 | }, 11 | "group": "build", 12 | "dependsOn": "conan install", 13 | "presentation": { 14 | "reveal": "silent", 15 | "panel": "shared" 16 | } 17 | }, 18 | { 19 | "label": "conan install", 20 | "type": "shell", 21 | "command": "conan", 22 | "args": [ 23 | "install", "\"${workspaceFolder}\"", 24 | "-b", "missing", 25 | "-of", "\"${command:cmake.buildDirectory}/.conan\"", 26 | "-g", "CMakeToolchain", 27 | // build context 28 | "-pr:b", "default", 29 | "-s:b", "build_type=Release", 30 | "-o:b", "\"*:shared=False\"", 31 | "-e:b", "CONAN_CMAKE_GENERATOR=Ninja", 32 | "-c:b", "tools.cmake.cmaketoolchain:generator=Ninja", 33 | "-g", "VirtualBuildEnv", 34 | // Host context 35 | "-pr:h", "\"${command:cmake.buildKit}\"", 36 | "-s:h", "\"build_type=${command:cmake.buildType}\"", 37 | "-e:h", "CONAN_CMAKE_GENERATOR=Ninja", 38 | "-c:h", "tools.cmake.cmaketoolchain:generator=Ninja", 39 | "-g", "CMakeDeps", 40 | "-g", "PkgConfigDeps", 41 | "-g", "VirtualRunEnv" 42 | ], 43 | "group": "build", 44 | "presentation": { 45 | "reveal": "always", 46 | "panel": "shared" 47 | } 48 | } 49 | ] 50 | } 51 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1) 2 | project(foo) 3 | 4 | add_executable(foo src/main.cpp) 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # C/C++ project template for VSCode, using CMake and conan 2 | 3 | ## Introduction 4 | 5 | This template provides a small set of `.json` files in `.vscode` folder to properly setup VSCode locally while developping C/C++ projects whose build tools are based on CMake (meta build system), Ninja generator, and conan 1.x client (C/C++ package manager). 6 | It is designed to: 7 | 8 | - allow non-intrusive integration of conan. 9 | - be as generic and with less manual tweaks as possible. 10 | 11 | Basically you add your dependencies in `conanfile.txt` (or `conanfile.py`), call `conan initialize` task, and update your CMakeLists files accordingly. Configure/Build & Debugging inside VSCode should work out of the box even when complex dependencies (like SDK and frameworks) are involved. 12 | 13 | **This template assumes usage of CMake kits of CMake Tools extension, not CMake presets (autodetection by CMake Tools extension is explicitly disabled).** 14 | *Contributions to provide a robust template based on `CMakePresets.json` files generated by conan (and/or a custom `CMakeUserPresets.json`) are welcome.* 15 | 16 | ## Prerequisites 17 | 18 | - A working C/C++ compiler/toolchain (e.g GCC, LLVM, Visual C++) 19 | - [conan](https://conan.io) 2.x client 20 | - [CMake](https://cmake.org) >= 3.15 21 | - [Ninja](https://ninja-build.org) 22 | - [VSCode](https://code.visualstudio.com) with these extensions: 23 | - [C/C++](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) 24 | - [clangd](https://marketplace.visualstudio.com/items?itemName=llvm-vs-code-extensions.vscode-clangd) 25 | - [CMake Tools](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cmake-tools) 26 | 27 | ## Workflow 28 | 29 | ### Global Setup 30 | 31 | 1. Initialize your Kits for `CMake Tools` extension if not already done. 32 | 2. Rename these Kits names or your conan profiles so that they can match. There should exist one conan profile per Kit. Indeed, this setup relies on Kit names to know which conan profile should be called. 33 | 3. Add `"environmentSetupScript": "${workspaceFolder}/build/${buildKit}/${buildType}/.conan/conanbuild[.sh|.bat]"` property in your Kits (`.bat` for Windows, `.sh` otherwise). 34 | 35 | ### Project Initialization 36 | 37 | 1. Select a Kit and build variant through `CMake Tools` interface. 38 | 2. Add your dependencies under `[requires]` section of `conanfile.txt`, and your build dependencies under `[tool_requires]`. 39 | 3. Launch `conan initialize` task in VSCode (through Command Palette or an extension like [Task Explorer](https://marketplace.visualstudio.com/items?itemName=spmeesseman.vscode-taskexplorer)). 40 | 4. Select the Kit again. 41 | 5. Run CMake reconfiguration. 42 | 6. Restart clangd server (in Command Palette). 43 | 44 | ### Configure/Build 45 | 46 | You can use CMake Tools extension as usual. 47 | 48 | ### Debug 49 | 50 | - In Debugger panel, select `C++ MSVC Debug` if compiler is MSVC, `C++ GNU Debug` otherwise. 51 | 52 | - Press F5. 53 | 54 | :warning: *DO NOT run the debugger through bottom task bar (`CMake: Launch the debugger for the selected target`).* 55 | 56 | ### Run without Debugger (`CMake: Launch`) 57 | 58 | Run without Debugger is not fully supported yet (it won't work if some dependencies handled by conan are shared, or define mandatory runtime environment variables, since `CMake Tools` extension doesn't provide a way to inject environment variable while running a target without Debugger). 59 | 60 | ### Modifications 61 | 62 | The first time you switch to another Kit/Variant, or after any modification in `conanfile.txt`, don't forget to run `conan initialize` task again, and then reselect the Kit. 63 | It won't be required anymore afterwards unless `conanfile.txt` has been modified. 64 | 65 | ## Frequently Asked Questions 66 | 67 | - [Is it a non-intrusive integration of `conan`?](#is-it-a-non-intrusive-integration-of-conan) 68 | - [Where can I find the proper `find_package()` names and imported target names of dependencies?](#where-can-i-find-the-proper-find_package-names-and-imported-target-names-of-dependencies) 69 | - [Do I need to copy shared libs or plugins of dependencies for runtime execution of my executables inside VSCode?](#do-i-need-to-copy-shared-libs-or-plugins-of-dependencies-for-runtime-execution-of-my-executables-inside-vscode) 70 | - [Can I use ccache to speed up recompilation?](#can-i-use-ccache-to-speed-up-recompilation) 71 | 72 | ### Is it a non-intrusive integration of `conan`? 73 | 74 | Yes, `CMakeLists.txt` files in your project don't have to know anything about `conan`. Under the hood, informations of installed libraries are injected through a toolchain file generated by `conan initialize` task. 75 | Just rely on `find_package()` (or eventually `pkg_check_modules()`) and imported targets in your CMakeLists like good citizens. Instructions like `find_library()`, `find_program()`, `find_file()` or `find_path()` should also be able to discover dependencies files. 76 | Therefore you can drop `conan` whenever you want without side effects in your CMakeLists files. 77 | 78 | ### Where can I find the proper `find_package()` names and imported target names of dependencies? 79 | 80 | The most obvious way is to read libraries documentation, since conan generates the same CMake imported targets. 81 | Otherwise, one markdown file per dependency is generated by conan in `/build/_/.conan` folder, with all these informations. 82 | 83 | ### Do I need to copy shared libs or plugins of dependencies for runtime execution of my executables inside VSCode? 84 | 85 | No, paths of shared libs and modules location in conan cache are automatically injected in the proper environment variables (`PATH`, `LD_LIBRARY_PATH` or `DYLD_LIBRARY_PATH`) before calling the debugger. Therefore, adding an `[imports]` section in you conanfile is useless. 86 | It's worth noting that all the specific runtime environment variables of dependencies (not very common, usually in SDK or Frameworks) are also automatically injected, so that you don't have to worry with these details during development. 87 | 88 | ### Can I use `ccache` to speed up recompilation? 89 | 90 | Yes, you just need to ensure that `ccache` is installed on your system obviously, check that it [supports your platform & compiler](https://ccache.dev/platform-compiler-language-support.html), and to edit `settings.json`: 91 | 92 | ```json 93 | "cmake.configureArgs": [ 94 | "-DCMAKE_TOOLCHAIN_FILE=${workspaceFolder}/build/${buildKit}/${buildType}/.conan/conan_toolchain.cmake", 95 | // here we wrap compiler calls with ccache 96 | "-DCMAKE_C_COMPILER_LAUNCHER=ccache", 97 | "-DCMAKE_CXX_COMPILER_LAUNCHER=ccache" 98 | ] 99 | ``` 100 | -------------------------------------------------------------------------------- /conanfile.txt: -------------------------------------------------------------------------------- 1 | [requires] 2 | [tool_requires] 3 | [generators] 4 | [options] 5 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | int main() { 2 | return 0; 3 | } --------------------------------------------------------------------------------