modules/performance/byte-compile-lua: support compiling directories and fixed-output derivations#4151
modules/performance/byte-compile-lua: support compiling directories and fixed-output derivations#4151stasjok wants to merge 3 commits into
Conversation
This reverts 16e3c17. `luarocks write-rockspec` command generates invalid rockspec file. This commit uses a manually crafted rockspec file.
Fetchers doesn't execute postFixup hooks, therefore byteCompileLuaHook doesn't work. And even if it would work, fetchers are fixed-output derivation which has outputHash known beforehand. We can't override such derivations using byteCompileLuaDrv. This commit uses byteCompileLuaFile for fixed-output derivations.
This commit adds support for byte-compiling path directories. Only paths like ./dir are supported. Directory derivations e.g. fetchers are not supported.
I was recently considering a new approach to byte-compiling extraFiles, which might tie in nicely with another potential refactor to demote Essentially, we add (psudocode): passthru.byteCompiled = symlinkJoin {
paths = [ finalAttrs.finalPackage ];
postBuild = ''
lua_files=("$out"/**/*.lua)
byte_compile_and_replace "''${lua_files[@]}"
'';
}Alternatively, instead of a bash array of lua symlinks, we could:
Or whatever variation on the concept that ends up working best. Once we have this |
MattSturgeon
left a comment
There was a problem hiding this comment.
Thanks for addressing these issues!
On my initial read through, I don't see any obvious technical issues with the changes. However, I do feel like the issues we're needing to solve highlight how we could benefit from a simpler, more delayed approach.
I'd appreciate you're thoughts on my above concept; whether you think the concept is better than the current architecture; whether you'd like to implement something like that; whether you'd like to continue with this PR (first/instead); whether you'd be interested in reviewing if someone else worked on the idea; etc
| # `text`, not from intermediate `source` | ||
| if lib.isDerivation config.source && !config.source ? outputHash then | ||
| # Source is a derivation (not fixed-output) | ||
| builders.byteCompileLuaDrv config.source |
There was a problem hiding this comment.
Fetchers doesn't execute postFixup hooks, therefore byteCompileLuaHook
doesn't work. And even if it would work, fetchers are fixed-output
derivation which has outputHash known beforehand. We can't override such
derivations using byteCompileLuaDrv.
This commit uses byteCompileLuaFile for fixed-output derivations.
Looking at this with fresh eyes, I'm questioning why we are overriding derivations at all; it's usually better to wrap them (e.g. with symlinkJoin) and then mess with the outputs in a fresh derivation instead of rebuilding the original derivation.
The exception being when the wrapped derivation and the wrapper derivation essentially need to do the same compilation step anyway.
I'm not keen on how we end up handling paths, FODs, drvs, files, directories, (etc) differently from one and other.
My proposal in #4151 (comment) would mean dropping the finalSource option entirely and handling this much later, in a wrapper of build.extraFiles.
| builtins.isPath config.source | ||
| && lib.filesystem.pathIsDirectory config.source | ||
| && builtins.any (lib.hasSuffix ".lua") (lib.filesystem.listFilesRecursive config.source) |
There was a problem hiding this comment.
This commit adds support for byte-compiling path directories. Only paths
like./dirare supported. Directory derivations e.g. fetchers are not
supported.
Again, my instinct is that delaying byte-comp until during/after building build.extraFiles, as per #4151 (comment), would massively simplify this. We wouldn't need any eval-time inspection. Instead all inspection of "symlink, file, or directory" would be done in the build script.
There is one caveat. I guess if the handling of runtimepath is changed (some of the discussion was in #1920), it could be the thing. For me it doesn't matter whether it There is another thing. The code need to be much smarter than Lines 129 to 137 in 03a6382
Originally this was implemented like this for optimization. In the build time, overridden derivation needs to be built once. With symlink it needs to be built twice: one derivation for For this reason I wanted to determine if byte-compilation is actually needed during evaluation (also as a precaution, who knows what can be in
Working on this, I already thought that the current approach is limiting. I don't like this if monstrosity. And it was already an idea that we'll have to switch to build-time byte-compilation at some point. I opted to the most direct/simple approach for now. To move forward, e.g. supporting byte-compilation of any directory-like path/string/derivation, I think the only option is to write a new
finalSource =
# Byte compile lua files if performance.byteCompileLua option is enabled
if byteCompileLua then
builders.byteCompileLuaDrv (
pkgs.stdenvNoCC.mkDerivation {
name = derivationName;
src = config.source;
phases = "installPhase fixupPhase";
installPhase = ''
if [ -d $src ]; then
cp -r --no-preserve=mode $src $out
else
cp --no-preserve=mode $src $out
fi
'';
}
)
else
config.source;
I don't think there is much difference at what point it's compiled. Originally I searched for the single place to add my changes, so all other places would work without changes. Same for passthru attr/another option. I don't particularly favor one "storage" for the compiled derivation over another.
I think I won't be doing a big refactoring. If
Currently I think this PR is a simple fix. The thing I'm not sure about is this complicated if statement. It can be dropped in favor of the code above with the potential of improving/rewriting of |
Yes, I hadn't thought about this when initially considering the idea, but quickly discovered it when experimenting locally. I think there's a few ways to handle this:
Yes, I'd already considered this but wanted to go over high-level concepts before discussing details 🙂 My idea would be to recursively copy the base drv's output tree into the wrapper's This could work as a new builder in
This makes sense in the typical case, where
Is that something you'd like to explore here or in future work?
Sure. I'll consider looking into it after this PR then, if it's still bothering me by then. |
To be honest, I'm fine with it as is. But if you think that the logic became too complicated, I can change it to something like above. Though I'm not a fan if all non-lua files will be symlinks (since most files are generated from |
This PR:
modules/performancetests disabled in [main] Update flake.lock & generated files #3562fetchurlNote, that for now it supports only simple directories like
./dir. It doesn't support derivations, likefetchFromGitHub.