From 9734fd3fec39aa53d52ef8fb45ef974ac27ecf89 Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Mon, 25 Jun 2018 16:22:35 -0300 Subject: build: resolve LUALIB at runtime Move logic from install.bat for resolving LUALIB (the name of the Lua library) reusing the standard LuaRocks functionality for finding external dependency libraries. --- src/luarocks/build.lua | 10 +- src/luarocks/core/cfg.lua | 5 +- src/luarocks/deps.lua | 301 +++++++++++++++++++++++++--------------------- 3 files changed, 178 insertions(+), 138 deletions(-) diff --git a/src/luarocks/build.lua b/src/luarocks/build.lua index 2d76ba05..a609615e 100644 --- a/src/luarocks/build.lua +++ b/src/luarocks/build.lua @@ -118,6 +118,14 @@ local function process_dependencies(rockspec, opts) return nil, err, errcode end end + + if cfg.link_lua_explicitly then + local ok, err, errcode = deps.check_lua_library(rockspec) + if not ok then + return nil, err, errcode + end + end + if opts.deps_mode == "none" then util.warning("skipping dependency checks.") return true @@ -130,7 +138,7 @@ local function process_dependencies(rockspec, opts) end end end - local ok, err, errcode = deps.fulfill_dependencies(rockspec, "dependencies", opts.deps_mode) + ok, err, errcode = deps.fulfill_dependencies(rockspec, "dependencies", opts.deps_mode) if err then return nil, err, errcode end diff --git a/src/luarocks/core/cfg.lua b/src/luarocks/core/cfg.lua index 5d538d68..75ddaa98 100644 --- a/src/luarocks/core/cfg.lua +++ b/src/luarocks/core/cfg.lua @@ -286,8 +286,9 @@ local function make_defaults(lua_version, target_cpu, platforms, home) defaults.local_cache = localappdata.."/LuaRocks/Cache" defaults.web_browser = "start" - defaults.external_deps_subdirs.lib = { "", "lib" } - defaults.runtime_external_deps_subdirs.lib = { "", "lib" } + defaults.external_deps_subdirs.lib = { "", "lib", "bin" } + defaults.runtime_external_deps_subdirs.lib = { "", "lib", "bin" } + defaults.link_lua_explicitly = true end if platforms.mingw32 then diff --git a/src/luarocks/deps.lua b/src/luarocks/deps.lua index 3217a18f..8abde2c2 100644 --- a/src/luarocks/deps.lua +++ b/src/luarocks/deps.lua @@ -247,164 +247,179 @@ local function add_all_patterns(file, patterns, files) end end ---- Set up path-related variables for external dependencies. --- For each key in the external_dependencies table in the --- rockspec file, four variables are created: _DIR, _BINDIR, --- _INCDIR and _LIBDIR. These are not overwritten --- if already set (e.g. by the LuaRocks config file or through the --- command-line). Values in the external_dependencies table --- are tables that may contain a "header" or a "library" field, --- with filenames to be tested for existence. --- @param rockspec table: The rockspec table. --- @param mode string: if "build" is given, checks all files; --- if "install" is given, do not scan for headers. --- @return boolean or (nil, string): True if no errors occurred, or --- nil and an error message if any test failed. -function deps.check_external_deps(rockspec, mode) - assert(rockspec:type() == "rockspec") - - local fs = require("luarocks.fs") - - local vars = rockspec.variables +local function get_external_deps_dirs(mode) local patterns = cfg.external_deps_patterns local subdirs = cfg.external_deps_subdirs if mode == "install" then patterns = cfg.runtime_external_deps_patterns subdirs = cfg.runtime_external_deps_subdirs end - if not rockspec.external_dependencies then - rockspec.external_dependencies = builtin.autodetect_external_dependencies(rockspec.build) + local dirs = { + BINDIR = { subdir = subdirs.bin, testfile = "program", pattern = patterns.bin }, + INCDIR = { subdir = subdirs.include, testfile = "header", pattern = patterns.include }, + LIBDIR = { subdir = subdirs.lib, testfile = "library", pattern = patterns.lib } + } + if mode == "install" then + dirs.INCDIR = nil end - if rockspec.external_dependencies then - for name, ext_files in util.sortedpairs(rockspec.external_dependencies) do - local ok = true - local failed_files = {program = {}, header = {}, library = {}} - local failed_dirname - local failed_testfile - for _, extdir in ipairs(cfg.external_deps_dirs) do - ok = true - local prefix = vars[name.."_DIR"] - local dirs = { - BINDIR = { subdir = subdirs.bin, testfile = "program", pattern = patterns.bin }, - INCDIR = { subdir = subdirs.include, testfile = "header", pattern = patterns.include }, - LIBDIR = { subdir = subdirs.lib, testfile = "library", pattern = patterns.lib } - } - if mode == "install" then - dirs.INCDIR = nil - end - if not prefix then - prefix = extdir - end - if type(prefix) == "table" then - if prefix.bin then - dirs.BINDIR.subdir = prefix.bin - end - if prefix.include then - if dirs.INCDIR then - dirs.INCDIR.subdir = prefix.include - end - end - if prefix.lib then - dirs.LIBDIR.subdir = prefix.lib + return dirs +end + +local function check_external_dependency_at(extdir, name, ext_files, vars, dirs, err_files) + local fs = require("luarocks.fs") + local prefix = vars[name.."_DIR"] + if not prefix then + prefix = extdir + end + if type(prefix) == "table" then + if prefix.bin then + dirs.BINDIR.subdir = prefix.bin + end + if prefix.include then + if dirs.INCDIR then + dirs.INCDIR.subdir = prefix.include + end + end + if prefix.lib then + dirs.LIBDIR.subdir = prefix.lib + end + prefix = prefix.prefix + end + for dirname, dirdata in util.sortedpairs(dirs) do + local paths + local path_var_value = vars[name.."_"..dirname] + if path_var_value then + paths = { path_var_value } + elseif type(dirdata.subdir) == "table" then + paths = {} + for i,v in ipairs(dirdata.subdir) do + paths[i] = dir.path(prefix, v) + end + else + paths = { dir.path(prefix, dirdata.subdir) } + end + dirdata.dir = paths[1] + local file = ext_files[dirdata.testfile] + if file then + local files = {} + if not file:match("%.") then + add_all_patterns(file, dirdata.pattern, files) + else + for _, pattern in ipairs(dirdata.pattern) do + local matched = deconstruct_pattern(file, pattern) + if matched then + add_all_patterns(matched, dirdata.pattern, files) end - prefix = prefix.prefix end - for dirname, dirdata in util.sortedpairs(dirs) do - local paths - local path_var_value = vars[name.."_"..dirname] - if path_var_value then - paths = { path_var_value } - elseif type(dirdata.subdir) == "table" then - paths = {} - for i,v in ipairs(dirdata.subdir) do - paths[i] = dir.path(prefix, v) - end - else - paths = { dir.path(prefix, dirdata.subdir) } - end - dirdata.dir = paths[1] - local file = ext_files[dirdata.testfile] - if file then - local files = {} - if not file:match("%.") then - add_all_patterns(file, dirdata.pattern, files) - else - for _, pattern in ipairs(dirdata.pattern) do - local matched = deconstruct_pattern(file, pattern) - if matched then - add_all_patterns(matched, dirdata.pattern, files) - end - end - table.insert(files, file) - end - local found = false - for _, f in ipairs(files) do + table.insert(files, file) + end + local found = false + for _, f in ipairs(files) do - -- small convenience hack - if f:match("%.so$") or f:match("%.dylib$") or f:match("%.dll$") then - f = f:gsub("%.[^.]+$", "."..cfg.external_lib_extension) - end + -- small convenience hack + if f:match("%.so$") or f:match("%.dylib$") or f:match("%.dll$") then + f = f:gsub("%.[^.]+$", "."..cfg.external_lib_extension) + end - local pattern - if f:match("%*") then - pattern = f:gsub("%.", "%%."):gsub("%*", ".*") - f = "matching "..f - end + local pattern + if f:match("%*") then + pattern = f:gsub("%.", "%%."):gsub("%*", ".*") + f = "matching "..f + end - for _, d in ipairs(paths) do - if pattern then - for entry in fs.dir(d) do - if entry:match(pattern) then - found = true - break - end - end - else - found = fs.is_file(dir.path(d, f)) - end - if found then - dirdata.dir = d - break - else - table.insert(failed_files[dirdata.testfile], f.." in "..d) - end - end - if found then + for _, d in ipairs(paths) do + if pattern then + for entry in fs.dir(d) do + if entry:match(pattern) then + found = true break end end - if not found then - ok = false - failed_dirname = dirname - failed_testfile = dirdata.testfile - break - end + else + found = fs.is_file(dir.path(d, f)) end - end - if ok then - for dirname, dirdata in pairs(dirs) do - vars[name.."_"..dirname] = dirdata.dir + if found then + dirdata.dir = d + dirdata.file = f + break + else + table.insert(err_files[dirdata.testfile], f.." in "..d) end - vars[name.."_DIR"] = prefix + end + if found then break end end - if not ok then - local lines = {"Could not find "..failed_testfile.." file for "..name} - - local failed_paths = {} - for _, failed_file in ipairs(failed_files[failed_testfile]) do - if not failed_paths[failed_file] then - failed_paths[failed_file] = true - table.insert(lines, " No file "..failed_file) - end - end + if not found then + return nil, dirname, dirdata.testfile + end + end + end - table.insert(lines, "You may have to install "..name.." in your system and/or pass "..name.."_DIR or "..name.."_"..failed_dirname.." to the luarocks command.") - table.insert(lines, "Example: luarocks install "..rockspec.name.." "..name.."_DIR=/usr/local") + for dirname, dirdata in pairs(dirs) do + vars[name.."_"..dirname] = dirdata.dir + vars[name.."_"..dirname.."_FILE"] = dirdata.file + end + vars[name.."_DIR"] = prefix + return true +end + +local function check_external_dependency(name, ext_files, vars, mode) + local err_files = {program = {}, header = {}, library = {}} + local err_dirname + local err_testfile + for _, extdir in ipairs(cfg.external_deps_dirs) do + local dirs = get_external_deps_dirs(mode) + local ok + ok, err_dirname, err_testfile = check_external_dependency_at(extdir, name, ext_files, vars, dirs, err_files) + if ok then + return true + end + end + + return nil, err_dirname, err_testfile, err_files +end + +--- Set up path-related variables for external dependencies. +-- For each key in the external_dependencies table in the +-- rockspec file, four variables are created: _DIR, _BINDIR, +-- _INCDIR and _LIBDIR. These are not overwritten +-- if already set (e.g. by the LuaRocks config file or through the +-- command-line). Values in the external_dependencies table +-- are tables that may contain a "header" or a "library" field, +-- with filenames to be tested for existence. +-- @param rockspec table: The rockspec table. +-- @param mode string: if "build" is given, checks all files; +-- if "install" is given, do not scan for headers. +-- @return boolean or (nil, string): True if no errors occurred, or +-- nil and an error message if any test failed. +function deps.check_external_deps(rockspec, mode) + assert(rockspec:type() == "rockspec") + + if not rockspec.external_dependencies then + rockspec.external_dependencies = builtin.autodetect_external_dependencies(rockspec.build) + end + if not rockspec.external_dependencies then + return true + end - return nil, table.concat(lines, "\n"), "dependency" + for name, ext_files in util.sortedpairs(rockspec.external_dependencies) do + local ok, err_dirname, err_testfile, err_files = check_external_dependency(name, ext_files, rockspec.variables, mode) + if not ok then + local lines = {"Could not find "..err_testfile.." file for "..name} + + local err_paths = {} + for _, err_file in ipairs(err_files[err_testfile]) do + if not err_paths[err_file] then + err_paths[err_file] = true + table.insert(lines, " No file "..err_file) + end end + + table.insert(lines, "You may have to install "..name.." in your system and/or pass "..name.."_DIR or "..name.."_"..err_dirname.." to the luarocks command.") + table.insert(lines, "Example: luarocks install "..rockspec.name.." "..name.."_DIR=/usr/local") + + return nil, table.concat(lines, "\n"), "dependency" end end return true @@ -453,6 +468,22 @@ function deps.scan_deps(results, manifest, name, version, deps_mode) end end +function deps.check_lua_library(rockspec) + local libnames = { + "lua" .. cfg.lua_version, + "lua" .. cfg.lua_version:gsub("%.", ""), + "lua", + } + for _, libname in ipairs(libnames) do + local ok = check_external_dependency("LUA", { library = libname }, rockspec.variables, "build") + if ok then + rockspec.variables.LUALIB = rockspec.variables.LUA_LIBDIR_FILE + return true + end + end + return nil, "Failed finding Lua library. You may need to configure LUA_LIBDIR.", "dependency" +end + local valid_deps_modes = { one = true, order = true, -- cgit v1.2.3-55-g6feb