diff --git a/docs/src/individual-docs/languages/cplusplus.md b/docs/src/individual-docs/languages/cplusplus.md index d3615c80f..f8c1c8138 100644 --- a/docs/src/individual-docs/languages/cplusplus.md +++ b/docs/src/individual-docs/languages/cplusplus.md @@ -1,4 +1,246 @@ +## Getting Started +The easiest way to get started with C++ is to simply enable it: + +```nix +languages.cplusplus = { + enable = true; +}; +``` + +This will automatically: + +- Use `clang` as the default C++ package +- Install it along with CMake and other tools + +Alternatively, you can manually specify packages: + +```nix +languages.cplusplus = { + enable = true; + package = pkgs.stdenv.cc; +}; +``` + +## Setting up the [Conan](https://conan.io/) package manager + +Add conan-flake to your inputs: + +```shell-session +$ devenv inputs add conan-flake git+https://codeberg.org/tarcisio/conan-flake +``` + +The conan-flake module bridges the gap between Nix and Conan, supporting a declarative configuration style. For instance, for a user profile configuration like the following: + +```ini +[settings] +build_type=Debug +compiler.cppstd=14 + +[platform_tool_requires] +cmake/X.Y.Z +``` + +There correspond the following conan-flake options: + +```nix +{ + compilerCppStd = "14"; + + profiles = { + settings.build_type = "Debug"; + + platformToolRequires = { + cmake = pkgs.cmake.version; + }; + }; + + devShell = { + # Programs you want to make available in the shell: + tools = { inherit (pkgs) cmake; }; + }; +} +``` + +You can check [the list of available options](/reference/options.md#languagescplusplusconanenable). The [`languages.cplusplus.conan.config`](/reference/options.md#languagescplusplusconanconfig) option, however, maps the whole of the options available in the [conan-flake](https://flake.parts/options/conan-flake.html) module — check the [official module documentation](https://flake.parts/options/conan-flake.html#options) and see the examples in [conan-flake's README file](https://codeberg.org/tarcisio/conan-flake/src/branch/main/README.md) to help you setting up. + +Config the `devenv.nix` file accordingly. For example, the above is equivalent to the following: + +```nix +languages.cplusplus = { + enable = true; + conan = { + enable = true; + install.enable = true; + config = { + profiles.settings.build_type = "Debug"; + compilerCppStd = "14"; + }; + }; +}; +``` + +By default, when Conan is enabled: + +- The default C++ package is set to `config.stdenv.cc` +- Conan is configured to use the same CMake available in the developmemnt shell; as can be seen from the above example, the devenv integration automatically takes care of the CMake part by default, and the `profiles.platformToolRequires` and `devShell.tools` options are not required to be set explicitly in the `languages.cplusplus.conan.config` namespace + +### In Action: + +```shell-session +$ devenv shell +Building shell ... +Entering shell ... + +conan profile show # This would show the configured profile. +``` + +## Additional Examples + +### LLVM-based C++ Toolchain + +If you would like to integrate with the LLVM compiler infrastructure: + +```nix +{ pkgs, config, lib, ... }: +let + inherit (lib) getExe; + cfg = config.languages.cplusplus.conan.config; + c = "'c': '${getExe cfg.stdenv.cc}'"; + cpp = "'cpp': '${builtins.dirOf (getExe cfg.stdenv.cc)}/clang++'"; +in +{ + languages.cplusplus = { + enable = true; + conan = { + enable = true; + install.enable = true; + config = { + profiles = { + settings.build_type = "Release"; + conf = { + "tools.build:compiler_executables" = "{${c}, ${cpp}}"; + }; + }; + stdenv = pkgs.overrideCC + ( + pkgs.llvmPackages.libcxxStdenv.override { + targetPlatform.useLLVM = true; + targetPlatform.linker = "lld"; + } + ) + pkgs.llvmPackages.clangUseLLVM; + # By default: compiler.libcxx=libstdc++11, so set it: + compilerLibCxx = "libc++"; + }; + }; + }; +} +``` + +Or even: + +```nix +{ pkgs, config, lib, ... }: +let + inherit (lib) getExe; + cfg = config.languages.cplusplus.conan.config; + c = "'c': '${getExe cfg.stdenv.cc}'"; + cpp = "'cpp': '${builtins.dirOf (getExe cfg.stdenv.cc)}/clang++'"; +in +{ + stdenv = pkgs.overrideCC + ( + pkgs.llvmPackages.libcxxStdenv.override { + targetPlatform.useLLVM = true; + targetPlatform.linker = "lld"; + } + ) + pkgs.llvmPackages.clangUseLLVM; + + languages.cplusplus = { + enable = true; + conan = { + enable = true; + install.enable = true; + config = { + profiles = { + settings.build_type = "Release"; + conf = { + "tools.build:compiler_executables" = "{${c}, ${cpp}}"; + }; + }; + # By default: compiler.libcxx=libstdc++11, so set it: + compilerLibCxx = "libc++"; + }; + }; + }; +} +``` + +In this second use case: + +- By default, conan-flake is configured using the same stdenv as devenv's (that is, `config.stdenv`) + +### In Action: + +```shell-session +$ devenv shell +Building shell ... +Entering shell ... + +conan profile show # This would show the configured profile. +conan create . --build=missing # This would create and test the current package. +``` + +### A local-recipe-index remote + +With [local-recipe-index](https://docs.conan.io/2/tutorial/conan_repositories/setup_local_recipes_index.html) remotes it's possible to declare dependencies from a simplified local index structure: + +```nix +{ + languages.cplusplus = { + enable = true; + + conan = { + enable = true; + install.enable = true; + + config = { + profiles.settings.build_type = "Release"; + compilerCppStd = "17"; + + remotes.local = { + url = "./repo"; + local = true; + allowedPackages = [ + "hello-world/0.0.1.cci.20260428" + ]; + }; + + offline = true; + }; + }; + }; +} +``` + +The options in the `languages.cplusplus.conan.config` namespace: + +- `remotes.local.url`: is taken as a relative path to the root of the configuration +- `offline`: enable only local remotes (that is, only of local-recipe-index type) + +### In Action: + +```shell-session +$ devenv shell +Building shell ... +Entering shell ... + +conan profile show # This would show the configured profile. +conan remote list # This would list the configured remotes. +conan create . --build=missing # This would create and test the current package. +``` [comment]: # (Please add your documentation on top of this line) diff --git a/docs/src/languages/cplusplus.md b/docs/src/languages/cplusplus.md index a145d67f7..3c494551a 100644 --- a/docs/src/languages/cplusplus.md +++ b/docs/src/languages/cplusplus.md @@ -1,5 +1,247 @@ [comment]: # (Do not edit this file as it is autogenerated. Go to docs/individual-docs if you want to make edits.) +## Getting Started +The easiest way to get started with C++ is to simply enable it: + +```nix +languages.cplusplus = { + enable = true; +}; +``` + +This will automatically: + +- Use `clang` as the default C++ package +- Install it along with CMake and other tools + +Alternatively, you can manually specify packages: + +```nix +languages.cplusplus = { + enable = true; + package = pkgs.stdenv.cc; +}; +``` + +## Setting up the [Conan](https://conan.io/) package manager + +Add conan-flake to your inputs: + +```shell-session +$ devenv inputs add conan-flake git+https://codeberg.org/tarcisio/conan-flake +``` + +The conan-flake module bridges the gap between Nix and Conan, supporting a declarative configuration style. For instance, for a user profile configuration like the following: + +```ini +[settings] +build_type=Debug +compiler.cppstd=14 + +[platform_tool_requires] +cmake/X.Y.Z +``` + +There correspond the following conan-flake options: + +```nix +{ + compilerCppStd = "14"; + + profiles = { + settings.build_type = "Debug"; + + platformToolRequires = { + cmake = pkgs.cmake.version; + }; + }; + + devShell = { + # Programs you want to make available in the shell: + tools = { inherit (pkgs) cmake; }; + }; +} +``` + +You can check [the list of available options](/reference/options.md#languagescplusplusconanenable). The [`languages.cplusplus.conan.config`](/reference/options.md#languagescplusplusconanconfig) option, however, maps the whole of the options available in the [conan-flake](https://flake.parts/options/conan-flake.html) module — check the [official module documentation](https://flake.parts/options/conan-flake.html#options) and see the examples in [conan-flake's README file](https://codeberg.org/tarcisio/conan-flake/src/branch/main/README.md) to help you setting up. + +Config the `devenv.nix` file accordingly. For example, the above is equivalent to the following: + +```nix +languages.cplusplus = { + enable = true; + conan = { + enable = true; + install.enable = true; + config = { + profiles.settings.build_type = "Debug"; + compilerCppStd = "14"; + }; + }; +}; +``` + +By default, when Conan is enabled: + +- The default C++ package is set to `config.stdenv.cc` +- Conan is configured to use the same CMake available in the developmemnt shell; as can be seen from the above example, the devenv integration automatically takes care of the CMake part by default, and the `profiles.platformToolRequires` and `devShell.tools` options are not required to be set explicitly in the `languages.cplusplus.conan.config` namespace + +### In Action: + +```shell-session +$ devenv shell +Building shell ... +Entering shell ... + +conan profile show # This would show the configured profile. +``` + +## Additional Examples + +### LLVM-based C++ Toolchain + +If you would like to integrate with the LLVM compiler infrastructure: + +```nix +{ pkgs, config, lib, ... }: +let + inherit (lib) getExe; + cfg = config.languages.cplusplus.conan.config; + c = "'c': '${getExe cfg.stdenv.cc}'"; + cpp = "'cpp': '${builtins.dirOf (getExe cfg.stdenv.cc)}/clang++'"; +in +{ + languages.cplusplus = { + enable = true; + conan = { + enable = true; + install.enable = true; + config = { + profiles = { + settings.build_type = "Release"; + conf = { + "tools.build:compiler_executables" = "{${c}, ${cpp}}"; + }; + }; + stdenv = pkgs.overrideCC + ( + pkgs.llvmPackages.libcxxStdenv.override { + targetPlatform.useLLVM = true; + targetPlatform.linker = "lld"; + } + ) + pkgs.llvmPackages.clangUseLLVM; + # By default: compiler.libcxx=libstdc++11, so set it: + compilerLibCxx = "libc++"; + }; + }; + }; +} +``` + +Or even: + +```nix +{ pkgs, config, lib, ... }: +let + inherit (lib) getExe; + cfg = config.languages.cplusplus.conan.config; + c = "'c': '${getExe cfg.stdenv.cc}'"; + cpp = "'cpp': '${builtins.dirOf (getExe cfg.stdenv.cc)}/clang++'"; +in +{ + stdenv = pkgs.overrideCC + ( + pkgs.llvmPackages.libcxxStdenv.override { + targetPlatform.useLLVM = true; + targetPlatform.linker = "lld"; + } + ) + pkgs.llvmPackages.clangUseLLVM; + + languages.cplusplus = { + enable = true; + conan = { + enable = true; + install.enable = true; + config = { + profiles = { + settings.build_type = "Release"; + conf = { + "tools.build:compiler_executables" = "{${c}, ${cpp}}"; + }; + }; + # By default: compiler.libcxx=libstdc++11, so set it: + compilerLibCxx = "libc++"; + }; + }; + }; +} +``` + +In this second use case: + +- By default, conan-flake is configured using the same stdenv as devenv's (that is, `config.stdenv`) + +### In Action: + +```shell-session +$ devenv shell +Building shell ... +Entering shell ... + +conan profile show # This would show the configured profile. +conan create . --build=missing # This would create and test the current package. +``` + +### A local-recipe-index remote + +With [local-recipe-index](https://docs.conan.io/2/tutorial/conan_repositories/setup_local_recipes_index.html) remotes it's possible to declare dependencies from a simplified local index structure: + +```nix +{ + languages.cplusplus = { + enable = true; + + conan = { + enable = true; + install.enable = true; + + config = { + profiles.settings.build_type = "Release"; + compilerCppStd = "17"; + + remotes.local = { + url = "./repo"; + local = true; + allowedPackages = [ + "hello-world/0.0.1.cci.20260428" + ]; + }; + + offline = true; + }; + }; + }; +} +``` + +The options in the `languages.cplusplus.conan.config` namespace: + +- `remotes.local.url`: is taken as a relative path to the root of the configuration +- `offline`: enable only local remotes (that is, only of local-recipe-index type) + +### In Action: + +```shell-session +$ devenv shell +Building shell ... +Entering shell ... + +conan profile show # This would show the configured profile. +conan remote list # This would list the configured remotes. +conan create . --build=missing # This would create and test the current package. +``` [comment]: # (Please add your documentation on top of this line) @@ -7,6 +249,8 @@ ### languages\.cplusplus\.enable + + Whether to enable tools for C++ development\. @@ -24,6 +268,188 @@ false +*Example:* + +```nix +true +``` + +*Declared by:* + - [https://github\.com/cachix/devenv/blob/main/src/modules/languages/cplusplus\.nix](https://github.com/cachix/devenv/blob/main/src/modules/languages/cplusplus.nix) + + + +### languages\.cplusplus\.package + + + +The C++ compiler to use\. + + + +*Type:* +package + + + +*Default:* + +```nix +pkgs.clang +``` + +*Declared by:* + - [https://github\.com/cachix/devenv/blob/main/src/modules/languages/cplusplus\.nix](https://github.com/cachix/devenv/blob/main/src/modules/languages/cplusplus.nix) + + + +### languages\.cplusplus\.cmake + +Configuration for cmake + + + +*Type:* +submodule + + + +*Default:* + +```nix +{ } +``` + +*Declared by:* + - [https://github\.com/cachix/devenv/blob/main/src/modules/languages/cplusplus\.nix](https://github.com/cachix/devenv/blob/main/src/modules/languages/cplusplus.nix) + + + +### languages\.cplusplus\.cmake\.package + + + +The CMake package to use\. + + + +*Type:* +package + + + +*Default:* + +```nix +pkgs.cmake +``` + +*Declared by:* + - [https://github\.com/cachix/devenv/blob/main/src/modules/languages/cplusplus\.nix](https://github.com/cachix/devenv/blob/main/src/modules/languages/cplusplus.nix) + + + +### languages\.cplusplus\.conan\.enable + + + +Whether to enable install conan\. + + + +*Type:* +boolean + + + +*Default:* + +```nix +false +``` + + + +*Example:* + +```nix +true +``` + +*Declared by:* + - [https://github\.com/cachix/devenv/blob/main/src/modules/languages/cplusplus\.nix](https://github.com/cachix/devenv/blob/main/src/modules/languages/cplusplus.nix) + + + +### languages\.cplusplus\.conan\.package + + + +The conan package to use\. + + + +*Type:* +package + + + +*Default:* + +```nix +pkgs.conan +``` + +*Declared by:* + - [https://github\.com/cachix/devenv/blob/main/src/modules/languages/cplusplus\.nix](https://github.com/cachix/devenv/blob/main/src/modules/languages/cplusplus.nix) + + + +### languages\.cplusplus\.conan\.config + + + +conan configuration\. + + + +*Type:* +attribute set + + + +*Default:* + +```nix +{ } +``` + +*Declared by:* + - [https://github\.com/cachix/devenv/blob/main/src/modules/languages/cplusplus\.nix](https://github.com/cachix/devenv/blob/main/src/modules/languages/cplusplus.nix) + + + +### languages\.cplusplus\.conan\.install\.enable + + + +Whether to enable conan install during devenv initialisation\. + + + +*Type:* +boolean + + + +*Default:* + +```nix +false +``` + + + *Example:* ```nix @@ -88,3 +514,56 @@ pkgs.ccls *Declared by:* - [https://github\.com/cachix/devenv/blob/main/src/modules/languages/cplusplus\.nix](https://github.com/cachix/devenv/blob/main/src/modules/languages/cplusplus.nix) + + + +### languages\.cplusplus\.tools\.enable + + + +Whether to enable Standalone command line tools for C++ development\. + + + +*Type:* +boolean + + + +*Default:* +Enabled by default for clang-based compilers + + + +*Example:* + +```nix +true +``` + +*Declared by:* + - [https://github\.com/cachix/devenv/blob/main/src/modules/languages/cplusplus\.nix](https://github.com/cachix/devenv/blob/main/src/modules/languages/cplusplus.nix) + + + +### languages\.cplusplus\.tools\.package + + + +The C++ command line tools package to use\. + + + +*Type:* +package + + + +*Default:* + +```nix +pkgs.clang-tools +``` + +*Declared by:* + - [https://github\.com/cachix/devenv/blob/main/src/modules/languages/cplusplus\.nix](https://github.com/cachix/devenv/blob/main/src/modules/languages/cplusplus.nix) diff --git a/docs/src/reference/options.md b/docs/src/reference/options.md index a3962593e..cb206d2b1 100644 --- a/docs/src/reference/options.md +++ b/docs/src/reference/options.md @@ -15045,6 +15045,190 @@ false +*Example:* + +```nix +true +``` + +*Declared by:* + - [https://github.com/cachix/devenv/blob/main/src/modules/languages/cplusplus.nix](https://github.com/cachix/devenv/blob/main/src/modules/languages/cplusplus.nix) + + + +## languages.cplusplus.package + + + +The C++ compiler to use. + + + +*Type:* +package + + + +*Default:* + +```nix +pkgs.clang +``` + +*Declared by:* + - [https://github.com/cachix/devenv/blob/main/src/modules/languages/cplusplus.nix](https://github.com/cachix/devenv/blob/main/src/modules/languages/cplusplus.nix) + + + +## languages.cplusplus.cmake + + + +Configuration for cmake + + + +*Type:* +submodule + + + +*Default:* + +```nix +{ } +``` + +*Declared by:* + - [https://github.com/cachix/devenv/blob/main/src/modules/languages/cplusplus.nix](https://github.com/cachix/devenv/blob/main/src/modules/languages/cplusplus.nix) + + + +## languages.cplusplus.cmake.package + + + +The CMake package to use. + + + +*Type:* +package + + + +*Default:* + +```nix +pkgs.cmake +``` + +*Declared by:* + - [https://github.com/cachix/devenv/blob/main/src/modules/languages/cplusplus.nix](https://github.com/cachix/devenv/blob/main/src/modules/languages/cplusplus.nix) + + + +## languages.cplusplus.conan.enable + + + +Whether to enable install conan. + + + +*Type:* +boolean + + + +*Default:* + +```nix +false +``` + + + +*Example:* + +```nix +true +``` + +*Declared by:* + - [https://github.com/cachix/devenv/blob/main/src/modules/languages/cplusplus.nix](https://github.com/cachix/devenv/blob/main/src/modules/languages/cplusplus.nix) + + + +## languages.cplusplus.conan.package + + + +The conan package to use. + + + +*Type:* +package + + + +*Default:* + +```nix +pkgs.conan +``` + +*Declared by:* + - [https://github.com/cachix/devenv/blob/main/src/modules/languages/cplusplus.nix](https://github.com/cachix/devenv/blob/main/src/modules/languages/cplusplus.nix) + + + +## languages.cplusplus.conan.config + + + +conan configuration. + + + +*Type:* +attribute set + + + +*Default:* + +```nix +{ } +``` + +*Declared by:* + - [https://github.com/cachix/devenv/blob/main/src/modules/languages/cplusplus.nix](https://github.com/cachix/devenv/blob/main/src/modules/languages/cplusplus.nix) + + + +## languages.cplusplus.conan.install.enable + + + +Whether to enable conan install during devenv initialisation. + + + +*Type:* +boolean + + + +*Default:* + +```nix +false +``` + + + *Example:* ```nix @@ -15112,6 +15296,59 @@ pkgs.ccls +## languages.cplusplus.tools.enable + + + +Whether to enable Standalone command line tools for C++ development. + + + +*Type:* +boolean + + + +*Default:* +Enabled by default for clang-based compilers + + + +*Example:* + +```nix +true +``` + +*Declared by:* + - [https://github.com/cachix/devenv/blob/main/src/modules/languages/cplusplus.nix](https://github.com/cachix/devenv/blob/main/src/modules/languages/cplusplus.nix) + + + +## languages.cplusplus.tools.package + + + +The C++ command line tools package to use. + + + +*Type:* +package + + + +*Default:* + +```nix +pkgs.clang-tools +``` + +*Declared by:* + - [https://github.com/cachix/devenv/blob/main/src/modules/languages/cplusplus.nix](https://github.com/cachix/devenv/blob/main/src/modules/languages/cplusplus.nix) + + + ## languages.crystal.enable diff --git a/src/modules/languages/cplusplus.nix b/src/modules/languages/cplusplus.nix index e67933276..8291198f0 100644 --- a/src/modules/languages/cplusplus.nix +++ b/src/modules/languages/cplusplus.nix @@ -2,11 +2,81 @@ let cfg = config.languages.cplusplus; + + inputArgs = { + name = "conan-flake"; + url = "git+https://codeberg.org/tarcisio/conan-flake"; + attribute = "conan"; + }; + + # When enabled, use getInput (throws helpful error if missing) + # Otherwise, use tryGetInput to populate the docs when the input is available. + conan-flake = + if cfg.conan.enable then config.lib.getInput inputArgs else config.lib.tryGetInput inputArgs; + + # Determine config root: prefer devenv.root, fallback to git.root + configRoot = if config.devenv.root != null then config.devenv.root else config.git.root; + + conanSubmodule = + if conan-flake != null then + # We automatically configure Conan with the correct tree root for the project. + conan-flake.lib.submoduleWith pkgs { inherit configRoot; } + else + lib.types.attrs; in { options.languages.cplusplus = { enable = lib.mkEnableOption "tools for C++ development"; + package = lib.mkOption { + type = lib.types.package; + default = pkgs.clang; + defaultText = lib.literalExpression "pkgs.clang"; + description = "The C++ compiler to use."; + }; + + cmake = lib.mkOption { + type = lib.types.submodule { + options.package = lib.mkOption { + type = lib.types.package; + default = pkgs.cmake; + defaultText = lib.literalExpression "pkgs.cmake"; + description = "The CMake package to use."; + }; + }; + description = "Configuration for cmake"; + default = { }; + }; + + tools = { + enable = lib.mkEnableOption "Standalone command line tools for C++ development" // { + default = cfg.package.isClang; + defaultText = lib.literalMD "Enabled by default for clang-based compilers"; + }; + package = lib.mkOption { + type = lib.types.package; + default = pkgs.clang-tools; + defaultText = lib.literalExpression "pkgs.clang-tools"; + description = "The C++ command line tools package to use."; + }; + }; + + conan = { + enable = lib.mkEnableOption "install conan"; + package = lib.mkOption { + type = lib.types.package; + default = pkgs.conan; + defaultText = lib.literalExpression "pkgs.conan"; + description = "The conan package to use."; + }; + config = lib.mkOption { + type = conanSubmodule; + description = "conan configuration."; + default = { }; + }; + install.enable = lib.mkEnableOption "conan install during devenv initialisation"; + }; + lsp = { enable = lib.mkEnableOption "C++ Language Server" // { default = true; }; package = lib.mkOption { @@ -18,11 +88,35 @@ in }; }; - config = lib.mkIf cfg.enable { - packages = with pkgs; [ - clang-tools - cmake - clang - ] ++ lib.optional cfg.lsp.enable cfg.lsp.package; - }; + config = lib.mkMerge [ + (lib.mkIf cfg.enable { + packages = with pkgs; [ + cfg.cmake.package + cfg.package + ] + ++ lib.optional cfg.tools.enable cfg.tools.package + ++ lib.optional cfg.lsp.enable cfg.lsp.package + ++ lib.optional cfg.conan.enable cfg.conan.package; + }) + + # + (lib.mkIf (cfg.enable && cfg.conan.enable) { + languages.cplusplus.conan.config.stdenv = lib.mkDefault (if config.stdenv.hasCC then config.stdenv else pkgs.stdenv); + languages.cplusplus.conan.config.package = lib.mkDefault cfg.conan.package; + languages.cplusplus.conan.config.profiles.platformToolRequires = lib.mkDefault { + cmake = cfg.cmake.package.version; + }; + languages.cplusplus.conan.config.devShell.tools = lib.mkDefault { + conan = null; + cmake = null; + "${cfg.package.cc.pname}" = null; + }; + languages.cplusplus.package = lib.mkDefault cfg.conan.config.stdenv.cc; + }) + + # + (lib.mkIf (cfg.enable && cfg.conan.enable && cfg.conan.install.enable) { + inputsFrom = [ cfg.conan.config.outputs.devShell ]; + }) + ]; } diff --git a/tests/cplusplus-conan-llvm-devenv/devenv.nix b/tests/cplusplus-conan-llvm-devenv/devenv.nix new file mode 100644 index 000000000..8a7eba75b --- /dev/null +++ b/tests/cplusplus-conan-llvm-devenv/devenv.nix @@ -0,0 +1,49 @@ +{ pkgs, config, lib, ... }: +let + inherit (lib) getExe; + getCommand = package: builtins.baseNameOf (getExe package); + cfg = config.languages.cplusplus.conan.config; + c = "'c': '${getExe cfg.stdenv.cc}'"; + cpp = "'cpp': '${builtins.dirOf (getExe cfg.stdenv.cc)}/clang++'"; +in +{ + stdenv = pkgs.overrideCC + ( + pkgs.llvmPackages.libcxxStdenv.override { + targetPlatform.useLLVM = true; + targetPlatform.linker = "lld"; + } + ) + pkgs.llvmPackages.clangUseLLVM; + + languages.cplusplus = { + enable = true; + conan = { + enable = true; + install.enable = true; + config = { + profiles = { + settings.build_type = "Release"; + conf = { + "tools.build:compiler_executables" = "{${c}, ${cpp}}"; + }; + }; + # By default: compiler.libcxx=libstdc++11, so set it: + compilerLibCxx = "libc++"; + }; + }; + }; + + enterTest = '' + ${getCommand config.languages.cplusplus.package} --version + ${getCommand config.languages.cplusplus.package} --version \ + | grep clang + ${getCommand config.languages.cplusplus.cmake.package} --version + ${getCommand config.languages.cplusplus.lsp.package} --version \ + | grep ${pkgs.lib.escapeShellArg config.languages.cplusplus.lsp.package.version} + ${getCommand config.languages.cplusplus.conan.package} --version + echo "enable:"${pkgs.lib.escapeShellArg config.languages.cplusplus.tools.enable}":" | grep "enable:1:" + ${getCommand config.languages.cplusplus.conan.package} profile show \ + | grep "cmake/"${pkgs.lib.escapeShellArg config.languages.cplusplus.cmake.package.version} + ''; +} diff --git a/tests/cplusplus-conan-llvm-devenv/devenv.yaml b/tests/cplusplus-conan-llvm-devenv/devenv.yaml new file mode 100644 index 000000000..0a9fd6c94 --- /dev/null +++ b/tests/cplusplus-conan-llvm-devenv/devenv.yaml @@ -0,0 +1,3 @@ +inputs: + conan-flake: + url: git+https://codeberg.org/tarcisio/conan-flake diff --git a/tests/cplusplus-conan-llvm/devenv.nix b/tests/cplusplus-conan-llvm/devenv.nix new file mode 100644 index 000000000..a223d4c5e --- /dev/null +++ b/tests/cplusplus-conan-llvm/devenv.nix @@ -0,0 +1,47 @@ +{ pkgs, config, lib, ... }: +let + inherit (lib) getExe; + getCommand = package: builtins.baseNameOf (getExe package); + cfg = config.languages.cplusplus.conan.config; + c = "'c': '${getExe cfg.stdenv.cc}'"; + cpp = "'cpp': '${builtins.dirOf (getExe cfg.stdenv.cc)}/clang++'"; +in +{ + languages.cplusplus = { + enable = true; + conan = { + enable = true; + install.enable = true; + config = { + profiles = { + settings.build_type = "Release"; + conf = { + "tools.build:compiler_executables" = "{${c}, ${cpp}}"; + }; + }; + stdenv = pkgs.overrideCC + ( + pkgs.llvmPackages.libcxxStdenv.override { + targetPlatform.useLLVM = true; + targetPlatform.linker = "lld"; + } + ) + pkgs.llvmPackages.clangUseLLVM; + # By default: compiler.libcxx=libstdc++11, so set it: + compilerLibCxx = "libc++"; + }; + }; + }; + enterTest = '' + ${getCommand config.languages.cplusplus.package} --version + ${getCommand config.languages.cplusplus.package} --version \ + | grep clang + ${getCommand config.languages.cplusplus.cmake.package} --version + ${getCommand config.languages.cplusplus.lsp.package} --version \ + | grep ${pkgs.lib.escapeShellArg config.languages.cplusplus.lsp.package.version} + ${getCommand config.languages.cplusplus.conan.package} --version + echo "enable:"${pkgs.lib.escapeShellArg config.languages.cplusplus.tools.enable}":" | grep "enable:1:" + ${getCommand config.languages.cplusplus.conan.package} profile show \ + | grep "cmake/"${pkgs.lib.escapeShellArg config.languages.cplusplus.cmake.package.version} + ''; +} diff --git a/tests/cplusplus-conan-llvm/devenv.yaml b/tests/cplusplus-conan-llvm/devenv.yaml new file mode 100644 index 000000000..0a9fd6c94 --- /dev/null +++ b/tests/cplusplus-conan-llvm/devenv.yaml @@ -0,0 +1,3 @@ +inputs: + conan-flake: + url: git+https://codeberg.org/tarcisio/conan-flake diff --git a/tests/cplusplus-conan-recipe/CMakeLists.txt b/tests/cplusplus-conan-recipe/CMakeLists.txt new file mode 100644 index 000000000..c4669de5c --- /dev/null +++ b/tests/cplusplus-conan-recipe/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.15) +project(example CXX) + +find_package(hello-world CONFIG REQUIRED) + +add_executable(example src/example.cpp src/main.cpp) + +target_link_libraries(example hello-world::hello-world) + +install( + TARGETS example + DESTINATION "." + RUNTIME DESTINATION bin + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib) diff --git a/tests/cplusplus-conan-recipe/conanfile.py b/tests/cplusplus-conan-recipe/conanfile.py new file mode 100644 index 000000000..e9a57d7ee --- /dev/null +++ b/tests/cplusplus-conan-recipe/conanfile.py @@ -0,0 +1,42 @@ +from conan import ConanFile +from conan.tools.cmake import CMake, CMakeDeps, CMakeToolchain, cmake_layout + + +class exampleRecipe(ConanFile): + name = "example" + version = "0.0.1" + package_type = "application" + + # Optional metadata + license = "MIT" + author = "Tarcisio G. Rodrigues" + homepage = "https://codeberg.org/tarcisio/conan-flake" + description = "This is the Example project." + topics = ("testing", "example", "conan") + + # Binary configuration + settings = "os", "compiler", "build_type", "arch" + + # Sources are located in the same place as this recipe, copy them to the recipe + exports_sources = "CMakeLists.txt", "src/*" + + def layout(self): + cmake_layout(self) + + def requirements(self): + self.requires("hello-world/0.0.1.cci.20260428") + + def generate(self): + deps = CMakeDeps(self) + deps.generate() + tc = CMakeToolchain(self) + tc.generate() + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def package(self): + cmake = CMake(self) + cmake.install() diff --git a/tests/cplusplus-conan-recipe/devenv.nix b/tests/cplusplus-conan-recipe/devenv.nix new file mode 100644 index 000000000..da05be691 --- /dev/null +++ b/tests/cplusplus-conan-recipe/devenv.nix @@ -0,0 +1,31 @@ +{ pkgs, config, ... }: +let + getCommand = package: builtins.baseNameOf (pkgs.lib.getExe package); +in +{ + languages.cplusplus = { + enable = true; + conan = { + enable = true; + install.enable = true; + config = { + profiles.settings.build_type = "Release"; + compilerCppStd = "17"; + remotes.local = { + url = "./repo"; + local = true; + allowedPackages = [ + "hello-world/0.0.1.cci.20260428" + ]; + }; + offline = true; + }; + }; + }; + enterTest = '' + ${getCommand config.languages.cplusplus.conan.package} create . --build=missing 2>&1 \ + | grep "example/0.0.1" + ${getCommand config.languages.cplusplus.conan.package} remote list \ + | grep "local-recipes-index, Enabled: True, Allowed packages: hello-world/0.0.1.cci.20260428" + ''; +} diff --git a/tests/cplusplus-conan-recipe/devenv.yaml b/tests/cplusplus-conan-recipe/devenv.yaml new file mode 100644 index 000000000..0a9fd6c94 --- /dev/null +++ b/tests/cplusplus-conan-recipe/devenv.yaml @@ -0,0 +1,3 @@ +inputs: + conan-flake: + url: git+https://codeberg.org/tarcisio/conan-flake diff --git a/tests/cplusplus-conan-recipe/repo/recipes/hello-world/all/CMakeLists.txt b/tests/cplusplus-conan-recipe/repo/recipes/hello-world/all/CMakeLists.txt new file mode 100644 index 000000000..a17fd8bc1 --- /dev/null +++ b/tests/cplusplus-conan-recipe/repo/recipes/hello-world/all/CMakeLists.txt @@ -0,0 +1,9 @@ +cmake_minimum_required(VERSION 3.15) + +project(hello-world LANGUAGES CXX) + +add_library(hello-world src/hello-world.cpp) + +target_include_directories(hello-world PUBLIC include) +set_target_properties(hello-world PROPERTIES PUBLIC_HEADER "include/hello-world.h") +install(TARGETS hello-world) diff --git a/tests/cplusplus-conan-recipe/repo/recipes/hello-world/all/conanfile.py b/tests/cplusplus-conan-recipe/repo/recipes/hello-world/all/conanfile.py new file mode 100644 index 000000000..cef4f1220 --- /dev/null +++ b/tests/cplusplus-conan-recipe/repo/recipes/hello-world/all/conanfile.py @@ -0,0 +1,53 @@ +from pathlib import Path + +from conan import ConanFile +from conan.tools.cmake import CMake, CMakeDeps, CMakeToolchain, cmake_layout +from conan.tools.files import save + +required_conan_version = ">=2.12" + + +class hello_worldRecipe(ConanFile): + name = "hello-world" + package_type = "library" + + # Optional metadata + license = "MIT" + url = "https://github.com/conan-io/conan-center-index" + description = "Dummy recipe for internal testing" + topics = ("conan-testing", "dummy") + + # Binary configuration + settings = "os", "compiler", "build_type", "arch" + options = {"shared": [True, False], "fPIC": [True, False]} + default_options = {"shared": False, "fPIC": True} + + # Sources are located in the same place as this recipe, copy them to the recipe + exports_sources = "CMakeLists.txt", "src/*", "include/*" + + implements = ["auto_shared_fpic"] + + def layout(self): + cmake_layout(self) + + def generate(self): + deps = CMakeDeps(self) + deps.generate() + tc = CMakeToolchain(self) + tc.generate() + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def package(self): + cmake = CMake(self) + cmake.install() + + # save a dummy .la file to trigger hook warning + la_file = Path(self.package_folder) / "lib" / "hello-world-foobar.la" + save(self, la_file.as_posix(), "foobar") + + def package_info(self): + self.cpp_info.libs = ["hello-world"] diff --git a/tests/cplusplus-conan-recipe/repo/recipes/hello-world/all/include/hello-world.h b/tests/cplusplus-conan-recipe/repo/recipes/hello-world/all/include/hello-world.h new file mode 100644 index 000000000..23d083c87 --- /dev/null +++ b/tests/cplusplus-conan-recipe/repo/recipes/hello-world/all/include/hello-world.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include + + +#ifdef _WIN32 + #define HELLO_WORLD_EXPORT __declspec(dllexport) +#else + #define HELLO_WORLD_EXPORT +#endif + +HELLO_WORLD_EXPORT void hello_world(); +HELLO_WORLD_EXPORT void hello_world_print_vector(const std::vector &strings); diff --git a/tests/cplusplus-conan-recipe/repo/recipes/hello-world/all/src/hello-world.cpp b/tests/cplusplus-conan-recipe/repo/recipes/hello-world/all/src/hello-world.cpp new file mode 100644 index 000000000..50f9f4ac1 --- /dev/null +++ b/tests/cplusplus-conan-recipe/repo/recipes/hello-world/all/src/hello-world.cpp @@ -0,0 +1,120 @@ +#include +#include "hello-world.h" + + + +void hello_world(){ + + + #ifdef NDEBUG + std::cout << "hello-world: Hello World Release!\n"; + #else + std::cout << "hello-world: Hello World Debug!\n"; + #endif + + // ARCHITECTURES + #ifdef _M_X64 + std::cout << " hello-world: _M_X64 defined\n"; + #endif + + #ifdef _M_IX86 + std::cout << " hello-world: _M_IX86 defined\n"; + #endif + + #ifdef _M_ARM64 + std::cout << " hello-world: _M_ARM64 defined\n"; + #endif + + #if __i386__ + std::cout << " hello-world: __i386__ defined\n"; + #endif + + #if __x86_64__ + std::cout << " hello-world: __x86_64__ defined\n"; + #endif + + #if __aarch64__ + std::cout << " hello-world: __aarch64__ defined\n"; + #endif + + // Libstdc++ + #if defined _GLIBCXX_USE_CXX11_ABI + std::cout << " hello-world: _GLIBCXX_USE_CXX11_ABI "<< _GLIBCXX_USE_CXX11_ABI << "\n"; + #endif + + // MSVC runtime + #if defined(_DEBUG) + #if defined(_MT) && defined(_DLL) + std::cout << " hello-world: MSVC runtime: MultiThreadedDebugDLL\n"; + #elif defined(_MT) + std::cout << " hello-world: MSVC runtime: MultiThreadedDebug\n"; + #endif + #else + #if defined(_MT) && defined(_DLL) + std::cout << " hello-world: MSVC runtime: MultiThreadedDLL\n"; + #elif defined(_MT) + std::cout << " hello-world: MSVC runtime: MultiThreaded\n"; + #endif + #endif + + // COMPILER VERSIONS + #if _MSC_VER + std::cout << " hello-world: _MSC_VER" << _MSC_VER<< "\n"; + #endif + + #if _MSVC_LANG + std::cout << " hello-world: _MSVC_LANG" << _MSVC_LANG<< "\n"; + #endif + + #if __cplusplus + std::cout << " hello-world: __cplusplus" << __cplusplus<< "\n"; + #endif + + #if __INTEL_COMPILER + std::cout << " hello-world: __INTEL_COMPILER" << __INTEL_COMPILER<< "\n"; + #endif + + #if __GNUC__ + std::cout << " hello-world: __GNUC__" << __GNUC__<< "\n"; + #endif + + #if __GNUC_MINOR__ + std::cout << " hello-world: __GNUC_MINOR__" << __GNUC_MINOR__<< "\n"; + #endif + + #if __clang_major__ + std::cout << " hello-world: __clang_major__" << __clang_major__<< "\n"; + #endif + + #if __clang_minor__ + std::cout << " hello-world: __clang_minor__" << __clang_minor__<< "\n"; + #endif + + #if __apple_build_version__ + std::cout << " hello-world: __apple_build_version__" << __apple_build_version__<< "\n"; + #endif + + // SUBSYSTEMS + + #if __MSYS__ + std::cout << " hello-world: __MSYS__" << __MSYS__<< "\n"; + #endif + + #if __MINGW32__ + std::cout << " hello-world: __MINGW32__" << __MINGW32__<< "\n"; + #endif + + #if __MINGW64__ + std::cout << " hello-world: __MINGW64__" << __MINGW64__<< "\n"; + #endif + + #if __CYGWIN__ + std::cout << " hello-world: __CYGWIN__" << __CYGWIN__<< "\n"; + #endif +} + +void hello_world_print_vector(const std::vector &strings) { + for(std::vector::const_iterator it = strings.begin(); it != strings.end(); ++it) { + std::cout << "hello_world " << *it << std::endl; + } +} diff --git a/tests/cplusplus-conan-recipe/repo/recipes/hello-world/all/test_package/CMakeLists.txt b/tests/cplusplus-conan-recipe/repo/recipes/hello-world/all/test_package/CMakeLists.txt new file mode 100644 index 000000000..ad9491538 --- /dev/null +++ b/tests/cplusplus-conan-recipe/repo/recipes/hello-world/all/test_package/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.15) +project(PackageTest CXX) + +find_package(hello-world CONFIG REQUIRED) + +add_executable(example src/example.cpp) +target_link_libraries(example hello-world::hello-world) diff --git a/tests/cplusplus-conan-recipe/repo/recipes/hello-world/all/test_package/conanfile.py b/tests/cplusplus-conan-recipe/repo/recipes/hello-world/all/test_package/conanfile.py new file mode 100644 index 000000000..4a96772e5 --- /dev/null +++ b/tests/cplusplus-conan-recipe/repo/recipes/hello-world/all/test_package/conanfile.py @@ -0,0 +1,26 @@ +import os + +from conan import ConanFile +from conan.tools.build import can_run +from conan.tools.cmake import CMake, cmake_layout + + +class hello_worldTestConan(ConanFile): + settings = "os", "compiler", "build_type", "arch" + generators = "CMakeDeps", "CMakeToolchain" + + def requirements(self): + self.requires(self.tested_reference_str) + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def layout(self): + cmake_layout(self) + + def test(self): + if can_run(self): + cmd = os.path.join(self.cpp.build.bindir, "example") + self.run(cmd, env="conanrun") diff --git a/tests/cplusplus-conan-recipe/repo/recipes/hello-world/all/test_package/src/example.cpp b/tests/cplusplus-conan-recipe/repo/recipes/hello-world/all/test_package/src/example.cpp new file mode 100644 index 000000000..7eaed2893 --- /dev/null +++ b/tests/cplusplus-conan-recipe/repo/recipes/hello-world/all/test_package/src/example.cpp @@ -0,0 +1,12 @@ +#include "hello-world.h" +#include +#include + +int main() { + hello_world(); + + std::vector vec; + vec.push_back("test_package"); + + hello_world_print_vector(vec); +} diff --git a/tests/cplusplus-conan-recipe/repo/recipes/hello-world/config.yml b/tests/cplusplus-conan-recipe/repo/recipes/hello-world/config.yml new file mode 100644 index 000000000..11d0bf94a --- /dev/null +++ b/tests/cplusplus-conan-recipe/repo/recipes/hello-world/config.yml @@ -0,0 +1,3 @@ +versions: + "0.0.1.cci.20260428": + folder: all diff --git a/tests/cplusplus-conan-recipe/src/example.cpp b/tests/cplusplus-conan-recipe/src/example.cpp new file mode 100644 index 000000000..8e6ad2418 --- /dev/null +++ b/tests/cplusplus-conan-recipe/src/example.cpp @@ -0,0 +1,10 @@ +#include + +#include "example.h" + +void example_print_vector(const std::vector &strings) { + for (std::vector::const_iterator it = strings.begin(); + it != strings.end(); ++it) { + std::cout << "example/0.0.1 " << *it << std::endl; + } +} diff --git a/tests/cplusplus-conan-recipe/src/example.h b/tests/cplusplus-conan-recipe/src/example.h new file mode 100644 index 000000000..f08bd5d75 --- /dev/null +++ b/tests/cplusplus-conan-recipe/src/example.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include + +#ifdef _WIN32 +#define EXAMPLE_EXPORT __declspec(dllexport) +#else +#define EXAMPLE_EXPORT +#endif + +EXAMPLE_EXPORT void example_print_vector(const std::vector &strings); diff --git a/tests/cplusplus-conan-recipe/src/main.cpp b/tests/cplusplus-conan-recipe/src/main.cpp new file mode 100644 index 000000000..2ea64b33a --- /dev/null +++ b/tests/cplusplus-conan-recipe/src/main.cpp @@ -0,0 +1,15 @@ +#include +#include + +#include "example.h" +#include "hello-world.h" + + +int main() { + hello_world(); + + std::vector vec; + vec.push_back("test_package"); + + example_print_vector(vec); +} diff --git a/tests/cplusplus-conan-recipe/test_package/.gitignore b/tests/cplusplus-conan-recipe/test_package/.gitignore new file mode 100644 index 000000000..cdb5a221d --- /dev/null +++ b/tests/cplusplus-conan-recipe/test_package/.gitignore @@ -0,0 +1,3 @@ +* +!.gitignore +!conanfile.py diff --git a/tests/cplusplus-conan-recipe/test_package/conanfile.py b/tests/cplusplus-conan-recipe/test_package/conanfile.py new file mode 100644 index 000000000..4b64c0da0 --- /dev/null +++ b/tests/cplusplus-conan-recipe/test_package/conanfile.py @@ -0,0 +1,15 @@ +import os + +from conan import ConanFile +from conan.tools.build import can_run + + +class exampleTestConan(ConanFile): + settings = "os", "compiler", "build_type", "arch" + + def requirements(self): + self.requires(self.tested_reference_str) + + def test(self): + if can_run(self): + self.run("example", env="conanrun") diff --git a/tests/cplusplus-conan-stdenvNoCC/devenv.nix b/tests/cplusplus-conan-stdenvNoCC/devenv.nix new file mode 100644 index 000000000..b21844c90 --- /dev/null +++ b/tests/cplusplus-conan-stdenvNoCC/devenv.nix @@ -0,0 +1,23 @@ +{ pkgs, config, ... }: +let + getCommand = package: builtins.baseNameOf (pkgs.lib.getExe package); +in +{ + stdenv = pkgs.stdenvNoCC; + languages.cplusplus.enable = true; + languages.cplusplus.conan.enable = true; + languages.cplusplus.conan.install.enable = true; + enterTest = '' + ${getCommand config.languages.cplusplus.package} --version + ${getCommand config.languages.cplusplus.package} --version \ + | grep ${pkgs.lib.escapeShellArg pkgs.stdenv.cc.cc.pname} + ${getCommand config.languages.cplusplus.cmake.package} --version + ${getCommand config.languages.cplusplus.lsp.package} --version \ + | grep ${pkgs.lib.escapeShellArg config.languages.cplusplus.lsp.package.version} + ${getCommand config.languages.cplusplus.conan.package} --version + echo "enable:"${pkgs.lib.escapeShellArg config.languages.cplusplus.tools.enable}":" \ + | grep "enable:"${pkgs.lib.escapeShellArg pkgs.stdenv.cc.isClang}":" + ${getCommand config.languages.cplusplus.conan.package} profile show \ + | grep "cmake/"${pkgs.lib.escapeShellArg config.languages.cplusplus.cmake.package.version} + ''; +} diff --git a/tests/cplusplus-conan-stdenvNoCC/devenv.yaml b/tests/cplusplus-conan-stdenvNoCC/devenv.yaml new file mode 100644 index 000000000..0a9fd6c94 --- /dev/null +++ b/tests/cplusplus-conan-stdenvNoCC/devenv.yaml @@ -0,0 +1,3 @@ +inputs: + conan-flake: + url: git+https://codeberg.org/tarcisio/conan-flake diff --git a/tests/cplusplus-conan/devenv.nix b/tests/cplusplus-conan/devenv.nix new file mode 100644 index 000000000..5eb524505 --- /dev/null +++ b/tests/cplusplus-conan/devenv.nix @@ -0,0 +1,22 @@ +{ pkgs, config, ... }: +let + getCommand = package: builtins.baseNameOf (pkgs.lib.getExe package); +in +{ + languages.cplusplus.enable = true; + languages.cplusplus.conan.enable = true; + languages.cplusplus.conan.install.enable = true; + enterTest = '' + ${getCommand config.languages.cplusplus.package} --version + ${getCommand config.languages.cplusplus.package} --version \ + | grep ${pkgs.lib.escapeShellArg config.stdenv.cc.cc.pname} + ${getCommand config.languages.cplusplus.cmake.package} --version + ${getCommand config.languages.cplusplus.lsp.package} --version \ + | grep ${pkgs.lib.escapeShellArg config.languages.cplusplus.lsp.package.version} + ${getCommand config.languages.cplusplus.conan.package} --version + echo "enable:"${pkgs.lib.escapeShellArg config.languages.cplusplus.tools.enable}":" \ + | grep "enable:"${pkgs.lib.escapeShellArg config.stdenv.cc.isClang}":" + ${getCommand config.languages.cplusplus.conan.package} profile show \ + | grep "cmake/"${pkgs.lib.escapeShellArg config.languages.cplusplus.cmake.package.version} + ''; +} diff --git a/tests/cplusplus-conan/devenv.yaml b/tests/cplusplus-conan/devenv.yaml new file mode 100644 index 000000000..0a9fd6c94 --- /dev/null +++ b/tests/cplusplus-conan/devenv.yaml @@ -0,0 +1,3 @@ +inputs: + conan-flake: + url: git+https://codeberg.org/tarcisio/conan-flake diff --git a/tests/cplusplus/devenv.nix b/tests/cplusplus/devenv.nix new file mode 100644 index 000000000..d52339055 --- /dev/null +++ b/tests/cplusplus/devenv.nix @@ -0,0 +1,18 @@ +{ pkgs, config, ... }: +let + getCommand = package: builtins.baseNameOf (pkgs.lib.getExe package); +in +{ + languages.cplusplus.enable = true; + enterTest = '' + clang --version + ${getCommand config.languages.cplusplus.package} --version \ + | grep clang + cmake --version + ccls --version | grep ${pkgs.lib.escapeShellArg config.languages.cplusplus.lsp.package.version} + # Validate some clang-tools are in the path: + clang-doc --version + clang-format --version + clang-tidy --version + ''; +}