Those two ‘import’s are really just two different things with similar name.
Nix’s builtins.import
really just loads and inserts a Nix expression from a different file in the place where it is called – you could just replace paste the file contents instead of the import
call and it should work the same (modulo file path resolution).
Contrary to local nature of the Nix built-in, imports
attribute of NixOS module makes the module system add modules to the list of modules to merge into the global namespace. It also supports wider range of arguments, not just paths, as described above.
But you could decide to sidestep the module system imports
and use Nix primitives for loading a module. For example, instead of
{ pkgs, lib, config, options, ...}@args:
{
imports = [
./quxinator.nix
];
config = {
foo.bar = true;
};
}
you could do something like
{ pkgs, lib, config, options, ...}@args:
lib.recursiveUpdate { # BEWARE!!!
config = {
foo.bar = true;
};
}
(import ./quxinator.nix args)
The result might end up the same. Or it might fail horribly – especially if both modules declare overlapping options.
You might try to make merging the modules module-aware:
{ pkgs, lib, config, options, ...}@args:
lib.mkMerge [ # Probably safer but still BEWARE!!!
{
config = {
foo.bar = true;
};
}
(import ./quxinator.nix args)
]
but I give you no warranty and there is no reason to avoid using the module system’s imports
feature.