diff --git a/modules/top-level/plugins/byte-compile-lua-lib.nix b/modules/top-level/plugins/byte-compile-lua-lib.nix new file mode 100644 index 00000000..b511ec95 --- /dev/null +++ b/modules/top-level/plugins/byte-compile-lua-lib.nix @@ -0,0 +1,28 @@ +/* + Byte compiling of lua dependencies of normalized plugin list + + Inputs: List of normalized plugins + Outputs: List of normalized plugins with all the propagatedBuildInputs byte-compiled +*/ +{ lib, pkgs }: +let + builders = lib.nixvim.builders.withPkgs pkgs; + inherit (import ./utils.nix lib) mapNormalizedPlugins; + + # Byte-compile only lua dependencies + byteCompileDeps = + drv: + drv.overrideAttrs ( + prev: + lib.optionalAttrs (prev ? propagatedBuildInputs) { + propagatedBuildInputs = map byteCompile prev.propagatedBuildInputs; + } + ); + # Byte-compile derivation (but only if it's a lua module) and its dependencies + byteCompile = + drv: + byteCompileDeps ( + if pkgs.luaPackages.luaLib.hasLuaModule drv then builders.byteCompileLuaDrv drv else drv + ); +in +mapNormalizedPlugins byteCompileDeps diff --git a/modules/top-level/plugins/default.nix b/modules/top-level/plugins/default.nix index 33f28beb..b20e98d7 100644 --- a/modules/top-level/plugins/default.nix +++ b/modules/top-level/plugins/default.nix @@ -34,6 +34,9 @@ in shouldCompilePlugins = byteCompileCfg.enable && byteCompileCfg.plugins; byteCompilePlugins = import ./byte-compile-plugins.nix { inherit lib pkgs; }; + shouldCompileLuaLib = byteCompileCfg.enable && byteCompileCfg.luaLib; + byteCompileLuaLib = import ./byte-compile-lua-lib.nix { inherit lib pkgs; }; + shouldCombinePlugins = config.performance.combinePlugins.enable; combinePlugins = import ./combine-plugins.nix { inherit lib pkgs; @@ -47,6 +50,7 @@ in lib.pipe config.extraPlugins ( [ normalizePlugins ] ++ lib.optionals shouldCompilePlugins [ byteCompilePlugins ] + ++ lib.optionals shouldCompileLuaLib [ byteCompileLuaLib ] ++ lib.optionals shouldCombinePlugins [ combinePlugins ] ); }; diff --git a/modules/top-level/plugins/utils.nix b/modules/top-level/plugins/utils.nix index 9afdb1fa..f85b6e49 100644 --- a/modules/top-level/plugins/utils.nix +++ b/modules/top-level/plugins/utils.nix @@ -35,4 +35,7 @@ lib.fix (self: { # Remove dependencies from all plugins in a list removeDeps = map (p: p // { plugin = removeAttrs p.plugin [ "dependencies" ]; }); + + # Apply a map function to each 'plugin' attr of the normalized plugin list + mapNormalizedPlugins = f: map (p: p // { plugin = f p.plugin; }); }) diff --git a/tests/test-sources/modules/performance/byte-compile-lua.nix b/tests/test-sources/modules/performance/byte-compile-lua.nix index a4b88ae0..2a4e78ab 100644 --- a/tests/test-sources/modules/performance/byte-compile-lua.nix +++ b/tests/test-sources/modules/performance/byte-compile-lua.nix @@ -299,7 +299,8 @@ in ''; }; - lua-lib = { + # performance.byteCompileLua.luaLib for extraLuaPackages + lua-lib-extra-lua-packages = { performance.byteCompileLua = { enable = true; luaLib = true; @@ -321,6 +322,77 @@ in test_lualib_file(argparse("test").parse, true) ''; }; + + # performance.byteCompileLua.luaLib for propagatedBuildInputs + lua-lib-propagated-build-inputs = + { + config, + lib, + pkgs, + ... + }: + { + performance.byteCompileLua = { + enable = true; + luaLib = true; + }; + + extraPlugins = + let + inherit (config.package) lua; + setDeps = + drv: deps: + # 'toLuaModule' is used here for updating 'requiredLuaModules' attr + lua.pkgs.luaLib.toLuaModule ( + drv.overrideAttrs { + propagatedBuildInputs = [ lua ] ++ deps; + } + ); + # Add the 'argparse' dependency to the 'say' module + say = setDeps lua.pkgs.say [ lua.pkgs.argparse ]; + in + [ + # 'lz-n' depends on 'say' which itself depends on 'argparse' + (setDeps pkgs.vimPlugins.lz-n [ say ]) + # 'nvim-cmp' depends on 'argparse' + (setDeps pkgs.vimPlugins.nvim-cmp [ lua.pkgs.argparse ]) + ]; + + extraConfigLuaPost = '' + ${isByteCompiledFun} + + -- Plugins themselves are importable + require("lz.n") + require("cmp") + + -- Lua modules are importable and byte compiled + local say = require("say") + test_lualib_file(say.set, true) + local argparse = require("argparse") + test_lualib_file(argparse("test").parse, true) + ''; + + assertions = + let + requiredLuaModules = lib.pipe config.extraPlugins [ + (builtins.catAttrs "requiredLuaModules") + builtins.concatLists + lib.unique + ]; + in + [ + # Ensure that propagatedBuildInputs are byte-compiled recursively + # by checking that every library is present only once + { + assertion = lib.allUnique (map lib.getName requiredLuaModules); + message = '' + Expected requiredLuaModules of all propagatedBuildInputs to have unique names. + Got the following derivations: ${builtins.concatStringsSep ", " requiredLuaModules}. + One possible reason is that not all dependencies are overridden the same way. + ''; + } + ]; + }; } // # Two equal tests, one with combinePlugins.enable = true