downgraded default profile to core2
[k8sbuild.git] / sbuild.lua
blobaa8a77a1fbbe8e58e98f4f99360ad9fac9a80b54
1 #!/usr/bin/lua
2 -- semi-automated SlackBuild script
4 local pinfo;
5 local pkgdir;
6 local buildDirName;
7 local getPrefixDir;
9 local myOpt = {
10 chownUser = "",
11 --profile = "speed",
12 profile = "empty",
13 cfgname = "./configure",
14 install_path = "/usr",
15 pkgExt = "txz",
16 srcBuildUser = "",
17 pkgdestdir = "",
18 no_pcp = false,
19 no_prcp = false,
20 no_dox = false,
21 no_cfg = false,
22 no_pss = false,
23 make_build_dir = false,
24 keep_build_dir = false,
25 use_fakeroot = false,
26 using_cmake = false,
27 --force_native_profile = true,
28 --no_docdir = true,
29 --no_libdir = true,
30 --no_localstatedir = true,
34 local function getCPUs ()
35 local fi =assert(io.popen("nproc", "r"));
36 local n = assert(fi:read("*n"));
37 --if n > 2 then n = n-1; end; -- leave one core free for other tasks
38 return n;
39 end;
41 local jobs = getCPUs();
42 local force_native_profile = true;
46 local function logMessage (fmt, ...)
47 local s = fmt:format(...);
48 s = s:gsub("\n", "\n*** ");
49 io.write("*** ", s, "\n"); io.flush();
50 end;
53 local function logMessageToFile (fmt, ...)
54 local s = fmt:format(...);
55 s = s:gsub("\n", "\n*** ");
56 local fo = io.open("/tmp/zsbuild_times.log", "a");
57 fo:write("*** ", s, "\n");
58 fo:close();
59 io.write("*** ", s, "\n"); io.flush();
60 end;
63 local function timeStr (secs)
64 local mins = math.floor(secs/60);
65 secs = secs%60;
66 local hours = math.floor(mins/60);
67 mins = mins%60;
68 return ("%02d:%02d:%02d"):format(hours, mins, secs);
69 end;
72 -- get user
73 --[[
74 local meUser, meGroup;
75 (function ()
76 local fl = assert(io.popen("whoami", "r"));
77 local s = assert(fl:read());
78 fl:close();
79 s = s:match("^%s*(.-)%s*$");
80 if s == "" then error("who am i?!"); end;
81 --print("me: "..s);
82 meUser = s;
83 end)();
84 -- get group
85 (function ()
86 local fl = assert(io.popen("id -gn", "r"));
87 local s = assert(fl:read());
88 fl:close();
89 s = s:match("^%s*(.-)%s*$");
90 if s == "" then error("who am i?!"); end;
91 --print("me: "..s);
92 meGroup = s;
93 end)();
94 myOpt.chownUser = meUser..":"..meGroup;
98 local weAreBuildingSrcz = false; -- this flag means that we are building sources and shouldn't be 'root'
101 local pkgDestDir;
103 local optPathList = {
104 "./!.xopt",
105 "~/.sbuild/!.xopt",
106 "~/.sbuild/xopt/!.xopt",
110 -- -mpreferred-stack-boundary=2
112 -- profiles
113 local defCompOptProfs = {
114 speed = {
115 CFLAGS = "-O3 -march=core2 -mtune=core2 -fwrapv -fno-strict-aliasing -fno-delete-null-pointer-checks -fno-strict-overflow -mstackrealign",
116 CXXFLAGS = "-O3 -march=core2 -mtune=core2 -fwrapv -fno-strict-aliasing -fno-delete-null-pointer-checks -fno-strict-overflow -mstackrealign",
118 speedfastmath = {
119 CFLAGS = "-O3 -march=core2 -mtune=core2 -fwrapv -ffast-math -fno-strict-aliasing -fno-delete-null-pointer-checks -fno-strict-overflow -mstackrealign",
120 CXXFLAGS = "-O3 -march=core2 -mtune=core2 -fwrapv -ffast-math -fno-strict-aliasing -fno-delete-null-pointer-checks -fno-strict-overflow -mstackrealign",
122 native = {
123 CFLAGS = "-O2 -march=core2 -mtune=core2 -fwrapv -fno-strict-aliasing -fno-delete-null-pointer-checks -fno-strict-overflow -mstackrealign",
124 CXXFLAGS = "-O2 -march=core2 -mtune=core2 -fwrapv -fno-strict-aliasing -fno-delete-null-pointer-checks -fno-strict-overflow -mstackrealign",
126 nativenoalias = {
127 CFLAGS = "-O2 -march=core2 -mtune=core2 -fno-strict-aliasing -fwrapv -fno-delete-null-pointer-checks -fno-strict-overflow -mstackrealign",
128 CXXFLAGS = "-O2 -march=core2 -mtune=core2 -fno-strict-aliasing -fwrapv -fno-delete-null-pointer-checks -fno-strict-overflow -mstackrealign",
130 nativenoaliasopt = {
131 CFLAGS = "-O3 -march=core2 -mtune=core2 -fno-strict-aliasing -fwrapv -fno-delete-null-pointer-checks -fno-strict-overflow -mstackrealign",
132 CXXFLAGS = "-O3 -march=core2 -mtune=core2 -fno-strict-aliasing -fwrapv -fno-delete-null-pointer-checks -fno-strict-overflow -mstackrealign",
134 size = {
135 CFLAGS = "-Os -march=i586 -fwrapv -fno-strict-aliasing -fno-delete-null-pointer-checks -fno-strict-overflow -mstackrealign",
136 CXXFLAGS = "-Os -march=i586 -fwrapv -fno-strict-aliasing -fno-delete-null-pointer-checks -fno-strict-overflow -mstackrealign",
138 wmaker = {
139 CFLAGS = "-O1 -fomit-frame-pointer -fwrapv -fno-strict-aliasing -fno-delete-null-pointer-checks -fno-strict-overflow -mstackrealign",
140 CXXFLAGS = "-O1 -fomit-frame-pointer -fwrapv -fno-strict-aliasing -fno-delete-null-pointer-checks -fno-strict-overflow -mstackrealign",
142 debug = {
143 CFLAGS = "-O0 -g -fwrapv -fno-strict-aliasing -fno-delete-null-pointer-checks -fno-strict-overflow -mstackrealign",
144 CXXFLAGS = "-O0 -g -fwrapv -fno-strict-aliasing -fno-delete-null-pointer-checks -fno-strict-overflow -mstackrealign",
145 LDFLAGS = "-g"
147 empty = {
148 CFLAGS = "",
149 CXXFLAGS = "",
151 nativeo2 = {
152 CFLAGS = "-O2 -march=core2 -mtune=core2 -fwrapv -fno-strict-aliasing -fno-delete-null-pointer-checks -fno-strict-overflow -mstackrealign",
153 CXXFLAGS = "-O2 -march=core2 -mtune=core2 -fwrapv -fno-strict-aliasing -fno-delete-null-pointer-checks -fno-strict-overflow -mstackrealign",
155 nativeemacs = {
156 CFLAGS = "-O2 -march=core2 -mtune=core2 -Wno-pointer-sign -fwrapv -fno-strict-aliasing -fno-delete-null-pointer-checks -fno-strict-overflow -mstackrealign",
157 CXXFLAGS = "-O2 -march=core2 -mtune=core2 -Wno-pointer-sign -fwrapv -fno-strict-aliasing -fno-delete-null-pointer-checks -fno-strict-overflow -mstackrealign",
159 nativeo1 = {
160 CFLAGS = "-O1 -fwrapv -fno-strict-aliasing -fno-delete-null-pointer-checks -fno-strict-overflow -mstackrealign",
161 CXXFLAGS = "-O1 -fwrapv -fno-strict-aliasing -fno-delete-null-pointer-checks -fno-strict-overflow -mstackrealign",
163 pngfix = {
164 CFLAGS = "-Dpng_set_gray_1_2_4_to_8=png_set_expand_gray_1_2_4_to_8",
165 CXXFLAGS = "-Dpng_set_gray_1_2_4_to_8=png_set_expand_gray_1_2_4_to_8",
167 original = {
168 CFLAGS = "",
169 CXXFLAGS = "",
171 i586 = {
172 CFLAGS = "-O2 -march=i586 -mtune=i586 -fwrapv -fno-strict-aliasing -fno-delete-null-pointer-checks -fno-strict-overflow -mstackrealign",
173 CXXFLAGS = "-O2 -march=i586 -mtune=i586 -fwrapv -fno-strict-aliasing -fno-delete-null-pointer-checks -fno-strict-overflow -mstackrealign",
175 i686 = {
176 CFLAGS = "-O2 -march=i686 -mtune=i686 -fwrapv -fno-strict-aliasing -fno-delete-null-pointer-checks -fno-strict-overflow -mstackrealign",
177 CXXFLAGS = "-O2 -march=i686 -mtune=i686 -fwrapv -fno-strict-aliasing -fno-delete-null-pointer-checks -fno-strict-overflow -mstackrealign",
179 core2 = {
180 CFLAGS = "-O2 -march=core2 -mtune=core2 -mno-avx -fwrapv -fno-strict-aliasing -fno-delete-null-pointer-checks -fno-strict-overflow -mstackrealign",
181 CXXFLAGS = "-O2 -march=core2 -mtune=core2 -mno-avx -fwrapv -fno-strict-aliasing -fno-delete-null-pointer-checks -fno-strict-overflow -mstackrealign",
183 pentium4 = {
184 CFLAGS = "-O2 -march=pentium4 -mtune=pentium4 -mno-avx -fwrapv -fno-strict-aliasing -fno-delete-null-pointer-checks -fno-strict-overflow -mstackrealign",
185 CXXFLAGS = "-O2 -march=pentium4 -mtune=pentium4 -mno-avx -fwrapv -fno-strict-aliasing -fno-delete-null-pointer-checks -fno-strict-overflow -mstackrealign",
187 nehalem = {
188 CFLAGS = "-O2 -march=nehalem -mtune=nehalem -fwrapv -fno-strict-aliasing -fno-delete-null-pointer-checks -fno-strict-overflow -mstackrealign",
189 CXXFLAGS = "-O2 -march=nehalem -mtune=nehalem -fwrapv -fno-strict-aliasing -fno-delete-null-pointer-checks -fno-strict-overflow -mstackrealign",
191 haswell = {
192 CFLAGS = "-O2 -march=haswell -mtune=haswell -fwrapv -fno-strict-aliasing -fno-delete-null-pointer-checks -fno-strict-overflow -mstackrealign",
193 CXXFLAGS = "-O2 -march=haswell -mtune=haswell -fwrapv -fno-strict-aliasing -fno-delete-null-pointer-checks -fno-strict-overflow -mstackrealign",
199 local confOpt = {};
200 local compOpt = {};
201 local slackDesc = {};
202 local slackReq = {};
203 local unpackScript = {};
204 local postcfgPatches = {};
205 local precfgPatches = {};
206 local doclist = {}; -- [docs...]
207 local cfglist = {};
208 local psslist = {};
209 local doinstlist = {};
210 local scinstalllist = {};
211 local scmakelist = {};
212 local scconfigurelist = {};
213 local scpreconfigurelist = {};
214 local scpremakelist = {};
215 local buildEnvVars = {};
218 local join = table.concat;
221 local function verCompare (v0, v1)
222 local s0, s1 = {}, {};
223 print(v0 < v1);
224 for m in v0:gmatch("[^.]+") do s0[#s0+1] = m; end;
225 for m in v1:gmatch("[^.]+") do s1[#s1+1] = m; end;
226 local f = 1;
227 while f <= #s0 and f <= #s1 do
228 local n0 = tonumber(s0[f]);
229 local n1 = tonumber(s1[f]);
230 if not n0 or not n1 then
231 n0 = s0[f]:lower();
232 n1 = s1[f]:lower();
233 end;
234 if n0 < n1 then return -1;
235 elseif n0 > n1 then return 1;
236 end;
237 f = f+1;
238 end;
239 if #s0 < #s1 then return -1;
240 elseif #s0 > #s1 then return 1;
241 end;
242 return 0;
243 end;
246 local function isShellCh (ch)
247 if (ch >= "\1" and ch <= "\42") or
248 (ch >= "\59" and ch <= "\60") or
249 (ch >= "\62" and ch <= "\63") or
250 (ch >= "\91" and ch <= "\93") or
251 (ch >= "\123" and ch <= "\125") or ch == "\96" then
252 return true;
253 end;
255 return false;
256 end;
259 function string.shQuote (s)
260 s = s:gsub(".", function (ch)
261 if ch == "\0" then return ""; end;
262 if isShellCh(ch) then return "\\"..ch; end; --
263 return ch;
264 end);
266 return s;
267 end;
270 -- find and open file
271 -- not pathList: take optPathList
272 -- return: io-file, filename or false
273 local function openFile (fname, pathList)
274 pathList = pathList or optPathList;
275 for _, path in ipairs(pathList) do
276 local fn = path:gsub("!!", "\0");
277 fn = fn:gsub("!", fname);
278 fn = fn:gsub("%z", "!");
279 if fn:match("^~/") then
280 local hp = os.getenv("HOME");
281 if not hp or hp == "" then error("no $HOME var set!"); end;
282 if not hp:match("/$") then hp = hp.."/"; end;
283 fn = hp..fn:sub(3, -1);
284 end;
285 local fl = io.open(fn, "r");
286 if fl then
287 io.stderr:write("using ", fn, "\n"); io.stderr:flush();
288 return fl, fn;
289 end;
290 end;
292 return false;
293 end;
296 -- i'm too lazy to do regexps
297 -- parse option string
298 local function parseOption (s)
299 local res, qq, screen, iscfgopt = {};
301 local o = s;
302 s = s:match("^%s*(.-)%s*$");
303 if s:match("^[#;]") then return false; end;
304 if s:match("^%-%-") then
305 iscfgopt = true;
306 s = s:sub(3, -1);
307 s = s:match("^%s*(.-)%s*$");
308 else
309 iscfgopt = false;
310 if o:match("^%s") then return false; end; -- some silly text
311 end;
312 if s == "" then return false; end;
313 for ch in s:gmatch(".") do
314 if screen then
315 screen = false;
316 else
317 if ch == "\92" then screen = true;
318 elseif ch == '"' then qq = not qq;
319 elseif not qq and ch <= " " then break;
320 end;
321 end;
322 if not screen then res[#res+1] = ch; end;
323 end;
324 if #res < 1 then return false; end;
325 if iscfgopt then res[1] = "--"..res[1]; end;
327 return join(res), iscfgopt;
328 end;
331 -- if iscfgopt is false, treat as compiler option
332 local function parseCMakeOption (s)
333 local iscfgopt = false;
335 local o = s;
336 s = s:match("^%s*(.-)%s*$");
337 if s:match("^[#;]") then return false; end;
338 if s == "" then return false; end;
339 if s:match("^%-") then
340 iscfgopt = true;
341 s = s:match("^%s*(.-)%s*$");
342 return s, iscfgopt;
343 elseif o:match("^%s") then
344 iscfgopt = true;
345 s = s:match("^([^%s]+)");
346 s = "-D"..s;
347 return s, iscfgopt;
348 end;
350 local res, qq, screen = {};
352 for ch in s:gmatch(".") do
353 if screen then
354 screen = false;
355 else
356 if ch == "\92" then screen = true;
357 elseif ch == '"' then qq = not qq;
358 elseif not qq and ch <= " " then break;
359 end;
360 end;
361 if not screen then res[#res+1] = ch; end;
362 end;
364 return join(res), false;
365 end;
368 -- split to name/value pair
369 -- return: name, value, condition (char after "=" or false)
370 local function nameValueSplit (s)
371 local n, c, v = s:match("^([^=]+)%=([?+!]?)(.*)$");
372 if not n or not c or not v then return s:match("^%s*(.-)%s*$"), "", false; end;
373 if c == "" then c = false; end;
374 v = v:match("^%s*(.-)%s*$");
375 local vv = v:match('^"(.-)"$'); if vv then v = vv; end;
376 return n:match("^%s*(.-)%s*$"), v, c;
377 end;
380 local function setProfile (name)
381 local prof = defCompOptProfs[name];
382 assert(prof, "unknown compiler profile");
383 for n, v in pairs(prof) do
384 if not compOpt[n] then compOpt[n] = v; end;
385 --print(n, v);
386 end;
387 myOpt.profile = name;
388 end;
391 local function fixFuckinCaret ()
392 if compOpt["CFLAGS"] then
393 compOpt["CFLAGS"] = compOpt["CFLAGS"].." -fno-diagnostics-show-caret";
394 end;
395 if compOpt["CXXFLAGS"] then
396 compOpt["CXXFLAGS"] = compOpt["CXXFLAGS"].." -fno-diagnostics-show-caret";
397 end;
398 end;
401 local function copyEnvVars ()
402 for k, v in pairs(buildEnvVars) do
403 if v == "" then
404 compOpt[k] = nil;
405 else
406 compOpt[k] = v;
407 end;
408 end;
409 end;
412 local function optparseBooleanOptValue (optname, value)
413 if not value then value = "ona"; end;
414 value = value:lower();
416 if value == "tan" or value == "yes" or value == "true" or
417 value == "1" or value == "t" or value == "y" then
418 return true;
419 end;
421 if value == "ona" or value == "no" or value == "false" or
422 value == "0" or value == "o" or value == "n" or value == "f" then
423 return false;
424 end;
426 error("option '"..optname.."' expects boolean, but got '"..value.."'");
427 end;
430 local function optparseBooleanOpt (name, value, cchar, str)
431 --print("name=["..name.."]; value=["..value.."]");
432 myOpt[name] = optparseBooleanOptValue(name, value);
433 --local v = myOpt[name];
434 --if v then v = "tan"; else v = "ona"; end;
435 --logMessage("BOOL: '%s' = '%s' (%s)", name, value or "", v);
436 end;
439 -- cchar: condition (char after "=" or false)
440 -- str: unparsed string
441 local myOptH = {
442 chown_user = {
443 dsc = "chown_user=username[:group] -- NO DEFAULT!",
444 handler = function (name, value, cchar, str)
445 if not value then value = ""; end;
446 myOpt.chownUser = value;
447 end;
449 pkg_dest_dir = {
450 dsc = "pkg_dest_dir=path-for-package (~/.sbuild/pkg)",
451 handler = function (name, value, cchar, str)
452 if not value then error("wtf?!"); end;
453 myOpt.pkgdestdir = value;
454 end;
456 pkg_ext = {
457 help = "pkg_ext=[txz]",
458 handler = function (name, value, cchar, str)
459 if not value then value = ""; end;
460 myOpt.pkgExt = value;
461 end;
463 src_build_user = {
464 help = "src_build_user user to chown when building the package (default to chown_user)",
465 handler = function (name, value, cchar, str)
466 if not value then value = ""; end;
467 myOpt.srcBuildUser = value;
468 end;
470 profile = {
471 help = "profile=[native|speed|size|empty]",
472 handler = function (name, value, cchar, str)
473 if not value then value = ""; end;
474 setProfile(value);
475 end;
477 xflags = {
478 help = "xflags=[+]flags -- modify CFLAGS and CXXFLAGS",
479 handler = function (name, value, cchar, str)
480 if not value then value = ""; end;
481 if cchar == "+" then
482 if value ~= "" then
483 if compOpt.CFLAGS then compOpt.CFLAGS = compOpt.CFLAGS.." ";
484 else compOpt.CFLAGS = "";
485 end;
486 compOpt.CFLAGS = compOpt.CFLAGS..value;
488 if compOpt.CXXFLAGS then compOpt.CXXFLAGS = compOpt.CXXFLAGS.." ";
489 else compOpt.CXXFLAGS = "";
490 end;
491 compOpt.CXXFLAGS = compOpt.CXXFLAGS..value;
492 end;
493 elseif not cchar then
494 compOpt.CFLAGS = value;
495 compOpt.CXXFLAGS = value;
496 else
497 assert(false, "invalid cflags operation");
498 end;
499 end;
501 cflags = {
502 help = "cflags=[+]flags -- modify CFLAGS",
503 handler = function (name, value, cchar, str)
504 if not value then value = ""; end;
505 if cchar == "+" then
506 if value ~= "" then
507 if compOpt.CFLAGS then compOpt.CFLAGS = compOpt.CFLAGS.." ";
508 else compOpt.CFLAGS = "";
509 end;
510 compOpt.CFLAGS = compOpt.CFLAGS..value;
511 end;
512 elseif not cchar then
513 compOpt.CFLAGS = value;
514 else
515 assert(false, "invalid cflags operation");
516 end;
517 end;
519 cxxflags = {
520 help = "cxxflags=[+]flags -- modify CXXFLAGS",
521 handler = function (name, value, cchar, str)
522 if not value then value = ""; end;
523 if cchar == "+" then
524 if value ~= "" then
525 if compOpt.CXXFLAGS then compOpt.CXXFLAGS = compOpt.CXXFLAGS.." ";
526 else compOpt.CXXFLAGS = "";
527 end;
528 compOpt.CXXFLAGS = compOpt.CXXFLAGS..value;
529 end;
530 elseif not cchar then
531 compOpt.CXXFLAGS = value;
532 else
533 assert(false, "invalid cflags operation");
534 end;
535 end;
537 cfg_name = {
538 help = "cfg_name=configure_script_name",
539 handler = function (name, value, cchar, str)
540 if not value then value = "./configure"; end;
541 myOpt.cfgname = value;
542 end;
544 makename = {
545 help = "makename=make_command",
546 handler = function (name, value, cchar, str)
547 if not value then value = "make"; end;
548 myOpt.makename = value;
549 end;
551 instname = {
552 help = "instname=install_command",
553 handler = function (name, value, cchar, str)
554 if not value then value = "make"; end;
555 myOpt.instname = value;
556 end;
558 no_prefix = {
559 help = "no_prefix=[tan]",
560 handler = optparseBooleanOpt,
562 no_mandir = {
563 help = "no_mandir=[tan]",
564 handler = optparseBooleanOpt,
566 no_docdir = {
567 help = "no_docdir=[tan]",
568 handler = optparseBooleanOpt,
570 no_libdir = {
571 help = "no_libdir=[tan]",
572 handler = optparseBooleanOpt,
574 no_localstatedir = {
575 help = "no_localstatedir=[tan]",
576 handler = optparseBooleanOpt,
578 no_sysconfdir = {
579 help = "no_sysconfdir=[tan]",
580 handler = optparseBooleanOpt,
582 localstatedir = {
583 help = "localstatedir=path",
584 handler = function (name, value, cchar, str)
585 if not value then value = ""; end;
586 myOpt.localstatedir = value;
587 end;
589 no_programprefix = {
590 help = "no_programprefix=[tan]",
591 handler = optparseBooleanOpt,
593 no_programsuffix = {
594 help = "no_programsuffix=[tan]",
595 handler = optparseBooleanOpt,
597 no_buildarch = {
598 help = "no_buildarch=[tan]",
599 handler = optparseBooleanOpt,
601 no_strip = {
602 help = "no_strip=[tan]",
603 handler = optparseBooleanOpt,
605 no_preconfigure = {
606 help = "no_preconfigure=[tan]",
607 handler = optparseBooleanOpt,
609 no_premake = {
610 help = "no_premake=[tan]",
611 handler = optparseBooleanOpt,
613 no_configure = {
614 help = "no_configure=[tan]",
615 handler = optparseBooleanOpt,
617 no_make = {
618 help = "no_make=[tan]",
619 handler = optparseBooleanOpt,
621 no_make_argflags = {
622 help = "no_make_argflags=[tan] -- do not pass vars as make arguments",
623 handler = optparseBooleanOpt,
625 no_inst_destdir = {
626 help = "no_inst_destdir=[tan] -- do not pass DESTDIR to installer",
627 handler = optparseBooleanOpt,
629 no_package = {
630 help = "no_package=[tan]",
631 handler = optparseBooleanOpt,
633 no_deptrack = {
634 help = "no_deptrack=[tan]",
635 handler = optparseBooleanOpt,
637 no_pcp = {
638 help = "no_pcp=[tan] -- disable postconfig patches",
639 handler = optparseBooleanOpt,
641 no_prcp = {
642 help = "no_prcp=[tan] -- disable preconfig patches",
643 handler = optparseBooleanOpt,
645 no_dox = {
646 help = "no_dox=[tan] -- disable doc copying",
647 handler = optparseBooleanOpt,
649 no_cfg = {
650 help = "no_cfcopy=[tan] -- disable config copying",
651 handler = optparseBooleanOpt,
653 no_pss = {
654 help = "no_psscripts=[tan] -- disable post-install scripts",
655 handler = optparseBooleanOpt,
657 make_install_var = {
658 help = "make_install_var=var_name_for_make_install_root",
659 handler = function (name, value, cchar, str)
660 value = value:match("^%s*(.-)%s*$");
661 myOpt.make_install_var = value;
662 if value == "" then myOpt.make_install_var = "THIS_IS_A_USELESS_TEMP_VAR"; end;
663 end;
665 pkg_author = {
666 help = "pkg_author=k8",
667 handler = function (name, value, cchar, str)
668 if not value then value = ""; end;
669 value = value:match("^%s*(.-)%s*$");
670 myOpt.pkg_author = value;
671 end;
673 install_path = {
674 help = "install_path=[/usr]",
675 handler = function (name, value, cchar, str)
676 if not value then value = "/usr"; end;
677 value = value:match("^%s*(.-)%s*$");
678 myOpt.install_path = value;
679 end;
681 make_build_dir = {
682 help = "make_build_dir=[tan] -- for cmake, for example",
683 handler = optparseBooleanOpt,
685 keep_build_dir = {
686 help = "keep_build_dir=[tan] -- do not remove building directory",
687 handler = optparseBooleanOpt,
689 use_fakeroot = {
690 help = "use_fakeroot=[tan] -- use fakeroot instead of su/sudo",
691 handler = optparseBooleanOpt,
693 using_cmake = {
694 help = "using_cmake=[tan] -- cmake is used as build system",
695 handler = optparseBooleanOpt,
697 --force_native_profile = {
698 -- help = "force_native_profile=[ona] -- replace 'empty' profile with 'native'",
699 -- handler = optparseBooleanOpt,
700 --},
704 local function compOptParse (s)
705 local n, v, c = nameValueSplit(s);
706 local opt = myOptH[n];
707 if opt and opt.handler then opt.handler(n, v, c, s);
708 else
709 if not n:match("^[A-Z_]+$") then error("unknown option: "..n); end;
710 -- compiler option
711 local opt = compOpt[n];
712 if c == "?" then -- set if not set yet
713 if not opt then compOpt[n] = v; end;
714 elseif c == "+" then -- add
715 opt = opt and (opt.." ") or "";
716 compOpt[n] = opt..v;
717 elseif c == "!" then -- set if already set
718 if opt then compOpt[n] = v; end;
719 else compOpt[n] = v;
720 end;
721 end;
722 end;
725 local function loadOptions (fname, failOnError)
726 local phase = false;
727 local tdsc = fname..":";
728 local tdsc1 = tdsc.." ";
729 local dsccnt = 0;
731 function phaseNothing (s)
732 local opt, iscfg;
733 -- ^var=name -- env var
734 if s ~= "" and s:sub(1, 1) == "^" then
735 local k, v = s:match("%^%s*([^=]-)%s*=%s*(.-)%s*$");
736 if k == "" then error("invalid envvar declaration: "..s); end;
737 --if v ~= "" then buildEnvVars[k] = v; else buildEnvVars[k] = nil; end;
738 buildEnvVars[k] = v;
739 --if v ~= "" then compOpt[k] = v; else compOpt[k] = nil; end;
740 --print("k="..k.."; v="..v.."|");
741 return;
742 end;
743 if myOpt.using_cmake then
744 opt, iscfg = parseCMakeOption(s);
745 --print(opt, ":", iscfg);
746 else
747 opt, iscfg = parseOption(s);
748 end;
749 if opt then
750 if iscfg then
751 -- configure option
752 confOpt[#confOpt+1] = opt;
753 else
754 compOptParse(s);
755 end;
756 end;
757 end;
759 function phaseDescr (s)
760 if s ~= "" or dsccnt > 0 then
761 if #slackDesc == 0 then
762 slackDesc[#slackDesc+1] = "# HOW TO EDIT THIS FILE:";
763 slackDesc[#slackDesc+1] = '# The "handy ruler" below makes it easier to edit a package description. Line';
764 slackDesc[#slackDesc+1] = "# up the first '|' above the ':' following the base package name, and the '|'";
765 slackDesc[#slackDesc+1] = "# on the right side marks the last column you can put a character in. You must";
766 slackDesc[#slackDesc+1] = "# make exactly 11 lines for the formatting to be correct. It's also";
767 slackDesc[#slackDesc+1] = "# customary to leave one space after the ':'.";
768 slackDesc[#slackDesc+1] = "";
769 local ss = string.rep(" ", #fname).."|-----handy-ruler------------------------------------------------------|";
770 slackDesc[#slackDesc+1] = ss;
771 end;
772 s = s:match("^%s*(.-)%s*$");
773 if s:sub(1, 1) ~= "#" then
774 if #s > 70 then error("package description: line too long (must be <= 70 chars)\n"..s); end;
775 dsccnt = dsccnt+1;
776 if dsccnt == 12 then error("package description: too many lines (11 max)\n"); end;
777 if s == "" then s = tdsc; else s = tdsc1..s; end;
778 slackDesc[#slackDesc+1] = s;
779 end;
780 end;
781 return false;
782 end;
784 function phaseReq (s)
785 s = s:match("^%s*(.-)%s*$");
786 local rc = #slackReq;
787 if s:match("^[^#]") then
788 if s:lower() == "or" or s == "|" then
789 if rc >= 1 then slackReq[#slackReq+1] = " | "; end;
790 else
791 if rc >= 1 and slackReq[rc] ~= " | " then slackReq[#slackReq+1] = ","; end;
792 end;
793 slackReq[#slackReq+1] = s;
794 end;
795 end;
797 function phaseUnp (s)
798 unpackScript[#unpackScript+1] = s;
799 end;
802 -----------------------------------------------------------------------------
803 local pcpStarted = false;
804 local pcpPre = false;
805 local pcpCurrent = false;
807 function phasePCPNew (s)
808 if pcpStarted then error("unclosed postconfig-patch section in file "..fname); end;
809 pcpStarted = true;
810 pcpPre = false;
811 pcpCurrent = {};
812 end;
814 function phasePRCPNew (s)
815 if pcpStarted then error("unclosed preconfig-patch section in file "..fname); end;
816 pcpStarted = true;
817 pcpPre = true;
818 pcpCurrent = {};
819 end;
821 function phasePCPEnd (s)
822 if not pcpStarted then error("bad postconfig-patch section in file "..fname); end;
823 if pcpPre then
824 precfgPatches[#precfgPatches+1] = pcpCurrent;
825 else
826 postcfgPatches[#postcfgPatches+1] = pcpCurrent;
827 end;
828 pcpStarted = false;
829 pcpCurrent = false;
830 pcpPre = false;
831 end;
833 function phasePCP (s, origs)
834 pcpCurrent[#pcpCurrent+1] = origs;
835 end;
838 -----------------------------------------------------------------------------
839 local doxStarted = false;
840 local doxCurrent = false;
841 local doxPath = false;
843 function phaseDoxNew (s)
844 if doxStarted then error("unclosed dox section in file "..fname); end;
845 doxStarted = true;
846 doxCurrent = {};
847 if not doxPath then doxPath = ""; end;
848 end;
850 function phaseDoxEnd (s)
851 if not doxStarted then error("bad dox section in file "..fname); end;
852 doclist[#doclist+1] = {["path"] = doxPath, ["list"] = doxCurrent};
853 doxStarted = false;
854 doxCurrent = false;
855 doxPath = false;
856 end;
858 function phaseDox (s, origs)
859 doxCurrent[#doxCurrent+1] = origs;
860 end;
863 -----------------------------------------------------------------------------
864 local cfgStarted = false;
866 function phaseCfgNew (s)
867 if cfgStarted then error("unclosed cfg section in file "..fname); end;
868 cfgStarted = true;
869 end;
871 function phaseCfgEnd (s)
872 if not cfgStarted then error("bad cfg section in file "..fname); end;
873 cfgStarted = false;
874 end;
876 function phaseCfg (s, origs)
877 cfglist[#cfglist+1] = origs;
878 end;
881 -----------------------------------------------------------------------------
882 local pssStarted = false;
883 local pssCurrent = false;
885 function phasePSSNew (s)
886 if pssStarted then error("unclosed postinstall section in file "..fname); end;
887 pssStarted = true;
888 pssCurrent = {};
889 end;
891 function phasePSSEnd (s)
892 if not pssStarted then error("bad postinstall section in file "..fname); end;
894 while #pssCurrent > 0 and pssCurrent[#pssCurrent] == "" do table.remove(pssCurrent); end;
896 if #pssCurrent > 0 then
897 pssCurrent[#pssCurrent+1] = "";
898 psslist[#psslist+1] = table.concat(pssCurrent, "\n");
899 end;
901 pssStarted = false;
902 pssCurrent = false;
903 end;
905 function phasePSS (s, origs)
906 pssCurrent[#pssCurrent+1] = origs:match("^.-%s*$");
907 end;
910 -----------------------------------------------------------------------------
911 local doinstStarted = false;
912 local doinstCurrent = false;
914 function phaseDoInstNew (s)
915 if doinstStarted then error("unclosed doinst.sh section in file "..fname); end;
916 doinstStarted = true;
917 doinstCurrent = {};
918 end;
920 function phaseDoInstEnd (s)
921 if not doinstStarted then error("bad doinst.sh section in file "..fname); end;
923 while #doinstCurrent > 0 and doinstCurrent[#doinstCurrent] == "" do table.remove(doinstCurrent); end;
925 if #doinstCurrent > 0 then
926 doinstCurrent[#doinstCurrent+1] = "";
927 if #doinstlist > 0 then doinstlist[#doinstlist+1] = "\n"; end;
928 doinstlist[#doinstlist+1] = table.concat(doinstCurrent, "\n");
929 end;
931 doinstStarted = false;
932 doinstCurrent = false;
933 end;
935 function phaseDoInst (s, origs)
936 doinstCurrent[#doinstCurrent+1] = origs:match("^.-%s*$");
937 end;
940 -----------------------------------------------------------------------------
941 local scinstallStarted = false;
942 local scinstallCurrent = false;
944 function phaseInstallNew (s)
945 if scinstallStarted then error("unclosed install section in file "..fname); end;
946 scinstallStarted = true;
947 scinstallCurrent = {};
948 end;
950 function phaseInstallEnd (s)
951 if not scinstallStarted then error("bad install section in file "..fname); end;
953 while #scinstallCurrent > 0 and scinstallCurrent[#scinstallCurrent] == "" do table.remove(scinstallCurrent); end;
955 if #scinstallCurrent > 0 then
956 scinstallCurrent[#scinstallCurrent+1] = "";
957 scinstalllist[#scinstalllist+1] = table.concat(scinstallCurrent, "\n");
958 end;
960 scinstallStarted = false;
961 scinstallCurrent = false;
962 end;
964 function phaseInstall (s, origs)
965 scinstallCurrent[#scinstallCurrent+1] = origs:match("^.-%s*$");
966 end;
969 -----------------------------------------------------------------------------
970 local scmakeStarted = false;
971 local scmakeCurrent = false;
973 function phaseMakeNew (s)
974 if scmakeStarted then error("unclosed make section in file "..fname); end;
975 scmakeStarted = true;
976 scmakeCurrent = {};
977 end;
979 function phaseMakeEnd (s)
980 if not scmakeStarted then error("bad make section in file "..fname); end;
982 while #scmakeCurrent > 0 and scmakeCurrent[#scmakeCurrent] == "" do table.remove(scmakeCurrent); end;
984 if #scmakeCurrent > 0 then
985 scmakeCurrent[#scmakeCurrent+1] = "";
986 scmakelist[#scmakelist+1] = table.concat(scmakeCurrent, "\n");
987 end;
989 scmakeStarted = false;
990 scmakeCurrent = false;
991 end;
993 function phaseMake (s, origs)
994 scmakeCurrent[#scmakeCurrent+1] = origs:match("^.-%s*$");
995 end;
998 -----------------------------------------------------------------------------
999 local scconfigureStarted = false;
1000 local scconfigureCurrent = false;
1002 function phaseConfigureNew (s)
1003 if scconfigureStarted then error("unclosed configure section in file "..fname); end;
1004 scconfigureStarted = true;
1005 scconfigureCurrent = {};
1006 end;
1008 function phaseConfigureEnd (s)
1009 if not scconfigureStarted then error("bad configure section in file "..fname); end;
1011 while #scconfigureCurrent > 0 and scconfigureCurrent[#scconfigureCurrent] == "" do table.remove(scconfigureCurrent); end;
1013 if #scconfigureCurrent > 0 then
1014 scconfigureCurrent[#scconfigureCurrent+1] = "";
1015 scconfigurelist[#scconfigurelist+1] = table.concat(scconfigureCurrent, "\n");
1016 end;
1018 scconfigureStarted = false;
1019 scconfigureCurrent = false;
1020 end;
1022 function phaseConfigure (s, origs)
1023 scconfigureCurrent[#scconfigureCurrent+1] = origs:match("^.-%s*$");
1024 end;
1027 -----------------------------------------------------------------------------
1028 local scpreconfigureStarted = false;
1029 local scpreconfigureCurrent = false;
1031 function phasePreConfigureNew (s)
1032 if scpreconfigureStarted then error("unclosed preconfigure section in file "..fname); end;
1033 scpreconfigureStarted = true;
1034 scpreconfigureCurrent = {};
1035 end;
1037 function phasePreConfigureEnd (s)
1038 if not scpreconfigureStarted then error("bad preconfigure section in file "..fname); end;
1040 while #scpreconfigureCurrent > 0 and scpreconfigureCurrent[#scpreconfigureCurrent] == "" do table.remove(scpreconfigureCurrent); end;
1042 if #scpreconfigureCurrent > 0 then
1043 scpreconfigureCurrent[#scpreconfigureCurrent+1] = "";
1044 scpreconfigurelist[#scpreconfigurelist+1] = table.concat(scpreconfigureCurrent, "\n");
1045 end;
1047 scpreconfigureStarted = false;
1048 scpreconfigureCurrent = false;
1049 end;
1051 function phasePreConfigure (s, origs)
1052 scpreconfigureCurrent[#scpreconfigureCurrent+1] = origs:match("^.-%s*$");
1053 end;
1056 -----------------------------------------------------------------------------
1057 local scpremakeStarted = false;
1058 local scpremakeCurrent = false;
1060 function phasePreMakeNew (s)
1061 if scpremakeStarted then error("unclosed premake section in file "..fname); end;
1062 scpremakeStarted = true;
1063 scpremakeCurrent = {};
1064 end;
1066 function phasePreMakeEnd (s)
1067 if not scpremakeStarted then error("bad premake section in file "..fname); end;
1069 while #scpremakeCurrent > 0 and scpremakeCurrent[#scpremakeCurrent] == "" do table.remove(scpremakeCurrent); end;
1071 if #scpremakeCurrent > 0 then
1072 scpremakeCurrent[#scpremakeCurrent+1] = "";
1073 scpremakelist[#scpremakelist+1] = table.concat(scpremakeCurrent, "\n");
1074 end;
1076 scpremakeStarted = false;
1077 scpremakeCurrent = false;
1078 end;
1080 function phasePreMake (s, origs)
1081 scpremakeCurrent[#scpremakeCurrent+1] = origs:match("^.-%s*$");
1082 end;
1085 -----------------------------------------------------------------------------
1086 local phaseFunc = phaseNothing;
1088 local phaseAliases = {
1089 ["!DESCRIPTION"] = "!DSC",
1090 ["!DESCR"] = "!DSC",
1091 ["!DESC"] = "!DSC",
1092 ["!REQUIRED"] = "!REQ",
1093 ["!UNPACK"] = "!UNP",
1096 local phases = {
1097 ["!DSC"] = { seen = false, func = phaseDescr },
1098 ["!REQ"] = { seen = false, func = phaseReq },
1099 ["!UNP"] = { seen = false, func = phaseUnp },
1100 ["[POSTCONFIG-PATCH]"] = { seen = false, allowMany = true, func = phasePCP, funcInit = phasePCPNew },
1101 ["[/POSTCONFIG-PATCH]"] = { seen = false, allowMany = true, func = phaseNothing, funcInit = phasePCPEnd },
1102 ["[PRECONFIG-PATCH]"] = { seen = false, allowMany = true, func = phasePCP, funcInit = phasePRCPNew },
1103 ["[/PRECONFIG-PATCH]"] = { seen = false, allowMany = true, func = phaseNothing, funcInit = phasePCPEnd },
1104 ["[DOCS]"] = { seen = false, allowMany = true, func = phaseDox, funcInit = phaseDoxNew },
1105 ["[/DOCS]"] = { seen = false, allowMany = true, func = phaseNothing, funcInit = phaseDoxEnd },
1106 ["[DOX]"] = { seen = false, allowMany = true, func = phaseDox, funcInit = phaseDoxNew },
1107 ["[/DOX]"] = { seen = false, allowMany = true, func = phaseNothing, funcInit = phaseDoxEnd },
1108 ["[CFG]"] = { seen = false, allowMany = true, func = phaseCfg, funcInit = phaseCfgNew },
1109 ["[/CFG]"] = { seen = false, allowMany = true, func = phaseNothing, funcInit = phaseCfgEnd },
1110 ["[PRECONFIGURE]"] = { seen = false, allowMany = true, func = phasePreConfigure, funcInit = phasePreConfigureNew },
1111 ["[/PRECONFIGURE]"] = { seen = false, allowMany = true, func = phaseNothing, funcInit = phasePreConfigureEnd },
1112 ["[PREMAKE]"] = { seen = false, allowMany = true, func = phasePreMake, funcInit = phasePreMakeNew },
1113 ["[/PREMAKE]"] = { seen = false, allowMany = true, func = phaseNothing, funcInit = phasePreMakeEnd },
1114 ["[CONFIGURE]"] = { seen = false, allowMany = true, func = phaseConfigure, funcInit = phaseConfigureNew },
1115 ["[/CONFIGURE]"] = { seen = false, allowMany = true, func = phaseNothing, funcInit = phaseConfigureEnd },
1116 ["[MAKE]"] = { seen = false, allowMany = true, func = phaseMake, funcInit = phaseMakeNew },
1117 ["[/MAKE]"] = { seen = false, allowMany = true, func = phaseNothing, funcInit = phaseMakeEnd },
1118 ["[INSTALL]"] = { seen = false, allowMany = true, func = phaseInstall, funcInit = phaseInstallNew },
1119 ["[/INSTALL]"] = { seen = false, allowMany = true, func = phaseNothing, funcInit = phaseInstallEnd },
1120 ["[POSTINSTALL]"] = { seen = false, allowMany = true, func = phasePSS, funcInit = phasePSSNew },
1121 ["[/POSTINSTALL]"] = { seen = false, allowMany = true, func = phaseNothing, funcInit = phasePSSEnd },
1122 ["[DOINST.SH]"] = { seen = false, allowMany = true, func = phaseDoInst, funcInit = phaseDoInstNew },
1123 ["[/DOINST.SH]"] = { seen = false, allowMany = true, func = phaseNothing, funcInit = phaseDoInstEnd },
1126 local files = {};
1127 local fileNames = {};
1130 function doInclude (fname, doFail)
1131 print("loading "..fname);
1132 local fl = openFile(fname);
1133 if not fl then
1134 if doFail or failOnError then error("can't open options file: "..fname); end;
1135 return false;
1136 end;
1137 files[#files+1] = fl;
1138 fileNames[#fileNames+1] = fname;
1139 return true;
1140 end;
1142 if not doInclude(fname, false) then return false; end;
1144 while #files > 0 do
1145 local fl = files[#files];
1146 local fname = fileNames[#fileNames];
1147 local s = fl:read();
1148 if s then
1149 local ostr = s;
1150 s = s:match("^(.-)%s*$");
1151 if s == "!EOF" then break; end;
1152 if s ~= "" and (s:sub(1, 1) == "!" or s:sub(1, 1) == "[") then
1153 local sn = phaseAliases[s];
1154 if not sn then sn = phaseAliases[s:upper()]; end;
1155 if sn then s = sn; end;
1157 if s:match("^%s*!INCLUDE%s") then
1158 local fn = s:match("^.-!.-%s+(.-)$");
1159 if not fn or fn == "" then error("invalid include in "..fname); end;
1160 doInclude(fn, true);
1161 else
1162 if not doxPath and s:upper():match("^%[DOCS=") then
1163 local pth = s:match("^%[[Dd][Oo][Cc][Ss]=(.-)%]$");
1164 if pth then
1165 doxPath = pth;
1166 s = "[DOCS]";
1167 end;
1168 end;
1170 local pp = phases[s];
1171 if not pp then pp = phases[s:upper()]; end;
1172 if not pp then error("unknown directive in "..fname..": "..s); end;
1173 if pp.seen and not pp.allowMany then error("duplicate directive in "..fname..": "..s); end;
1174 if pp.funcInit then pp.funcInit(s); end;
1175 phaseFunc = pp.func;
1176 pp.seen = true;
1177 end;
1178 else
1179 phaseFunc(s, ostr);
1180 end;
1181 else
1182 fl:close();
1183 table.remove(files);
1184 table.remove(fileNames);
1185 end;
1186 end;
1188 if dsccnt > 0 then
1189 while dsccnt < 11 do
1190 slackDesc[#slackDesc+1] = tdsc;
1191 dsccnt = dsccnt+1;
1192 end;
1193 end;
1195 return true;
1196 end;
1199 local function dumpOptions ()
1200 print("compiler options:");
1201 for k, v in pairs(compOpt) do
1202 print(string.format(" %s={%s}", k, tostring(v)));
1203 end;
1205 print("configure options:");
1206 for k, v in pairs(confOpt) do
1207 print(string.format(" %s={%s}", k, tostring(v)));
1208 end;
1210 print("other options:");
1211 for k, v in pairs(myOpt) do
1212 print(string.format(" %s={%s}", k, tostring(v)));
1213 end;
1214 end;
1217 --[[
1218 if #arg < 1 then
1219 io.stderr:write("usage: dosb pkgname [build]\n");
1220 io.stderr:flush();
1221 os.exit(1);
1222 end;
1226 local olderr = error;
1227 function error (msg)
1228 if myOpt["chownUser"] ~= "" then
1229 logMessage("restoring owner: %s", myOpt["chownUser"]);
1230 os.execute("chown "..(myOpt["chownUser"]):shQuote().." -R .");
1231 end;
1232 olderr(msg);
1233 end;
1236 local function writeSlackDesc (path)
1237 if #slackDesc > 0 then
1238 os.execute("mkdir -p "..path:shQuote());
1239 local fl = io.open(path.."slack-desc", "w");
1240 if not fl then error("can't create 'slack-desc'"); end;
1241 for _, s in ipairs(slackDesc) do fl:write(s, "\n"); end;
1242 fl:close();
1243 return;
1244 end;
1245 end;
1248 local function writeSlackReq (path)
1249 if #slackReq > 0 then
1250 os.execute("mkdir -p "..path:shQuote());
1251 local fl = io.open(path.."slack-required", "w");
1252 if not fl then error("can't create 'slack-required'"); end;
1253 local s = table.concat(slackReq);
1254 fl:write(s, "\n");
1255 fl:close();
1256 return;
1257 end;
1258 end;
1261 local function getUID ()
1262 local fl = io.popen("echo $UID");
1263 if not fl then return -1; end;
1264 local s = fl:read();
1265 fl:close();
1267 return tonumber(s) or -1;
1268 end;
1271 local function getPrefixDir ()
1272 local ipath = myOpt.install_path or "/usr";
1273 ipath = ipath:match("^%s*(.-)%s*$");
1274 if ipath:match("/$") then ipath = ipath:sub(1, -2); end;
1275 if ipath == "" then ipath = "/usr"; end;
1276 return ipath;
1277 end;
1280 local build_stage = "configure"; -- "configure", "make"
1282 local function getBuildFlags (nowrexport)
1283 local s = "";
1284 --logMessage("*STAGE*: %s (%s)", build_stage, (nowrexport and "nowrexport" or ""));
1285 if build_stage == "configure" then
1286 for k, v in pairs(compOpt) do
1287 --logMessage(" k=[%s] v=[%s]", k, v);
1288 if v and v ~= "" then
1289 if not nowrexport then
1290 s = s.."export "..k.."="..v:shQuote().." ; ";
1291 else
1292 s = s.." "..k.."="..v:shQuote();
1293 end;
1294 end;
1295 end;
1296 end;
1297 --logMessage("*S*: %s", s);
1298 return s;
1299 end;
1302 -- $PKG: package dir (/tmp/...)
1303 -- $INSTPFX: install prefix (/usr)
1304 -- $JOBS: number of jobs (1)
1305 -- $PKGNAM: package name (fluxbox)
1306 -- $VERSION: package version (1.4.1)
1307 -- $BUILD: package build (1k8)
1308 -- $ARCH: package architecture (i686)
1309 -- $PKGDOCSDIR: docs directory (/tmp/...)
1310 -- $USRDOCSDIR: install docs directory (/usr/doc/...)
1311 -- pwd: original package directory (that one with 'configure')
1312 local function getScriptVars (noexport)
1313 local usrdocpath = getPrefixDir().."/doc/"..pinfo.name.."-"..pinfo.version;
1314 local docpath = pkgdir..usrdocpath;
1316 local vars = {
1317 PKG = pkgdir,
1318 INSTPFX = getPrefixDir(),
1319 PKGNAM = pinfo.name,
1320 VERSION = pinfo.version,
1321 ARCH = pinfo.arch,
1322 BUILD = tostring(pinfo.build)..pinfo.author,
1323 PKGDOCSDIR = docpath,
1324 USRDOCSDIR = usrdocpath,
1325 JOBS = tostring(jobs),
1328 local s = "";
1329 for n, v in pairs(vars) do
1330 --if not noexport then s = s.." export"; end;
1331 s = s.." "..n.."="..v:shQuote();
1332 end;
1333 for n, v in pairs(buildEnvVars) do
1334 --if not noexport then s = s.." export"; end;
1335 s = s.." "..n.."="..v:shQuote();
1336 end;
1337 --logMessage("*scv: %s", s);
1338 --error("DBGBREAK");
1339 return s;
1340 end;
1343 local function runCmdEx (loPriv, ignoreFail, cmd, ...)
1344 local s = cmd:format(...);
1345 logMessage("run: %s", s);
1346 --local flg = 'export CFLAGS="'..CFLAGS..'" ; export CXXFLAGS="'..CXXFLAGS..'" ; export LDFLAGS="'..LDFLAGS..'" ; ';
1347 local flg = "( ";
1348 if myOpt.make_build_dir then
1349 flg = flg.."cd "..buildDirName.." ; ";
1350 end;
1351 flg = flg..getBuildFlags()..s.." )";
1352 logMessage("*run: %s", flg);
1353 --print(flg);
1354 --s = s:gsub("\n", "\\\n");
1355 local tsh = false;
1356 if loPriv and not myOpt.use_fakeroot then
1357 if not myOpt.srcBuildUser or myOpt.srcBuildUser == "" then
1358 error("can't lower privileges for command!");
1359 end;
1360 --!logMessage("*LOPRV");
1361 --flg = "su "..myOpt.srcBuildUser..' -c "'..flg:shQuote()..'"';
1362 --logMessage("[%s]", flg);
1363 tsh = "/tmp/"..tostring(os.time())..".sh";
1364 local fl = io.open(tsh, "w+");
1365 if not fl then error("can't create file: "..tsh); end;
1366 --fl:write("whoami\n");
1367 fl:write(flg, "\n");
1368 fl:close();
1369 os.execute("chown "..myOpt.srcBuildUser.." "..tsh:shQuote());
1370 flg = "su "..myOpt.srcBuildUser..' -c "sh '..tsh:shQuote()..'"';
1371 end;
1372 local sttime = os.time();
1373 local res = os.execute(flg);
1374 local entime = os.time();
1375 if tsh then os.remove(tsh); end;
1376 logMessageToFile("%s [%s]", timeStr(entime-sttime), s);
1377 --os.exit(1);
1378 --local res = 0;
1379 if not ignoreFail and res ~= 0 then error("command is fucked up!"); end;
1380 end;
1382 local function runCmdRoot (cmd, ...)
1383 return runCmdEx(false, false, cmd, ...);
1384 end;
1386 local function runCmdRootFuckFail (cmd, ...)
1387 return runCmdEx(false, true, cmd, ...);
1388 end;
1390 local function runCmd (cmd, ...)
1391 return runCmdEx(true, false, cmd, ...);
1392 end;
1394 local function runCmdFuckFail (cmd, ...)
1395 return runCmdEx(true, true, cmd, ...);
1396 end;
1399 local function runShCmdEx (loPriv, cmd, nofail)
1400 logMessage("run:\n%s\n=====", cmd);
1401 local tsh = "/tmp/"..tostring(os.time())..".sh";
1402 local fl = io.open(tsh, "w+");
1403 if not fl then error("can't create file: "..tsh); end;
1404 fl:write(cmd, "\n");
1405 fl:close();
1406 --local flg = '( export CFLAGS="'..CFLAGS..'" ; export CXXFLAGS="'..CXXFLAGS..'" ; export LDFLAGS="'..LDFLAGS..'" ; bash '..tsh..' )';
1407 local flg = "( "..getBuildFlags().." "..getScriptVars().." bash "..tsh.." )";
1408 --s = s:gsub("\n", "\\\n");
1409 if loPriv then
1410 if not myOpt.srcBuildUser or myOpt.srcBuildUser == "" then
1411 error("can't lower privileges for command!");
1412 end;
1413 os.execute("chown "..myOpt.srcBuildUser.." "..tsh:shQuote());
1414 --!logMessage("*LOPRV");
1415 flg = "su "..myOpt.srcBuildUser..' -c "'..flg:shQuote()..'"';
1416 end;
1417 local res = os.execute(flg);
1418 --local res = 0;
1419 os.remove(tsh);
1420 if not nofail and res ~= 0 then error("command is fucked up!"); end;
1421 end;
1423 local function runShCmd (cmd, nofail)
1424 return runShCmdEx(true, cmd, nofail);
1425 end;
1427 local function runShCmdRoot (cmd, nofail)
1428 return runShCmdEx(false, cmd, nofail);
1429 end;
1432 local function runXCowSay (cmd, msg)
1433 local fl = io.popen("which xcowsay", "r");
1434 if fl then
1435 local s = fl:read();
1436 fl:close();
1437 if s and s ~= "" then
1438 runCmd(s, msg);
1439 end;
1440 end;
1441 end;
1443 local function parsePkgName (name)
1444 local spl = {};
1445 for w in (name.."-"):gmatch("[^-]*") do
1446 w = w:match("^%s*(.-)%s*$");
1447 if w ~= "" then spl[#spl+1] = w; end;
1448 end;
1449 assert(#spl >= 2);
1450 local pinfo = {};
1451 pinfo.version = spl[#spl];
1452 table.remove(spl);
1453 pinfo.name = join(spl, "-");
1454 pinfo.build = 1;
1455 pinfo.author = "";
1456 pinfo.arch = "i686";
1457 return pinfo;
1458 end;
1461 local function pkgInfoToStr (pinfo)
1462 local s = string.format("%s-%s-%s-%i%s", pinfo.name, pinfo.version, pinfo.arch, pinfo.build or 1, pinfo.author or "k8");
1463 return s;
1464 end;
1467 local function printHelp ()
1468 print([[
1469 usage: sbuild pkgname-ver [options] [buildnum]
1470 options:
1471 -nocfg don't run configure
1472 -noprecfg don't run preconfigure script
1473 -nopremk don't run premake script
1474 -dump dump vars
1475 -dummy don't run anything
1476 -nomake don't run make
1477 -nopkg don't build package
1478 -nopcp disable postconfig patches
1479 -noprcp disable preconfig patches
1480 -jn # of jobs (default: ]]..jobs..[[)
1481 -kbd keep build dir
1482 -nonative disable replacing 'empty' profile with 'native'
1484 xopt options:]]); --
1485 local maxlen = 0;
1486 local names = {};
1487 for name, opt in pairs(myOptH) do
1488 if opt.help then
1489 names[#names+1] = name;
1490 maxlen = math.max(maxlen, #name);
1491 end;
1492 end;
1493 table.sort(names);
1495 maxlen = maxlen+2;
1497 for _, name in pairs(names) do
1498 local opt = myOptH[name];
1499 if opt.help then
1500 local lpad = string.rep(" ", maxlen-#name);
1501 print(name..lpad..opt.help);
1502 end;
1503 end;
1504 end;
1507 local apkgname = false;
1508 local doDump = false;
1509 local dummy = false;
1510 local ooNoCfg = false;
1511 local ooNoPreCfg = false;
1512 local ooNoPreMk = false;
1513 local ooNoMake = false;
1514 local ooNoPkg = false;
1515 local ooNoPCP = false;
1516 local ooNoPRCP = false;
1517 local bldnum = false;
1518 local ooKBD = nil;
1519 local inFakeRoot = false;
1521 -- check for special flag
1522 --[[
1523 if arg[1] and arg[1] == "K8XBUILDSRC" then
1524 weAreBuildingSrcz = true;
1525 local cnt = #arg+1;
1526 for f = 2, cnt do arg[f-1] = arg[f]; end;
1527 end;
1530 local in_pfx_arg = false;
1531 local inst_pfx = false;
1534 for f = 1, #arg do
1535 if in_pfx_arg then in_pfx_arg = false; inst_pfx = arg[f];
1536 elseif arg[f] == "-nocfg" or arg[f] == "--nocfg" then ooNoCfg = true;
1537 elseif arg[f] == "-noprecfg" or arg[f] == "--noprecfg" then ooNoPreCfg = true;
1538 elseif arg[f] == "-nopremk" or arg[f] == "--nopremk" then ooNoPreMk = true;
1539 elseif arg[f] == "-nomake" or arg[f] == "--nomake" then ooNoMake = true;
1540 elseif arg[f] == "-nopkg" or arg[f] == "--nopkg" then ooNoPkg = true;
1541 elseif arg[f] == "-nopcp" or arg[f] == "--nopcp" then ooNoPCP = true;
1542 elseif arg[f] == "-noprcp" or arg[f] == "--noprcp" then ooNoPCP = true;
1543 elseif arg[f] == "-dump" or arg[f] == "--dump" then doDump = true;
1544 elseif arg[f] == "-dummy" or arg[f] == "--dummy" then dummy = true;
1545 elseif arg[f] == "-kbd" or arg[f] == "--kbd" then ooKBD = true;
1546 elseif arg[f] == "-nonative" or arg[f] == "--nonative" then force_native_profile = false;
1547 elseif arg[f] == "-pfx" or arg[f] == "--pfx" or
1548 arg[f] == "-prefix" or arg[f] == "--prefix" then
1549 in_pfx_arg = true;
1550 if f+1 > #arg then
1551 io.stderr:write("*ERROR: ", argv[f], "expects argument!\n");
1552 os.exit(1);
1553 end;
1554 elseif arg[f] == "-h" or arg[f] == "-help" or arg[f] == "--help" then printHelp(); os.exit(1);
1555 elseif arg[f] == "--in-fake-root-mode-internal-option--" then inFakeRoot = true;
1556 elseif arg[f]:match("^-j") then
1557 local jn = tonumber(arg[f]:match("^-j(%d+)"));
1558 if not jn or jn < 1 then jn = 1; end;
1559 jobs = jn;
1560 else
1561 if apkgname then
1562 if bldnum then
1563 io.stderr:write("*ERROR: extra options!\n");
1564 os.exit(1);
1565 end;
1566 bldnum = tonumber(arg[f]);
1567 if not bldnum or bldnum < 1 then
1568 io.stderr:write("*ERROR: invalid build number!\n");
1569 os.exit(1);
1570 end;
1571 bldnum = math.floor(bldnum);
1572 else apkgname = arg[f];
1573 end;
1574 end;
1575 end;
1578 if not apkgname then
1579 print("*ERROR: no package name!");
1580 printHelp();
1581 os.exit(1);
1582 end;
1585 if force_native_profile then
1586 -- easy hack
1587 --defCompOptProfs.empty = defCompOptProfs.native;
1588 -- this, 'cause otherwise some libs (notably, OpenAL) doesn't work with DMD
1589 --defCompOptProfs.empty = defCompOptProfs.i586;
1590 --defCompOptProfs.empty = defCompOptProfs.haswell;
1591 --defCompOptProfs.empty = defCompOptProfs.nehalem;
1592 defCompOptProfs.empty = defCompOptProfs.core2;
1593 --defCompOptProfs.empty = defCompOptProfs.native;
1594 end;
1597 pinfo = parsePkgName(apkgname);
1598 pinfo.build = bldnum or pinfo.build;
1599 pkgdir = "/tmp/0sb_"..(pinfo.name);--..(os.time());
1602 logMessage("building %s...", pkgInfoToStr(pinfo));
1604 loadOptions(pinfo.name, true);
1605 loadOptions("_dosb");
1606 loadOptions("_local");
1608 if ooNoPCP then myOpt.no_pcp = true; end;
1609 if ooNoPRCP then myOpt.no_prcp = true; end;
1611 if inst_pfx then
1612 print("FORCING PREFIX TO "..inst_pfx);
1613 myOpt.install_path = inst_pfx;
1614 end;
1616 --[[
1617 for _, ppp in ipairs(postcfgPatches) do
1618 print("patch #".._..":");
1619 for _, s in ipairs(ppp) do print(" "..s.."|"); end;
1620 end;
1621 os.exit(1);
1624 -- last minute fixups
1625 if not myOpt.chownUser or myOpt.chownUser == "" then
1626 olderr("too bad! we are mad! (no chown_user)");
1627 end;
1629 if not myOpt.srcBuildUser or myOpt.srcBuildUser == "" then
1630 local uname = myOpt.chownUser:match("^(.-):");
1631 if not uname then uname = myOpt.chownUser; end;
1632 if not uname or uname == "" then olderr("too bad! we are mad!"); end;
1633 myOpt.srcBuildUser = uname;
1634 end;
1636 --local pkgDestDir = "/home/ketmar/zoft/pkg/";
1637 if not myOpt.pkgdestdir or myOpt.pkgdestdir == "" then
1638 myOpt.pkgdestdir = os.getenv("HOME").."/.sbuild/pkg";
1639 end;
1640 pkgDestDir = myOpt.pkgdestdir;
1643 if ooNoCfg then myOpt.no_configure = true; end;
1644 if ooNoPreCfg then myOpt.no_preconfigure = true; end;
1645 if ooNoPreMk then myOpt.no_premake = true; end;
1646 if ooNoMake then myOpt.no_make = true; end;
1647 if ooNoPkg then myOpt.no_package = true; end;
1649 local a = myOpt.pkg_author;
1650 if a and a ~= "" then pinfo.author = a; end;
1652 if doDump then
1653 dumpOptions();
1654 end;
1656 if dummy then
1657 os.exit(1);
1658 end;
1661 if myOpt.use_fakeroot then
1662 myOpt.srcBuildUser = "";
1663 end;
1665 --if not inFakeRoot and getUID() ~= 0 then
1666 if getUID() ~= 0 then
1667 if myOpt.use_fakeroot then
1668 io.stderr:write("restarting in 'fakeroot' mode...\n");
1669 --local cmdline = "fakeroot "..(arg[0]):shQuote().." --in-fake-root-mode-internal-option--";
1670 local cmdline = "fakeroot "..(arg[0]):shQuote();
1671 for f = 1, #arg do
1672 cmdline = cmdline.." "..(arg[f]):shQuote();
1673 end;
1674 --io.stderr:write("[", cmdline, "]\n");
1675 local res = os.execute(cmdline);
1676 os.exit(res);
1677 else
1678 io.stderr:write("this script must be run with su/sudo!\n");
1679 io.stderr:flush();
1680 os.exit(2);
1681 end;
1682 end;
1685 if ooKBD == true then
1686 myOpt.keep_build_dir = true;
1687 end;
1689 buildDirName = "_sbuild_"..(pinfo.name);--..(os.time());
1690 if myOpt.make_build_dir then
1691 os.execute("rm -rf "..buildDirName.." >/dev/null 2>&1");
1692 logMessage("making directory: %s", buildDirName);
1693 --print("making directory: "..buildDirName);
1694 os.execute("mkdir "..buildDirName.." >/dev/null 2>&1");
1695 end;
1698 local function sanitizePerms ()
1699 -- Make sure ownerships and permissions are sane
1700 --runCmd("chown -R root:root .");
1701 if myOpt.srcBuildUser ~= "" then
1702 logMessage("chown to "..myOpt.srcBuildUser);
1703 os.execute("chown "..(myOpt["srcBuildUser"]):shQuote().." -R .");
1704 end;
1705 -- k8: runCmd("find . -perm 666 -exec chmod 644 {} \\;");
1706 -- k8: runCmd("find . -perm 664 -exec chmod 644 {} \\;");
1707 -- k8: runCmd("find . -perm 600 -exec chmod 644 {} \\;");
1708 -- k8: runCmd("find . -perm 444 -exec chmod 644 {} \\;");
1709 -- k8: runCmd("find . -perm 400 -exec chmod 644 {} \\;");
1710 -- k8: runCmd("find . -perm 440 -exec chmod 644 {} \\;");
1711 -- k8: runCmd("find . -perm 777 -exec chmod 755 {} \\;");
1712 -- k8: runCmd("find . -perm 775 -exec chmod 755 {} \\;");
1713 -- k8: runCmd("find . -perm 511 -exec chmod 755 {} \\;");
1714 -- k8: runCmd("find . -perm 711 -exec chmod 755 {} \\;");
1715 -- k8: runCmd("find . -perm 555 -exec chmod 755 {} \\;");
1716 end;
1719 local function runScriptList (sclist, msg)
1720 if #sclist > 0 then
1721 logMessage("executing custom '%s' script(s)...", msg);
1722 for _, script in ipairs(sclist) do
1723 runShCmdRoot(script, false);
1724 end;
1725 return true; -- something was executed
1726 end;
1727 return false; -- e4xecute 'standard'
1728 end;
1731 local function runConfigureStd ()
1732 if myOpt.no_configure then return; end;
1733 logMessage("configure...");
1734 local s = myOpt.cfgname;
1736 local ipath = myOpt.install_path or "/usr";
1737 ipath = ipath:match("^%s*(.-)%s*$");
1738 if ipath:match("/$") then ipath = ipath:sub(1, -2); end;
1739 if ipath == "" then ipath = "/usr"; end;
1741 if not myOpt.no_prefix then s = s.." --prefix="..ipath; end;
1742 if not myOpt.no_mandir then s = s.." --mandir="..ipath.."/man"; end;
1743 if not myOpt.no_docdir then s = s.." --docdir="..ipath.."/doc/"..pinfo.name.."-"..pinfo.version; end;
1744 if not myOpt.no_libdir then s = s.." --libdir="..ipath.."/lib"; end;
1745 --if not myOpt.no_localstatedir then s = s.." --localstatedir="..ipath.."/var"; end;
1746 local lsd = myOpt.localstatedir and myOpt.localstatedir or "/var";
1748 local scpath = "/etc";
1749 if ipath ~= "/usr" then
1750 myOpt.no_sysconfdir = true;
1751 end;
1752 if not myOpt.no_sysconfdir then s = s.." --sysconfdir="..scpath; end;
1753 if not myOpt.no_localstatedir then s = s.." --localstatedir="..lsd; end;
1755 if not myOpt.no_programprefix then s = s.." --program-prefix="; end;
1756 if not myOpt.no_programsuffix then s = s.." --program-suffix="; end;
1757 if not myOpt.no_buildarch then s = s.." --build="..(pinfo.arch).."-slackware-linux "; end;
1758 for _, opt in ipairs(confOpt) do
1759 --print("!", opt);
1760 s = s.." "..opt:shQuote();
1761 end;
1762 if not s:match("dependency%-tracking") and not myOpt.no_deptrack then
1763 s = s.." --disable-dependency-tracking";
1764 end;
1765 --logMessage("**RUN**: %s", s);
1766 runCmd(s);
1767 end;
1770 local function runConfigure ()
1771 if not myOpt.no_configure then
1772 if not runScriptList(scconfigurelist, "configure") then runConfigureStd(); end;
1773 end;
1774 end;
1777 local function runPreConfigure ()
1778 if not myOpt.no_preconfigure then
1779 runScriptList(scpreconfigurelist, "preconfigure");
1780 end;
1781 end;
1784 local function runPreMake ()
1785 if not myOpt.no_preconfigure then
1786 runScriptList(scpremakelist, "premake");
1787 end;
1788 end;
1791 local function runMakeStd ()
1792 if myOpt.no_make then return; end;
1793 logMessage("make...");
1794 local mk = myOpt.makename or "make";
1795 --mk = mk:shQuote();
1796 if jobs > 1 then
1797 if mk == "rake" then mk = mk.." -m"; end;
1798 mk = string.format("%s -j%i", mk, jobs);
1799 end;
1800 if not myOpt.no_make_argflags then mk = mk..getBuildFlags(true); end;
1801 for k, v in pairs(buildEnvVars) do if v ~= "" then mk = mk.." "..k:shQuote().."="..v:shQuote(); end; end;
1802 runCmd(mk);
1803 end;
1806 local function runMake ()
1807 if not myOpt.no_make then
1808 if not runScriptList(scmakelist, "make") then runMakeStd(); end;
1809 end;
1810 end;
1813 local function runInstallStd ()
1814 if myOpt.no_package then return; end;
1815 logMessage("install...");
1816 runCmdRoot("rm -fR "..pkgdir);
1817 local cmd;
1818 if myOpt.instname then cmd = myOpt.instname;
1819 elseif myOpt.makename then cmd = myOpt.makename.." install";
1820 else cmd = "make install";
1821 end;
1822 local v = myOpt.make_install_var or "DESTDIR";
1823 local pfx = "";
1824 local sfx = "";
1825 for k, v in pairs(buildEnvVars) do if v ~= "" then pfx = pfx.."export "..k.."="..(v:shQuote()).." ; "; end; end;
1826 if not myOpt.no_inst_destdir then
1827 if not myOpt.no_make_argflags then
1828 sfx = v.."="..(pkgdir:shQuote())..getBuildFlags(true);
1829 else
1830 pfx = pfx.."export "..v.."="..(pkgdir:shQuote()).." ; "..getBuildFlags();
1831 end;
1832 end;
1833 runCmdRoot(pfx.." "..cmd.." "..sfx);
1834 end;
1837 local function runInstall ()
1838 if not myOpt.no_package then
1839 if not runScriptList(scinstalllist, "install") then runInstallStd(); end;
1840 end;
1841 end;
1844 local function runStrip ()
1845 if not myOpt.no_strip then
1846 logMessage("stripping...");
1847 local s = [[
1848 cd $PKG
1849 find . | xargs file | grep "executable" | grep ELF | cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null
1850 find . | xargs file | grep "shared object" | grep ELF | cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null
1852 --s = s:gsub("%$PKG", pkgdir);
1853 runShCmdRoot(s, true);
1854 end;
1855 end;
1858 local function compressMans ()
1859 logMessage("compressing mans...");
1860 runShCmdRoot([[
1861 if [ -d $PKG/usr/man ]; then
1862 ( cd $PKG/usr/man
1863 for manpagedir in $(find . -type d -name "man*") ; do
1864 ( cd $manpagedir
1865 for eachpage in $( find . -type l -maxdepth 1) ; do
1866 ln -s $( readlink $eachpage ).gz $eachpage.gz
1867 rm $eachpage
1868 done
1869 gzip -9 *.*
1871 done
1874 ]], true);
1875 end;
1878 local function compressInfos ()
1879 logMessage("compressing infos...");
1880 runShCmdRoot([[
1881 if [ -d $PKG/usr/info ]; then
1882 ( cd $PKG/usr/info
1883 rm -f dir
1884 gzip -9 *
1887 if [ -d $PKG/usr/share/info ]; then
1888 ( cd $PKG/usr/share/info
1889 rm -f dir
1890 gzip -9 *
1893 ]], true);
1894 end;
1897 local function writeSDesc ()
1898 logMessage("writing slack-desc...");
1899 writeSlackDesc(pkgdir.."/install/");
1900 end;
1903 local function writeSReq ()
1904 logMessage("writing slack-required...");
1905 writeSlackReq(pkgdir.."/install/");
1906 end;
1909 local function copyDox ()
1910 if not myOpt.no_dox and #doclist > 0 then
1911 logMessage("copying dox...");
1912 for _, dinfo in ipairs(doclist) do
1913 if #dinfo.list > 0 then
1914 local path = pkgdir..getPrefixDir().."/doc/"..pinfo.name.."-"..pinfo.version;
1915 if dinfo.path ~= "" then
1916 if not dinfo.path:match("^/") then path = path.."/"; end;
1917 path = path..dinfo.path;
1918 end;
1919 local cpcmd = "cp -a";
1920 for _, msk in ipairs(dinfo.list) do cpcmd = cpcmd.." "..msk; end;
1921 if not cpcmd:match("^cp%s+%-a%s*$") then
1922 cpcmd = cpcmd.." "..path.."/";
1923 --print(("%s|").format(path));
1924 --print(cpcmd.."|");
1925 os.execute("mkdir -p "..path:shQuote());
1926 runCmdRootFuckFail(cpcmd);
1927 end;
1928 end;
1929 end;
1930 end;
1931 end;
1934 local function doPostInstall ()
1935 if not myOpt.no_pss and #psslist > 0 then
1936 logMessage("executing post-install scripts...");
1937 for _, script in ipairs(psslist) do
1938 runShCmdRoot(script, false);
1939 end;
1940 end;
1941 end;
1944 local function processConfigs ()
1945 if not myOpt.no_cfg and #cfglist > 0 then
1946 logMessage("process configs...");
1948 local cl = {};
1949 for _, fname in ipairs(cfglist) do
1950 if fname:match("^/") then fname = fname:match("^/*(.*)$"); end;
1951 if fname ~= "" then
1952 local fl = io.open(pkgdir.."/"..fname, "r");
1953 if fl then
1954 fl:close();
1955 os.rename(pkgdir.."/"..fname, pkgdir.."/"..fname..".new");
1956 cl[#cl+1] = fname..".new";
1957 end;
1958 end;
1959 end;
1961 if #cl > 0 then
1962 logMessage("making install script...");
1963 local dis = [[
1964 config() {
1965 NEW="$1"
1966 OLD="$(dirname $NEW)/$(basename $NEW .new)"
1967 # If there's no config file by that name, mv it over:
1968 if [ ! -r $OLD ]; then
1969 mv $NEW $OLD
1970 elif [ "$(cat $OLD | md5sum)" = "$(cat $NEW | md5sum)" ]; then
1971 # toss the redundant copy
1972 rm $NEW
1974 # Otherwise, we leave the .new copy for the admin to consider...
1978 --config etc/acpi/acpi_handler.sh.new
1979 for _, fn in ipairs(cl) do dis = dis.."config "..fn.."\n"; end;
1980 doinstlist[#doinstlist+1] = dis;
1981 end;
1982 end;
1983 end;
1986 local function processDoInst ()
1987 if #doinstlist > 0 then
1988 logMessage("writing doist.sh...");
1989 local path = pkgdir.."/install/";
1990 os.execute("mkdir -p "..path:shQuote());
1991 local fl = io.open(path.."doinst.sh", "w");
1992 if not fl then error("can't create 'doinst.sh'"); end;
1993 for _, s in ipairs(doinstlist) do fl:write(s); end;
1994 fl:close();
1995 end;
1996 end;
1999 local function buildPkg ()
2000 logMessage("building package...");
2001 local xPkgExt = myOpt.pkgExt;
2002 if not xPkgExt or xPkgExt == "" then xPkgExt = "tgz"; end;
2003 local s = [[
2004 cd $PKG
2005 rm -f ../$PNAME.]]..xPkgExt..[[ 2>/dev/null
2006 rm -f $DESTDIR$PNAME.]]..xPkgExt..[[ 2>/dev/null
2007 /sbin/makepkg -l y -c y $DESTDIR$PNAME.]]..xPkgExt..[[
2009 --s = s:gsub("%$PKG", pkgdir);
2010 s = s:gsub("%$PNAME", pkgInfoToStr(pinfo));
2011 s = s:gsub("%$DESTDIR", pkgDestDir);
2012 runShCmdRoot(s);
2013 local s = [[
2014 cd $PKG
2015 cd ..
2016 rm -fR $PKG
2018 --s = s:gsub("%$PKG", pkgdir);
2019 runShCmdRoot(s);
2020 if myOpt["chownUser"] ~= "" then
2021 local s = pkgDestDir..pkgInfoToStr(pinfo).."."..xPkgExt;
2022 os.execute("chown "..(myOpt["chownUser"]):shQuote().." "..s:shQuote());
2023 end;
2024 end;
2027 local function runPatch (lines)
2028 if #lines < 1 then return; end;
2029 local n = io.popen("patch -p1 --verbose", "w");
2030 for _, s in ipairs(lines) do n:write(s, "\n"); end;
2031 n:close();
2032 end;
2035 local function runPreConfigPatches ()
2036 if not myOpt.no_prcp then
2037 for _, ppp in ipairs(precfgPatches) do runPatch(ppp); end;
2038 end;
2039 end;
2042 local function runPostConfigPatches ()
2043 if not myOpt.no_pcp then
2044 for _, ppp in ipairs(postcfgPatches) do runPatch(ppp); end;
2045 end;
2046 end;
2049 --copyDox();
2050 --os.exit(1);
2052 fixFuckinCaret();
2053 --copyEnvVars();
2054 build_stage = "configure";
2055 sanitizePerms();
2056 runPreConfigPatches();
2057 runPreConfigure();
2058 runConfigure();
2059 runPostConfigPatches();
2060 build_stage = "make";
2061 runPreMake();
2062 runMake();
2063 if not myOpt.no_package then
2064 io.write("MAKE COMPLETE!\n"); io.flush();
2065 os.execute("xcowsay 'build complete'");
2066 os.execute("sleep 2");
2068 --[[
2069 if getUID() ~= 0 then
2070 --io.stderr:write("this script must be run with su/sudo!\n");
2071 --io.stderr:flush();
2072 --os.exit(2);
2073 local msg = "package "..table.concat(pinfo, "-").." compiled\nneed root provs to build it!";
2074 os.system(string.format("xcowsay %s", msg:shQuote()));
2075 print("executing sudo!");
2076 local cmd =
2077 print(cmd);
2078 os.execute(string.format("sudo %s", cmd:shQuote());
2079 end;
2082 runInstall();
2083 runStrip();
2084 compressMans();
2085 compressInfos();
2086 writeSDesc();
2087 writeSReq();
2088 copyDox();
2089 doPostInstall();
2090 processConfigs();
2091 processDoInst();
2092 buildPkg();
2093 end;
2096 if myOpt["chownUser"] ~= "" then
2097 logMessage("restoring owner: %s", myOpt["chownUser"]);
2098 os.execute("chown "..(myOpt["chownUser"]):shQuote().." -R .");
2099 end;
2101 if myOpt.make_build_dir and not myOpt.keep_build_dir then
2102 logMessage("removing directory: %s", buildDirName);
2103 os.execute("rm -rf "..buildDirName.." >/dev/null 2>&1");
2104 end;
2106 --runXCowSay("package building complete");
2107 logMessage("done.");