From 9474ce916acd721deb89c832c78f20e14784ee5c Mon Sep 17 00:00:00 2001 From: Stanislav Asunkin <1353637+stasjok@users.noreply.github.com> Date: Sat, 10 May 2025 22:07:02 +0300 Subject: [PATCH] modules/performance: ensure all lua dependencies are byte-compiled This commit replaces custom lua plugins in tests with shared stub plugins from utils module. After this change the test has started to fail. Debugging this issue I found out that dependencies of plugins weren't processed. This commit improves the test assertion to detect duplicated dependencies in this case and fixes the underlying issue by also processing dependencies. --- .../plugins/byte-compile-lua-lib.nix | 37 ++++++--- .../modules/performance/byte-compile-lua.nix | 83 +++++++++---------- 2 files changed, 65 insertions(+), 55 deletions(-) diff --git a/modules/top-level/plugins/byte-compile-lua-lib.nix b/modules/top-level/plugins/byte-compile-lua-lib.nix index b511ec95..0d50cf6b 100644 --- a/modules/top-level/plugins/byte-compile-lua-lib.nix +++ b/modules/top-level/plugins/byte-compile-lua-lib.nix @@ -9,20 +9,35 @@ let builders = lib.nixvim.builders.withPkgs pkgs; inherit (import ./utils.nix lib) mapNormalizedPlugins; + luaPackages = pkgs.neovim-unwrapped.lua.pkgs; + + # Applies a function to the derivation, but only if it's a lua module, + # otherwise returns it as is + mapLuaModule = f: drv: if luaPackages.luaLib.hasLuaModule drv then f drv else drv; + # Byte-compile only lua dependencies byteCompileDeps = drv: - drv.overrideAttrs ( - prev: - lib.optionalAttrs (prev ? propagatedBuildInputs) { - propagatedBuildInputs = map byteCompile prev.propagatedBuildInputs; - } - ); + lib.pipe drv [ + ( + drv: + if drv.dependencies or [ ] != [ ] then + drv.overrideAttrs { dependencies = map byteCompileDeps drv.dependencies; } + else + drv + ) + ( + drv: + if drv.propagatedBuildInputs or [ ] != [ ] then + drv.overrideAttrs { propagatedBuildInputs = map byteCompile drv.propagatedBuildInputs; } + else + drv + ) + # 'toLuaModule' updates requiredLuaModules attr + # It works without it, but update it anyway for consistency + (mapLuaModule luaPackages.toLuaModule) + ]; # 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 - ); + byteCompile = drv: byteCompileDeps (mapLuaModule builders.byteCompileLuaDrv drv); in mapNormalizedPlugins byteCompileDeps diff --git a/tests/test-sources/modules/performance/byte-compile-lua.nix b/tests/test-sources/modules/performance/byte-compile-lua.nix index 2a4e78ab..40c3c01b 100644 --- a/tests/test-sources/modules/performance/byte-compile-lua.nix +++ b/tests/test-sources/modules/performance/byte-compile-lua.nix @@ -1,5 +1,7 @@ -{ pkgs, ... }: +{ lib, pkgs, ... }: let + pluginStubs = pkgs.callPackage ../../../utils/plugin-stubs.nix { }; + isByteCompiledFun = # lua '' -- LuaJIT bytecode header is: ESC L J version @@ -325,70 +327,63 @@ in # performance.byteCompileLua.luaLib for propagatedBuildInputs lua-lib-propagated-build-inputs = - { - config, - lib, - pkgs, - ... - }: + { config, ... }: { 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 ]) - ]; + extraPlugins = pluginStubs.pluginPack; extraConfigLuaPost = '' + ${pluginStubs.pluginChecks} + ${isByteCompiledFun} - -- Plugins themselves are importable - require("lz.n") - require("cmp") + -- Lua modules are byte-compiled + ${lib.concatMapStringsSep "\n" ( + name: "test_lualib_file(require('${name}').name, true)" + ) pluginStubs.libNames} - -- 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) + -- Plugins themselves are not byte-compiled + ${lib.concatMapStringsSep "\n" ( + name: "test_rtp_file('lua/${name}/init.lua', false)" + ) pluginStubs.pluginNames} ''; assertions = let - requiredLuaModules = lib.pipe config.extraPlugins [ - (builtins.catAttrs "requiredLuaModules") - builtins.concatLists + # Get plugins with all dependencies + getDeps = drv: [ drv ] ++ builtins.concatMap getDeps drv.dependencies or [ ]; + plugins = lib.pipe config.build.plugins [ + (builtins.catAttrs "plugin") + (builtins.concatMap getDeps) lib.unique ]; + # Collect both propagatedBuildInputs and requiredLuaModules to one list + getAllRequiredLuaModules = lib.flip lib.pipe [ + ( + drvs: builtins.catAttrs "propagatedBuildInputs" drvs ++ builtins.catAttrs "requiredLuaModules" drvs + ) + (builtins.concatMap (deps: deps ++ getAllRequiredLuaModules deps)) + lib.unique + ]; + allRequiredLuaModules = getAllRequiredLuaModules plugins; in [ - # Ensure that propagatedBuildInputs are byte-compiled recursively - # by checking that every library is present only once + # Ensure that lua dependencies are byte-compiled recursively + # by checking that every library is present only once. + # If there are two different derivations with the same name, + # then one of them probably isn't byte-compiled. { - assertion = lib.allUnique (map lib.getName requiredLuaModules); + assertion = lib.allUnique (map lib.getName allRequiredLuaModules); 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. + Expected propagatedBuildInputs and requiredLuaModules of all plugins to have unique names. + Got the following derivations:''\n${lib.concatLines allRequiredLuaModules} + Possible reasons: + - not all dependencies are overridden the same way + - requiredLuaModules are not updated along with propagatedBuildInputs ''; } ];