diff options
| author | V1K1NGbg <victor@ilchev.com> | 2024-08-15 11:59:58 +0300 |
|---|---|---|
| committer | V1K1NGbg <victor@ilchev.com> | 2024-08-15 11:59:58 +0300 |
| commit | 05d07042bef9b5ed400a5058ac7e4f2886d8d5ee (patch) | |
| tree | 7012ae536b4766360d09cf17e42c5b0f9e33707c | |
| parent | 38f2dc2ab50e06d6b8be5eaec5d06f7c57e270c8 (diff) | |
| download | luarocks-05d07042bef9b5ed400a5058ac7e4f2886d8d5ee.tar.gz luarocks-05d07042bef9b5ed400a5058ac7e4f2886d8d5ee.tar.bz2 luarocks-05d07042bef9b5ed400a5058ac7e4f2886d8d5ee.zip | |
builin
| -rw-r--r-- | src/luarocks/build/builtin-original.lua | 395 | ||||
| -rw-r--r-- | src/luarocks/build/builtin.lua | 184 | ||||
| -rw-r--r-- | src/luarocks/core/types/installs.d.tl | 1 |
3 files changed, 495 insertions, 85 deletions
diff --git a/src/luarocks/build/builtin-original.lua b/src/luarocks/build/builtin-original.lua new file mode 100644 index 00000000..4c15d2bf --- /dev/null +++ b/src/luarocks/build/builtin-original.lua | |||
| @@ -0,0 +1,395 @@ | |||
| 1 | |||
| 2 | --- A builtin build system: back-end to provide a portable way of building C-based Lua modules. | ||
| 3 | local builtin = {} | ||
| 4 | |||
| 5 | -- This build driver checks LUA_INCDIR and LUA_LIBDIR on demand, | ||
| 6 | -- so that pure-Lua rocks don't need to have development headers | ||
| 7 | -- installed. | ||
| 8 | builtin.skip_lua_inc_lib_check = true | ||
| 9 | |||
| 10 | local unpack = unpack or table.unpack | ||
| 11 | local dir_sep = package.config:sub(1, 1) | ||
| 12 | |||
| 13 | local fs = require("luarocks.fs") | ||
| 14 | local path = require("luarocks.path") | ||
| 15 | local util = require("luarocks.util") | ||
| 16 | local cfg = require("luarocks.core.cfg") | ||
| 17 | local dir = require("luarocks.dir") | ||
| 18 | local deps = require("luarocks.deps") | ||
| 19 | |||
| 20 | local function autoextract_libs(external_dependencies, variables) | ||
| 21 | if not external_dependencies then | ||
| 22 | return nil, nil, nil | ||
| 23 | end | ||
| 24 | local libs = {} | ||
| 25 | local incdirs = {} | ||
| 26 | local libdirs = {} | ||
| 27 | for name, data in pairs(external_dependencies) do | ||
| 28 | if data.library then | ||
| 29 | table.insert(libs, data.library) | ||
| 30 | table.insert(incdirs, variables[name .. "_INCDIR"]) | ||
| 31 | table.insert(libdirs, variables[name .. "_LIBDIR"]) | ||
| 32 | end | ||
| 33 | end | ||
| 34 | return libs, incdirs, libdirs | ||
| 35 | end | ||
| 36 | |||
| 37 | do | ||
| 38 | local function get_cmod_name(file) | ||
| 39 | local fd = io.open(dir.path(fs.current_dir(), file), "r") | ||
| 40 | if not fd then return nil end | ||
| 41 | local data = fd:read("*a") | ||
| 42 | fd:close() | ||
| 43 | return (data:match("int%s+luaopen_([a-zA-Z0-9_]+)")) | ||
| 44 | end | ||
| 45 | |||
| 46 | local skiplist = { | ||
| 47 | ["spec"] = true, | ||
| 48 | [".luarocks"] = true, | ||
| 49 | ["lua_modules"] = true, | ||
| 50 | ["test.lua"] = true, | ||
| 51 | ["tests.lua"] = true, | ||
| 52 | } | ||
| 53 | |||
| 54 | function builtin.autodetect_modules(libs, incdirs, libdirs) | ||
| 55 | local modules = {} | ||
| 56 | local install | ||
| 57 | local copy_directories | ||
| 58 | |||
| 59 | local prefix = "" | ||
| 60 | for _, parent in ipairs({"src", "lua", "lib"}) do | ||
| 61 | if fs.is_dir(parent) then | ||
| 62 | fs.change_dir(parent) | ||
| 63 | prefix = parent .. dir_sep | ||
| 64 | break | ||
| 65 | end | ||
| 66 | end | ||
| 67 | |||
| 68 | for _, file in ipairs(fs.find()) do | ||
| 69 | local base = file:match("^([^\\/]*)") | ||
| 70 | if not skiplist[base] then | ||
| 71 | local luamod = file:match("(.*)%.lua$") | ||
| 72 | if luamod then | ||
| 73 | modules[path.path_to_module(file)] = prefix .. file | ||
| 74 | else | ||
| 75 | local cmod = file:match("(.*)%.c$") | ||
| 76 | if cmod then | ||
| 77 | local modname = get_cmod_name(file) or path.path_to_module(file:gsub("%.c$", ".lua")) | ||
| 78 | modules[modname] = { | ||
| 79 | sources = prefix..file, | ||
| 80 | libraries = libs, | ||
| 81 | incdirs = incdirs, | ||
| 82 | libdirs = libdirs, | ||
| 83 | } | ||
| 84 | end | ||
| 85 | end | ||
| 86 | end | ||
| 87 | end | ||
| 88 | |||
| 89 | if prefix ~= "" then | ||
| 90 | fs.pop_dir() | ||
| 91 | end | ||
| 92 | |||
| 93 | local bindir = (fs.is_dir(dir.path("src", "bin")) and dir.path("src", "bin")) | ||
| 94 | or (fs.is_dir("bin") and "bin") | ||
| 95 | if bindir then | ||
| 96 | install = { bin = {} } | ||
| 97 | for _, file in ipairs(fs.list_dir(bindir)) do | ||
| 98 | table.insert(install.bin, dir.path(bindir, file)) | ||
| 99 | end | ||
| 100 | end | ||
| 101 | |||
| 102 | for _, directory in ipairs({ "doc", "docs", "samples", "tests" }) do | ||
| 103 | if fs.is_dir(directory) then | ||
| 104 | if not copy_directories then | ||
| 105 | copy_directories = {} | ||
| 106 | end | ||
| 107 | table.insert(copy_directories, directory) | ||
| 108 | end | ||
| 109 | end | ||
| 110 | |||
| 111 | return modules, install, copy_directories | ||
| 112 | end | ||
| 113 | end | ||
| 114 | |||
| 115 | --- Run a command displaying its execution on standard output. | ||
| 116 | -- @return boolean: true if command succeeds (status code 0), false | ||
| 117 | -- otherwise. | ||
| 118 | local function execute(...) | ||
| 119 | io.stdout:write(table.concat({...}, " ").."\n") | ||
| 120 | return fs.execute(...) | ||
| 121 | end | ||
| 122 | |||
| 123 | --- Driver function for the builtin build back-end. | ||
| 124 | -- @param rockspec table: the loaded rockspec. | ||
| 125 | -- @return boolean or (nil, string): true if no errors occurred, | ||
| 126 | -- nil and an error message otherwise. | ||
| 127 | function builtin.run(rockspec, no_install) | ||
| 128 | assert(rockspec:type() == "rockspec") | ||
| 129 | local compile_object, compile_library, compile_static_library | ||
| 130 | |||
| 131 | local build = rockspec.build | ||
| 132 | local variables = rockspec.variables | ||
| 133 | local checked_lua_h = false | ||
| 134 | |||
| 135 | for _, var in ipairs{ "CC", "CFLAGS", "LDFLAGS" } do | ||
| 136 | variables[var] = variables[var] or os.getenv(var) or "" | ||
| 137 | end | ||
| 138 | |||
| 139 | local function add_flags(extras, flag, flags) | ||
| 140 | if flags then | ||
| 141 | if type(flags) ~= "table" then | ||
| 142 | flags = { tostring(flags) } | ||
| 143 | end | ||
| 144 | util.variable_substitutions(flags, variables) | ||
| 145 | for _, v in ipairs(flags) do | ||
| 146 | table.insert(extras, flag:format(v)) | ||
| 147 | end | ||
| 148 | end | ||
| 149 | end | ||
| 150 | |||
| 151 | if cfg.is_platform("mingw32") then | ||
| 152 | compile_object = function(object, source, defines, incdirs) | ||
| 153 | local extras = {} | ||
| 154 | add_flags(extras, "-D%s", defines) | ||
| 155 | add_flags(extras, "-I%s", incdirs) | ||
| 156 | return execute(variables.CC.." "..variables.CFLAGS, "-c", "-o", object, "-I"..variables.LUA_INCDIR, source, unpack(extras)) | ||
| 157 | end | ||
| 158 | compile_library = function(library, objects, libraries, libdirs, name) | ||
| 159 | local extras = { unpack(objects) } | ||
| 160 | add_flags(extras, "-L%s", libdirs) | ||
| 161 | add_flags(extras, "-l%s", libraries) | ||
| 162 | extras[#extras+1] = dir.path(variables.LUA_LIBDIR, variables.LUALIB) | ||
| 163 | |||
| 164 | if variables.CC == "clang" or variables.CC == "clang-cl" then | ||
| 165 | local exported_name = name:gsub("%.", "_") | ||
| 166 | exported_name = exported_name:match('^[^%-]+%-(.+)$') or exported_name | ||
| 167 | extras[#extras+1] = string.format("-Wl,-export:luaopen_%s", exported_name) | ||
| 168 | else | ||
| 169 | extras[#extras+1] = "-l" .. (variables.MSVCRT or "m") | ||
| 170 | end | ||
| 171 | |||
| 172 | local ok = execute(variables.LD.." "..variables.LDFLAGS.." "..variables.LIBFLAG, "-o", library, unpack(extras)) | ||
| 173 | return ok | ||
| 174 | end | ||
| 175 | --[[ TODO disable static libs until we fix the conflict in the manifest, which will take extending the manifest format. | ||
| 176 | compile_static_library = function(library, objects, libraries, libdirs, name) | ||
| 177 | local ok = execute(variables.AR, "rc", library, unpack(objects)) | ||
| 178 | if ok then | ||
| 179 | ok = execute(variables.RANLIB, library) | ||
| 180 | end | ||
| 181 | return ok | ||
| 182 | end | ||
| 183 | ]] | ||
| 184 | elseif cfg.is_platform("win32") then | ||
| 185 | compile_object = function(object, source, defines, incdirs) | ||
| 186 | local extras = {} | ||
| 187 | add_flags(extras, "-D%s", defines) | ||
| 188 | add_flags(extras, "-I%s", incdirs) | ||
| 189 | return execute(variables.CC.." "..variables.CFLAGS, "-c", "-Fo"..object, "-I"..variables.LUA_INCDIR, source, unpack(extras)) | ||
| 190 | end | ||
| 191 | compile_library = function(library, objects, libraries, libdirs, name) | ||
| 192 | local extras = { unpack(objects) } | ||
| 193 | add_flags(extras, "-libpath:%s", libdirs) | ||
| 194 | add_flags(extras, "%s.lib", libraries) | ||
| 195 | local basename = dir.base_name(library):gsub(".[^.]*$", "") | ||
| 196 | local deffile = basename .. ".def" | ||
| 197 | local def = io.open(dir.path(fs.current_dir(), deffile), "w+") | ||
| 198 | local exported_name = name:gsub("%.", "_") | ||
| 199 | exported_name = exported_name:match('^[^%-]+%-(.+)$') or exported_name | ||
| 200 | def:write("EXPORTS\n") | ||
| 201 | def:write("luaopen_"..exported_name.."\n") | ||
| 202 | def:close() | ||
| 203 | local ok = execute(variables.LD, "-dll", "-def:"..deffile, "-out:"..library, dir.path(variables.LUA_LIBDIR, variables.LUALIB), unpack(extras)) | ||
| 204 | local basedir = "" | ||
| 205 | if name:find("%.") ~= nil then | ||
| 206 | basedir = name:gsub("%.%w+$", "\\") | ||
| 207 | basedir = basedir:gsub("%.", "\\") | ||
| 208 | end | ||
| 209 | local manifestfile = basedir .. basename..".dll.manifest" | ||
| 210 | |||
| 211 | if ok and fs.exists(manifestfile) then | ||
| 212 | ok = execute(variables.MT, "-manifest", manifestfile, "-outputresource:"..basedir..basename..".dll;2") | ||
| 213 | end | ||
| 214 | return ok | ||
| 215 | end | ||
| 216 | --[[ TODO disable static libs until we fix the conflict in the manifest, which will take extending the manifest format. | ||
| 217 | compile_static_library = function(library, objects, libraries, libdirs, name) | ||
| 218 | local ok = execute(variables.AR, "-out:"..library, unpack(objects)) | ||
| 219 | return ok | ||
| 220 | end | ||
| 221 | ]] | ||
| 222 | else | ||
| 223 | compile_object = function(object, source, defines, incdirs) | ||
| 224 | local extras = {} | ||
| 225 | add_flags(extras, "-D%s", defines) | ||
| 226 | add_flags(extras, "-I%s", incdirs) | ||
| 227 | return execute(variables.CC.." "..variables.CFLAGS, "-I"..variables.LUA_INCDIR, "-c", source, "-o", object, unpack(extras)) | ||
| 228 | end | ||
| 229 | compile_library = function (library, objects, libraries, libdirs) | ||
| 230 | local extras = { unpack(objects) } | ||
| 231 | add_flags(extras, "-L%s", libdirs) | ||
| 232 | if cfg.gcc_rpath then | ||
| 233 | add_flags(extras, "-Wl,-rpath,%s", libdirs) | ||
| 234 | end | ||
| 235 | add_flags(extras, "-l%s", libraries) | ||
| 236 | if cfg.link_lua_explicitly then | ||
| 237 | extras[#extras+1] = "-L"..variables.LUA_LIBDIR | ||
| 238 | extras[#extras+1] = "-llua" | ||
| 239 | end | ||
| 240 | return execute(variables.LD.." "..variables.LDFLAGS.." "..variables.LIBFLAG, "-o", library, unpack(extras)) | ||
| 241 | end | ||
| 242 | compile_static_library = function(library, objects, libraries, libdirs, name) -- luacheck: ignore 211 | ||
| 243 | local ok = execute(variables.AR, "rc", library, unpack(objects)) | ||
| 244 | if ok then | ||
| 245 | ok = execute(variables.RANLIB, library) | ||
| 246 | end | ||
| 247 | return ok | ||
| 248 | end | ||
| 249 | end | ||
| 250 | |||
| 251 | local ok, err | ||
| 252 | local lua_modules = {} | ||
| 253 | local lib_modules = {} | ||
| 254 | local luadir = path.lua_dir(rockspec.name, rockspec.version) | ||
| 255 | local libdir = path.lib_dir(rockspec.name, rockspec.version) | ||
| 256 | |||
| 257 | local autolibs, autoincdirs, autolibdirs = autoextract_libs(rockspec.external_dependencies, rockspec.variables) | ||
| 258 | |||
| 259 | if not build.modules then | ||
| 260 | if rockspec:format_is_at_least("3.0") then | ||
| 261 | local install, copy_directories | ||
| 262 | build.modules, install, copy_directories = builtin.autodetect_modules(autolibs, autoincdirs, autolibdirs) | ||
| 263 | build.install = build.install or install | ||
| 264 | build.copy_directories = build.copy_directories or copy_directories | ||
| 265 | else | ||
| 266 | return nil, "Missing build.modules table" | ||
| 267 | end | ||
| 268 | end | ||
| 269 | |||
| 270 | local compile_temp_dir | ||
| 271 | |||
| 272 | local mkdir_cache = {} | ||
| 273 | local function cached_make_dir(name) | ||
| 274 | if name == "" or mkdir_cache[name] then | ||
| 275 | return true | ||
| 276 | end | ||
| 277 | mkdir_cache[name] = true | ||
| 278 | return fs.make_dir(name) | ||
| 279 | end | ||
| 280 | |||
| 281 | for name, info in pairs(build.modules) do | ||
| 282 | local moddir = path.module_to_path(name) | ||
| 283 | if type(info) == "string" then | ||
| 284 | local ext = info:match("%.([^.]+)$") | ||
| 285 | if ext == "lua" then | ||
| 286 | local filename = dir.base_name(info) | ||
| 287 | if filename == "init.lua" and not name:match("%.init$") then | ||
| 288 | moddir = path.module_to_path(name..".init") | ||
| 289 | else | ||
| 290 | local basename = name:match("([^.]+)$") | ||
| 291 | filename = basename..".lua" | ||
| 292 | end | ||
| 293 | local dest = dir.path(luadir, moddir, filename) | ||
| 294 | lua_modules[info] = dest | ||
| 295 | else | ||
| 296 | info = {info} | ||
| 297 | end | ||
| 298 | end | ||
| 299 | if type(info) == "table" then | ||
| 300 | if not checked_lua_h then | ||
| 301 | local ok, err, errcode = deps.check_lua_incdir(rockspec.variables) | ||
| 302 | if not ok then | ||
| 303 | return nil, err, errcode | ||
| 304 | end | ||
| 305 | |||
| 306 | if cfg.link_lua_explicitly then | ||
| 307 | local ok, err, errcode = deps.check_lua_libdir(rockspec.variables) | ||
| 308 | if not ok then | ||
| 309 | return nil, err, errcode | ||
| 310 | end | ||
| 311 | end | ||
| 312 | checked_lua_h = true | ||
| 313 | end | ||
| 314 | local objects = {} | ||
| 315 | local sources = info.sources | ||
| 316 | if info[1] then sources = info end | ||
| 317 | if type(sources) == "string" then sources = {sources} end | ||
| 318 | if type(sources) ~= "table" then | ||
| 319 | return nil, "error in rockspec: module '" .. name .. "' entry has no 'sources' list" | ||
| 320 | end | ||
| 321 | for _, source in ipairs(sources) do | ||
| 322 | if type(source) ~= "string" then | ||
| 323 | return nil, "error in rockspec: module '" .. name .. "' does not specify source correctly." | ||
| 324 | end | ||
| 325 | local object = source:gsub("%.[^.]*$", "."..cfg.obj_extension) | ||
| 326 | if not object then | ||
| 327 | object = source.."."..cfg.obj_extension | ||
| 328 | end | ||
| 329 | ok = compile_object(object, source, info.defines, info.incdirs or autoincdirs) | ||
| 330 | if not ok then | ||
| 331 | return nil, "Failed compiling object "..object | ||
| 332 | end | ||
| 333 | table.insert(objects, object) | ||
| 334 | end | ||
| 335 | |||
| 336 | if not compile_temp_dir then | ||
| 337 | compile_temp_dir = fs.make_temp_dir("build-" .. rockspec.package .. "-" .. rockspec.version) | ||
| 338 | util.schedule_function(fs.delete, compile_temp_dir) | ||
| 339 | end | ||
| 340 | |||
| 341 | local module_name = name:match("([^.]*)$").."."..util.matchquote(cfg.lib_extension) | ||
| 342 | if moddir ~= "" then | ||
| 343 | module_name = dir.path(moddir, module_name) | ||
| 344 | end | ||
| 345 | |||
| 346 | local build_name = dir.path(compile_temp_dir, module_name) | ||
| 347 | local build_dir = dir.dir_name(build_name) | ||
| 348 | cached_make_dir(build_dir) | ||
| 349 | |||
| 350 | lib_modules[build_name] = dir.path(libdir, module_name) | ||
| 351 | ok = compile_library(build_name, objects, info.libraries, info.libdirs or autolibdirs, name) | ||
| 352 | if not ok then | ||
| 353 | return nil, "Failed compiling module "..module_name | ||
| 354 | end | ||
| 355 | |||
| 356 | -- for backwards compatibility, try keeping a copy of the module | ||
| 357 | -- in the old location (luasec-1.3.2-1 rockspec breaks otherwise) | ||
| 358 | if cached_make_dir(dir.dir_name(module_name)) then | ||
| 359 | fs.copy(build_name, module_name) | ||
| 360 | end | ||
| 361 | |||
| 362 | --[[ TODO disable static libs until we fix the conflict in the manifest, which will take extending the manifest format. | ||
| 363 | module_name = name:match("([^.]*)$").."."..util.matchquote(cfg.static_lib_extension) | ||
| 364 | if moddir ~= "" then | ||
| 365 | module_name = dir.path(moddir, module_name) | ||
| 366 | end | ||
| 367 | lib_modules[module_name] = dir.path(libdir, module_name) | ||
| 368 | ok = compile_static_library(module_name, objects, info.libraries, info.libdirs, name) | ||
| 369 | if not ok then | ||
| 370 | return nil, "Failed compiling static library "..module_name | ||
| 371 | end | ||
| 372 | ]] | ||
| 373 | end | ||
| 374 | end | ||
| 375 | if not no_install then | ||
| 376 | for _, mods in ipairs({{ tbl = lua_modules, perms = "read" }, { tbl = lib_modules, perms = "exec" }}) do | ||
| 377 | for name, dest in pairs(mods.tbl) do | ||
| 378 | cached_make_dir(dir.dir_name(dest)) | ||
| 379 | ok, err = fs.copy(name, dest, mods.perms) | ||
| 380 | if not ok then | ||
| 381 | return nil, "Failed installing "..name.." in "..dest..": "..err | ||
| 382 | end | ||
| 383 | end | ||
| 384 | end | ||
| 385 | if fs.is_dir("lua") then | ||
| 386 | ok, err = fs.copy_contents("lua", luadir) | ||
| 387 | if not ok then | ||
| 388 | return nil, "Failed copying contents of 'lua' directory: "..err | ||
| 389 | end | ||
| 390 | end | ||
| 391 | end | ||
| 392 | return true | ||
| 393 | end | ||
| 394 | |||
| 395 | return builtin | ||
diff --git a/src/luarocks/build/builtin.lua b/src/luarocks/build/builtin.lua index 4c15d2bf..478f45c1 100644 --- a/src/luarocks/build/builtin.lua +++ b/src/luarocks/build/builtin.lua | |||
| @@ -1,13 +1,26 @@ | |||
| 1 | local _tl_compat; if (tonumber((_VERSION or ''):match('[%d.]*$')) or 0) < 5.3 then local p, m = pcall(require, 'compat53.module'); if p then _tl_compat = m end end; local io = _tl_compat and _tl_compat.io or io; local ipairs = _tl_compat and _tl_compat.ipairs or ipairs; local os = _tl_compat and _tl_compat.os or os; local package = _tl_compat and _tl_compat.package or package; local pairs = _tl_compat and _tl_compat.pairs or pairs; local string = _tl_compat and _tl_compat.string or string; local table = _tl_compat and _tl_compat.table or table; local _tl_table_unpack = unpack or table.unpack | ||
| 1 | 2 | ||
| 2 | --- A builtin build system: back-end to provide a portable way of building C-based Lua modules. | ||
| 3 | local builtin = {} | 3 | local builtin = {} |
| 4 | 4 | ||
| 5 | -- This build driver checks LUA_INCDIR and LUA_LIBDIR on demand, | 5 | |
| 6 | -- so that pure-Lua rocks don't need to have development headers | 6 | |
| 7 | -- installed. | 7 | |
| 8 | |||
| 9 | |||
| 10 | |||
| 11 | |||
| 12 | local Install = i.Install | ||
| 13 | |||
| 14 | |||
| 15 | local Build = b.Build | ||
| 16 | |||
| 17 | |||
| 18 | |||
| 19 | |||
| 20 | |||
| 21 | |||
| 8 | builtin.skip_lua_inc_lib_check = true | 22 | builtin.skip_lua_inc_lib_check = true |
| 9 | 23 | ||
| 10 | local unpack = unpack or table.unpack | ||
| 11 | local dir_sep = package.config:sub(1, 1) | 24 | local dir_sep = package.config:sub(1, 1) |
| 12 | 25 | ||
| 13 | local fs = require("luarocks.fs") | 26 | local fs = require("luarocks.fs") |
| @@ -57,7 +70,7 @@ do | |||
| 57 | local copy_directories | 70 | local copy_directories |
| 58 | 71 | ||
| 59 | local prefix = "" | 72 | local prefix = "" |
| 60 | for _, parent in ipairs({"src", "lua", "lib"}) do | 73 | for _, parent in ipairs({ "src", "lua", "lib" }) do |
| 61 | if fs.is_dir(parent) then | 74 | if fs.is_dir(parent) then |
| 62 | fs.change_dir(parent) | 75 | fs.change_dir(parent) |
| 63 | prefix = parent .. dir_sep | 76 | prefix = parent .. dir_sep |
| @@ -67,16 +80,16 @@ do | |||
| 67 | 80 | ||
| 68 | for _, file in ipairs(fs.find()) do | 81 | for _, file in ipairs(fs.find()) do |
| 69 | local base = file:match("^([^\\/]*)") | 82 | local base = file:match("^([^\\/]*)") |
| 70 | if not skiplist[base] then | 83 | if not (skiplist)[base] then |
| 71 | local luamod = file:match("(.*)%.lua$") | 84 | local luamod = file:match("(.*)%.lua$") |
| 72 | if luamod then | 85 | if luamod then |
| 73 | modules[path.path_to_module(file)] = prefix .. file | 86 | modules[path.path_to_module(file)] = prefix .. file |
| 74 | else | 87 | else |
| 75 | local cmod = file:match("(.*)%.c$") | 88 | local cmod = file:match("(.*)%.c$") |
| 76 | if cmod then | 89 | if cmod then |
| 77 | local modname = get_cmod_name(file) or path.path_to_module(file:gsub("%.c$", ".lua")) | 90 | local modname = get_cmod_name(file) or path.path_to_module((file:gsub("%.c$", ".lua"))) |
| 78 | modules[modname] = { | 91 | modules[modname] = { |
| 79 | sources = prefix..file, | 92 | sources = prefix .. file, |
| 80 | libraries = libs, | 93 | libraries = libs, |
| 81 | incdirs = incdirs, | 94 | incdirs = incdirs, |
| 82 | libdirs = libdirs, | 95 | libdirs = libdirs, |
| @@ -90,8 +103,8 @@ do | |||
| 90 | fs.pop_dir() | 103 | fs.pop_dir() |
| 91 | end | 104 | end |
| 92 | 105 | ||
| 93 | local bindir = (fs.is_dir(dir.path("src", "bin")) and dir.path("src", "bin")) | 106 | local bindir = (fs.is_dir(dir.path("src", "bin")) and dir.path("src", "bin")) or |
| 94 | or (fs.is_dir("bin") and "bin") | 107 | (fs.is_dir("bin") and "bin") |
| 95 | if bindir then | 108 | if bindir then |
| 96 | install = { bin = {} } | 109 | install = { bin = {} } |
| 97 | for _, file in ipairs(fs.list_dir(bindir)) do | 110 | for _, file in ipairs(fs.list_dir(bindir)) do |
| @@ -112,33 +125,34 @@ do | |||
| 112 | end | 125 | end |
| 113 | end | 126 | end |
| 114 | 127 | ||
| 115 | --- Run a command displaying its execution on standard output. | 128 | |
| 116 | -- @return boolean: true if command succeeds (status code 0), false | 129 | |
| 117 | -- otherwise. | 130 | |
| 118 | local function execute(...) | 131 | local function execute(...) |
| 119 | io.stdout:write(table.concat({...}, " ").."\n") | 132 | io.stdout:write(table.concat({ ... }, " ") .. "\n") |
| 120 | return fs.execute(...) | 133 | return fs.execute(...) |
| 121 | end | 134 | end |
| 122 | 135 | ||
| 123 | --- Driver function for the builtin build back-end. | 136 | |
| 124 | -- @param rockspec table: the loaded rockspec. | 137 | |
| 125 | -- @return boolean or (nil, string): true if no errors occurred, | 138 | |
| 126 | -- nil and an error message otherwise. | 139 | |
| 127 | function builtin.run(rockspec, no_install) | 140 | function builtin.run(rockspec, no_install) |
| 128 | assert(rockspec:type() == "rockspec") | 141 | local compile_object |
| 129 | local compile_object, compile_library, compile_static_library | 142 | local compile_library |
| 143 | local compile_static_library | ||
| 130 | 144 | ||
| 131 | local build = rockspec.build | 145 | local build = rockspec.build |
| 132 | local variables = rockspec.variables | 146 | local variables = rockspec.variables |
| 133 | local checked_lua_h = false | 147 | local checked_lua_h = false |
| 134 | 148 | ||
| 135 | for _, var in ipairs{ "CC", "CFLAGS", "LDFLAGS" } do | 149 | for _, var in ipairs({ "CC", "CFLAGS", "LDFLAGS" }) do |
| 136 | variables[var] = variables[var] or os.getenv(var) or "" | 150 | variables[var] = variables[var] or os.getenv(var) or "" |
| 137 | end | 151 | end |
| 138 | 152 | ||
| 139 | local function add_flags(extras, flag, flags) | 153 | local function add_flags(extras, flag, flags) |
| 140 | if flags then | 154 | if flags then |
| 141 | if type(flags) ~= "table" then | 155 | if not (type(flags) == "table") then |
| 142 | flags = { tostring(flags) } | 156 | flags = { tostring(flags) } |
| 143 | end | 157 | end |
| 144 | util.variable_substitutions(flags, variables) | 158 | util.variable_substitutions(flags, variables) |
| @@ -153,43 +167,43 @@ function builtin.run(rockspec, no_install) | |||
| 153 | local extras = {} | 167 | local extras = {} |
| 154 | add_flags(extras, "-D%s", defines) | 168 | add_flags(extras, "-D%s", defines) |
| 155 | add_flags(extras, "-I%s", incdirs) | 169 | add_flags(extras, "-I%s", incdirs) |
| 156 | return execute(variables.CC.." "..variables.CFLAGS, "-c", "-o", object, "-I"..variables.LUA_INCDIR, source, unpack(extras)) | 170 | return execute(variables.CC .. " " .. variables.CFLAGS, "-c", "-o", object, "-I" .. variables.LUA_INCDIR, source, _tl_table_unpack(extras)) |
| 157 | end | 171 | end |
| 158 | compile_library = function(library, objects, libraries, libdirs, name) | 172 | compile_library = function(library, objects, libraries, libdirs, name) |
| 159 | local extras = { unpack(objects) } | 173 | local extras = { _tl_table_unpack(objects) } |
| 160 | add_flags(extras, "-L%s", libdirs) | 174 | add_flags(extras, "-L%s", libdirs) |
| 161 | add_flags(extras, "-l%s", libraries) | 175 | add_flags(extras, "-l%s", libraries) |
| 162 | extras[#extras+1] = dir.path(variables.LUA_LIBDIR, variables.LUALIB) | 176 | extras[#extras + 1] = dir.path(variables.LUA_LIBDIR, variables.LUALIB) |
| 163 | 177 | ||
| 164 | if variables.CC == "clang" or variables.CC == "clang-cl" then | 178 | if variables.CC == "clang" or variables.CC == "clang-cl" then |
| 165 | local exported_name = name:gsub("%.", "_") | 179 | local exported_name = name:gsub("%.", "_") |
| 166 | exported_name = exported_name:match('^[^%-]+%-(.+)$') or exported_name | 180 | exported_name = exported_name:match('^[^%-]+%-(.+)$') or exported_name |
| 167 | extras[#extras+1] = string.format("-Wl,-export:luaopen_%s", exported_name) | 181 | extras[#extras + 1] = string.format("-Wl,-export:luaopen_%s", exported_name) |
| 168 | else | 182 | else |
| 169 | extras[#extras+1] = "-l" .. (variables.MSVCRT or "m") | 183 | extras[#extras + 1] = "-l" .. (variables.MSVCRT or "m") |
| 170 | end | 184 | end |
| 171 | 185 | ||
| 172 | local ok = execute(variables.LD.." "..variables.LDFLAGS.." "..variables.LIBFLAG, "-o", library, unpack(extras)) | 186 | local ok = execute(variables.LD .. " " .. variables.LDFLAGS .. " " .. variables.LIBFLAG, "-o", library, _tl_table_unpack(extras)) |
| 173 | return ok | ||
| 174 | end | ||
| 175 | --[[ TODO disable static libs until we fix the conflict in the manifest, which will take extending the manifest format. | ||
| 176 | compile_static_library = function(library, objects, libraries, libdirs, name) | ||
| 177 | local ok = execute(variables.AR, "rc", library, unpack(objects)) | ||
| 178 | if ok then | ||
| 179 | ok = execute(variables.RANLIB, library) | ||
| 180 | end | ||
| 181 | return ok | 187 | return ok |
| 182 | end | 188 | end |
| 183 | ]] | 189 | |
| 190 | |||
| 191 | |||
| 192 | |||
| 193 | |||
| 194 | |||
| 195 | |||
| 196 | |||
| 197 | |||
| 184 | elseif cfg.is_platform("win32") then | 198 | elseif cfg.is_platform("win32") then |
| 185 | compile_object = function(object, source, defines, incdirs) | 199 | compile_object = function(object, source, defines, incdirs) |
| 186 | local extras = {} | 200 | local extras = {} |
| 187 | add_flags(extras, "-D%s", defines) | 201 | add_flags(extras, "-D%s", defines) |
| 188 | add_flags(extras, "-I%s", incdirs) | 202 | add_flags(extras, "-I%s", incdirs) |
| 189 | return execute(variables.CC.." "..variables.CFLAGS, "-c", "-Fo"..object, "-I"..variables.LUA_INCDIR, source, unpack(extras)) | 203 | return execute(variables.CC .. " " .. variables.CFLAGS, "-c", "-Fo" .. object, "-I" .. variables.LUA_INCDIR, source, _tl_table_unpack(extras)) |
| 190 | end | 204 | end |
| 191 | compile_library = function(library, objects, libraries, libdirs, name) | 205 | compile_library = function(library, objects, libraries, libdirs, name) |
| 192 | local extras = { unpack(objects) } | 206 | local extras = { _tl_table_unpack(objects) } |
| 193 | add_flags(extras, "-libpath:%s", libdirs) | 207 | add_flags(extras, "-libpath:%s", libdirs) |
| 194 | add_flags(extras, "%s.lib", libraries) | 208 | add_flags(extras, "%s.lib", libraries) |
| 195 | local basename = dir.base_name(library):gsub(".[^.]*$", "") | 209 | local basename = dir.base_name(library):gsub(".[^.]*$", "") |
| @@ -198,49 +212,49 @@ function builtin.run(rockspec, no_install) | |||
| 198 | local exported_name = name:gsub("%.", "_") | 212 | local exported_name = name:gsub("%.", "_") |
| 199 | exported_name = exported_name:match('^[^%-]+%-(.+)$') or exported_name | 213 | exported_name = exported_name:match('^[^%-]+%-(.+)$') or exported_name |
| 200 | def:write("EXPORTS\n") | 214 | def:write("EXPORTS\n") |
| 201 | def:write("luaopen_"..exported_name.."\n") | 215 | def:write("luaopen_" .. exported_name .. "\n") |
| 202 | def:close() | 216 | def:close() |
| 203 | local ok = execute(variables.LD, "-dll", "-def:"..deffile, "-out:"..library, dir.path(variables.LUA_LIBDIR, variables.LUALIB), unpack(extras)) | 217 | local ok = execute(variables.LD, "-dll", "-def:" .. deffile, "-out:" .. library, dir.path(variables.LUA_LIBDIR, variables.LUALIB), _tl_table_unpack(extras)) |
| 204 | local basedir = "" | 218 | local basedir = "" |
| 205 | if name:find("%.") ~= nil then | 219 | if name:find("%.") ~= nil then |
| 206 | basedir = name:gsub("%.%w+$", "\\") | 220 | basedir = name:gsub("%.%w+$", "\\") |
| 207 | basedir = basedir:gsub("%.", "\\") | 221 | basedir = basedir:gsub("%.", "\\") |
| 208 | end | 222 | end |
| 209 | local manifestfile = basedir .. basename..".dll.manifest" | 223 | local manifestfile = basedir .. basename .. ".dll.manifest" |
| 210 | 224 | ||
| 211 | if ok and fs.exists(manifestfile) then | 225 | if ok and fs.exists(manifestfile) then |
| 212 | ok = execute(variables.MT, "-manifest", manifestfile, "-outputresource:"..basedir..basename..".dll;2") | 226 | ok = execute(variables.MT, "-manifest", manifestfile, "-outputresource:" .. basedir .. basename .. ".dll;2") |
| 213 | end | 227 | end |
| 214 | return ok | 228 | return ok |
| 215 | end | 229 | end |
| 216 | --[[ TODO disable static libs until we fix the conflict in the manifest, which will take extending the manifest format. | 230 | |
| 217 | compile_static_library = function(library, objects, libraries, libdirs, name) | 231 | |
| 218 | local ok = execute(variables.AR, "-out:"..library, unpack(objects)) | 232 | |
| 219 | return ok | 233 | |
| 220 | end | 234 | |
| 221 | ]] | 235 | |
| 222 | else | 236 | else |
| 223 | compile_object = function(object, source, defines, incdirs) | 237 | compile_object = function(object, source, defines, incdirs) |
| 224 | local extras = {} | 238 | local extras = {} |
| 225 | add_flags(extras, "-D%s", defines) | 239 | add_flags(extras, "-D%s", defines) |
| 226 | add_flags(extras, "-I%s", incdirs) | 240 | add_flags(extras, "-I%s", incdirs) |
| 227 | return execute(variables.CC.." "..variables.CFLAGS, "-I"..variables.LUA_INCDIR, "-c", source, "-o", object, unpack(extras)) | 241 | return execute(variables.CC .. " " .. variables.CFLAGS, "-I" .. variables.LUA_INCDIR, "-c", source, "-o", object, _tl_table_unpack(extras)) |
| 228 | end | 242 | end |
| 229 | compile_library = function (library, objects, libraries, libdirs) | 243 | compile_library = function(library, objects, libraries, libdirs, name) |
| 230 | local extras = { unpack(objects) } | 244 | local extras = { _tl_table_unpack(objects) } |
| 231 | add_flags(extras, "-L%s", libdirs) | 245 | add_flags(extras, "-L%s", libdirs) |
| 232 | if cfg.gcc_rpath then | 246 | if cfg.gcc_rpath then |
| 233 | add_flags(extras, "-Wl,-rpath,%s", libdirs) | 247 | add_flags(extras, "-Wl,-rpath,%s", libdirs) |
| 234 | end | 248 | end |
| 235 | add_flags(extras, "-l%s", libraries) | 249 | add_flags(extras, "-l%s", libraries) |
| 236 | if cfg.link_lua_explicitly then | 250 | if cfg.link_lua_explicitly then |
| 237 | extras[#extras+1] = "-L"..variables.LUA_LIBDIR | 251 | extras[#extras + 1] = "-L" .. variables.LUA_LIBDIR |
| 238 | extras[#extras+1] = "-llua" | 252 | extras[#extras + 1] = "-llua" |
| 239 | end | 253 | end |
| 240 | return execute(variables.LD.." "..variables.LDFLAGS.." "..variables.LIBFLAG, "-o", library, unpack(extras)) | 254 | return execute(variables.LD .. " " .. variables.LDFLAGS .. " " .. variables.LIBFLAG, "-o", library, _tl_table_unpack(extras)) |
| 241 | end | 255 | end |
| 242 | compile_static_library = function(library, objects, libraries, libdirs, name) -- luacheck: ignore 211 | 256 | compile_static_library = function(library, objects, libraries, libdirs, name) |
| 243 | local ok = execute(variables.AR, "rc", library, unpack(objects)) | 257 | local ok = execute(variables.AR, "rc", library, _tl_table_unpack(objects)) |
| 244 | if ok then | 258 | if ok then |
| 245 | ok = execute(variables.RANLIB, library) | 259 | ok = execute(variables.RANLIB, library) |
| 246 | end | 260 | end |
| @@ -285,15 +299,15 @@ function builtin.run(rockspec, no_install) | |||
| 285 | if ext == "lua" then | 299 | if ext == "lua" then |
| 286 | local filename = dir.base_name(info) | 300 | local filename = dir.base_name(info) |
| 287 | if filename == "init.lua" and not name:match("%.init$") then | 301 | if filename == "init.lua" and not name:match("%.init$") then |
| 288 | moddir = path.module_to_path(name..".init") | 302 | moddir = path.module_to_path(name .. ".init") |
| 289 | else | 303 | else |
| 290 | local basename = name:match("([^.]+)$") | 304 | local basename = name:match("([^.]+)$") |
| 291 | filename = basename..".lua" | 305 | filename = basename .. ".lua" |
| 292 | end | 306 | end |
| 293 | local dest = dir.path(luadir, moddir, filename) | 307 | local dest = dir.path(luadir, moddir, filename) |
| 294 | lua_modules[info] = dest | 308 | lua_modules[info] = dest |
| 295 | else | 309 | else |
| 296 | info = {info} | 310 | info = { info } |
| 297 | end | 311 | end |
| 298 | end | 312 | end |
| 299 | if type(info) == "table" then | 313 | if type(info) == "table" then |
| @@ -314,21 +328,21 @@ function builtin.run(rockspec, no_install) | |||
| 314 | local objects = {} | 328 | local objects = {} |
| 315 | local sources = info.sources | 329 | local sources = info.sources |
| 316 | if info[1] then sources = info end | 330 | if info[1] then sources = info end |
| 317 | if type(sources) == "string" then sources = {sources} end | 331 | if type(sources) == "string" then sources = { sources } end |
| 318 | if type(sources) ~= "table" then | 332 | if not (type(sources) == "table") then |
| 319 | return nil, "error in rockspec: module '" .. name .. "' entry has no 'sources' list" | 333 | return nil, "error in rockspec: module '" .. name .. "' entry has no 'sources' list" |
| 320 | end | 334 | end |
| 321 | for _, source in ipairs(sources) do | 335 | for _, source in ipairs(sources) do |
| 322 | if type(source) ~= "string" then | 336 | if not (type(source) == "string") then |
| 323 | return nil, "error in rockspec: module '" .. name .. "' does not specify source correctly." | 337 | return nil, "error in rockspec: module '" .. name .. "' does not specify source correctly." |
| 324 | end | 338 | end |
| 325 | local object = source:gsub("%.[^.]*$", "."..cfg.obj_extension) | 339 | local object = source:gsub("%.[^.]*$", "." .. cfg.obj_extension) |
| 326 | if not object then | 340 | if not object then |
| 327 | object = source.."."..cfg.obj_extension | 341 | object = source .. "." .. cfg.obj_extension |
| 328 | end | 342 | end |
| 329 | ok = compile_object(object, source, info.defines, info.incdirs or autoincdirs) | 343 | ok = compile_object(object, source, info.defines, info.incdirs or autoincdirs) |
| 330 | if not ok then | 344 | if not ok then |
| 331 | return nil, "Failed compiling object "..object | 345 | return nil, "Failed compiling object " .. object |
| 332 | end | 346 | end |
| 333 | table.insert(objects, object) | 347 | table.insert(objects, object) |
| 334 | end | 348 | end |
| @@ -338,7 +352,7 @@ function builtin.run(rockspec, no_install) | |||
| 338 | util.schedule_function(fs.delete, compile_temp_dir) | 352 | util.schedule_function(fs.delete, compile_temp_dir) |
| 339 | end | 353 | end |
| 340 | 354 | ||
| 341 | local module_name = name:match("([^.]*)$").."."..util.matchquote(cfg.lib_extension) | 355 | local module_name = name:match("([^.]*)$") .. "." .. util.matchquote(cfg.lib_extension) |
| 342 | if moddir ~= "" then | 356 | if moddir ~= "" then |
| 343 | module_name = dir.path(moddir, module_name) | 357 | module_name = dir.path(moddir, module_name) |
| 344 | end | 358 | end |
| @@ -350,42 +364,42 @@ function builtin.run(rockspec, no_install) | |||
| 350 | lib_modules[build_name] = dir.path(libdir, module_name) | 364 | lib_modules[build_name] = dir.path(libdir, module_name) |
| 351 | ok = compile_library(build_name, objects, info.libraries, info.libdirs or autolibdirs, name) | 365 | ok = compile_library(build_name, objects, info.libraries, info.libdirs or autolibdirs, name) |
| 352 | if not ok then | 366 | if not ok then |
| 353 | return nil, "Failed compiling module "..module_name | 367 | return nil, "Failed compiling module " .. module_name |
| 354 | end | 368 | end |
| 355 | 369 | ||
| 356 | -- for backwards compatibility, try keeping a copy of the module | 370 | |
| 357 | -- in the old location (luasec-1.3.2-1 rockspec breaks otherwise) | 371 | |
| 358 | if cached_make_dir(dir.dir_name(module_name)) then | 372 | if cached_make_dir(dir.dir_name(module_name)) then |
| 359 | fs.copy(build_name, module_name) | 373 | fs.copy(build_name, module_name) |
| 360 | end | 374 | end |
| 361 | 375 | ||
| 362 | --[[ TODO disable static libs until we fix the conflict in the manifest, which will take extending the manifest format. | 376 | |
| 363 | module_name = name:match("([^.]*)$").."."..util.matchquote(cfg.static_lib_extension) | 377 | |
| 364 | if moddir ~= "" then | 378 | |
| 365 | module_name = dir.path(moddir, module_name) | 379 | |
| 366 | end | 380 | |
| 367 | lib_modules[module_name] = dir.path(libdir, module_name) | 381 | |
| 368 | ok = compile_static_library(module_name, objects, info.libraries, info.libdirs, name) | 382 | |
| 369 | if not ok then | 383 | |
| 370 | return nil, "Failed compiling static library "..module_name | 384 | |
| 371 | end | 385 | |
| 372 | ]] | 386 | |
| 373 | end | 387 | end |
| 374 | end | 388 | end |
| 375 | if not no_install then | 389 | if not no_install then |
| 376 | for _, mods in ipairs({{ tbl = lua_modules, perms = "read" }, { tbl = lib_modules, perms = "exec" }}) do | 390 | for _, mods in ipairs({ { tbl = lua_modules, perms = "read" }, { tbl = lib_modules, perms = "exec" } }) do |
| 377 | for name, dest in pairs(mods.tbl) do | 391 | for name, dest in pairs(mods.tbl) do |
| 378 | cached_make_dir(dir.dir_name(dest)) | 392 | cached_make_dir(dir.dir_name(dest)) |
| 379 | ok, err = fs.copy(name, dest, mods.perms) | 393 | ok, err = fs.copy(name, dest, mods.perms) |
| 380 | if not ok then | 394 | if not ok then |
| 381 | return nil, "Failed installing "..name.." in "..dest..": "..err | 395 | return nil, "Failed installing " .. name .. " in " .. dest .. ": " .. err |
| 382 | end | 396 | end |
| 383 | end | 397 | end |
| 384 | end | 398 | end |
| 385 | if fs.is_dir("lua") then | 399 | if fs.is_dir("lua") then |
| 386 | ok, err = fs.copy_contents("lua", luadir) | 400 | ok, err = fs.copy_contents("lua", luadir) |
| 387 | if not ok then | 401 | if not ok then |
| 388 | return nil, "Failed copying contents of 'lua' directory: "..err | 402 | return nil, "Failed copying contents of 'lua' directory: " .. err |
| 389 | end | 403 | end |
| 390 | end | 404 | end |
| 391 | end | 405 | end |
diff --git a/src/luarocks/core/types/installs.d.tl b/src/luarocks/core/types/installs.d.tl index 1e0747fc..92e58658 100644 --- a/src/luarocks/core/types/installs.d.tl +++ b/src/luarocks/core/types/installs.d.tl | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | local record installs | 1 | local record installs |
| 2 | record Install | 2 | record Install |
| 3 | is {string} | ||
| 3 | name: string | 4 | name: string |
| 4 | is_module_path: boolean | 5 | is_module_path: boolean |
| 5 | perms: string | 6 | perms: string |
