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

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 = "611c64cbf71b05bdd916cb45dfedd396f1ae10da";
      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.