diff share/lua/5.2/luarocks/build/builtin.lua @ 1132:d137f631bad5

<GreyKnight> (cd luabuild/luarocks-2.0.12; make install)
author HackBot
date Fri, 14 Dec 2012 22:24:27 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/build/builtin.lua	Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,252 @@
+
+--- A builtin build system: back-end to provide a portable way of building C-based Lua modules.
+module("luarocks.build.builtin", package.seeall)
+
+local fs = require("luarocks.fs")
+local path = require("luarocks.path")
+local util = require("luarocks.util")
+local cfg = require("luarocks.cfg")
+local dir = require("luarocks.dir")
+
+--- Run a command displaying its execution on standard output.
+-- @return boolean: true if command succeeds (status code 0), false
+-- otherwise.
+local function execute(...)
+   io.stdout:write(table.concat({...}, " ").."\n")
+   return fs.execute(...)
+end
+
+--- Makes an RC file with an embedded Lua script, for building .exes on Windows
+-- @return nil if could open files, error otherwise
+local function make_rc(luafilename, rcfilename)
+   local rcfile = io.open(rcfilename, "w")
+   if not rcfile then
+      error("Could not open "..rcfilename.." for writing.")
+   end
+   rcfile:write("STRINGTABLE\r\nBEGIN\r\n")
+
+   local i = 1
+   for line in io.lines(luafilename) do
+      if not line:match("^#!") then
+         rcfile:write(i .. " \"")
+         line = line:gsub("\\", "\\\\"):gsub('"', '""'):gsub("[\r\n]+", "")
+         rcfile:write(line .. "\\r\\n\"\r\n")
+         i = i + 1
+      end
+   end
+
+   rcfile:write("END\r\n")
+
+   rcfile:close()
+end
+
+--- Driver function for the builtin build back-end.
+-- @param rockspec table: the loaded rockspec.
+-- @return boolean or (nil, string): true if no errors ocurred,
+-- nil and an error message otherwise.
+function run(rockspec)
+   assert(type(rockspec) == "table")
+   local compile_object, compile_library, compile_wrapper_binary
+
+   local build = rockspec.build
+   local variables = rockspec.variables
+
+   local function add_flags(extras, flag, flags)
+      if flags then
+         if type(flags) ~= "table" then
+            flags = { tostring(flags) }
+         end
+         util.variable_substitutions(flags, variables)
+         for _, v in ipairs(flags) do
+            table.insert(extras, flag:format(v))
+         end
+      end
+   end
+
+   if cfg.is_platform("mingw32") then
+      compile_object = function(object, source, defines, incdirs)
+         local extras = {}
+         add_flags(extras, "-D%s", defines)
+         add_flags(extras, "-I%s", incdirs)
+         return execute(variables.CC.." "..variables.CFLAGS, "-c", "-o", object, "-I"..variables.LUA_INCDIR, source, unpack(extras))
+      end
+      compile_library = function(library, objects, libraries, libdirs, name)
+         local extras = { unpack(objects) }
+         add_flags(extras, "-L%s", libdirs)
+         add_flags(extras, "%s.lib", libraries)
+         extras[#extras+1] = dir.path(variables.LUA_LIBDIR, variables.LUALIB)
+         extras[#extras+1] = "-l" .. (variables.MSVCRT or "msvcr80")
+         local ok = execute(variables.LD.." "..variables.LIBFLAG, "-o", library, unpack(extras))
+         return ok
+      end
+      compile_wrapper_binary = function(fullname, name)
+         local fullbasename = fullname:gsub("%.lua$", ""):gsub("/", "\\")
+         local basename = name:gsub("%.lua$", ""):gsub("/", "\\")
+         local rcname = basename..".rc"
+         local resname = basename..".o"
+         local wrapname = basename..".exe"
+         make_rc(fullname, fullbasename..".rc")
+         local ok = execute(variables.RC, "-o", resname, rcname)
+         if not ok then return ok end
+         ok = execute(variables.LD, "-o", wrapname, resname, variables.WRAPPER,
+                      dir.path(variables.LUA_LIBDIR, variables.LUALIB), "-l" .. (variables.MSVCRT or "msvcr80"), "-luser32")
+         return ok, wrapname
+      end
+   elseif cfg.is_platform("win32") then
+      compile_object = function(object, source, defines, incdirs)
+         local extras = {}
+         add_flags(extras, "-D%s", defines)
+         add_flags(extras, "-I%s", incdirs)
+         return execute(variables.CC.." "..variables.CFLAGS, "-c", "-Fo"..object, "-I"..variables.LUA_INCDIR, source, unpack(extras))
+      end
+      compile_library = function(library, objects, libraries, libdirs, name)
+         local extras = { unpack(objects) }
+         add_flags(extras, "-libpath:%s", libdirs)
+         add_flags(extras, "%s.lib", libraries)
+         local basename = dir.base_name(library):gsub(".[^.]*$", "")
+         local deffile = basename .. ".def"
+         local def = io.open(dir.path(fs.current_dir(), deffile), "w+")
+         def:write("EXPORTS\n")
+         def:write("luaopen_"..name:gsub("%.", "_").."\n")
+         def:close()
+         local ok = execute(variables.LD, "-dll", "-def:"..deffile, "-out:"..library, dir.path(variables.LUA_LIBDIR, variables.LUALIB), unpack(extras))
+         local manifestfile = basename..".dll.manifest"
+         if ok and fs.exists(manifestfile) then
+            ok = execute(variables.MT, "-manifest", manifestfile, "-outputresource:"..basename..".dll;2")
+         end
+         return ok
+      end
+      compile_wrapper_binary = function(fullname, name)
+         local fullbasename = fullname:gsub("%.lua$", ""):gsub("/", "\\")
+         local basename = name:gsub("%.lua$", ""):gsub("/", "\\")
+         local rcname = basename..".rc"
+         local resname = basename..".res"
+         local wrapname = basename..".exe"
+         make_rc(fullname, fullbasename..".rc")
+         local ok = execute(variables.RC, "-r", "-fo"..resname, rcname)
+         if not ok then return ok end
+         ok = execute(variables.LD, "-out:"..wrapname, resname, variables.WRAPPER,
+                      dir.path(variables.LUA_LIBDIR, variables.LUALIB), "user32.lib")
+         local manifestfile = wrapname..".manifest"
+         if ok and fs.exists(manifestfile) then
+            ok = execute(variables.MT, "-manifest", manifestfile, "-outputresource:"..wrapname..";1")
+         end
+         return ok, wrapname
+      end
+   else
+      compile_object = function(object, source, defines, incdirs)
+         local extras = {}
+         add_flags(extras, "-D%s", defines)
+         add_flags(extras, "-I%s", incdirs)
+         return execute(variables.CC.." "..variables.CFLAGS, "-I"..variables.LUA_INCDIR, "-c", source, "-o", object, unpack(extras))
+      end
+      compile_library = function (library, objects, libraries, libdirs)
+         local extras = { unpack(objects) }
+         add_flags(extras, "-L%s", libdirs)
+         if cfg.gcc_rpath then
+            add_flags(extras, "-Wl,-rpath,%s:", libdirs)
+         end
+         add_flags(extras, "-l%s", libraries)
+         if cfg.is_platform("cygwin") then
+            add_flags(extras, "-l%s", {"lua"})
+         end
+         return execute(variables.LD.." "..variables.LIBFLAG, "-o", library, "-L"..variables.LUA_LIBDIR, unpack(extras))
+      end
+      compile_wrapper_binary = function(fullname, name) return true, name end
+   end
+
+   local ok = true
+   local err = "Build error"
+   local built_modules = {}
+   local luadir = path.lua_dir(rockspec.name, rockspec.version)
+   local libdir = path.lib_dir(rockspec.name, rockspec.version)
+   local docdir = path.doc_dir(rockspec.name, rockspec.version)
+   -- On Windows, compiles an .exe for each Lua file in build.install.bin, and
+   -- replaces the filename with the .exe name. Strips the .lua extension if it exists,
+   -- otherwise just appends .exe to the name
+   if build.install and build.install.bin then
+     for i, name in ipairs(build.install.bin) do
+       local fullname = dir.path(fs.current_dir(), name)
+       local match = name:match("%.lua$")
+       local basename = name:gsub("%.lua$", "")
+       local file
+       if not match then
+          file = io.open(fullname)
+       end
+       if match or (file and file:read():match("#!.*lua.*")) then
+          ok, name = compile_wrapper_binary(fullname, name)
+          if ok then
+             build.install.bin[i] = name
+          else
+             if file then file:close() end
+             return nil, "Build error in wrapper binaries"
+          end
+       end
+       if file then file:close() end
+     end
+   end
+   for name, info in pairs(build.modules) do
+      local moddir = path.module_to_path(name)
+      if type(info) == "string" then
+         local ext = info:match(".([^.]+)$")
+         if ext == "lua" then
+            if info:match("init%.lua$") and not name:match("%.init$") then
+               moddir = path.module_to_path(name..".init")
+            end
+            local dest = dir.path(luadir, moddir)
+            built_modules[info] = dest
+         else
+            info = {info}
+         end
+      end
+      if type(info) == "table" then
+         local objects = {}
+         local sources = info.sources
+         if info[1] then sources = info end
+         if type(sources) == "string" then sources = {sources} end
+         for _, source in ipairs(sources) do
+            local object = source:gsub(".[^.]*$", "."..cfg.obj_extension)
+            if not object then
+               object = source.."."..cfg.obj_extension
+            end
+            ok = compile_object(object, source, info.defines, info.incdirs)
+            if not ok then
+               err = "Failed compiling object "..object
+               break
+            end
+            table.insert(objects, object)
+         end
+         if not ok then break end
+         local module_name = dir.path(moddir, name:match("([^.]*)$").."."..cfg.lib_extension):gsub("//", "/")
+         if moddir ~= "" then
+            fs.make_dir(moddir)
+         end
+         local dest = dir.path(libdir, moddir)
+         built_modules[module_name] = dest
+         ok = compile_library(module_name, objects, info.libraries, info.libdirs, name)
+         if not ok then
+            err = "Failed compiling module "..module_name
+            break
+         end
+      end
+   end
+   for name, dest in pairs(built_modules) do
+      fs.make_dir(dest)
+      ok = fs.copy(name, dest)
+      if not ok then
+         err = "Failed installing "..name.." in "..dest
+         break
+      end
+   end
+   if ok then
+      if fs.is_dir("lua") then
+         ok = fs.copy_contents("lua", luadir)
+         if not ok then err = "Failed copying contents of 'lua' directory." end
+      end
+   end
+   if ok then
+      return true
+   else
+      return nil, err
+   end
+end