Mercurial > repo
comparison 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 |
comparison
equal
deleted
inserted
replaced
1131:ff65dfb63263 | 1132:d137f631bad5 |
---|---|
1 | |
2 --- A builtin build system: back-end to provide a portable way of building C-based Lua modules. | |
3 module("luarocks.build.builtin", package.seeall) | |
4 | |
5 local fs = require("luarocks.fs") | |
6 local path = require("luarocks.path") | |
7 local util = require("luarocks.util") | |
8 local cfg = require("luarocks.cfg") | |
9 local dir = require("luarocks.dir") | |
10 | |
11 --- Run a command displaying its execution on standard output. | |
12 -- @return boolean: true if command succeeds (status code 0), false | |
13 -- otherwise. | |
14 local function execute(...) | |
15 io.stdout:write(table.concat({...}, " ").."\n") | |
16 return fs.execute(...) | |
17 end | |
18 | |
19 --- Makes an RC file with an embedded Lua script, for building .exes on Windows | |
20 -- @return nil if could open files, error otherwise | |
21 local function make_rc(luafilename, rcfilename) | |
22 local rcfile = io.open(rcfilename, "w") | |
23 if not rcfile then | |
24 error("Could not open "..rcfilename.." for writing.") | |
25 end | |
26 rcfile:write("STRINGTABLE\r\nBEGIN\r\n") | |
27 | |
28 local i = 1 | |
29 for line in io.lines(luafilename) do | |
30 if not line:match("^#!") then | |
31 rcfile:write(i .. " \"") | |
32 line = line:gsub("\\", "\\\\"):gsub('"', '""'):gsub("[\r\n]+", "") | |
33 rcfile:write(line .. "\\r\\n\"\r\n") | |
34 i = i + 1 | |
35 end | |
36 end | |
37 | |
38 rcfile:write("END\r\n") | |
39 | |
40 rcfile:close() | |
41 end | |
42 | |
43 --- Driver function for the builtin build back-end. | |
44 -- @param rockspec table: the loaded rockspec. | |
45 -- @return boolean or (nil, string): true if no errors ocurred, | |
46 -- nil and an error message otherwise. | |
47 function run(rockspec) | |
48 assert(type(rockspec) == "table") | |
49 local compile_object, compile_library, compile_wrapper_binary | |
50 | |
51 local build = rockspec.build | |
52 local variables = rockspec.variables | |
53 | |
54 local function add_flags(extras, flag, flags) | |
55 if flags then | |
56 if type(flags) ~= "table" then | |
57 flags = { tostring(flags) } | |
58 end | |
59 util.variable_substitutions(flags, variables) | |
60 for _, v in ipairs(flags) do | |
61 table.insert(extras, flag:format(v)) | |
62 end | |
63 end | |
64 end | |
65 | |
66 if cfg.is_platform("mingw32") then | |
67 compile_object = function(object, source, defines, incdirs) | |
68 local extras = {} | |
69 add_flags(extras, "-D%s", defines) | |
70 add_flags(extras, "-I%s", incdirs) | |
71 return execute(variables.CC.." "..variables.CFLAGS, "-c", "-o", object, "-I"..variables.LUA_INCDIR, source, unpack(extras)) | |
72 end | |
73 compile_library = function(library, objects, libraries, libdirs, name) | |
74 local extras = { unpack(objects) } | |
75 add_flags(extras, "-L%s", libdirs) | |
76 add_flags(extras, "%s.lib", libraries) | |
77 extras[#extras+1] = dir.path(variables.LUA_LIBDIR, variables.LUALIB) | |
78 extras[#extras+1] = "-l" .. (variables.MSVCRT or "msvcr80") | |
79 local ok = execute(variables.LD.." "..variables.LIBFLAG, "-o", library, unpack(extras)) | |
80 return ok | |
81 end | |
82 compile_wrapper_binary = function(fullname, name) | |
83 local fullbasename = fullname:gsub("%.lua$", ""):gsub("/", "\\") | |
84 local basename = name:gsub("%.lua$", ""):gsub("/", "\\") | |
85 local rcname = basename..".rc" | |
86 local resname = basename..".o" | |
87 local wrapname = basename..".exe" | |
88 make_rc(fullname, fullbasename..".rc") | |
89 local ok = execute(variables.RC, "-o", resname, rcname) | |
90 if not ok then return ok end | |
91 ok = execute(variables.LD, "-o", wrapname, resname, variables.WRAPPER, | |
92 dir.path(variables.LUA_LIBDIR, variables.LUALIB), "-l" .. (variables.MSVCRT or "msvcr80"), "-luser32") | |
93 return ok, wrapname | |
94 end | |
95 elseif cfg.is_platform("win32") then | |
96 compile_object = function(object, source, defines, incdirs) | |
97 local extras = {} | |
98 add_flags(extras, "-D%s", defines) | |
99 add_flags(extras, "-I%s", incdirs) | |
100 return execute(variables.CC.." "..variables.CFLAGS, "-c", "-Fo"..object, "-I"..variables.LUA_INCDIR, source, unpack(extras)) | |
101 end | |
102 compile_library = function(library, objects, libraries, libdirs, name) | |
103 local extras = { unpack(objects) } | |
104 add_flags(extras, "-libpath:%s", libdirs) | |
105 add_flags(extras, "%s.lib", libraries) | |
106 local basename = dir.base_name(library):gsub(".[^.]*$", "") | |
107 local deffile = basename .. ".def" | |
108 local def = io.open(dir.path(fs.current_dir(), deffile), "w+") | |
109 def:write("EXPORTS\n") | |
110 def:write("luaopen_"..name:gsub("%.", "_").."\n") | |
111 def:close() | |
112 local ok = execute(variables.LD, "-dll", "-def:"..deffile, "-out:"..library, dir.path(variables.LUA_LIBDIR, variables.LUALIB), unpack(extras)) | |
113 local manifestfile = basename..".dll.manifest" | |
114 if ok and fs.exists(manifestfile) then | |
115 ok = execute(variables.MT, "-manifest", manifestfile, "-outputresource:"..basename..".dll;2") | |
116 end | |
117 return ok | |
118 end | |
119 compile_wrapper_binary = function(fullname, name) | |
120 local fullbasename = fullname:gsub("%.lua$", ""):gsub("/", "\\") | |
121 local basename = name:gsub("%.lua$", ""):gsub("/", "\\") | |
122 local rcname = basename..".rc" | |
123 local resname = basename..".res" | |
124 local wrapname = basename..".exe" | |
125 make_rc(fullname, fullbasename..".rc") | |
126 local ok = execute(variables.RC, "-r", "-fo"..resname, rcname) | |
127 if not ok then return ok end | |
128 ok = execute(variables.LD, "-out:"..wrapname, resname, variables.WRAPPER, | |
129 dir.path(variables.LUA_LIBDIR, variables.LUALIB), "user32.lib") | |
130 local manifestfile = wrapname..".manifest" | |
131 if ok and fs.exists(manifestfile) then | |
132 ok = execute(variables.MT, "-manifest", manifestfile, "-outputresource:"..wrapname..";1") | |
133 end | |
134 return ok, wrapname | |
135 end | |
136 else | |
137 compile_object = function(object, source, defines, incdirs) | |
138 local extras = {} | |
139 add_flags(extras, "-D%s", defines) | |
140 add_flags(extras, "-I%s", incdirs) | |
141 return execute(variables.CC.." "..variables.CFLAGS, "-I"..variables.LUA_INCDIR, "-c", source, "-o", object, unpack(extras)) | |
142 end | |
143 compile_library = function (library, objects, libraries, libdirs) | |
144 local extras = { unpack(objects) } | |
145 add_flags(extras, "-L%s", libdirs) | |
146 if cfg.gcc_rpath then | |
147 add_flags(extras, "-Wl,-rpath,%s:", libdirs) | |
148 end | |
149 add_flags(extras, "-l%s", libraries) | |
150 if cfg.is_platform("cygwin") then | |
151 add_flags(extras, "-l%s", {"lua"}) | |
152 end | |
153 return execute(variables.LD.." "..variables.LIBFLAG, "-o", library, "-L"..variables.LUA_LIBDIR, unpack(extras)) | |
154 end | |
155 compile_wrapper_binary = function(fullname, name) return true, name end | |
156 end | |
157 | |
158 local ok = true | |
159 local err = "Build error" | |
160 local built_modules = {} | |
161 local luadir = path.lua_dir(rockspec.name, rockspec.version) | |
162 local libdir = path.lib_dir(rockspec.name, rockspec.version) | |
163 local docdir = path.doc_dir(rockspec.name, rockspec.version) | |
164 -- On Windows, compiles an .exe for each Lua file in build.install.bin, and | |
165 -- replaces the filename with the .exe name. Strips the .lua extension if it exists, | |
166 -- otherwise just appends .exe to the name | |
167 if build.install and build.install.bin then | |
168 for i, name in ipairs(build.install.bin) do | |
169 local fullname = dir.path(fs.current_dir(), name) | |
170 local match = name:match("%.lua$") | |
171 local basename = name:gsub("%.lua$", "") | |
172 local file | |
173 if not match then | |
174 file = io.open(fullname) | |
175 end | |
176 if match or (file and file:read():match("#!.*lua.*")) then | |
177 ok, name = compile_wrapper_binary(fullname, name) | |
178 if ok then | |
179 build.install.bin[i] = name | |
180 else | |
181 if file then file:close() end | |
182 return nil, "Build error in wrapper binaries" | |
183 end | |
184 end | |
185 if file then file:close() end | |
186 end | |
187 end | |
188 for name, info in pairs(build.modules) do | |
189 local moddir = path.module_to_path(name) | |
190 if type(info) == "string" then | |
191 local ext = info:match(".([^.]+)$") | |
192 if ext == "lua" then | |
193 if info:match("init%.lua$") and not name:match("%.init$") then | |
194 moddir = path.module_to_path(name..".init") | |
195 end | |
196 local dest = dir.path(luadir, moddir) | |
197 built_modules[info] = dest | |
198 else | |
199 info = {info} | |
200 end | |
201 end | |
202 if type(info) == "table" then | |
203 local objects = {} | |
204 local sources = info.sources | |
205 if info[1] then sources = info end | |
206 if type(sources) == "string" then sources = {sources} end | |
207 for _, source in ipairs(sources) do | |
208 local object = source:gsub(".[^.]*$", "."..cfg.obj_extension) | |
209 if not object then | |
210 object = source.."."..cfg.obj_extension | |
211 end | |
212 ok = compile_object(object, source, info.defines, info.incdirs) | |
213 if not ok then | |
214 err = "Failed compiling object "..object | |
215 break | |
216 end | |
217 table.insert(objects, object) | |
218 end | |
219 if not ok then break end | |
220 local module_name = dir.path(moddir, name:match("([^.]*)$").."."..cfg.lib_extension):gsub("//", "/") | |
221 if moddir ~= "" then | |
222 fs.make_dir(moddir) | |
223 end | |
224 local dest = dir.path(libdir, moddir) | |
225 built_modules[module_name] = dest | |
226 ok = compile_library(module_name, objects, info.libraries, info.libdirs, name) | |
227 if not ok then | |
228 err = "Failed compiling module "..module_name | |
229 break | |
230 end | |
231 end | |
232 end | |
233 for name, dest in pairs(built_modules) do | |
234 fs.make_dir(dest) | |
235 ok = fs.copy(name, dest) | |
236 if not ok then | |
237 err = "Failed installing "..name.." in "..dest | |
238 break | |
239 end | |
240 end | |
241 if ok then | |
242 if fs.is_dir("lua") then | |
243 ok = fs.copy_contents("lua", luadir) | |
244 if not ok then err = "Failed copying contents of 'lua' directory." end | |
245 end | |
246 end | |
247 if ok then | |
248 return true | |
249 else | |
250 return nil, err | |
251 end | |
252 end |