18378665fSKyle Evans-- 28378665fSKyle Evans-- Copyright (c) 2023 Kyle Evans <kevans@FreeBSD.org> 38378665fSKyle Evans-- 48378665fSKyle Evans-- SPDX-License-Identifier: BSD-2-Clause 58378665fSKyle Evans-- 68378665fSKyle Evans 78378665fSKyle Evanslocal libgen = require('posix.libgen') 88378665fSKyle Evanslocal lfs = require('lfs') 98378665fSKyle Evanslocal stdlib = require('posix.stdlib') 108378665fSKyle Evanslocal unistd = require('posix.unistd') 118378665fSKyle Evanslocal sys_wait = require('posix.sys.wait') 128378665fSKyle Evans 138378665fSKyle Evanslocal curdate = os.date("%B %e, %Y") 148378665fSKyle Evans 158378665fSKyle Evanslocal output_head <const> = ".\\\" DO NOT EDIT-- this file is @" .. [[generated by tools/build/options/makeman. 168378665fSKyle Evans.Dd ]] .. curdate .. [[ 178378665fSKyle Evans 188378665fSKyle Evans.Dt SRC.CONF 5 198378665fSKyle Evans.Os 208378665fSKyle Evans.Sh NAME 218378665fSKyle Evans.Nm src.conf 228378665fSKyle Evans.Nd "source build options" 238378665fSKyle Evans.Sh DESCRIPTION 248378665fSKyle EvansThe 258378665fSKyle Evans.Nm 268378665fSKyle Evansfile contains variables that control what components will be generated during 278378665fSKyle Evansthe build process of the 288378665fSKyle Evans.Fx 298378665fSKyle Evanssource tree; see 308378665fSKyle Evans.Xr build 7 . 318378665fSKyle Evans.Pp 328378665fSKyle EvansThe 338378665fSKyle Evans.Nm 348378665fSKyle Evansfile uses the standard makefile syntax. 358378665fSKyle EvansHowever, 368378665fSKyle Evans.Nm 378378665fSKyle Evansshould not specify any dependencies to 388378665fSKyle Evans.Xr make 1 . 398378665fSKyle EvansInstead, 408378665fSKyle Evans.Nm 418378665fSKyle Evansis to set 428378665fSKyle Evans.Xr make 1 438378665fSKyle Evansvariables that control the aspects of how the system builds. 448378665fSKyle Evans.Pp 458378665fSKyle EvansThe default location of 468378665fSKyle Evans.Nm 472619d439SEd Masteis the top level of the source tree, or 482619d439SEd Maste.Pa /etc/src.conf 492619d439SEd Masteif no 502619d439SEd Maste.Nm 512619d439SEd Masteis found in the source tree itself, 528378665fSKyle Evansthough an alternative location can be specified in the 538378665fSKyle Evans.Xr make 1 548378665fSKyle Evansvariable 558378665fSKyle Evans.Va SRCCONF . 568378665fSKyle EvansOverriding the location of 578378665fSKyle Evans.Nm 588378665fSKyle Evansmay be necessary if the system-wide settings are not suitable 598378665fSKyle Evansfor a particular build. 608378665fSKyle EvansFor instance, setting 618378665fSKyle Evans.Va SRCCONF 628378665fSKyle Evansto 638378665fSKyle Evans.Pa /dev/null 648378665fSKyle Evanseffectively resets all build controls to their defaults. 658378665fSKyle Evans.Pp 668378665fSKyle EvansThe only purpose of 678378665fSKyle Evans.Nm 688378665fSKyle Evansis to control the compilation of the 698378665fSKyle Evans.Fx 708378665fSKyle Evanssource code, which is usually located in 718378665fSKyle Evans.Pa /usr/src . 728378665fSKyle EvansAs a rule, the system administrator creates 738378665fSKyle Evans.Nm 748378665fSKyle Evanswhen the values of certain control variables need to be changed 758378665fSKyle Evansfrom their defaults. 768378665fSKyle Evans.Pp 778378665fSKyle EvansIn addition, control variables can be specified 788378665fSKyle Evansfor a particular build via the 798378665fSKyle Evans.Fl D 808378665fSKyle Evansoption of 818378665fSKyle Evans.Xr make 1 828378665fSKyle Evansor in its environment; see 838378665fSKyle Evans.Xr environ 7 . 848378665fSKyle Evans.Pp 858378665fSKyle EvansThe environment of 868378665fSKyle Evans.Xr make 1 878378665fSKyle Evansfor the build can be controlled via the 888378665fSKyle Evans.Va SRC_ENV_CONF 898378665fSKyle Evansvariable, which defaults to 908378665fSKyle Evans.Pa /etc/src-env.conf . 918378665fSKyle EvansSome examples that may only be set in this file are 928378665fSKyle Evans.Va WITH_DIRDEPS_BUILD , 938378665fSKyle Evansand 948378665fSKyle Evans.Va WITH_META_MODE , 958378665fSKyle Evansand 968378665fSKyle Evans.Va MAKEOBJDIRPREFIX 978378665fSKyle Evansas they are environment-only variables. 988378665fSKyle Evans.Pp 998378665fSKyle EvansThe values of 1008378665fSKyle Evans.Va WITH_ 1018378665fSKyle Evansand 1028378665fSKyle Evans.Va WITHOUT_ 1038378665fSKyle Evansvariables are ignored regardless of their setting; 1048378665fSKyle Evanseven if they would be set to 1058378665fSKyle Evans.Dq Li FALSE 1068378665fSKyle Evansor 1078378665fSKyle Evans.Dq Li NO . 1088378665fSKyle EvansThe presence of an option causes 1098378665fSKyle Evansit to be honored by 1108378665fSKyle Evans.Xr make 1 . 1118378665fSKyle Evans.Pp 1128378665fSKyle EvansThis list provides a name and short description for variables 1138378665fSKyle Evansthat can be used for source builds. 1148378665fSKyle Evans.Bl -tag -width indent 1158378665fSKyle Evans]] 1168378665fSKyle Evans 1178378665fSKyle Evanslocal output_tail <const> = [[.El 1188378665fSKyle Evans.Sh FILES 1198378665fSKyle Evans.Bl -tag -compact -width Pa 1208378665fSKyle Evans.It Pa /etc/src.conf 1218378665fSKyle Evans.It Pa /etc/src-env.conf 1228378665fSKyle Evans.It Pa /usr/share/mk/bsd.own.mk 1238378665fSKyle Evans.El 1248378665fSKyle Evans.Sh SEE ALSO 1258378665fSKyle Evans.Xr make 1 , 1268378665fSKyle Evans.Xr make.conf 5 , 1278378665fSKyle Evans.Xr build 7 , 1288378665fSKyle Evans.Xr ports 7 1298378665fSKyle Evans.Sh HISTORY 1308378665fSKyle EvansThe 1318378665fSKyle Evans.Nm 1328378665fSKyle Evansfile appeared in 1338378665fSKyle Evans.Fx 7.0 . 1348378665fSKyle Evans.Sh AUTHORS 1358378665fSKyle EvansThis manual page was autogenerated by 1368378665fSKyle Evans.An tools/build/options/makeman . 1378378665fSKyle Evans]] 1388378665fSKyle Evans 1398378665fSKyle Evanslocal scriptdir <const> = libgen.dirname(stdlib.realpath(arg[0])) 1408378665fSKyle Evanslocal srcdir <const> = stdlib.realpath(scriptdir .. "/../../../") 1418378665fSKyle Evanslocal makesysdir <const> = srcdir .. "/share/mk" 1428378665fSKyle Evans 1438378665fSKyle Evanslocal make_envvar = os.getenv("MAKE") 1448378665fSKyle Evanslocal make_cmd_override = {} 1458378665fSKyle Evansif make_envvar then 1468378665fSKyle Evans for word in make_envvar:gmatch("[^%s]+") do 1478378665fSKyle Evans make_cmd_override[#make_cmd_override + 1] = word 1488378665fSKyle Evans end 1498378665fSKyle Evansend 1508378665fSKyle Evans 1518378665fSKyle Evans-- Lifted from bsdinstall/scripts/pkgbase.in (read_all) 1528378665fSKyle Evanslocal function read_pipe(pipe) 1538378665fSKyle Evans local ret = "" 1548378665fSKyle Evans repeat 1558378665fSKyle Evans local buffer = assert(unistd.read(pipe, 1024)) 1568378665fSKyle Evans ret = ret .. buffer 1578378665fSKyle Evans until buffer == "" 1588378665fSKyle Evans return ret 1598378665fSKyle Evansend 1608378665fSKyle Evanslocal function run_make(args) 1618378665fSKyle Evans local cmd_args = {"env", "-i", "make", "-C", srcdir, "-m", makesysdir, 1628378665fSKyle Evans "__MAKE_CONF=/dev/null", "SRCCONF=/dev/null"} 1638378665fSKyle Evans 1648378665fSKyle Evans if #make_cmd_override > 0 then 1658378665fSKyle Evans cmd_args[3] = make_cmd_override[1] 1668378665fSKyle Evans for k = 2, #make_cmd_override do 1678378665fSKyle Evans local val = make_cmd_override[k] 1688378665fSKyle Evans 1698378665fSKyle Evans table.insert(cmd_args, 3 + (k - 1), val) 1708378665fSKyle Evans end 1718378665fSKyle Evans end 1728378665fSKyle Evans for k, v in ipairs(args) do 1738378665fSKyle Evans cmd_args[#cmd_args + 1] = v 1748378665fSKyle Evans end 1758378665fSKyle Evans 1768378665fSKyle Evans local r, w = assert(unistd.pipe()) 1778378665fSKyle Evans local pid = assert(unistd.fork()) 1788378665fSKyle Evans if pid == 0 then 1798378665fSKyle Evans -- Child 1808378665fSKyle Evans assert(unistd.close(r)) 1818378665fSKyle Evans assert(unistd.dup2(w, 1)) 1828378665fSKyle Evans assert(unistd.dup2(w, 2)) 1838378665fSKyle Evans assert(unistd.execp("env", cmd_args)) 1848378665fSKyle Evans unistd._exit() 1858378665fSKyle Evans end 1868378665fSKyle Evans 1878378665fSKyle Evans -- Parent 1888378665fSKyle Evans assert(unistd.close(w)) 1898378665fSKyle Evans 1908378665fSKyle Evans local output = read_pipe(r) 1918378665fSKyle Evans assert(unistd.close(r)) 1928378665fSKyle Evans 1938378665fSKyle Evans local _, exit_type, exit_code = assert(sys_wait.wait(pid)) 1948378665fSKyle Evans assert(exit_type == "exited", "make exited with wrong status") 1958378665fSKyle Evans assert(exit_code == 0, "make exited unsuccessfully") 1968378665fSKyle Evans return output 1978378665fSKyle Evansend 1988378665fSKyle Evans 1998378665fSKyle Evanslocal function native_target() 2008378665fSKyle Evans local output = run_make({"MK_AUTO_OBJ=NO", "-V", "MACHINE", 2018378665fSKyle Evans "-V", "MACHINE_ARCH"}) 2028378665fSKyle Evans 2038378665fSKyle Evans local arch, machine_arch 2048378665fSKyle Evans for x in output:gmatch("[^\n]+") do 2058378665fSKyle Evans if not arch then 2068378665fSKyle Evans arch = x 2078378665fSKyle Evans elseif not machine_arch then 2088378665fSKyle Evans machine_arch = x 2098378665fSKyle Evans end 2108378665fSKyle Evans end 2118378665fSKyle Evans 2128378665fSKyle Evans return arch .. "/" .. machine_arch 2138378665fSKyle Evansend 2148378665fSKyle Evans 2158378665fSKyle Evanslocal function src_targets() 2168378665fSKyle Evans local targets = {} 2178378665fSKyle Evans targets[native_target()] = true 2188378665fSKyle Evans 2198378665fSKyle Evans local output = run_make({"MK_AUTO_OBJ=no", "targets"}) 2208378665fSKyle Evans local curline = 0 2218378665fSKyle Evans 2228378665fSKyle Evans for line in output:gmatch("[^\n]+") do 2238378665fSKyle Evans curline = curline + 1 2248378665fSKyle Evans if curline ~= 1 then 2258378665fSKyle Evans local arch = line:match("[^%s]+/[^%s]+") 2268378665fSKyle Evans 2278378665fSKyle Evans -- Make sure we don't roll over our default arch 2288378665fSKyle Evans if arch and not targets[arch] then 2298378665fSKyle Evans targets[arch] = false 2308378665fSKyle Evans end 2318378665fSKyle Evans end 2328378665fSKyle Evans end 2338378665fSKyle Evans 2348378665fSKyle Evans return targets 2358378665fSKyle Evansend 2368378665fSKyle Evans 2378378665fSKyle Evanslocal function config_options(srcconf, env, take_dupes, linting) 2388378665fSKyle Evans srcconf = srcconf or "/dev/null" 2398378665fSKyle Evans env = env or {} 2408378665fSKyle Evans 2418378665fSKyle Evans local option_args = {".MAKE.MODE=normal", "showconfig", 2428378665fSKyle Evans "SRC_ENV_CONF=" .. srcconf} 2438378665fSKyle Evans 2448378665fSKyle Evans for _, val in ipairs(env) do 2458378665fSKyle Evans option_args[#option_args + 1] = val 2468378665fSKyle Evans end 2478378665fSKyle Evans 2488378665fSKyle Evans local output = run_make(option_args) 2498378665fSKyle Evans 2508378665fSKyle Evans local options = {} 2518378665fSKyle Evans local known_dupes = {} 2528378665fSKyle Evans 2538378665fSKyle Evans local function warn_on_dupe(option, val) 2548378665fSKyle Evans if not linting or known_dupes[option] then 2558378665fSKyle Evans return false 2568378665fSKyle Evans end 2578378665fSKyle Evans if not option:match("^OPT_") then 2588378665fSKyle Evans val = val == "yes" 2598378665fSKyle Evans end 2608378665fSKyle Evans 2618378665fSKyle Evans known_dupes[option] = true 2628378665fSKyle Evans return val ~= options[val] 2638378665fSKyle Evans end 2648378665fSKyle Evans 2658378665fSKyle Evans for opt in output:gmatch("[^\n]+") do 2668378665fSKyle Evans if opt:match("^MK_[%a%d_]+%s+=%s+.+") then 2678378665fSKyle Evans local name = opt:match("MK_[%a%d_]+") 2688378665fSKyle Evans local val = opt:match("= .+"):sub(3) 2698378665fSKyle Evans 2708378665fSKyle Evans -- Some settings, e.g., MK_INIT_ALL_ZERO, may end up 2718378665fSKyle Evans -- output twice for some reason that I haven't dug into; 2728378665fSKyle Evans -- take the first value. In some circumstances, though, 2738378665fSKyle Evans -- we do make an exception and actually want to take the 2748378665fSKyle Evans -- latest. 2758378665fSKyle Evans if take_dupes or options[name] == nil then 2768378665fSKyle Evans options[name] = val == "yes" 2778378665fSKyle Evans elseif warn_on_dupe(name, val) then 2788378665fSKyle Evans io.stderr:write("ignoring duplicate option " .. 2798378665fSKyle Evans name .. "\n") 2808378665fSKyle Evans end 2818378665fSKyle Evans elseif opt:match("^OPT_[%a%d_]+%s+=%s+.+") then 2828378665fSKyle Evans local name = opt:match("OPT_[%a%d_]+") 2838378665fSKyle Evans local val = opt:match("= .+"):sub(3) 2848378665fSKyle Evans 2858378665fSKyle Evans -- Multi-value options will arbitrarily use a table here 2868378665fSKyle Evans -- to indicate the difference. 2878378665fSKyle Evans if take_dupes or options[name] == nil then 2888378665fSKyle Evans options[name] = val 2898378665fSKyle Evans elseif warn_on_dupe(name, val) then 2908378665fSKyle Evans io.stderr:write("ignoring duplicate option " .. 2918378665fSKyle Evans name .. "\n") 2928378665fSKyle Evans end 2938378665fSKyle Evans end 2948378665fSKyle Evans end 2958378665fSKyle Evans 2968378665fSKyle Evans return options 2978378665fSKyle Evansend 2988378665fSKyle Evans 2998378665fSKyle Evanslocal function env_only_options() 3008378665fSKyle Evans local output = run_make({"MK_AUTO_OBJ=no", "-V", "__ENV_ONLY_OPTIONS"}) 3018378665fSKyle Evans local options = {} 3028378665fSKyle Evans 3038378665fSKyle Evans for opt in output:gmatch("[^%s]+") do 3048378665fSKyle Evans options["MK_" .. opt] = true 3058378665fSKyle Evans end 3068378665fSKyle Evans 3078378665fSKyle Evans return options 3088378665fSKyle Evansend 3098378665fSKyle Evans 3108378665fSKyle Evanslocal function required_options() 3118378665fSKyle Evans local output = run_make({"-f", "share/mk/src.opts.mk", "-V", 3128378665fSKyle Evans "__REQUIRED_OPTIONS"}) 3138378665fSKyle Evans local options = {} 3148378665fSKyle Evans 3158378665fSKyle Evans for opt in output:gmatch("[^%s]+") do 3168378665fSKyle Evans options["MK_" .. opt] = true 3178378665fSKyle Evans end 3188378665fSKyle Evans 3198378665fSKyle Evans return options 3208378665fSKyle Evansend 3218378665fSKyle Evans 3228378665fSKyle Evanslocal function config_description(option_name) 3238378665fSKyle Evans local fh = io.open(scriptdir .. "/" .. option_name) 3248378665fSKyle Evans local desc 3258378665fSKyle Evans 3268378665fSKyle Evans if fh then 3278378665fSKyle Evans desc = "" 3288378665fSKyle Evans for line in fh:lines() do 3298378665fSKyle Evans if not line:match("%$FreeBSD%$") then 3308378665fSKyle Evans desc = desc .. line .. "\n" 3318378665fSKyle Evans end 3328378665fSKyle Evans end 3338378665fSKyle Evans 3348378665fSKyle Evans assert(fh:close()) 3358378665fSKyle Evans end 3368378665fSKyle Evans 3378378665fSKyle Evans return desc 3388378665fSKyle Evansend 3398378665fSKyle Evans 3408378665fSKyle Evanslocal function config_descriptions(options) 3418378665fSKyle Evans local desc = {} 3428378665fSKyle Evans for name, _ in pairs(options) do 3438378665fSKyle Evans if name:match("^MK_") then 3448378665fSKyle Evans local basename = name:gsub("^MK_", "") 3458378665fSKyle Evans local with_name = "WITH_" .. basename 3468378665fSKyle Evans local without_name = "WITHOUT_" .. basename 3478378665fSKyle Evans 3488378665fSKyle Evans desc[with_name] = config_description(with_name) 3498378665fSKyle Evans desc[without_name] = config_description(without_name) 3508378665fSKyle Evans elseif name:match("^OPT_") then 3518378665fSKyle Evans local basename = name:gsub("^OPT_", "") 3528378665fSKyle Evans 3538378665fSKyle Evans desc[name] = config_description(basename) 3548378665fSKyle Evans end 3558378665fSKyle Evans end 3568378665fSKyle Evans return desc 3578378665fSKyle Evansend 3588378665fSKyle Evans 3598378665fSKyle Evanslocal function dependent_options(tmpdir, option_name, all_opts, omit_others) 3608378665fSKyle Evans local opt_sense = not not option_name:match("^WITH_") 3618378665fSKyle Evans local base_option_name = option_name:gsub("^[^_]+_", "") 3628378665fSKyle Evans local prefix = (opt_sense and "WITHOUT_") or "WITH_" 3638378665fSKyle Evans 3648378665fSKyle Evans local srcconf = tmpdir .. "/src-" ..prefix .. "ALL_" .. 3658378665fSKyle Evans option_name .. ".conf" 3668378665fSKyle Evans local fh = assert(io.open(srcconf, "w+")) 3678378665fSKyle Evans 3688378665fSKyle Evans fh:write(option_name .. "=\"YES\"\n") 3698378665fSKyle Evans if not omit_others then 3708378665fSKyle Evans for opt, value in pairs(all_opts) do 3718378665fSKyle Evans local base_opt = opt:gsub("^MK_", "") 3728378665fSKyle Evans 3738378665fSKyle Evans if base_opt ~= base_option_name then 3748378665fSKyle Evans local opt_prefix = (value and "WITH_") or "WITHOUT_" 3758378665fSKyle Evans fh:write(opt_prefix .. base_opt .. "=\"YES\"\n") 3768378665fSKyle Evans end 3778378665fSKyle Evans end 3788378665fSKyle Evans end 3798378665fSKyle Evans assert(fh:close()) 3808378665fSKyle Evans 3818378665fSKyle Evans local option_name_key = "MK_" .. base_option_name 3828378665fSKyle Evans local options = config_options(srcconf, nil, omit_others) 3838378665fSKyle Evans for name, value in pairs(options) do 3848378665fSKyle Evans if name == option_name_key or value == all_opts[name] then 3858378665fSKyle Evans options[name] = nil 3868378665fSKyle Evans elseif name:match("^OPT_") then 3878378665fSKyle Evans -- Strip out multi-option values at the moment, they do 3888378665fSKyle Evans -- not really make sense. 3898378665fSKyle Evans options[name] = nil 3908378665fSKyle Evans end 3918378665fSKyle Evans end 3928378665fSKyle Evans 3938378665fSKyle Evans return options 3948378665fSKyle Evansend 3958378665fSKyle Evans 3968378665fSKyle Evanslocal function export_option_table(fd, name, options) 3978378665fSKyle Evans unistd.write(fd, name .. " = {") 3988378665fSKyle Evans for k, v in pairs(options) do 3998378665fSKyle Evans v = (v and "true") or "false" 4008378665fSKyle Evans unistd.write(fd, "['" .. k .. "'] = " .. v .. ",") 4018378665fSKyle Evans end 4028378665fSKyle Evans unistd.write(fd, "}") 4038378665fSKyle Evansend 4048378665fSKyle Evans 4058378665fSKyle Evanslocal function all_dependent_options(tmpdir, options, default_opts, 4068378665fSKyle Evans with_all_opts, without_all_opts) 4078378665fSKyle Evans local all_enforced_options = {} 4088378665fSKyle Evans local all_effect_options = {} 4098378665fSKyle Evans local children = {} 4108378665fSKyle Evans 4118378665fSKyle Evans for _, name in ipairs(options) do 4128378665fSKyle Evans local rfd, wfd = assert(unistd.pipe()) 4138378665fSKyle Evans local pid = assert(unistd.fork()) 4148378665fSKyle Evans 4158378665fSKyle Evans if pid == 0 then 4168378665fSKyle Evans -- We need to pcall() this so that errors bubble up to 4178378665fSKyle Evans -- our _exit() call rather than the main exit. 4188378665fSKyle Evans local ret, errobj = pcall(function() 4198378665fSKyle Evans unistd.close(rfd) 4208378665fSKyle Evans 4218378665fSKyle Evans local compare_table 4228378665fSKyle Evans if name:match("^WITHOUT") then 4238378665fSKyle Evans compare_table = with_all_opts 4248378665fSKyle Evans else 4258378665fSKyle Evans compare_table = without_all_opts 4268378665fSKyle Evans end 4278378665fSKyle Evans 4288378665fSKyle Evans -- List of knobs forced on by this one 4298378665fSKyle Evans local enforced_options = dependent_options(tmpdir, name, 4308378665fSKyle Evans compare_table) 4318378665fSKyle Evans -- List of knobs implied by this by one (once additionally 4328378665fSKyle Evans -- filtered based on enforced_options values) 4338378665fSKyle Evans local effect_options = dependent_options(tmpdir, name, 4348378665fSKyle Evans default_opts, true) 4358378665fSKyle Evans 4368378665fSKyle Evans export_option_table(wfd, "enforced_options", 4378378665fSKyle Evans enforced_options) 4388378665fSKyle Evans export_option_table(wfd, "effect_options", 4398378665fSKyle Evans effect_options) 4408378665fSKyle Evans end) 4418378665fSKyle Evans 4428378665fSKyle Evans io.stderr:write(".") 4438378665fSKyle Evans 4448378665fSKyle Evans if ret then 4458378665fSKyle Evans unistd._exit(0) 4468378665fSKyle Evans else 4478378665fSKyle Evans unistd.write(wfd, errobj) 4488378665fSKyle Evans unistd._exit(1) 4498378665fSKyle Evans end 4508378665fSKyle Evans end 4518378665fSKyle Evans 4528378665fSKyle Evans unistd.close(wfd) 4538378665fSKyle Evans children[pid] = {name, rfd} 4548378665fSKyle Evans end 4558378665fSKyle Evans 4568378665fSKyle Evans while next(children) ~= nil do 4578378665fSKyle Evans::again:: 4588378665fSKyle Evans local pid, status, exitcode = sys_wait.wait(-1) 4598378665fSKyle Evans 4608378665fSKyle Evans if status ~= "exited" then 4618378665fSKyle Evans goto again 4628378665fSKyle Evans end 4638378665fSKyle Evans 4648378665fSKyle Evans local info = children[pid] 4658378665fSKyle Evans children[pid] = nil 4668378665fSKyle Evans 4678378665fSKyle Evans local name = info[1] 4688378665fSKyle Evans local rfd = info[2] 4698378665fSKyle Evans local buf = '' 4708378665fSKyle Evans local rbuf, sz 4718378665fSKyle Evans 4728378665fSKyle Evans -- Drain the pipe 4738378665fSKyle Evans rbuf = unistd.read(rfd, 512) 4748378665fSKyle Evans while #rbuf ~= 0 do 4758378665fSKyle Evans buf = buf .. rbuf 4768378665fSKyle Evans rbuf = unistd.read(rfd, 512) 4778378665fSKyle Evans end 4788378665fSKyle Evans 4798378665fSKyle Evans unistd.close(rfd) 4808378665fSKyle Evans 4818378665fSKyle Evans if exitcode ~= 0 then 4828378665fSKyle Evans error("Child " .. pid .. " failed, buf: " .. buf) 4838378665fSKyle Evans end 4848378665fSKyle Evans 4858378665fSKyle Evans -- The child has written a pair of tables named enforced_options 4868378665fSKyle Evans -- and effect_options to the pipe. We'll load the pipe buffer 4878378665fSKyle Evans -- as a string and then yank these out of the clean environment 4888378665fSKyle Evans -- that we execute the chunk in. 4898378665fSKyle Evans local child_env = {} 4908378665fSKyle Evans local res, err = pcall(load(buf, "child", "t", child_env)) 4918378665fSKyle Evans 4928378665fSKyle Evans all_enforced_options[name] = child_env["enforced_options"] 4938378665fSKyle Evans all_effect_options[name] = child_env["effect_options"] 4948378665fSKyle Evans end 4958378665fSKyle Evans 4968378665fSKyle Evans io.stderr:write("\n") 4978378665fSKyle Evans return all_enforced_options, all_effect_options 4988378665fSKyle Evansend 4998378665fSKyle Evans 5008378665fSKyle Evanslocal function get_defaults(target_archs, native_default_opts) 5018378665fSKyle Evans local target_defaults = {} 5028378665fSKyle Evans -- Set of options with differing defaults in some archs 5038378665fSKyle Evans local different_defaults = {} 5048378665fSKyle Evans 5058378665fSKyle Evans for tgt, dflt in pairs(target_archs) do 5068378665fSKyle Evans if dflt then 5078378665fSKyle Evans local native_copy = {} 5088378665fSKyle Evans for opt, val in pairs(native_default_opts) do 5098378665fSKyle Evans native_copy[opt] = val 5108378665fSKyle Evans end 5118378665fSKyle Evans target_defaults[tgt] = native_copy 5128378665fSKyle Evans goto skip 5138378665fSKyle Evans end 5148378665fSKyle Evans 5158378665fSKyle Evans local target = tgt:gsub("/.+$", "") 5168378665fSKyle Evans local target_arch = tgt:gsub("^.+/", "") 5178378665fSKyle Evans 5188378665fSKyle Evans local target_opts = config_options(nil, {"TARGET=" .. target, 5198378665fSKyle Evans "TARGET_ARCH=" .. target_arch}) 5208378665fSKyle Evans 5218378665fSKyle Evans for opt, val in pairs(target_opts) do 5228378665fSKyle Evans if val ~= native_default_opts[opt] then 5238378665fSKyle Evans different_defaults[opt] = true 5248378665fSKyle Evans end 5258378665fSKyle Evans end 5268378665fSKyle Evans 5278378665fSKyle Evans target_defaults[tgt] = target_opts 5288378665fSKyle Evans::skip:: 5298378665fSKyle Evans end 5308378665fSKyle Evans 5318378665fSKyle Evans for opt in pairs(native_default_opts) do 5328378665fSKyle Evans if different_defaults[opt] == nil then 5338378665fSKyle Evans for _, opts in pairs(target_defaults) do 5348378665fSKyle Evans opts[opt] = nil 5358378665fSKyle Evans end 5368378665fSKyle Evans end 5378378665fSKyle Evans end 5388378665fSKyle Evans 5398378665fSKyle Evans for tgt, opts in pairs(target_defaults) do 5408378665fSKyle Evans local val = opts["MK_ACPI"] 5418378665fSKyle Evans 5428378665fSKyle Evans if val ~= nil then 5438378665fSKyle Evans print(" - " .. tgt .. ": " .. ((val and "yes") or "no")) 5448378665fSKyle Evans end 5458378665fSKyle Evans end 5468378665fSKyle Evans 5478378665fSKyle Evans return target_defaults, different_defaults 5488378665fSKyle Evansend 5498378665fSKyle Evans 5508378665fSKyle Evanslocal function option_comparator(lhs, rhs) 5518378665fSKyle Evans -- Convert both options to the base name, compare that instead unless 5528378665fSKyle Evans -- they're the same option. For the same option, we just want to get 5538378665fSKyle Evans -- ordering between WITH_/WITHOUT_ correct. 5548378665fSKyle Evans local base_lhs = lhs:gsub("^[^_]+_", "") 5558378665fSKyle Evans local base_rhs = rhs:gsub("^[^_]+_", "") 5568378665fSKyle Evans 5578378665fSKyle Evans if base_lhs == base_rhs then 5588378665fSKyle Evans return lhs < rhs 5598378665fSKyle Evans else 5608378665fSKyle Evans return base_lhs < base_rhs 5618378665fSKyle Evans end 5628378665fSKyle Evansend 5638378665fSKyle Evans 5648378665fSKyle Evanslocal function main(tmpdir) 5658378665fSKyle Evans io.stderr:write("building src.conf.5 man page from files in " .. 5668378665fSKyle Evans scriptdir .. "\n") 5678378665fSKyle Evans 5688378665fSKyle Evans local env_only_opts <const> = env_only_options() 5698378665fSKyle Evans local default_opts = config_options(nil, nil, nil, true) 5708378665fSKyle Evans local opt_descriptions = config_descriptions(default_opts) 5718378665fSKyle Evans local srcconf_all <const> = tmpdir .. "/src-all-enabled.conf" 5728378665fSKyle Evans local fh = io.open(srcconf_all, "w+") 5738378665fSKyle Evans local all_targets = src_targets() 5748378665fSKyle Evans local target_defaults, different_defaults = get_defaults(all_targets, 5758378665fSKyle Evans default_opts) 5768378665fSKyle Evans local options = {} 5778378665fSKyle Evans local without_all_opts = {} 5788378665fSKyle Evans 5798378665fSKyle Evans for name, value in pairs(default_opts) do 5808378665fSKyle Evans if name:match("^MK_") then 5818378665fSKyle Evans local base_name = name:gsub("^MK_", "") 5828378665fSKyle Evans local with_name = "WITH_" .. base_name 5838378665fSKyle Evans local without_name = "WITHOUT_" .. base_name 5848378665fSKyle Evans -- If it's differently defaulted on some architectures, 5858378665fSKyle Evans -- we'll split it into WITH_/WITHOUT_ just to simplify 5868378665fSKyle Evans -- some later bits. 5878378665fSKyle Evans if different_defaults[name] ~= nil then 5888378665fSKyle Evans options[#options + 1] = with_name 5898378665fSKyle Evans options[#options + 1] = without_name 5908378665fSKyle Evans elseif value then 5918378665fSKyle Evans options[#options + 1] = without_name 5928378665fSKyle Evans else 5938378665fSKyle Evans options[#options + 1] = with_name 5948378665fSKyle Evans end 5958378665fSKyle Evans 5968378665fSKyle Evans without_all_opts[name] = false 5978378665fSKyle Evans assert(fh:write(with_name .. '="YES"\n')) 5988378665fSKyle Evans else 5998378665fSKyle Evans options[#options + 1] = name 6008378665fSKyle Evans end 6018378665fSKyle Evans end 6028378665fSKyle Evans 6038378665fSKyle Evans assert(fh:close()) 6048378665fSKyle Evans 6058378665fSKyle Evans local with_all_opts = config_options(srcconf_all) 6068378665fSKyle Evans local all_enforced_options, all_effect_options 6078378665fSKyle Evans local all_required_options = required_options() 6088378665fSKyle Evans 6098378665fSKyle Evans all_enforced_options, all_effect_options = all_dependent_options(tmpdir, 6108378665fSKyle Evans options, default_opts, with_all_opts, without_all_opts) 6118378665fSKyle Evans 6128378665fSKyle Evans table.sort(options, option_comparator) 6138378665fSKyle Evans io.stdout:write(output_head) 6148378665fSKyle Evans for _, name in ipairs(options) do 6158378665fSKyle Evans local value 6168378665fSKyle Evans 6178378665fSKyle Evans if name:match("^OPT_") then 6188378665fSKyle Evans goto skip 6198378665fSKyle Evans end 6208378665fSKyle Evans assert(name:match("^WITH"), "Name looks wrong: " .. name) 6218378665fSKyle Evans local describe_option = name 6228378665fSKyle Evans 6238378665fSKyle Evans value = not not name:match("^WITHOUT") 6248378665fSKyle Evans 6258378665fSKyle Evans -- Normalize name to MK_ for indexing into various other 6268378665fSKyle Evans -- arrays 6278378665fSKyle Evans name = "MK_" .. name:gsub("^[^_]+_", "") 6288378665fSKyle Evans 6298378665fSKyle Evans print(".It Va " .. describe_option:gsub("^OPT_", "")) 6308378665fSKyle Evans if opt_descriptions[describe_option] then 6318378665fSKyle Evans io.stdout:write(opt_descriptions[describe_option]) 6328378665fSKyle Evans else 6338378665fSKyle Evans io.stderr:write("Missing description for " .. 6348378665fSKyle Evans describe_option .. "\n") 6358378665fSKyle Evans end 6368378665fSKyle Evans 6378378665fSKyle Evans local enforced_options = all_enforced_options[describe_option] 6388378665fSKyle Evans local effect_options = all_effect_options[describe_option] 6398378665fSKyle Evans 6408378665fSKyle Evans if different_defaults[name] ~= nil then 6418378665fSKyle Evans print([[.Pp 6428378665fSKyle EvansThis is a default setting on]]) 6438378665fSKyle Evans 6448378665fSKyle Evans local which_targets = {} 6458378665fSKyle Evans for tgt, tgt_options in pairs(target_defaults) do 6468378665fSKyle Evans if tgt_options[name] ~= value then 6478378665fSKyle Evans which_targets[#which_targets + 1] = tgt 6488378665fSKyle Evans end 6498378665fSKyle Evans end 6508378665fSKyle Evans 6518378665fSKyle Evans table.sort(which_targets) 6528378665fSKyle Evans for idx, tgt in ipairs(which_targets) do 6538378665fSKyle Evans io.stdout:write(tgt) 6548378665fSKyle Evans if idx < #which_targets - 1 then 6558378665fSKyle Evans io.stdout:write(", ") 6568378665fSKyle Evans elseif idx == #which_targets - 1 then 6578378665fSKyle Evans io.stdout:write(" and ") 6588378665fSKyle Evans end 6598378665fSKyle Evans end 6608378665fSKyle Evans print(".") 6618378665fSKyle Evans end 6628378665fSKyle Evans 6638378665fSKyle Evans -- Unset any implied options that are actually required. 6648378665fSKyle Evans for dep_opt in pairs(enforced_options) do 6658378665fSKyle Evans if all_required_options[dep_opt] then 6668378665fSKyle Evans enforced_options[dep_opt] = nil 6678378665fSKyle Evans end 6688378665fSKyle Evans end 6698378665fSKyle Evans if next(enforced_options) ~= nil then 6708378665fSKyle Evans print([[When set, it enforces these options: 6718378665fSKyle Evans.Pp 6728378665fSKyle Evans.Bl -item -compact]]) 6738378665fSKyle Evans 6748378665fSKyle Evans local sorted_dep_opt = {} 6758378665fSKyle Evans for dep_opt in pairs(enforced_options) do 6768378665fSKyle Evans sorted_dep_opt[#sorted_dep_opt + 1] = dep_opt 6778378665fSKyle Evans end 6788378665fSKyle Evans 6798378665fSKyle Evans table.sort(sorted_dep_opt) 6808378665fSKyle Evans for _, dep_opt in ipairs(sorted_dep_opt) do 6818378665fSKyle Evans local dep_val = enforced_options[dep_opt] 6828378665fSKyle Evans local dep_prefix = (dep_val and "WITH_") or 6838378665fSKyle Evans "WITHOUT_" 6848378665fSKyle Evans local dep_name = dep_opt:gsub("^MK_", 6858378665fSKyle Evans dep_prefix) 6868378665fSKyle Evans print(".It") 6878378665fSKyle Evans print(".Va " .. dep_name) 6888378665fSKyle Evans end 6898378665fSKyle Evans 6908378665fSKyle Evans print(".El") 6918378665fSKyle Evans end 6928378665fSKyle Evans 6938378665fSKyle Evans if next(effect_options) ~= nil then 6948378665fSKyle Evans if next(enforced_options) ~= nil then 6958378665fSKyle Evans -- Remove any options that were previously 6968378665fSKyle Evans -- noted as enforced... 6978378665fSKyle Evans for opt, val in pairs(effect_options) do 6988378665fSKyle Evans if enforced_options[opt] == val then 6998378665fSKyle Evans effect_options[opt] = nil 7008378665fSKyle Evans end 7018378665fSKyle Evans end 7028378665fSKyle Evans 7038378665fSKyle Evans -- ... and this could leave us with an empty 7048378665fSKyle Evans -- set. 7058378665fSKyle Evans if next(effect_options) == nil then 7068378665fSKyle Evans goto noenforce 7078378665fSKyle Evans end 7088378665fSKyle Evans 7098378665fSKyle Evans print(".Pp") 7108378665fSKyle Evans end 7118378665fSKyle Evans 7128378665fSKyle Evans print([[When set, these options are also in effect: 7138378665fSKyle Evans.Pp 7148378665fSKyle Evans.Bl -inset -compact]]) 7158378665fSKyle Evans 7168378665fSKyle Evans local sorted_dep_opt = {} 7178378665fSKyle Evans for dep_opt in pairs(effect_options) do 7188378665fSKyle Evans sorted_dep_opt[#sorted_dep_opt + 1] = dep_opt 7198378665fSKyle Evans end 7208378665fSKyle Evans 7218378665fSKyle Evans table.sort(sorted_dep_opt) 7228378665fSKyle Evans for _, dep_opt in ipairs(sorted_dep_opt) do 7238378665fSKyle Evans local dep_val = effect_options[dep_opt] 7248378665fSKyle Evans local dep_prefix = (dep_val and "WITH_") or 7258378665fSKyle Evans "WITHOUT_" 7268378665fSKyle Evans local not_dep_prefix = ((not dep_val) and "WITH_") or 7278378665fSKyle Evans "WITHOUT_" 7288378665fSKyle Evans local dep_name = dep_opt:gsub("^MK_", 7298378665fSKyle Evans dep_prefix) 7308378665fSKyle Evans local not_dep_name = dep_opt:gsub("^MK_", 7318378665fSKyle Evans not_dep_prefix) 7328378665fSKyle Evans 7338378665fSKyle Evans print(".It Va " .. dep_name) 7348378665fSKyle Evans print("(unless") 7358378665fSKyle Evans print(".Va " .. not_dep_name) 7368378665fSKyle Evans print("is set explicitly)") 7378378665fSKyle Evans end 7388378665fSKyle Evans 7398378665fSKyle Evans print(".El") 7408378665fSKyle Evans::noenforce:: 7418378665fSKyle Evans end 7428378665fSKyle Evans 7438378665fSKyle Evans if env_only_opts[name] ~= nil then 7448378665fSKyle Evans print([[.Pp 7458378665fSKyle EvansThis must be set in the environment, make command line, or 7468378665fSKyle Evans.Pa /etc/src-env.conf , 7478378665fSKyle Evansnot 7488378665fSKyle Evans.Pa /etc/src.conf .]]) 7498378665fSKyle Evans end 7508378665fSKyle Evans ::skip:: 7518378665fSKyle Evans end 7528378665fSKyle Evans print([[.El 7538378665fSKyle Evans.Pp 7548378665fSKyle EvansThe following options accept a single value from a list of valid values. 7558378665fSKyle Evans.Bl -tag -width indent]]) 7568378665fSKyle Evans for _, name in ipairs(options) do 7578378665fSKyle Evans if name:match("^OPT_") then 7588378665fSKyle Evans local desc = opt_descriptions[name] 7598378665fSKyle Evans 7608378665fSKyle Evans print(".It Va " .. name:gsub("^OPT_", "")) 7618378665fSKyle Evans if desc then 7628378665fSKyle Evans io.stdout:write(desc) 7638378665fSKyle Evans else 7648378665fSKyle Evans io.stderr:write("Missing description for " .. 7658378665fSKyle Evans name .. "\n") 7668378665fSKyle Evans end 7678378665fSKyle Evans end 7688378665fSKyle Evans end 7698378665fSKyle Evans io.stdout:write(output_tail) 7708378665fSKyle Evansend 7718378665fSKyle Evans 7728378665fSKyle Evanslocal tmpdir = "/tmp/makeman." .. unistd.getpid() 7738378665fSKyle Evans 7748378665fSKyle Evansif not lfs.mkdir(tmpdir) then 7758378665fSKyle Evans error("Failed to create tempdir " .. tmpdir) 7768378665fSKyle Evansend 7778378665fSKyle Evans 7788378665fSKyle Evans-- Catch any errors so that we can properly clean up, then re-throw it. 7798378665fSKyle Evanslocal ret, errobj = pcall(main, tmpdir) 7808378665fSKyle Evans 7818378665fSKyle Evansfor fname in lfs.dir(tmpdir) do 7828378665fSKyle Evans if fname ~= "." and fname ~= ".." then 7838378665fSKyle Evans assert(os.remove(tmpdir .. "/" .. fname)) 7848378665fSKyle Evans end 7858378665fSKyle Evansend 7868378665fSKyle Evans 7878378665fSKyle Evansif not lfs.rmdir(tmpdir) then 7888378665fSKyle Evans assert(io.stderr:write("Failed to clean up tmpdir: " .. tmpdir .. "\n")) 7898378665fSKyle Evansend 7908378665fSKyle Evans 7918378665fSKyle Evansif not ret then 7928378665fSKyle Evans io.stderr:write(errobj .. "\n") 7938378665fSKyle Evans os.exit(1) 7948378665fSKyle Evansend 795