2 -- semi-automated SlackBuild script
13 cfgname
= "./configure",
14 install_path
= "/usr",
23 make_build_dir
= false,
24 keep_build_dir
= false,
27 --force_native_profile = 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
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();
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");
59 io
.write("*** ", s
, "\n"); io
.flush();
63 local function timeStr (secs
)
64 local mins
= math
.floor(secs
/60);
66 local hours
= math
.floor(mins
/60);
68 return ("%02d:%02d:%02d"):format(hours
, mins
, secs
);
74 local meUser, meGroup;
76 local fl = assert(io.popen("whoami", "r"));
77 local s = assert(fl:read());
79 s = s:match("^%s*(.-)%s*$");
80 if s == "" then error("who am i?!"); end;
86 local fl = assert(io.popen("id -gn", "r"));
87 local s = assert(fl:read());
89 s = s:match("^%s*(.-)%s*$");
90 if s == "" then error("who am i?!"); end;
94 myOpt.chownUser = meUser..":"..meGroup;
98 local weAreBuildingSrcz
= false; -- this flag means that we are building sources and shouldn't be 'root'
103 local optPathList
= {
106 "~/.sbuild/xopt/!.xopt",
110 -- -mpreferred-stack-boundary=2
113 local defCompOptProfs
= {
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",
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",
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",
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",
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",
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",
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",
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",
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",
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",
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",
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",
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",
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",
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",
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",
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",
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",
201 local slackDesc
= {};
203 local unpackScript
= {};
204 local postcfgPatches
= {};
205 local precfgPatches
= {};
206 local doclist
= {}; -- [docs...]
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
= {}, {};
224 for m
in v0
:gmatch("[^.]+") do s0
[#s0
+1] = m
; end;
225 for m
in v1
:gmatch("[^.]+") do s1
[#s1
+1] = m
; end;
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
234 if n0
< n1
then return -1;
235 elseif n0
> n1
then return 1;
239 if #s0
< #s1
then return -1;
240 elseif #s0
> #s1
then return 1;
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
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; --
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);
285 local fl
= io
.open(fn
, "r");
287 io
.stderr
:write("using ", fn
, "\n"); io
.stderr
:flush();
296 -- i'm too lazy to do regexps
297 -- parse option string
298 local function parseOption (s
)
299 local res
, qq
, screen
, iscfgopt
= {};
302 s
= s
:match("^%s*(.-)%s*$");
303 if s
:match("^[#;]") then return false; end;
304 if s
:match("^%-%-") then
307 s
= s
:match("^%s*(.-)%s*$");
310 if o
:match("^%s") then return false; end; -- some silly text
312 if s
== "" then return false; end;
313 for ch
in s
:gmatch(".") do
317 if ch
== "\92" then screen
= true;
318 elseif ch
== '"' then qq
= not qq
;
319 elseif not qq
and ch
<= " " then break;
322 if not screen
then res
[#res
+1] = ch
; end;
324 if #res
< 1 then return false; end;
325 if iscfgopt
then res
[1] = "--"..res
[1]; end;
327 return join(res
), iscfgopt
;
331 -- if iscfgopt is false, treat as compiler option
332 local function parseCMakeOption (s
)
333 local iscfgopt
= false;
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
341 s
= s
:match("^%s*(.-)%s*$");
343 elseif o
:match("^%s") then
345 s
= s
:match("^([^%s]+)");
350 local res
, qq
, screen
= {};
352 for ch
in s
:gmatch(".") do
356 if ch
== "\92" then screen
= true;
357 elseif ch
== '"' then qq
= not qq
;
358 elseif not qq
and ch
<= " " then break;
361 if not screen
then res
[#res
+1] = ch
; end;
364 return join(res
), false;
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
;
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;
387 myOpt
.profile
= name
;
391 local function fixFuckinCaret ()
392 if compOpt
["CFLAGS"] then
393 compOpt
["CFLAGS"] = compOpt
["CFLAGS"].." -fno-diagnostics-show-caret";
395 if compOpt
["CXXFLAGS"] then
396 compOpt
["CXXFLAGS"] = compOpt
["CXXFLAGS"].." -fno-diagnostics-show-caret";
401 local function copyEnvVars ()
402 for k
, v
in pairs(buildEnvVars
) do
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
421 if value
== "ona" or value
== "no" or value
== "false" or
422 value
== "0" or value
== "o" or value
== "n" or value
== "f" then
426 error("option '"..optname
.."' expects boolean, but got '"..value
.."'");
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);
439 -- cchar: condition (char after "=" or false)
440 -- str: unparsed string
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
;
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
;
457 help
= "pkg_ext=[txz]",
458 handler
= function (name
, value
, cchar
, str
)
459 if not value
then value
= ""; end;
460 myOpt
.pkgExt
= value
;
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
;
471 help
= "profile=[native|speed|size|empty]",
472 handler
= function (name
, value
, cchar
, str
)
473 if not value
then value
= ""; end;
478 help
= "xflags=[+]flags -- modify CFLAGS and CXXFLAGS",
479 handler
= function (name
, value
, cchar
, str
)
480 if not value
then value
= ""; end;
483 if compOpt
.CFLAGS
then compOpt
.CFLAGS
= compOpt
.CFLAGS
.." ";
484 else compOpt
.CFLAGS
= "";
486 compOpt
.CFLAGS
= compOpt
.CFLAGS
..value
;
488 if compOpt
.CXXFLAGS
then compOpt
.CXXFLAGS
= compOpt
.CXXFLAGS
.." ";
489 else compOpt
.CXXFLAGS
= "";
491 compOpt
.CXXFLAGS
= compOpt
.CXXFLAGS
..value
;
493 elseif not cchar
then
494 compOpt
.CFLAGS
= value
;
495 compOpt
.CXXFLAGS
= value
;
497 assert(false, "invalid cflags operation");
502 help
= "cflags=[+]flags -- modify CFLAGS",
503 handler
= function (name
, value
, cchar
, str
)
504 if not value
then value
= ""; end;
507 if compOpt
.CFLAGS
then compOpt
.CFLAGS
= compOpt
.CFLAGS
.." ";
508 else compOpt
.CFLAGS
= "";
510 compOpt
.CFLAGS
= compOpt
.CFLAGS
..value
;
512 elseif not cchar
then
513 compOpt
.CFLAGS
= value
;
515 assert(false, "invalid cflags operation");
520 help
= "cxxflags=[+]flags -- modify CXXFLAGS",
521 handler
= function (name
, value
, cchar
, str
)
522 if not value
then value
= ""; end;
525 if compOpt
.CXXFLAGS
then compOpt
.CXXFLAGS
= compOpt
.CXXFLAGS
.." ";
526 else compOpt
.CXXFLAGS
= "";
528 compOpt
.CXXFLAGS
= compOpt
.CXXFLAGS
..value
;
530 elseif not cchar
then
531 compOpt
.CXXFLAGS
= value
;
533 assert(false, "invalid cflags operation");
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
;
545 help
= "makename=make_command",
546 handler
= function (name
, value
, cchar
, str
)
547 if not value
then value
= "make"; end;
548 myOpt
.makename
= value
;
552 help
= "instname=install_command",
553 handler
= function (name
, value
, cchar
, str
)
554 if not value
then value
= "make"; end;
555 myOpt
.instname
= value
;
559 help
= "no_prefix=[tan]",
560 handler
= optparseBooleanOpt
,
563 help
= "no_mandir=[tan]",
564 handler
= optparseBooleanOpt
,
567 help
= "no_docdir=[tan]",
568 handler
= optparseBooleanOpt
,
571 help
= "no_libdir=[tan]",
572 handler
= optparseBooleanOpt
,
575 help
= "no_localstatedir=[tan]",
576 handler
= optparseBooleanOpt
,
579 help
= "no_sysconfdir=[tan]",
580 handler
= optparseBooleanOpt
,
583 help
= "localstatedir=path",
584 handler
= function (name
, value
, cchar
, str
)
585 if not value
then value
= ""; end;
586 myOpt
.localstatedir
= value
;
590 help
= "no_programprefix=[tan]",
591 handler
= optparseBooleanOpt
,
594 help
= "no_programsuffix=[tan]",
595 handler
= optparseBooleanOpt
,
598 help
= "no_buildarch=[tan]",
599 handler
= optparseBooleanOpt
,
602 help
= "no_strip=[tan]",
603 handler
= optparseBooleanOpt
,
606 help
= "no_preconfigure=[tan]",
607 handler
= optparseBooleanOpt
,
610 help
= "no_premake=[tan]",
611 handler
= optparseBooleanOpt
,
614 help
= "no_configure=[tan]",
615 handler
= optparseBooleanOpt
,
618 help
= "no_make=[tan]",
619 handler
= optparseBooleanOpt
,
622 help
= "no_make_argflags=[tan] -- do not pass vars as make arguments",
623 handler
= optparseBooleanOpt
,
626 help
= "no_inst_destdir=[tan] -- do not pass DESTDIR to installer",
627 handler
= optparseBooleanOpt
,
630 help
= "no_package=[tan]",
631 handler
= optparseBooleanOpt
,
634 help
= "no_deptrack=[tan]",
635 handler
= optparseBooleanOpt
,
638 help
= "no_pcp=[tan] -- disable postconfig patches",
639 handler
= optparseBooleanOpt
,
642 help
= "no_prcp=[tan] -- disable preconfig patches",
643 handler
= optparseBooleanOpt
,
646 help
= "no_dox=[tan] -- disable doc copying",
647 handler
= optparseBooleanOpt
,
650 help
= "no_cfcopy=[tan] -- disable config copying",
651 handler
= optparseBooleanOpt
,
654 help
= "no_psscripts=[tan] -- disable post-install scripts",
655 handler
= optparseBooleanOpt
,
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;
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
;
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
;
682 help
= "make_build_dir=[tan] -- for cmake, for example",
683 handler
= optparseBooleanOpt
,
686 help
= "keep_build_dir=[tan] -- do not remove building directory",
687 handler
= optparseBooleanOpt
,
690 help
= "use_fakeroot=[tan] -- use fakeroot instead of su/sudo",
691 handler
= optparseBooleanOpt
,
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,
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
);
709 if not n
:match("^[A-Z_]+$") then error("unknown option: "..n
); end;
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 "";
717 elseif c
== "!" then -- set if already set
718 if opt
then compOpt
[n
] = v
; end;
725 local function loadOptions (fname
, failOnError
)
727 local tdsc
= fname
..":";
728 local tdsc1
= tdsc
.." ";
731 function phaseNothing (s
)
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;
739 --if v ~= "" then compOpt[k] = v; else compOpt[k] = nil; end;
740 --print("k="..k.."; v="..v.."|");
743 if myOpt
.using_cmake
then
744 opt
, iscfg
= parseCMakeOption(s
);
745 --print(opt, ":", iscfg);
747 opt
, iscfg
= parseOption(s
);
752 confOpt
[#confOpt
+1] = opt
;
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
;
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;
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
;
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;
791 if rc
>= 1 and slackReq
[rc
] ~= " | " then slackReq
[#slackReq
+1] = ","; end;
793 slackReq
[#slackReq
+1] = s
;
797 function phaseUnp (s
)
798 unpackScript
[#unpackScript
+1] = s
;
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;
814 function phasePRCPNew (s
)
815 if pcpStarted
then error("unclosed preconfig-patch section in file "..fname
); end;
821 function phasePCPEnd (s
)
822 if not pcpStarted
then error("bad postconfig-patch section in file "..fname
); end;
824 precfgPatches
[#precfgPatches
+1] = pcpCurrent
;
826 postcfgPatches
[#postcfgPatches
+1] = pcpCurrent
;
833 function phasePCP (s
, origs
)
834 pcpCurrent
[#pcpCurrent
+1] = origs
;
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;
847 if not doxPath
then doxPath
= ""; 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
};
858 function phaseDox (s
, origs
)
859 doxCurrent
[#doxCurrent
+1] = origs
;
863 -----------------------------------------------------------------------------
864 local cfgStarted
= false;
866 function phaseCfgNew (s
)
867 if cfgStarted
then error("unclosed cfg section in file "..fname
); end;
871 function phaseCfgEnd (s
)
872 if not cfgStarted
then error("bad cfg section in file "..fname
); end;
876 function phaseCfg (s
, origs
)
877 cfglist
[#cfglist
+1] = origs
;
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;
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");
905 function phasePSS (s
, origs
)
906 pssCurrent
[#pssCurrent
+1] = origs
:match("^.-%s*$");
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;
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");
931 doinstStarted
= false;
932 doinstCurrent
= false;
935 function phaseDoInst (s
, origs
)
936 doinstCurrent
[#doinstCurrent
+1] = origs
:match("^.-%s*$");
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
= {};
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");
960 scinstallStarted
= false;
961 scinstallCurrent
= false;
964 function phaseInstall (s
, origs
)
965 scinstallCurrent
[#scinstallCurrent
+1] = origs
:match("^.-%s*$");
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;
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");
989 scmakeStarted
= false;
990 scmakeCurrent
= false;
993 function phaseMake (s
, origs
)
994 scmakeCurrent
[#scmakeCurrent
+1] = origs
:match("^.-%s*$");
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
= {};
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");
1018 scconfigureStarted
= false;
1019 scconfigureCurrent
= false;
1022 function phaseConfigure (s
, origs
)
1023 scconfigureCurrent
[#scconfigureCurrent
+1] = origs
:match("^.-%s*$");
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
= {};
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");
1047 scpreconfigureStarted
= false;
1048 scpreconfigureCurrent
= false;
1051 function phasePreConfigure (s
, origs
)
1052 scpreconfigureCurrent
[#scpreconfigureCurrent
+1] = origs
:match("^.-%s*$");
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
= {};
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");
1076 scpremakeStarted
= false;
1077 scpremakeCurrent
= false;
1080 function phasePreMake (s
, origs
)
1081 scpremakeCurrent
[#scpremakeCurrent
+1] = origs
:match("^.-%s*$");
1085 -----------------------------------------------------------------------------
1086 local phaseFunc
= phaseNothing
;
1088 local phaseAliases
= {
1089 ["!DESCRIPTION"] = "!DSC",
1090 ["!DESCR"] = "!DSC",
1092 ["!REQUIRED"] = "!REQ",
1093 ["!UNPACK"] = "!UNP",
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
},
1127 local fileNames
= {};
1130 function doInclude (fname
, doFail
)
1131 print("loading "..fname
);
1132 local fl
= openFile(fname
);
1134 if doFail
or failOnError
then error("can't open options file: "..fname
); end;
1137 files
[#files
+1] = fl
;
1138 fileNames
[#fileNames
+1] = fname
;
1142 if not doInclude(fname
, false) then return false; end;
1145 local fl
= files
[#files
];
1146 local fname
= fileNames
[#fileNames
];
1147 local s
= fl
:read();
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);
1162 if not doxPath
and s
:upper():match("^%[DOCS=") then
1163 local pth
= s
:match("^%[[Dd][Oo][Cc][Ss]=(.-)%]$");
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
;
1183 table.remove(files
);
1184 table.remove(fileNames
);
1189 while dsccnt
< 11 do
1190 slackDesc
[#slackDesc
+1] = tdsc
;
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
)));
1205 print("configure options:");
1206 for k
, v
in pairs(confOpt
) do
1207 print(string.format(" %s={%s}", k
, tostring(v
)));
1210 print("other options:");
1211 for k
, v
in pairs(myOpt
) do
1212 print(string.format(" %s={%s}", k
, tostring(v
)));
1219 io.stderr:write("usage: dosb pkgname [build]\n");
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 .");
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;
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
);
1261 local function getUID ()
1262 local fl
= io
.popen("echo $UID");
1263 if not fl
then return -1; end;
1264 local s
= fl
:read();
1267 return tonumber(s
) or -1;
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;
1280 local build_stage
= "configure"; -- "configure", "make"
1282 local function getBuildFlags (nowrexport
)
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().." ; ";
1292 s
= s
.." "..k
.."="..v
:shQuote();
1297 --logMessage("*S*: %s", s);
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
;
1318 INSTPFX
= getPrefixDir(),
1319 PKGNAM
= pinfo
.name
,
1320 VERSION
= pinfo
.version
,
1322 BUILD
= tostring(pinfo
.build
)..pinfo
.author
,
1323 PKGDOCSDIR
= docpath
,
1324 USRDOCSDIR
= usrdocpath
,
1325 JOBS
= tostring(jobs
),
1329 for n
, v
in pairs(vars
) do
1330 --if not noexport then s = s.." export"; end;
1331 s
= s
.." "..n
.."="..v
:shQuote();
1333 for n
, v
in pairs(buildEnvVars
) do
1334 --if not noexport then s = s.." export"; end;
1335 s
= s
.." "..n
.."="..v
:shQuote();
1337 --logMessage("*scv: %s", s);
1338 --error("DBGBREAK");
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..'" ; ';
1348 if myOpt
.make_build_dir
then
1349 flg
= flg
.."cd "..buildDirName
.." ; ";
1351 flg
= flg
..getBuildFlags()..s
.." )";
1352 logMessage("*run: %s", flg
);
1354 --s = s:gsub("\n", "\\\n");
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!");
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");
1369 os
.execute("chown "..myOpt
.srcBuildUser
.." "..tsh
:shQuote());
1370 flg
= "su "..myOpt
.srcBuildUser
..' -c "sh '..tsh
:shQuote()..'"';
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
);
1379 if not ignoreFail
and res
~= 0 then error("command is fucked up!"); end;
1382 local function runCmdRoot (cmd
, ...)
1383 return runCmdEx(false, false, cmd
, ...);
1386 local function runCmdRootFuckFail (cmd
, ...)
1387 return runCmdEx(false, true, cmd
, ...);
1390 local function runCmd (cmd
, ...)
1391 return runCmdEx(true, false, cmd
, ...);
1394 local function runCmdFuckFail (cmd
, ...)
1395 return runCmdEx(true, true, cmd
, ...);
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");
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");
1410 if not myOpt
.srcBuildUser
or myOpt
.srcBuildUser
== "" then
1411 error("can't lower privileges for command!");
1413 os
.execute("chown "..myOpt
.srcBuildUser
.." "..tsh
:shQuote());
1414 --!logMessage("*LOPRV");
1415 flg
= "su "..myOpt
.srcBuildUser
..' -c "'..flg
:shQuote()..'"';
1417 local res
= os
.execute(flg
);
1420 if not nofail
and res
~= 0 then error("command is fucked up!"); end;
1423 local function runShCmd (cmd
, nofail
)
1424 return runShCmdEx(true, cmd
, nofail
);
1427 local function runShCmdRoot (cmd
, nofail
)
1428 return runShCmdEx(false, cmd
, nofail
);
1432 local function runXCowSay (cmd
, msg
)
1433 local fl
= io
.popen("which xcowsay", "r");
1435 local s
= fl
:read();
1437 if s
and s
~= "" then
1443 local function parsePkgName (name
)
1445 for w
in (name
.."-"):gmatch("[^-]*") do
1446 w
= w
:match("^%s*(.-)%s*$");
1447 if w
~= "" then spl
[#spl
+1] = w
; end;
1451 pinfo
.version
= spl
[#spl
];
1453 pinfo
.name
= join(spl
, "-");
1456 pinfo
.arch
= "i686";
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");
1467 local function printHelp ()
1469 usage: sbuild pkgname-ver [options] [buildnum]
1471 -nocfg don't run configure
1472 -noprecfg don't run preconfigure script
1473 -nopremk don't run premake script
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
..[[)
1482 -nonative disable replacing 'empty' profile with 'native'
1484 xopt options:]]); --
1487 for name
, opt
in pairs(myOptH
) do
1489 names
[#names
+1] = name
;
1490 maxlen
= math
.max(maxlen
, #name
);
1497 for _
, name
in pairs(names
) do
1498 local opt
= myOptH
[name
];
1500 local lpad
= string.rep(" ", maxlen
-#name
);
1501 print(name
..lpad
..opt
.help
);
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;
1519 local inFakeRoot
= false;
1521 -- check for special flag
1523 if arg[1] and arg[1] == "K8XBUILDSRC" then
1524 weAreBuildingSrcz = true;
1526 for f = 2, cnt do arg[f-1] = arg[f]; end;
1530 local in_pfx_arg
= false;
1531 local inst_pfx
= false;
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
1551 io
.stderr
:write("*ERROR: ", argv
[f
], "expects argument!\n");
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;
1563 io
.stderr
:write("*ERROR: extra options!\n");
1566 bldnum
= tonumber(arg
[f
]);
1567 if not bldnum
or bldnum
< 1 then
1568 io
.stderr
:write("*ERROR: invalid build number!\n");
1571 bldnum
= math
.floor(bldnum
);
1572 else apkgname
= arg
[f
];
1578 if not apkgname
then
1579 print("*ERROR: no package name!");
1585 if force_native_profile
then
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;
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;
1612 print("FORCING PREFIX TO "..inst_pfx
);
1613 myOpt
.install_path
= inst_pfx
;
1617 for _, ppp in ipairs(postcfgPatches) do
1618 print("patch #".._..":");
1619 for _, s in ipairs(ppp) do print(" "..s.."|"); end;
1624 -- last minute fixups
1625 if not myOpt
.chownUser
or myOpt
.chownUser
== "" then
1626 olderr("too bad! we are mad! (no chown_user)");
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
;
1636 --local pkgDestDir = "/home/ketmar/zoft/pkg/";
1637 if not myOpt
.pkgdestdir
or myOpt
.pkgdestdir
== "" then
1638 myOpt
.pkgdestdir
= os
.getenv("HOME").."/.sbuild/pkg";
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;
1661 if myOpt
.use_fakeroot
then
1662 myOpt
.srcBuildUser
= "";
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();
1672 cmdline
= cmdline
.." "..(arg
[f
]):shQuote();
1674 --io.stderr:write("[", cmdline, "]\n");
1675 local res
= os
.execute(cmdline
);
1678 io
.stderr
:write("this script must be run with su/sudo!\n");
1685 if ooKBD
== true then
1686 myOpt
.keep_build_dir
= true;
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");
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 .");
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 {} \\;");
1719 local function runScriptList (sclist
, msg
)
1721 logMessage("executing custom '%s' script(s)...", msg
);
1722 for _
, script
in ipairs(sclist
) do
1723 runShCmdRoot(script
, false);
1725 return true; -- something was executed
1727 return false; -- e4xecute 'standard'
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;
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
1760 s
= s
.." "..opt
:shQuote();
1762 if not s
:match("dependency%-tracking") and not myOpt
.no_deptrack
then
1763 s
= s
.." --disable-dependency-tracking";
1765 --logMessage("**RUN**: %s", s);
1770 local function runConfigure ()
1771 if not myOpt
.no_configure
then
1772 if not runScriptList(scconfigurelist
, "configure") then runConfigureStd(); end;
1777 local function runPreConfigure ()
1778 if not myOpt
.no_preconfigure
then
1779 runScriptList(scpreconfigurelist
, "preconfigure");
1784 local function runPreMake ()
1785 if not myOpt
.no_preconfigure
then
1786 runScriptList(scpremakelist
, "premake");
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();
1797 if mk
== "rake" then mk
= mk
.." -m"; end;
1798 mk
= string.format("%s -j%i", mk
, jobs
);
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;
1806 local function runMake ()
1807 if not myOpt
.no_make
then
1808 if not runScriptList(scmakelist
, "make") then runMakeStd(); end;
1813 local function runInstallStd ()
1814 if myOpt
.no_package
then return; end;
1815 logMessage("install...");
1816 runCmdRoot("rm -fR "..pkgdir
);
1818 if myOpt
.instname
then cmd
= myOpt
.instname
;
1819 elseif myOpt
.makename
then cmd
= myOpt
.makename
.." install";
1820 else cmd
= "make install";
1822 local v
= myOpt
.make_install_var
or "DESTDIR";
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);
1830 pfx
= pfx
.."export "..v
.."="..(pkgdir
:shQuote()).." ; "..getBuildFlags();
1833 runCmdRoot(pfx
.." "..cmd
.." "..sfx
);
1837 local function runInstall ()
1838 if not myOpt
.no_package
then
1839 if not runScriptList(scinstalllist
, "install") then runInstallStd(); end;
1844 local function runStrip ()
1845 if not myOpt
.no_strip
then
1846 logMessage("stripping...");
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);
1858 local function compressMans ()
1859 logMessage("compressing mans...");
1861 if [ -d $PKG/usr/man ]; then
1863 for manpagedir in $(find . -type d -name "man*") ; do
1865 for eachpage in $( find . -type l -maxdepth 1) ; do
1866 ln -s $( readlink $eachpage ).gz $eachpage.gz
1878 local function compressInfos ()
1879 logMessage("compressing infos...");
1881 if [ -d $PKG/usr/info ]; then
1887 if [ -d $PKG/usr/share/info ]; then
1888 ( cd $PKG/usr/share/info
1897 local function writeSDesc ()
1898 logMessage("writing slack-desc...");
1899 writeSlackDesc(pkgdir
.."/install/");
1903 local function writeSReq ()
1904 logMessage("writing slack-required...");
1905 writeSlackReq(pkgdir
.."/install/");
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
;
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
);
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);
1944 local function processConfigs ()
1945 if not myOpt
.no_cfg
and #cfglist
> 0 then
1946 logMessage("process configs...");
1949 for _
, fname
in ipairs(cfglist
) do
1950 if fname
:match("^/") then fname
= fname
:match("^/*(.*)$"); end;
1952 local fl
= io
.open(pkgdir
.."/"..fname
, "r");
1955 os
.rename(pkgdir
.."/"..fname
, pkgdir
.."/"..fname
..".new");
1956 cl
[#cl
+1] = fname
..".new";
1962 logMessage("making install script...");
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
1970 elif [ "$(cat $OLD | md5sum)" = "$(cat $NEW | md5sum)" ]; then
1971 # toss the redundant copy
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
;
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;
1999 local function buildPkg ()
2000 logMessage("building package...");
2001 local xPkgExt
= myOpt
.pkgExt
;
2002 if not xPkgExt
or xPkgExt
== "" then xPkgExt
= "tgz"; end;
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
);
2018 --s = s:gsub("%$PKG", pkgdir);
2020 if myOpt
["chownUser"] ~= "" then
2021 local s
= pkgDestDir
..pkgInfoToStr(pinfo
).."."..xPkgExt
;
2022 os
.execute("chown "..(myOpt
["chownUser"]):shQuote().." "..s
:shQuote());
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;
2035 local function runPreConfigPatches ()
2036 if not myOpt
.no_prcp
then
2037 for _
, ppp
in ipairs(precfgPatches
) do runPatch(ppp
); end;
2042 local function runPostConfigPatches ()
2043 if not myOpt
.no_pcp
then
2044 for _
, ppp
in ipairs(postcfgPatches
) do runPatch(ppp
); end;
2054 build_stage
= "configure";
2056 runPreConfigPatches();
2059 runPostConfigPatches();
2060 build_stage
= "make";
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");
2069 if getUID() ~= 0 then
2070 --io.stderr:write("this script must be run with su/sudo!\n");
2071 --io.stderr:flush();
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!");
2078 os.execute(string.format("sudo %s", cmd:shQuote());
2096 if myOpt
["chownUser"] ~= "" then
2097 logMessage("restoring owner: %s", myOpt
["chownUser"]);
2098 os
.execute("chown "..(myOpt
["chownUser"]):shQuote().." -R .");
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");
2106 --runXCowSay("package building complete");
2107 logMessage("done.");