From 8eabbb3d205541a33658779dc70dc217d3161ed2 Mon Sep 17 00:00:00 2001 From: Alexei Robyn Date: Thu, 13 Jun 2019 20:53:53 +1000 Subject: [PATCH] buildLuarocksPackage: Several improvements Summary of main changes: - Now makes use of luarocks dependency resolution (builds will fail if rockspec dependencies are unmet) - Renamed argument `external_deps` -> `exernalDeps` and add functionality to handle external dependencies that are multiple-output derivations - Added an `extraVariables` argument for appending to the contents of luarocks config `variables` table - The `rockspecFilename` argument default is now actually used - The `disabled` argument can now be overriden with a less-restrictive check, as it now just sets `meta.broken` instead of throwing an error during eval - The `doCheck` argument is now actually honored if set to `true` --- .../interpreters/lua-5/build-lua-package.nix | 115 +++++++++++++----- 1 file changed, 86 insertions(+), 29 deletions(-) diff --git a/pkgs/development/interpreters/lua-5/build-lua-package.nix b/pkgs/development/interpreters/lua-5/build-lua-package.nix index bc41d86256b2..6a879d12704a 100644 --- a/pkgs/development/interpreters/lua-5/build-lua-package.nix +++ b/pkgs/development/interpreters/lua-5/build-lua-package.nix @@ -28,12 +28,13 @@ name ? "${attrs.pname}-${attrs.version}" , propagatedNativeBuildInputs ? [] # used to disable derivation, useful for specific lua versions +# TODO move from this setting meta.broken to a 'disabled' attribute on the +# package, then use that to skip/include in each lua${ver}Packages set? , disabled ? false # Additional arguments to pass to the makeWrapper function, which wraps # generated binaries. , makeWrapperArgs ? [] -, external_deps ? propagatedBuildInputs ++ buildInputs # Skip wrapping of lua programs altogether , dontWrapLuaPrograms ? false @@ -43,11 +44,19 @@ name ? "${attrs.pname}-${attrs.version}" , passthru ? {} , doCheck ? false -# appended to the luarocks generated config -# in peculiar variables like { EVENT_INCDIR } can be useful to work around -# luarocks limitations, ie, luarocks consider include/lib folders to be subfolders of the same package in external_deps_dirs -# as explained in https://github.com/luarocks/luarocks/issues/766 +# Non-Lua / system (e.g. C library) dependencies. Is a list of deps, where +# each dep is either a derivation, or an attribute set like +# { name = "rockspec external_dependencies key"; dep = derivation; } +# The latter is used to work-around luarocks having a problem with +# multiple-output derivations as external deps: +# https://github.com/luarocks/luarocks/issues/766 +, externalDeps ? lib.unique (lib.filter (drv: !drv ? luaModule) (propagatedBuildInputs ++ buildInputs)) + +# Appended to the generated luarocks config , extraConfig ? "" +# Inserted into the generated luarocks config in the "variables" table +, extraVariables ? "" +# The two above arguments have access to builder variables -- e.g. to $out # relative to srcRoot, path to the rockspec to use when using rocks , rockspecFilename ? "../*.rockspec" @@ -59,44 +68,95 @@ name ? "${attrs.pname}-${attrs.version}" # Keep extra attributes from `attrs`, e.g., `patchPhase', etc. -if disabled -then throw "${name} not supported for interpreter ${lua}" -else let - - deps_dirs= lib.concatStringsSep ", " ( - map (x: "\"${builtins.toString x}\"") external_deps - ); - - # TODO - # - add rocktrees (look at torch-distro.nix/https://github.com/luarocks/luarocks/wiki/Config-file-format) - # - silence warnings - luarocks_config = "luarocksConfig"; + # TODO fix warnings "Couldn't load rockspec for ..." during manifest + # construction -- from initial investigation, appears it will require + # upstream luarocks changes to fix cleanly (during manifest construction, + # luarocks only looks for rockspecs in the default/system tree instead of all + # configured trees) + luarocks_config = "luarocks-config.lua"; luarocks_content = '' local_cache = "" - -- array of strings - external_deps_dirs = { - ${deps_dirs} - } + -- To prevent collisions when creating environments, we install the rock + -- files into per-package subdirectories + rocks_subdir = '${rocksSubdir}' + -- Then we need to tell luarocks where to find the rock files per + -- dependency rocks_trees = { + ${lib.concatStringsSep "\n, " rocksTrees} + } + '' + lib.optionalString lua.pkgs.isLuaJIT '' + -- Luajit provides some additional functionality built-in; this exposes + -- that to luarock's dependency system + rocks_provided = { + jit='${lua.luaversion}-1'; + ffi='${lua.luaversion}-1'; + luaffi='${lua.luaversion}-1'; + bit='${lua.luaversion}-1'; + } + '' + '' + -- For single-output external dependencies + external_deps_dirs = { + ${lib.concatStringsSep "\n, " externalDepsDirs} + } + variables = { + -- Some needed machinery to handle multiple-output external dependencies, + -- as per https://github.com/luarocks/luarocks/issues/766 + ${lib.optionalString (lib.length depVariables > 0) '' + ${lib.concatStringsSep "\n " depVariables}''} + ${extraVariables} } ${extraConfig} ''; + + rocksSubdir = "${attrs.pname}-${version}-rocks"; + + externalDepsDirs = map + (x: "'${builtins.toString x}'") + (lib.filter (lib.isDerivation) externalDeps); + + rocksTrees = lib.imap0 + (i: dep: "{ name = [[dep-${toString i}]], root = '${dep}', rocks_dir = '${dep}/${dep.rocksSubdir}' }") + requiredLuaRocks; + + # Filter out the lua derivation itself from the Lua module dependency + # closure, as it doesn't have a rock tree :) + requiredLuaRocks = lib.filter (d: d ? luaModule) + (lua.pkgs.requiredLuaModules propagatedBuildInputs); + + # Explicitly point luarocks to the relevant locations for multiple-output + # derivations that are external dependencies, to work around an issue it has + # (https://github.com/luarocks/luarocks/issues/766) + depVariables = lib.concatMap ({name, dep}: [ + "${name}_INCDIR='${lib.getDev dep}/include';" + "${name}_LIBDIR='${lib.getLib dep}/lib';" + "${name}_BINDIR='${lib.getBin dep}/bin';" + ]) externalDeps'; + + # example externalDeps': [ { name = "CRYPTO"; dep = pkgs.openssl; } ] + externalDeps' = lib.filter (dep: !lib.isDerivation dep) externalDeps; in toLuaModule ( lua.stdenv.mkDerivation ( -builtins.removeAttrs attrs ["disabled" "checkInputs"] // { +builtins.removeAttrs attrs ["disabled" "checkInputs" "externalDeps"] // { name = namePrefix + name; buildInputs = [ wrapLua lua.pkgs.luarocks ] ++ buildInputs ++ lib.optionals doCheck checkInputs + ++ (map (d: d.dep) externalDeps') ; # propagate lua to active setup-hook in nix-shell propagatedBuildInputs = propagatedBuildInputs ++ [ lua ]; - doCheck = false; + inherit doCheck; + + # @-patterns do not capture formal argument default values, so we need to + # explicitly inherit this for it to be available as a shell variable in the + # builder + inherit rockspecFilename; + inherit rocksSubdir; # enabled only for src.rock setSourceRoot= let @@ -163,23 +223,20 @@ builtins.removeAttrs attrs ["disabled" "checkInputs"] // { nix_debug "ROCKSPEC $rockspecFilename" nix_debug "cwd: $PWD" - $LUAROCKS make --deps-mode=none --tree $out ''${rockspecFilename} - - # to prevent collisions when creating environments - # also added -f as it doesn't always exist - # don't remove the whole directory as - rm -rf $out/lib/luarocks/rocks-${lua.luaversion}/manifest + $LUAROCKS make --deps-mode=all --tree=$out ''${rockspecFilename} runHook postInstall ''; passthru = { inherit lua; # The lua interpreter + inherit externalDeps; } // passthru; meta = with lib.maintainers; { platforms = lua.meta.platforms; # add extra maintainer(s) to every package maintainers = (meta.maintainers or []) ++ [ ]; + broken = disabled; } // meta; }))