From c905deaa146dcd285b5b6a0edf0d569c52ea1e5a Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Wed, 6 Jun 2018 14:28:27 -0300 Subject: builtin: auto-detect modules when build.modules (or build!) is absent --- spec/build_spec.lua | 42 ++++++++++++++++++ spec/fixtures/autodetect/bla.lua | 1 + src/luarocks/build.lua | 8 +++- src/luarocks/build/builtin.lua | 86 ++++++++++++++++++++++++++++++++++++- src/luarocks/cmd/write_rockspec.lua | 56 +----------------------- 5 files changed, 137 insertions(+), 56 deletions(-) create mode 100644 spec/fixtures/autodetect/bla.lua diff --git a/spec/build_spec.lua b/spec/build_spec.lua index b703478e..af2dfe38 100644 --- a/spec/build_spec.lua +++ b/spec/build_spec.lua @@ -269,6 +269,48 @@ describe("LuaRocks build tests #integration", function() assert.truthy(run.luarocks_bool("build " .. rockspec)) assert.is.truthy(run.luarocks("show a_rock")) end) + + it("'builtin' detects lua files if modules are not given", function() + local rockspec = "autodetect-1.0-1.rockspec" + test_env.write_file(rockspec, [[ + rockspec_format = "3.0" + package = "autodetect" + version = "1.0-1" + source = { + url = "file://]] .. testing_paths.fixtures_dir .. [[/autodetect/bla.lua" + } + description = { + summary = "An example rockspec", + } + dependencies = { + "lua >= 5.1" + } + build = { + } + ]], finally) + assert.truthy(run.luarocks_bool("build " .. rockspec)) + assert.match("bla.lua", run.luarocks("show autodetect")) + end) + + it("'builtin' detects lua files if build is not given", function() + local rockspec = "autodetect-1.0-1.rockspec" + test_env.write_file(rockspec, [[ + rockspec_format = "3.0" + package = "autodetect" + version = "1.0-1" + source = { + url = "file://]] .. testing_paths.fixtures_dir .. [[/autodetect/bla.lua" + } + description = { + summary = "An example rockspec", + } + dependencies = { + "lua >= 5.1" + } + ]], finally) + assert.truthy(run.luarocks_bool("build " .. rockspec)) + assert.match("bla.lua", run.luarocks("show autodetect")) + end) end) describe("#mock external dependencies", function() diff --git a/spec/fixtures/autodetect/bla.lua b/spec/fixtures/autodetect/bla.lua new file mode 100644 index 00000000..a5647075 --- /dev/null +++ b/spec/fixtures/autodetect/bla.lua @@ -0,0 +1 @@ +return {} diff --git a/src/luarocks/build.lua b/src/luarocks/build.lua index ac4ecfad..0cfbccd7 100644 --- a/src/luarocks/build.lua +++ b/src/luarocks/build.lua @@ -353,7 +353,13 @@ function build.build_rockspec(rockspec, opts) assert(opts:type() == "build.opts") if not rockspec.build then - return nil, "Rockspec error: build table not specified" + if rockspec:format_is_at_least("3.0") then + rockspec.build = { + type = "builtin" + } + else + return nil, "Rockspec error: build table not specified" + end end if not rockspec.build.type then diff --git a/src/luarocks/build/builtin.lua b/src/luarocks/build/builtin.lua index 41cc31b0..4ff59f8b 100644 --- a/src/luarocks/build/builtin.lua +++ b/src/luarocks/build/builtin.lua @@ -10,6 +10,85 @@ local util = require("luarocks.util") local cfg = require("luarocks.core.cfg") local dir = require("luarocks.dir") +local function autoextract_libs(external_dependencies, variables) + if not external_dependencies then + return nil, nil, nil + end + local libs = {} + local incdirs = {} + local libdirs = {} + for name, data in pairs(external_dependencies) do + if data.library then + table.insert(libs, data.library) + table.insert(incdirs, variables[name .. "_INCDIR"]) + table.insert(libdirs, variables[name .. "_LIBDIR"]) + end + end + return libs, incdirs, libdirs +end + +do + local function get_cmod_name(file) + local fd = io.open(dir.path(fs.current_dir(), file), "r") + if not fd then return nil end + local data = fd:read("*a") + fd:close() + return (data:match("int%s+luaopen_([a-zA-Z0-9_]+)")) + end + + local luamod_blacklist = { + test = true, + tests = true, + } + + function builtin.autodetect_modules(libs, incdirs, libdirs) + local modules = {} + local copy_directories + + local prefix = "" + for _, parent in ipairs({"src", "lua"}) do + if fs.is_dir(parent) then + fs.change_dir(parent) + prefix = parent.."/" + break + end + end + + for _, file in ipairs(fs.find()) do + local luamod = file:match("(.*)%.lua$") + if luamod and not luamod_blacklist[luamod] then + modules[path.path_to_module(file)] = prefix..file + else + local cmod = file:match("(.*)%.c$") + if cmod then + local modname = get_cmod_name(file) or path.path_to_module(file:gsub("%.c$", ".lua")) + modules[modname] = { + sources = prefix..file, + libraries = libs, + incdirs = incdirs, + libdirs = libdirs, + } + end + end + end + + for _, directory in ipairs({ "doc", "docs", "samples", "tests" }) do + if fs.is_dir(directory) then + if not copy_directories then + copy_directories = {} + end + table.insert(copy_directories, directory) + end + end + + if prefix ~= "" then + fs.pop_dir() + end + + return modules, copy_directories + end +end + --- Run a command displaying its execution on standard output. -- @return boolean: true if command succeeds (status code 0), false -- otherwise. @@ -140,7 +219,12 @@ function builtin.run(rockspec) local libdir = path.lib_dir(rockspec.name, rockspec.version) if not build.modules then - return nil, "Missing build.modules table" + if rockspec:format_is_at_least("3.0") then + local libs, incdirs, libdirs = autoextract_libs(rockspec.external_dependencies, rockspec.variables) + build.modules = builtin.autodetect_modules(libs, incdirs, libdirs) + else + return nil, "Missing build.modules table" + end end for name, info in pairs(build.modules) do local moddir = path.module_to_path(name) diff --git a/src/luarocks/cmd/write_rockspec.lua b/src/luarocks/cmd/write_rockspec.lua index 36beffd0..b4007e85 100644 --- a/src/luarocks/cmd/write_rockspec.lua +++ b/src/luarocks/cmd/write_rockspec.lua @@ -1,11 +1,11 @@ local write_rockspec = {} +local builtin = require("luarocks.build.builtin") local cfg = require("luarocks.core.cfg") local dir = require("luarocks.dir") local fetch = require("luarocks.fetch") local fs = require("luarocks.fs") -local path = require("luarocks.path") local persist = require("luarocks.persist") local rockspecs = require("luarocks.rockspecs") local type_rockspec = require("luarocks.type.rockspec") @@ -172,31 +172,8 @@ local function check_license() return nil, data end -local function get_cmod_name(file) - local fd = open_file(file) - if not fd then return nil end - local data = fd:read("*a") - fd:close() - return (data:match("int%s+luaopen_([a-zA-Z0-9_]+)")) -end - -local luamod_blacklist = { - test = true, - tests = true, -} - local function fill_as_builtin(rockspec, libs) rockspec.build.type = "builtin" - rockspec.build.modules = {} - local prefix = "" - - for _, parent in ipairs({"src", "lua"}) do - if fs.is_dir(parent) then - fs.change_dir(parent) - prefix = parent.."/" - break - end - end local incdirs, libdirs if libs then @@ -207,37 +184,8 @@ local function fill_as_builtin(rockspec, libs) libdirs[#libdirs+1] = "$("..upper.."_LIBDIR)" end end - - for _, file in ipairs(fs.find()) do - local luamod = file:match("(.*)%.lua$") - if luamod and not luamod_blacklist[luamod] then - rockspec.build.modules[path.path_to_module(file)] = prefix..file - else - local cmod = file:match("(.*)%.c$") - if cmod then - local modname = get_cmod_name(file) or path.path_to_module(file:gsub("%.c$", ".lua")) - rockspec.build.modules[modname] = { - sources = prefix..file, - libraries = libs, - incdirs = incdirs, - libdirs = libdirs, - } - end - end - end - for _, directory in ipairs({ "doc", "docs", "samples", "tests" }) do - if fs.is_dir(directory) then - if not rockspec.build.copy_directories then - rockspec.build.copy_directories = {} - end - table.insert(rockspec.build.copy_directories, directory) - end - end - - if prefix ~= "" then - fs.pop_dir() - end + rockspec.build.modules, rockspec.build.copy_directories = builtin.autodetect_modules(libs, incdirs, libdirs) end local function rockspec_cleanup(rockspec) -- cgit v1.2.3-55-g6feb