Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

conan-flake

The conan-flake module bridges the gap between Nix and the Conan C/C++ Package Manager, supporting a declarative configuration style and common development workflows.

For a user profile configuration like the following:

[settings]
build_type=Debug
compiler.cppstd=14

[platform_tool_requires]
cmake/X.Y.Z

There correspond the following options:

{
  profiles.default = {
    settings.build_type = "Debug";
    settings."compiler.cppstd" = "14";

    platformToolRequires = {
      cmake = pkgs.cmake.version;
    };
  };

  devShell = {
    # Programs you want to make available in the shell:
    tools = { inherit (pkgs) cmake; };
  };
}

The conan-flake module works with plain Nix (no flakes), Nix flakes, flake-parts, or as a devenv module.

Where to go next

  • Getting started takes an empty directory to a working Conan configuration, using one of the templates.
  • flake-parts covers the flake-parts integration.
  • devenv covers the devenv integration, both through devenv’s own languages.cplusplus.conan option and with conan-flake used directly as a devenv module.
  • Standalone covers plain Nix usage, with and without flakes.
  • Toolchains covers the LLVM/libc++ and CUDA scenarios.
  • The option reference lists every option of the module, generated from the module itself, along with initial setup instructions for flake-parts scenarios.

The source lives at codeberg.org/tarcisio/conan-flake, where issues and pull requests are welcome; see Contributing for the development environment, and the Changelog for the revision history.

Getting started

Every example of this site is a runnable project, collected under examples in the source repository, and each one is also exposed as a flake template. The quickest way from an empty directory to a working Conan configuration is to instantiate one of them:

mkdir -p hello-conan && cd hello-conan
git init
nix flake init -t "git+https://codeberg.org/tarcisio/conan-flake"#templates.devenv-module-recipe

That template is the devenv example featuring a local-recipe-index remote; it carries a complete C++ project — a conanfile.py recipe, its sources and a test package — alongside the Conan configuration itself, which is the devenv.nix shown in the devenv chapter.

The shell can be activated with direnv:

direnv allow .

It can take a while before completing. After that, the conan command is available in the path, with the profile and the other Conan settings already in place, so the Conan package defined by the recipe can be built and tested with a call to conan create:

conan create . --build=missing

Whose output can be used to validate if the configuration was applied successfully:

hello-world: Hello World Release!
  hello-world: __x86_64__ defined
  hello-world: _GLIBCXX_USE_CXX11_ABI 1
  hello-world: __cplusplus201703
  hello-world: __GNUC__15
  hello-world: __GNUC_MINOR__2
example/0.0.1 test_package

Warning

Depending when this page is being accessed, the devenv integration may still be pending approval upstream. The devenv samples here can still be tested nonetheless, by overriding devenv itself with the version from our upstream PR. See examples/devenv-module-recipe and devenv.yaml therein for more details. The flake-parts and standalone templates are unaffected.

Working from a clone

It’s also possible to interact directly with the example projects from a clone of this repository:1

git clone ssh://git@codeberg.org/tarcisio/conan-flake.git
cd conan-flake

The example above is on the examples/devenv-module-recipe directory:

cd examples/devenv-module-recipe
direnv allow .

And the same conan create call applies from there.

Where to go next

  • The option reference lists every option of the module, and carries the initial setup instructions for flake-parts scenarios.
  • The templates chapter lists the remaining templates, one per integration style.
  • The flake-parts, devenv and standalone chapters walk through each of those styles.

  1. Or, via https:

    git clone https://codeberg.org/tarcisio/conan-flake.git
    cd conan-flake
    

flake-parts

The flake-parts integration requires conan-flake and infuse to be added to the flake inputs:

# file: examples/flake-parts/flake.nix
{
  inputs = {
    nixpkgs.url = "github:cachix/devenv-nixpkgs/rolling";
    flake-parts.url = "github:hercules-ci/flake-parts";
    treefmt-nix.url = "github:numtide/treefmt-nix";

    # Add these two:
    conan-flake.url = "git+https://codeberg.org/tarcisio/conan-flake";
    infuse = {
      url = "git+https://codeberg.org/amjoseph/infuse.nix?rev=364ea18b5611b5fd6a6acd7151411b430a70e194";
      flake = false;
    };
  };
  # ...
}

After importing inputs.conan-flake.flakeModule, it’s possible to use the options from perSystem.conan to configure a suitable Conan profile:

# file: examples/flake-parts/flake.nix
{
  # ...
  outputs = inputs@{ self, nixpkgs, flake-parts, ... }:
    flake-parts.lib.mkFlake { inherit inputs; } {
      systems = nixpkgs.lib.systems.flakeExposed;

      imports = [
        inputs.conan-flake.flakeModule # Import this module
        inputs.treefmt-nix.flakeModule
      ];

      perSystem = { pkgs, config, ... }: {

        # A suitable Conan profile:
        conan = {
          profiles.default = {
            settings.build_type = "Release";
            settings."compiler.cppstd" = "23";
          };
        };

        devShells.default = pkgs.mkShell {
          inputsFrom = [
            # conan-flake computes a devShell that can be used directly or
            # appended to the `inputsFrom` option of another devShell as a
            # means to compose with other devShell modules:
            config.conan.outputs.devShell
            config.treefmt.build.devShell
          ];
          packages = [ pkgs.just ];
        }; # devShells

        treefmt.config = {
          projectRoot = self;
          projectRootFile = "README.md";
          programs = {
            cmake-format.enable = true;
          };
        };
      };
    };
}

The example above can be found in the examples/flake-parts directory:

cd examples/flake-parts
direnv allow .

It can take a while before completing. After that, the conan command should be available in the path, and the required profile and other Conan settings already in place:

conan profile show

A Release, C++23 profile is expected:

Host profile:
[settings]
arch=x86_64
build_type=Release
compiler=gcc
compiler.cppstd=23
compiler.libcxx=libstdc++11
compiler.version=15.3.0
os=Linux
[platform_tool_requires]
cmake/4.3.4
[conf]


Build profile:
[settings]
arch=x86_64
build_type=Release
compiler=gcc
compiler.cppstd=23
compiler.libcxx=libstdc++11
compiler.version=15.3.0
os=Linux
[platform_tool_requires]
cmake/4.3.4
[conf]


Note

By default, conan-flake sets both CMake and the configured stdenv.cc compiler as devShell.tools. Also, whatever CMake version, if any, ends up being in the devShell.tools is also set, by default, as a profiles.<name>.platformToolRequires of every profile.

The resulting default devShell defined above is a composition — it merges config.conan.outputs.devShell and config.treefmt.build.devShell, and appends pkgs.just to the resulting devShell’s package list for its own sake:

devShells.default = pkgs.mkShell {
  inputsFrom = [
    # conan-flake computes a devShell that can be used directly or
    # appended to the `inputsFrom` option of another devShell as a
    # means to compose with other devShell modules:
    config.conan.outputs.devShell
    config.treefmt.build.devShell
  ];
  packages = [ pkgs.just ];
}; # devShells

A possible sanity check could be to find the corresponding commands available in the path:

cmake --version
conan --version
treefmt --version
echo
just --version

Also, CMake’s version should match the one listed in the [platform_tool_requires] section of the conan profile show command’s output above:

cmake version 4.3.4

CMake suite maintained and supported by Kitware (kitware.com/cmake).
Conan version 2.32.0-dev
treefmt v2.5.0
just 1.57.0

The complete list of the options available under perSystem.conan, along with the initial setup instructions for flake-parts scenarios, is in the option reference.

devenv

There are two ways of using conan-flake with devenv: the languages.cplusplus.conan option, which devenv itself provides and which carries conan-flake’s own options under languages.cplusplus.conan.config, and a devenv shell that takes conan-flake’s computed devShell directly.

The languages.cplusplus.conan option

Configure Conan in any devenv shell with the supported integration:

# file: examples/devenv-module-recipe/devenv.nix
languages.cplusplus = {
  enable = true;

  conan = {
    enable = true;
    install.enable = true;

    config = {
      profiles.default = {
        settings.build_type = "Release";
        settings."compiler.cppstd" = "17";
      };

      # It's possible to specify Conan remotes explicitly, including
      # local-recipe-index remotes, in which case the `url` is taken as a
      # relative path to the root of the configuration:
      remotes.local = {
        url = "./repo";
        local = true;
        allowedPackages = [
          "hello-world/0.0.1.cci.20260428"
        ];
      };

      # Enable only local remotes (i.e., only of local-recipe-index type):
      offline = true;
    };
  };
}; # languages.cplusplus

Note

See how to setup Conan in devenv for further details. As can be seen from the above example, the devenv integration automatically takes care of the CMake part by default, and the profiles.<name>.platformToolRequires and devShell.tools options are not required to be set explicitly in the languages.cplusplus.conan.config namespace.

Warning

Depending when this page is being accessed, the devenv integration may still be pending approval upstream and the above links to the devenv docs may be missing. The devenv samples here can still be tested nonetheless, by overriding devenv itself with the version from our upstream PR. See examples/devenv-module-recipe and devenv.yaml therein for more details.

The example above is on the examples/devenv-module-recipe directory, and the Getting started chapter walks through it. A variant without the local-recipe-index remote is on examples/devenv-module; its profile settings, and the Conan profile they produce, are the pair shown on the front page.

A devenv shell taking conan-flake’s devShell

Where devenv shells are declared through flake-parts, conan-flake can be used without the languages.cplusplus option at all: importing inputs.conan-flake.flakeModule next to inputs.devenv.flakeModule makes config.conan.outputs.devShell available, which composes into a devenv shell the same way it composes into a pkgs.mkShell:

devenv = {
  shells.default = {
    name = "conan-flake-dev";

    inputsFrom = [
      # conan-flake exposes a `configuration` devShell by default that
      # can be used directly, or passed in the inputsFrom option as a
      # means to compose with other devShell modules.
      config.conan.outputs.devShell
    ];

    packages = [ pkgs.just ];

    treefmt = {
      enable = true;
      config = {
        programs = {
          nixpkgs-fmt.enable = true;
          cmake-format.enable = true;
        };
      };
    };
  };
}; # devenv

That example is on the examples/devenv directory, whose Conan configuration is written with the same perSystem.conan options the flake-parts chapter describes:

cd examples/devenv
direnv allow .

Either way, the options being set are conan-flake’s own, and the complete list of them is in the option reference — under perSystem.conan for the flake-parts spelling, and under languages.cplusplus.conan.config for the devenv one.

Standalone

Although conan-flake is presented as a flake-parts module, there is a subset of its options that can be imported independently, directly into any Nix code. This use case is supported by two helper functions, exposed in the lib namespace of the flake defined by this repository: evalConanConfig and submoduleWith.

To use these functions, add conan-flake to your flake inputs:

{
  inputs = {
    nixpkgs.url = "github:cachix/devenv-nixpkgs/rolling";

    # Add this:
    conan-flake.url = "git+https://codeberg.org/tarcisio/conan-flake";
  };
  # ...
}

Now conan-flake.lib.evalConanConfig can be used to configure, for each system supported, a Conan configuration and output a devShell and a check command. With this schema in place:

{
  # ...
  outputs = { self, nixpkgs, conan-flake, ... }:
    let
      eachSystem = nixpkgs.lib.genAttrs nixpkgs.lib.systems.flakeExposed;

      # See below for the actual `perSystem` function definition:
      perSystem = system:
        let
          # ...
          configuration = conan-flake.lib.evalConanConfig pkgs (
            # ...
          );
        in
        {
          devShells = {
            # ...
          };
          checks = {
            # ...
          };
        };
      systemOutputs = eachSystem perSystem;
    in
    {
      devShells = nixpkgs.lib.mapAttrs (_: s: s.devShells) systemOutputs;
      checks = nixpkgs.lib.mapAttrs (_: s: s.checks) systemOutputs;
    };
}

The two chapters that follow fill in the perSystem function, one with each helper:

Warning

There’s still no support for the automatic nixification of conanfile.py package definitions;1 the conan-flake module is about the Conan configuration side of things, that is: profiles, settings, remotes…

The options accepted by both helpers are the ones documented in the option reference (the perSystem.conan.* entries, minus their perSystem.conan prefix).


  1. Or even of conanfile.txt, for that matter.

evalConanConfig

This example can be found in the standalone-eval-conan-config directory:

cd examples/standalone-eval-conan-config

Where the actual perSystem function — the one left out of the schema of the previous chapter — is used to configure a Release, C++17 profile:

# file: examples/standalone-eval-conan-config/flake.nix
{
  # ...
  perSystem = system:
    let
      pkgs = nixpkgs.legacyPackages.${system};

      configuration = conan-flake.lib.evalConanConfig pkgs (

        { pkgs, config, ... }: {

          configRoot = self;

          profiles.default = {
            settings.build_type = "Release";
            settings."compiler.cppstd" = "17";
          };

          remotes.local = {
            url = "./repo";
            local = true;
            allowedPackages = [ "hello-world/0.0.1.cci.20260428" ];
          };

          offline = true;

          checks.example = {
            enable = true;
            drv =
              conan-flake.lib.runCommandWithInSimulatedShell pkgs config.stdenv config.outputs.devShell
                config.info.configRoot "./config"
                "standalone-eval-conan-config-example-conan-create"
                { }
                ''
                  (
                  set -x
                  conan create . --build=missing 2>&1 | grep -F "example/0.0.1"
                  touch $out
                  )
                ''; # checks.example
          };
        }
      );
    in
    {
      devShells.default = configuration.config.outputs.devShell;
      checks = configuration.config.outputs.checks;
    };
    # ...
}

This configuration now can be used to set a developer environment with direnv:

direnv allow .

But even a plain nix develop would suffice:

nix develop .

From within this shell, the following command can be used to obtain the resulting profile:

conan profile show

To the profiles.default.settings.build_type and profiles.default.settings."compiler.cppstd" conan-flake options correspond, respectively, the build_type and compiler.cppstd entries in its output:

Host profile:
[settings]
arch=x86_64
build_type=Release
compiler=gcc
compiler.cppstd=17
compiler.libcxx=libstdc++11
compiler.version=15.3.0
os=Linux
[platform_tool_requires]
cmake/4.3.4
[conf]


Build profile:
[settings]
arch=x86_64
build_type=Release
compiler=gcc
compiler.cppstd=17
compiler.libcxx=libstdc++11
compiler.version=15.3.0
os=Linux
[platform_tool_requires]
cmake/4.3.4
[conf]


In the standalone-eval-conan-config directory, the conanfile.py recipe file defines a C++ package — example/0.0.1 — it’s possible to call conan create on it, and export this package into the local Conan cache:

conan create . --build=missing

The above command is going to install the dependencies and then build the example/0.0.1 package. Then export it to the local Conan cache and test it afterwards against standalone-eval-conan-config/test_package. If everything goes well, the last lines from the previous command would be the test package’s output:

hello-world: Hello World Release!
  hello-world: __x86_64__ defined
  hello-world: _GLIBCXX_USE_CXX11_ABI 1
  hello-world: __cplusplus201703
  hello-world: __GNUC__15
  hello-world: __GNUC_MINOR__2
example/0.0.1 test_package

There’s also a check example function defined along with each default devShell:

checks.example = {
  enable = true;
  drv =
    conan-flake.lib.runCommandWithInSimulatedShell pkgs config.stdenv config.outputs.devShell
      config.info.configRoot "./config"
      "standalone-eval-conan-config-example-conan-create"
      { }
      ''
        (
        set -x
        conan create . --build=missing 2>&1 | grep -F "example/0.0.1"
        touch $out
        )
      ''; # checks.example

Run the check via nix flake check:

nix flake check .

submoduleWith

This example can be found in the examples/standalone-submodule-with directory:

cd examples/standalone-submodule-with

Where the actual perSystem function is used to configure a Debug, C++14 profile:

# file: examples/standalone-submodule-with/flake.nix
{
  # ...
  perSystem =
    system:
    let
      pkgs = nixpkgs.legacyPackages.${system};
      lib = pkgs.lib;
      conanSubmodule = conan-flake.lib.submoduleWith lib {
        modules = [
          {
            options.pkgs = lib.mkOption {
              default = pkgs;
              defaultText = lib.literalExpression "pkgs";
            };
            config.configRoot = self;
          }
        ];
      };
      conanModule = {
        options = {
          conan = lib.mkOption {
            type = conanSubmodule;
            description = "Conan configuration";
            default = { };
          };
        };
      }; # conanModule
      conanModuleConfig =
        (lib.evalModules {
          modules = [
            ({ config, ... }: {
              imports = [ conanModule ];

              conan = {
                profiles.default = {
                  settings.build_type = "Debug";
                  settings."compiler.cppstd" = "14";
                };

                devShell = {
                  tools = { inherit (pkgs) just; };
                };

                remotes.local = {
                  url = "./repo";
                  local = true;
                  allowedPackages = [ "hello-world/0.0.1.cci.20260428" ];
                };

                offline = true;

                checks.example = {
                  enable = true;
                  drv =
                    conan-flake.lib.runCommandWithInSimulatedShell pkgs config.conan.stdenv config.conan.outputs.devShell
                      config.conan.info.configRoot "./config"
                      "standalone-submodule-with-example-conan-create"
                      { }
                      ''
                        (
                        set -x
                        conan create . --build=missing 2>&1 | grep -F "example/0.0.1"
                        touch $out
                        )
                      ''; # checks.example
                };
              };
            })
          ];
        }).config.conan; # conanModuleConfig
    in
    {
      devShells.default = conanModuleConfig.outputs.devShell;
      checks = conanModuleConfig.outputs.checks;
    };
  # ...
}

Differently from the example in the previous chapter, here the options are loaded apart:

conanSubmodule = conan-flake.lib.submoduleWith lib {

And integrated as a submodule of a larger configuration:

conanModule = {
  options = {
    conan = lib.mkOption {
      type = conanSubmodule;
      description = "Conan configuration";
      default = { };
    };
  };
}; # conanModule

And the final configuration can be obtained with lib.evalModules:

conanModuleConfig =
  (lib.evalModules {
    modules = [
      ({ config, ... }: {
        imports = [ conanModule ];

        conan = {
          profiles.default = {
            settings.build_type = "Debug";
            settings."compiler.cppstd" = "14";
          };

          devShell = {
            tools = { inherit (pkgs) just; };
          };

          remotes.local = {
            url = "./repo";
            local = true;
            allowedPackages = [ "hello-world/0.0.1.cci.20260428" ];
          };

          offline = true;

          checks.example = {
            enable = true;
            drv =
              conan-flake.lib.runCommandWithInSimulatedShell pkgs config.conan.stdenv config.conan.outputs.devShell
                config.conan.info.configRoot "./config"
                "standalone-submodule-with-example-conan-create"
                { }
                ''
                  (
                  set -x
                  conan create . --build=missing 2>&1 | grep -F "example/0.0.1"
                  touch $out
                  )
                ''; # checks.example
          };
        };
      })
    ];
  }).config.conan; # conanModuleConfig

Apart from that, all the other commands and considerations from the previous chapter also apply here.1

Without flakes

To make this difference clearer, the standalone-submodule-with/default.nix file defines and configures a conan option using only a fetched conan-flake module:

# file: examples/standalone-submodule-with/default.nix
{
  lib,
  pkgs,
  inputs,
  ...
}:
let
  conan-flake = (
    fetchGit {
      url = "https://codeberg.org/tarcisio/conan-flake";
      name = "conan-flake";
      ref = "refs/branches/main";
      rev = "55a3e4025974d01980f637e37e636d7a43a22a91";
      shallow = true;
    }
  );
  conanSubmodule =
    (import "${conan-flake}/nix/lib/lib.nix" { inherit inputs; }).conanFlakeLib.submoduleWith lib
      {
        modules = [
          {
            options.pkgs = lib.mkOption {
              default = pkgs;
              defaultText = lib.literalExpression "pkgs";
            };
            config.configRoot = ./.;
          }
        ];
      };
in
{
  options = {
    conan = lib.mkOption {
      type = conanSubmodule;
      description = "Conan configuration";
      default = { };
    };
  };

  config = {
    conan = {
      profiles.default = {
        settings.build_type = "Debug";
        settings."compiler.cppstd" = "14";
      };

      devShell = {
        tools = { inherit (pkgs) just; };
      };

      remotes.local = {
        url = "./repo";
        local = true;
        allowedPackages = [ "hello-world/0.0.1.cci.20260428" ];
      };

      offline = true;
    };
  };
}

To validate this setup, the standalone-submodule-with/eval.nix file can be used to evaluate the previous definitions:

# file: examples/standalone-submodule-with/eval.nix
let
  pkgs = import <nixpkgs> { };
in
pkgs.lib.evalModules {
  modules = [
    ({ ... }: { config._module.args = { inherit pkgs; }; })
    ./default.nix
    # ./infuse.nix
  ];
}

To put these together, the following command instantiate the Nix files and print the resulting expression at a given attribute path:

nix-instantiate --eval eval.nix -A config.conan.profiles.default.text.text

The retuned value is that of the resulting default profile:

"[settings]\narch=x86_64\nbuild_type=Debug\ncompiler=gcc\ncompiler.cppstd=14\ncompiler.libcxx=libstdc++11\ncompiler.version=15.3.0\nos=Linux\n\n[options]\n\n\n[tool_requires]\n\n\n[buildenv]\n\n\n[runenv]\n\n\n[conf]\n\n\n[replace_requires]\n\n\n[replace_tool_requires]\n\n\n[platform_requires]\n\n\n[platform_tool_requires]\ncmake/4.3.4\n"

Which can be compared with the one already generated:

cat .conan2/profiles/default

Both outputs match, but for the \n propper printing:

[settings]
arch=x86_64
build_type=Debug
compiler=gcc
compiler.cppstd=14
compiler.libcxx=libstdc++11
compiler.version=15.3.0
os=Linux

[options]


[tool_requires]


[buildenv]


[runenv]


[conf]


[replace_requires]


[replace_tool_requires]


[platform_requires]


[platform_tool_requires]
cmake/4.3.4

  1. The definitions of the two methods: conan-flake.lib.evalConanConfig and conan-flake.lib.submoduleWith try to mimic treefmt-nix’s related design. Cf. their default.nix to compare definitions.

Toolchains

A common way to support C and C++ packages in Nix is to integrate their build system and expose a specialized stdenv derivation responsible to bring in all of the necessary tools required to consistently generate, configure, build and link those, and related, packages. The stdenv derivation is a special derivation, defined in Nixpkgs, and can be regarded as a kind of a pattern as well — see its reference: The Standard Environment, on the Nixpkgs Reference Manual. For an introduction to the stdenv as a pattern, see 19. Fundamentals of Stdenv, from the Nix Pills series.

conan-flake is parameterized by a stdenv option (defaulting to pkgs.stdenv), driving this complexity away from this module, which can then be regarded as its interface with the compile infrastructure of the Nix system. It’s used to extract mainly compiler related information and, together with the other options, compute the final configuration, which is exposed as a devShell output.

The two scenarios this project demonstrates are:

  • LLVM — a stdenv in which all dependencies come from the LLVM project, and the compiler.libcxx setting that goes with it.
  • CUDA — the NVIDIA toolchain, linking against the CUDA libraries available in pkgs.cudaPackages.

LLVM

The way LLVM is packaged in Nix is an example of the stdenv pattern described in the previous chapter. To integrate with the LLVM compiler infrastructure, there is a pkgs.llvmPackages.libcxxStdenv derivation — however this will not provide a pure llvm stdenv in which all dependencies come from the LLVM project and none from GCC.1 A different approach would be something like this:

stdenv = pkgs.overrideCC
  (
    pkgs.llvmPackages.libcxxStdenv.override {
      targetPlatform.useLLVM = true;
      targetPlatform.linker = "lld";
    }
  )
  pkgs.llvmPackages.clangUseLLVM

That stdenv is what the stdenv option is given, and the devShell conan-flake computes from it can then be appended to an inputsFrom option for composition:

# file: examples/llvm-flake-parts/flake.nix
{
  outputs = inputs@{ nixpkgs, flake-parts, ... }:
    flake-parts.lib.mkFlake { inherit inputs; } {
      systems = nixpkgs.lib.systems.flakeExposed;
      imports = [
        inputs.conan-flake.flakeModule
      ];
      perSystem = { pkgs, config, ... }:
      {
        conan = {
          profiles.default = {
            settings = {
              build_type = "Release";
              "compiler.cppstd" = "23";
            };
          };

          stdenv = pkgs.overrideCC
            (
              pkgs.llvmPackages.libcxxStdenv.override {
                targetPlatform.useLLVM = true;
                targetPlatform.linker = "lld";
              }
            )
            pkgs.llvmPackages.clangUseLLVM;
        };

        devShells.default = pkgs.mkShell {
          inputsFrom = [
            config.conan.outputs.devShell
          ];
        };
      };
    };
}

The above example is on the examples/llvm-flake-parts directory:

cd examples/llvm-flake-parts
direnv allow .

By default, conan-flake sets defaults.profiles.settings."compiler.libcxx" to "libstdc++11", which would result in the wrong choice for compiler.libcxx — with the LLVM stdenv above it is detected as libc++ instead:

conan profile show

To the conan.profiles.default.settings.build_type and conan.profiles.default.settings."compiler.cppstd" options correspond, respectivelly, the build_type and compiler.cppstd entries in the command output:

Host profile:
[settings]
arch=x86_64
build_type=Release
compiler=clang
compiler.cppstd=23
compiler.libcxx=libc++
compiler.version=21.1.8
os=Linux
[platform_tool_requires]
cmake/4.3.4
[conf]
tools.build:compiler_executables={'c': '/nix/store/va889lnfilh11sjb1rcnrdvp813jpg03-clang-wrapper-21.1.8/bin/clang', 'cpp': '/nix/store/va889lnfilh11sjb1rcnrdvp813jpg03-clang-wrapper-21.1.8/bin/clang++'}

Build profile:
[settings]
arch=x86_64
build_type=Release
compiler=clang
compiler.cppstd=23
compiler.libcxx=libc++
compiler.version=21.1.8
os=Linux
[platform_tool_requires]
cmake/4.3.4
[conf]
tools.build:compiler_executables={'c': '/nix/store/va889lnfilh11sjb1rcnrdvp813jpg03-clang-wrapper-21.1.8/bin/clang', 'cpp': '/nix/store/va889lnfilh11sjb1rcnrdvp813jpg03-clang-wrapper-21.1.8/bin/clang++'}

The package defined in the examples/llvm-flake-parts/conanfile.py recipe — example/0.0.1 — can be created in order to validate these settings:

conan create . --build=missing

Lines from its output correspond to entries from the Conan profile and, ultimately, to the conan-flake options:

hello-conan: Hello World Release!
  hello-conan: __x86_64__ defined
  hello-conan: __cplusplus202302
  hello-conan: __GNUC__4
  hello-conan: __GNUC_MINOR__2
  hello-conan: __clang_major__21
  hello-conan: __clang_minor__1
example/0.0.1 test_package

  1. See this question, or this issue, for further details on how to create a LLVM-based stdenv for C++ development.

CUDA

The pkgs.cudaPackages.backendStdenv derivation helps integrate the NVIDIA and the host compilers while making it possible to link against the CUDA libraries available in pkgs.cudaPackages.1

Nixpkgs parametrization can affect the compatibility and availability of CUDA packages:

_module.args.pkgs = import inputs.nixpkgs {
  inherit system;
  config.allowUnfree = true;
  config.allowUnsupportedSystem = false;
  config.cudaForwardCompat = true;
  config.cudaSupport = true;
}; # _module.args.pkgs

The configuration can be done entirely with perSystem.conan options:

# file: examples/cuda-flake-parts/flake.nix
conan = {
  stdenv = pkgs.cudaPackages_13_2.backendStdenv;
  devShell = {
    tools = {
      inherit (pkgs.cudaPackages_13_2)
        cuda_nvcc
        cuda_cccl
        cuda_cudart
        cuda_nvrtc
        cuda_nvtx
        cuda_profiler_api
        cuda_cuxxfilt
        libcublas
        libnvfatbin
        libnvptxcompiler;
    };
    env = {
      LD_LIBRARY_PATH = "/usr/lib/wsl/lib";
      MESA_D3D12_DEFAULT_ADAPTER_NAME = "NVIDIA";
      GALLIUM_DRIVER = "d3d12";
    };
  };
  profiles.default = {
    settings = {
      build_type = "Release";
      "compiler.cppstd" = "20";
    };
    runEnv = [
      {
        name = "LD_LIBRARY_PATH";
        op = "+=(path)";
        value = "/usr/lib/wsl/lib";
      }
      {
        name = "MESA_D3D12_DEFAULT_ADAPTER_NAME";
        op = "=";
        value = "NVIDIA";
      }
      {
        name = "GALLIUM_DRIVER";
        op = "=";
        value = "d3d12";
      }
    ];
  };
  remotes.local = {
    url = "./repo";
    local = true;
    allowedPackages = [ "hello-world/0.0.1.cci.20260428" ];
  };
}; # conan }

The above example is on the examples/cuda-flake-parts directory:

cd examples/cuda-flake-parts
direnv allow .

And it can be validated with a call to conan create:

conan create . --build=missing

Which returns the result of the program defined in the src/modified_cuda_samples/matrixMulCUBLAS/matrixMulCUBLAS.cpp source file, on the examples/cuda-flake-parts directory:2

[Matrix Multiply CUBLAS] - Starting...
Using CUDA device NVIDIA GeForce RTX 3060 Laptop GPU (having device ID 0)
GPU Device 0: "NVIDIA GeForce RTX 3060 Laptop GPU" with compute capability 8.6
MatrixA(640,480), MatrixB(480,320), MatrixC(640,320)
Computing result using CUBLAS... done.
Performance= 4266.67 GFlop/s, Time= 0.046 msec, Size= 196608000 Ops
Computing result using host CPU... done.
CUBLAS Matrix Multiply is close enough to CPU results: Yes
SUCCESS

  1. See CUDA Modules for an overview on how CUDA packages are structured in Nixpkgs.

  2. The source files src/modified_cuda_samples/matrixMulCUBLAS/matrixMulCUBLAS.cpp and src/common.hpp are taken from the examples of the cuda-api-wrappers project — examples/modified_cuda_samples/matrixMulCUBLAS/matrixMulCUBLAS.cpp and examples/common.hpp, respectively.

Templates

Every example of this project is also a flake template, so each one can be instantiated into an empty directory with nix flake init. The Getting started chapter walks through the first steps with one of them.

Simple conan-flake project with only a flake-parts-based configuration

This template will get you only the flake.nix, .envrc and .gitignore files.

mkdir -p default && cd default
nix flake init -t "git+https://codeberg.org/tarcisio/conan-flake"

C++ conan-flake, flake-parts-based project

Alongside the files from the previous item, this template will provide you also with a complete sample Conan-based C++ project.

mkdir -p example && cd example
git init
nix flake init -t "git+https://codeberg.org/tarcisio/conan-flake"#templates.example
direnv allow .

After this initial setup is complete, test if everything is working:

conan create . --build=missing

The remaining templates in this chapter can be initialized and validated in a similar manner.

LLVM-based C++ conan-flake project

This template is also flake-parts-based; see the LLVM chapter.

nix flake init -t "git+https://codeberg.org/tarcisio/conan-flake"#templates.llvm

C++ conan-flake, “devenv with flake-parts”-based project

nix flake init -t "git+https://codeberg.org/tarcisio/conan-flake"#templates.devenv

C++ conan-flake, devenv-based project

nix flake init -t "git+https://codeberg.org/tarcisio/conan-flake"#templates.devenv-module

C++ conan-flake, devenv-based project featuring a local-recipe-index remote

nix flake init -t "git+https://codeberg.org/tarcisio/conan-flake"#templates.devenv-module-recipe

C++ conan-flake standalone Nix module project

See the Standalone chapter.

nix flake init -t "git+https://codeberg.org/tarcisio/conan-flake"#templates.standalone

C++ conan-flake, flake-parts-based project demonstrating CUDA integration

See the CUDA chapter.

nix flake init -t "git+https://codeberg.org/tarcisio/conan-flake"#templates.cuda

Contributing

The development environment

To get started, clone this repository and allow devenv to set up the environment with the configuration from the ./dev directory:

git clone ssh://git@codeberg.org/tarcisio/conan-flake.git
cd conan-flake
devenv --from path:dev allow

It will complain that conan-flake is not available:

    error: To use 'conan', run the following command:

      $ devenv inputs add conan-flake git+https://codeberg.org/tarcisio/conan-flake

Add the conan-flake input pointing to the local checkout (the root of this repository) and activate devenv shell:

devenv inputs add conan-flake path:"$PWD"
devenv shell

Check that a default Conan profile was configured successfully:

conan profile show
Host profile:
[settings]
arch=x86_64
build_type=Release
compiler=gcc
compiler.cppstd=20
compiler.libcxx=libstdc++11
compiler.version=15.3.0
os=Linux
[platform_tool_requires]
cmake/4.3.4
[conf]


Build profile:
[settings]
arch=x86_64
build_type=Release
compiler=gcc
compiler.cppstd=20
compiler.libcxx=libstdc++11
compiler.version=15.3.0
os=Linux
[platform_tool_requires]
cmake/4.3.4
[conf]


Commands can also be run without entering the shell interactively, by prefixing them with devenv shell --. To pick a different secretspec provider when activating it:

devenv inputs add conan-flake path:"$PWD"
devenv --secretspec-provider dotenv shell

Running the checks

The justfile recipes all point nix at ./dev and override the conan-flake input with the local checkout:

just show            # nix flake show ./dev
just check           # nix flake check ./dev
just repl            # nix repl ./dev
just ci              # the full local CI, via `vira`
just vira <args>     # `vira` with arbitrary arguments
just search <query>  # conan search "<query>" (defaults to "*")

just show and just check also accept a path or flake reference, so a single scenario can be targeted:

just check ./examples/flake-parts

Each directory under examples and test is an independent flake, and can be validated in isolation against the local checkout:

nix flake check ./examples/flake-parts --override-input conan-flake . --show-trace --no-pure-eval

Most examples define a checks.test derivation that runs conan install and conan build inside a simulated shell, so nix flake check is the whole test runner — there is no separate one.

vira.hs is the source of truth for which example and test flakes CI exercises: a new scenario under examples/ or test/ has to be added to its build.flakes list to be checked. The pipelines themselves are in .woodpecker: checks.yml runs nix flake check ./dev, then vira ci -b, then a build of flake.parts-website against this repository, which is what publishes the option reference; release.yml runs vira ci -b again on release events.

Note

Option documentation is generated from the module options’ own description and example attributes, so an option is documented by writing those — never by transcribing them into this site, which would silently go stale. The generated result is the option reference this site links to throughout.

The documentation site

The sources of this site are the Markdown files under docs, rendered by mdBook. From the development shell:

just docs         # build the site, exactly as CI builds it
just docs-serve   # serve it locally, reloading on every source change

A new page has to be listed in docs/src/SUMMARY.md; mdBook renders nothing that the summary does not name.

just docs builds through Nix, from a filtered copy of the sources, and its output carries the site alone. just docs-serve runs mdbook serve over the checkout instead, so it follows the docs/src/.examples symbolic link described below: the preview publishes that link and mdBook watches the whole examples tree, including whatever an example run left behind there. That is a property of the local preview only, never of the built site.

How the generated blocks are refreshed

Code samples are never written into the Markdown sources by hand. Each one is declared by an embedmd marker naming the example file and the region to take, and the fenced block below the marker is rewritten from that file:

[embedmd]:# (./.examples/flake-parts/flake.nix nix !/.*{ inputs/ !/.*inputs }/ s/#  // dedent)

embedmd resolves the path relative to the Markdown file and refuses to leave that directory, which is why the site’s markers go through docs/src/.examples, a symbolic link to the examples directory at the root of the repository.

Running embedmd over the sources rewrites every such block in place:

embedmd README.md docs/src/*.md

That same command runs as a pre-commit hook and as a treefmt formatter, so in practice the blocks are refreshed on commit, and a sample that no longer matches its example project fails the authoring.EMBEDDING.2 check in CI — the checks over the site are named after the requirement each one proves.

Note

Only nix and ini blocks are guarded that way. The few text blocks that transcribe a command’s output without an mdsh block above them — the conan create outputs, mostly — are hand-maintained, and have to be updated by hand when the example they came from changes.

Command-output blocks are generated the same way, by mdsh: the command that produces the output is recorded next to the block, either visibly —

```sh > text $
conan profile show
```

<!-- BEGIN mdsh -->
```text
…output…
```
<!-- END mdsh -->

— or hidden, when the command is scaffolding rather than something the reader would type:

<!-- > $
echo '```text'
cd "$(git rev-parse --show-toplevel)/examples/flake-parts"
nix develop --command bash -c "profile-show-wrapper 2>/dev/null"
echo '```'
-->

mdsh runs each block from the directory of the Markdown file that carries it, which is why the site’s blocks cd to the repository root first. Running it replaces the block that follows with the command’s current output:

mdsh --inputs docs/src/*.md

The sources of the site are the whole of that list: README.md is a pointer at this site and carries no command-output block, so it is off programs.mdsh.includes in dev/treefmt.nix. It does keep one embedded sample, which is why it is still named in the embedmd command above.

Warning

Those commands run the examples/* projects, and those resolve conan-flake from the published upstream rather than from the checkout. Between a breaking option change and the release that publishes it, the examples fail to evaluate and mdsh writes back empty blocks, deleting committed content. For the duration of that window, set programs.mdsh.excludes = [ "docs/src/*.md" ] in dev/treefmt.nix — the same list programs.mdsh.includes carries there, so mdsh is then pointed at zero files, which turns it off without unwiring it and leaves the committed blocks untouched. Clear the exclude once the release is on main. embedmd is unaffected either way.

Publishing the site

This site is a Codeberg Page of this repository: the content of its pages branch is served at https://tarcisio.codeberg.page/conan-flake/. One command builds the site and updates that branch from the build:

just docs-publish

It runs scripts/publish-pages.sh, which is also what CI runs, so what a contributor publishes and what a pipeline publishes are produced by the same code. It needs no credential beyond the one that already pushes to this repository: the push goes through the checkout’s own origin.

What it does, and why it does it that way:

  • the site is built first, and nothing else happens if that build fails, so a broken build cannot leave a half-published branch behind;
  • the branch is updated through a temporary git worktree, never by switching this checkout, so the branch that was checked out stays checked out and the working tree is not touched — including when the run fails;
  • pages is created as an orphan branch: it carries no source of the repository and its history starts at a root commit of its own;
  • everything the branch carried is dropped before the new build is copied in, so a page removed from the site stops being served;
  • the build output is copied out of the Nix store dereferencing symbolic links and without the store’s permissions, since a store path is read-only and its links point back into a store no visitor has. What lands on the branch is the output of the site’s derivation, whole: the server builds nothing.

The pipeline that runs the same script from main is .woodpecker/pages.yml. A push to main that touches the sources the site is built from publishes it, and the pipeline can still be run on demand, which is how the site is republished without a commit. The checklist below is how that was set up.

When two publications race, the second push loses: its run fails on a rejected push, and the site goes on carrying the other run’s build until the next change or a manual run.

Switching publication on

These steps need administration rights on the Codeberg repository and on its Woodpecker project, so they cannot be done from a checkout. All of them have been taken here: the webhook and the codeberg_token secret are registered, https://tarcisio.codeberg.page/conan-flake/ serves this site from the pages branch, and CI publishes it on every change to its sources on main. They are kept because they are what a fork, or a move to another forge, has to repeat — and a fork has to repeat them before its pages workflow runs at all: the publishing step names codeberg_token, and a workflow whose secret Woodpecker cannot resolve fails to compile rather than reporting that nothing was published.

Important

Order matters between the fourth step and the last one. Woodpecker resolves a from_secret: while it compiles the workflow, so a run whose event the secret does not list fails before any step starts. codeberg_token therefore has to be available at the push event before the commit that makes the pages step run on a push — otherwise that very push is the run that fails.

  • Register the webhook. Repository settings → Webhooks → Add webhook → type Forgejo, with Target URL https://tarcisio.codeberg.page/conan-flake/ — which doubles as the address the site is served from — and Branch filter pages. This is what tells git-pages to pull the branch when it is pushed.
  • Do not read a failed test delivery as a broken setup. The “Test delivery” button fails by design; Codeberg’s own documentation says so. Verify by pushing the branch and loading the site instead.
  • Create the push credential. A Codeberg access token with write access to this repository, belonging to the account the pipeline pushes as (tarcisio, or whatever PAGES_USER in scripts/publish-pages-ci.sh names), stored as a secret named exactly codeberg_token on this repository’s Woodpecker project. .woodpecker/pages.yml reads it, and publishes nothing while it is empty.
  • Allow that secret at both events the pipeline runs on. Open the secret and tick push and manual under “Available at the following events”. Woodpecker offers a secret only to a run whose event the secret lists, and a new secret lists push, tag and deployment — so manual has to be added, and push has to be left ticked. It resolves secrets while compiling the workflow, before anything runs, so a missing event does not fail a step: it fails the whole run, with secret "codeberg_token" is not allowed to be used with pipeline event "push" (or "manual"). This is the one step of this checklist that cannot be taken from a checkout, and the one to take before the commit that turns publishing on, or that very push is the run that fails.
  • Publish once, with just docs-publish from a checkout. That first run is what creates the pages branch, and it uses your own push credentials rather than the secret.
  • Publish from CI on demand. Once codeberg_token exists and allows manual, run the pages pipeline of the main branch from Woodpecker’s interface: that publishes the site, with no commit to make. This is still how the site is republished when the sources did not change.
  • Let CI publish on every change. .woodpecker/pages.yml has a single step, pages, which runs on - event: [push, manual]: a push to main touching the paths the workflow filters on publishes the site, and so does a run started by hand. There is no second, tokenless step beside it — on a push that one would run the publishing wrapper again without a credential and announce that nothing was published next to a successful publication. What keeps unrelated pushes from publishing is the workflow’s own when, which was already filtering on main and on the site’s sources. The ordering matters: the codeberg_token secret has to allow the push event before the commit that makes this change lands, or that push is compiled with a secret it may not read and fails before it starts.
  • Verify. Load https://tarcisio.codeberg.page/conan-flake/; content can take a few minutes to refresh. If it does not appear, ask git-pages what it deployed, with curl https://tarcisio.codeberg.page/conan-flake/.git-pages/manifest.json — the manifest names the repository, the branch and the commit it served the site from.

A path the site does not carry is answered with the site’s own 404.html, which mdBook generates at the root of the output and links back into the sub-path the site is built for (site-url in docs/book.toml).

Note

.domains files are obsolete: git-pages authorises custom domains through DNS TXT records instead, and a codeberg.page sub-path site needs neither.

References

Projects

This project is heavily based on haskell-flake, from which it takes its overall structure.

It’s also influenced, indebted by the following projects in a number of ways:

It goes without saying that these proejects don’t have anything to do with conan-flake — all wrong design decisions taken on the present scope are on our own account.

Tutorials

A good overview of the Nix module system is on nix.dev:

specially the second part:

As for the standard environment, it’s worth emphasizing the already mentioned:

Docs

A good source of information is Nixpkgs Reference Manual:

The conan-flake options themselves are published, generated from the module, at the conan-flake option reference — see also the Conan documentation for the configuration files those options render.

Revision history for conan-flake

0.11.0 (Aug 18, 2026)

Documentation

  • The project’s documentation is now a site, published at https://tarcisio.codeberg.page/conan-flake/ and written in mdBook under docs/: a chapter per integration style (getting started, flake-parts, devenv, standalone with evalConanConfig and submoduleWith, LLVM/CUDA toolchains), plus templates, contributing, references and this revision history. It is built by conan-flake.lib.packages.docs (just docs, just docs-serve), asserted over by one check per requirement in nix flake check ./dev, and published to Codeberg Pages by scripts/publish-pages.sh (just docs-publish, .woodpecker/pages.yml).

  • README.md is now a pointer at that site: what conan-flake is, one embedded configuration example, how to instantiate a template, a link per chapter, and the option reference. Every topic it used to carry is on the site; nothing was dropped. Its command-output blocks moved there with the prose, so mdsh is pointed at the site’s sources alone and no longer runs over README.md (embedmd still does, for the one sample it kept).

  • The site is now published by CI on every change to its sources on main: the pages step of .woodpecker/pages.yml runs on a push as well as on demand, and the tokenless step that used to keep such a push green while announcing that nothing was published is gone. The workflow’s existing branch and path filters are what keep unrelated pushes from publishing, and a manual run still republishes the site without a commit. The codeberg_token secret has to be available at Woodpecker’s push event for this, since secrets are resolved while the workflow is compiled; the activation checklist in the contributing chapter says so. For the same reason a fork now has to work through that checklist before its own pages workflow compiles at all, rather than getting a green run that announces that nothing was published.

0.10.0 (Aug 13, 2026)

Bug Fixes

  • profiles.<name>.buildEnv and profiles.<name>.runEnv are now merged with the conan-flake defaults and rendered from the final profile state, like every other profile section. They were the only two sections rendered straight from the profile’s own values, which silently exempted them from the defaults merging and from the null-removal marker. Added the matching defaults.profiles.buildEnv and defaults.profiles.runEnv options (empty by default). An entry replaces the default entry carrying the same name, and setting its value to null removes that default entry; the merged defaults keep their relative order and come first. Rendered profiles are unchanged for configurations that set no environment defaults.

  • Removed references to proactive from claude.code.agents.* (this property is going to be deprecated).

Improvements

  • Updated default Conan package to 2.31.2 version
  • Added profiles.<name>.options, profiles.<name>.toolRequires, profiles.<name>.replaceRequires, profiles.<name>.replaceToolRequires and profiles.<name>.platformRequires options, rendering the Conan profile [options], [tool_requires], [replace_requires], [replace_tool_requires] and [platform_requires] sections.
  • Added the matching defaults.profiles.* options (empty by default), so every profile section can be given configuration-wide defaults and removed per profile by assigning null to an entry.

Breaking Changes

  • Flattened the Conan profile [settings] section into a single attribute set, removing the compiler/_ split:

    • profiles.<name>.settings.compiler.* and profiles.<name>.settings._.* become profiles.<name>.settings.*;
    • final.profiles.<name>.settings.compiler.* and final.profiles.<name>.settings._.* become final.profiles.<name>.settings.*;
    • defaults.profiles.settings.compiler.* and defaults.profiles.settings._.* become defaults.profiles.settings.*.

    There is no alias and no deprecation period: the new settings option is a free-form attribute set that must accept an entry literally named compiler, so the old declared compiler sub-option cannot coexist with it at the same path. To migrate, merge the two sets into one, keeping the entry names exactly as Conan spells them (compiler, compiler.cppstd, compiler.libcxx, compiler.version, arch, build_type, os, …). null still removes the corresponding default. For example, settings.compiler."compiler.cppstd" = "17"; settings._.build_type = "Release"; becomes settings."compiler.cppstd" = "17"; settings.build_type = "Release";.

    The top-level settings.compiler option (the settings_user.yml producer) is a different, unrelated option and is not affected.

Notes

  • dev/flake.lock is now committed. The development flake declared its inputs by branch (nixpkgs-unstable, devenv-nixpkgs/rolling, and the unpinned flake-parts, git-hooks, devenv, treefmt-nix, nix2container and mk-shell-bin) with no lockfile, so the Woodpecker dev step resolved whatever each of them happened to point at when it ran, and two runs of the same commit could build different closures. Refresh the lock deliberately with nix flake update ./dev. This affects the development environment only: nothing under nix/ is involved, and conan-flake consumers are unaffected.

  • Generated Conan profile files now emit the [settings] section as a single alphabetically ordered run of entries instead of two consecutive groups (non-compiler entries first, then the compiler* ones). Anyone diffing generated profile files will see os= move past the compiler* entries; the set of rendered lines is unchanged, and Conan parses [settings] into a dictionary, so intra-section order carries no meaning.

  • The README.md command-output blocks are regenerated against this release, with examples/standalone-submodule-with/default.nix’s fetchGit rev bumped to it and mdsh no longer excluded from README.md in dev/treefmt.nix. They now show the ten profile sections and the [settings] entries in one alphabetically ordered run: the same rendering change described above, observed end to end through a real Conan profile.

  • Generated Conan profile files now contain all ten sections, ordered as [settings], [options], [tool_requires], [buildenv], [runenv], [conf], [replace_requires], [replace_tool_requires], [platform_requires] and [platform_tool_requires]. Anyone diffing generated configuration files will see the new (empty) sections and the changed section order.

0.9.0 (Aug 05, 2026)

Improvements

  • Added support for multiple Conan profiles (profiles.<name>), each one rendered as a config/profiles/<name> Conan profile and linked into ${configLocal}/profiles/.
  • Added profiles.<name>.name option to override the profile name.

Breaking Changes

  • Moved profiles.* options under profiles.<name>.* (profiles.X becomes profiles.default.X).
  • Moved final.profiles.* options under final.profiles.<name>.* (final.profiles.X becomes final.profiles.default.X).

Notes

  • Until this release lands on main and the conan-flake pins used by the examples are bumped (examples/standalone-submodule-with/default.nix’s fetchGit rev, and the unlocked flake inputs of the other examples), do not run treefmt/mdsh against README.md: the pinned revisions still expose the old profiles.* interface, so the migrated examples fail to evaluate and mdsh empties the README.md command-output blocks. The committed README.md is the correct post-release state.

0.8.1 (Jul 31, 2026)

Bug Fixes

  • Fix autowiring of packages outputs.

Improvements

  • Added local package infrastructure.
  • Added devenv project development integration (under ./dev/).

0.8.0 (Jul 29, 2026)

Improvements

  • Added nix/packages/conan/package.nix to track Conan releases and tweak Conan CLI.
  • Redirected the output of all conan remote commands to stderr.

Breaking Changes

  • Set nix/packages/conan/package.nix as default Conan package.

0.7.0 (Jul 21, 2026)

Improvements

  • Silence noisy pushd/popd during shell activation.
  • Added profile-show-wrapper.
  • Flush profile-show-wrapper output to avoid buffering issues.
  • Added pnameFromStdenvCc and versionFromStdenvCc utility functions.
  • Added global.conf support.
  • Default core.graph:compatibility_mode to optimized.

0.6.1 (Jul 07, 2026)

Improvements

  • Added create-lock-install-wrapper.

0.6.0 (Jul 07, 2026)

Improvements

  • Added support to shared Conan home directory.
  • Added wrapping infrastructure.

0.5.1 (Jun 30, 2026)

Bug Fixes

  • Fix exposing of lib utility functions for flake-parts module integration.

0.5.0 (Jun 29, 2026)

Improvements

  • Add generators option to conan-flake.
  • Refactored and improved environment variable handling:
    • CONAN_FLAKE_ROOT: Root directory of the configuration.
    • CONAN_FLAKE_HOME: If there’s a homeDirectory in the configuration, it will be appended to CONAN_FLAKE_ROOT and used as the home directory.
    • CONAN_FLAKE_CONFIG: $CONAN_FLAKE_HOME/${configLocal}
    • CONAN_HOME: $CONAN_FLAKE_HOME/${conanHome}

Breaking Changes

  • Refactored lib interface.

0.4.0 (Jun 13, 2026)

Bug Fixes

  • Fixed flake-parts docs: added missing defaultText for defaults.devShell.tools option.
  • Fixed treefmt’s project root configuration of flake-parts test.
  • Excluded ./examples/devenv-module/devenv.nix from dev treefmt settings.
  • Fixed handling of root configuration path when setting local recipe index repos.
  • Set info.configRoot option.
  • Fixed tests to use grep -F.

Improvements

  • Improved docs on devenv integration.
  • Added tests on overriding defaults.
  • Trimmed embedded snippets in README (using veggiemonk’s embedmd’s PR: https://github.com/veggiemonk/embedmd/tree/feat/issue-47-directive-options).
  • Added devenv integration example featuring local-recipe-index remote.
  • Added conf option (to compose profiles [conf] section).
  • Added autoWire option (initially supporting only devShells and mapping only the configuration).
  • Added buildEnv option (to compose profiles [buildenv] section).
  • Added runEnv option (to compose profiles [runenv] section).
  • Added final.devShell.tools option to map the final state of devShell.tools after defaults resolution.
  • Added CMake by default to devShell.tools.
  • Added a defaults.profiles.platformToolRequires option and set a cmake attribute by default depending whether CMake is a required tool or not.
  • conan.stdenv.cc added as a default tool.
  • Added final.profiles.platformToolRequires option.
  • Added final.settings.compiler, defaults.settings.compiler and settings.compiler options using infuse to merge and filterAttrs to filter out nulled attributes.
  • Added profiles.settings, final.profiles.settings and defaults.profiles.settings options.
  • Added defaults for arch, build_type and os in defaults.profiles.settings.
  • Added defaults and finals for profiles.conf.
  • Added profiles.settings.compiler, final.profiles.settings.compiler and defaults.profiles.settings.compiler options.
  • Whenever a LLVM toolchain is detected (with libcxx):
    • Set defaults.profiles.conf."tools.build:compiler_executables" appropriately.
    • Set defaults.profiles.settings.compiler."compiler.libcxx" to "libc++".

Breaking Changes

  • Removed default info output command.
  • Removed automatic mapping of config.conan.outputs.packages.
  • Removed platformToolRequires option (profiles.platformToolRequires must be used instead).
  • Removed the buildEnv, runEnv and conf options (keep only those in the profiles namespace).
  • Removed settings.base option.
  • Removed arch, buildType and os options; the arch, build_type and os profiles.settings must be used instead respectively.
  • Removed compiler, compilerCppStd, compilerLibCxx and compilerVersion options. The following should be used as a replacement (only if necessary):
    • profiles.settings.compiler."compiler";
    • profiles.settings.compiler."compiler.cppstd";
    • profiles.settings.compiler."compiler.libcxx";
    • profiles.settings.compiler."compiler.version".

0.3.1 (May 29, 2026)

Improvements

  • Added release.yml workflow.
  • Improved documentation.

0.3.0 (May 28, 2026)

Improvements

  • Added defaults option to track defaults (initially, this contains only defaults.devShell.tools).
  • Improved tests.

Breaking Changes

  • Renamed the devShell.package option to devShell.tools and changed its type to package set.

0.2.0 (May 25, 2026)

Breaking Changes

  • Removed the devShell.apple.sdk option.

0.1.0 (May 05, 2026)