1*8378665fSKyle Evans-- 2*8378665fSKyle Evans-- Copyright (c) 2023 Kyle Evans <kevans@FreeBSD.org> 3*8378665fSKyle Evans-- 4*8378665fSKyle Evans-- SPDX-License-Identifier: BSD-2-Clause 5*8378665fSKyle Evans-- 6*8378665fSKyle Evans 7*8378665fSKyle Evanslocal libgen = require('posix.libgen') 8*8378665fSKyle Evanslocal lfs = require('lfs') 9*8378665fSKyle Evanslocal stdlib = require('posix.stdlib') 10*8378665fSKyle Evanslocal unistd = require('posix.unistd') 11*8378665fSKyle Evanslocal sys_wait = require('posix.sys.wait') 12*8378665fSKyle Evans 13*8378665fSKyle Evanslocal curdate = os.date("%B %e, %Y") 14*8378665fSKyle Evans 15*8378665fSKyle Evanslocal output_head <const> = ".\\\" DO NOT EDIT-- this file is @" .. [[generated by tools/build/options/makeman. 16*8378665fSKyle Evans.Dd ]] .. curdate .. [[ 17*8378665fSKyle Evans 18*8378665fSKyle Evans.Dt SRC.CONF 5 19*8378665fSKyle Evans.Os 20*8378665fSKyle Evans.Sh NAME 21*8378665fSKyle Evans.Nm src.conf 22*8378665fSKyle Evans.Nd "source build options" 23*8378665fSKyle Evans.Sh DESCRIPTION 24*8378665fSKyle EvansThe 25*8378665fSKyle Evans.Nm 26*8378665fSKyle Evansfile contains variables that control what components will be generated during 27*8378665fSKyle Evansthe build process of the 28*8378665fSKyle Evans.Fx 29*8378665fSKyle Evanssource tree; see 30*8378665fSKyle Evans.Xr build 7 . 31*8378665fSKyle Evans.Pp 32*8378665fSKyle EvansThe 33*8378665fSKyle Evans.Nm 34*8378665fSKyle Evansfile uses the standard makefile syntax. 35*8378665fSKyle EvansHowever, 36*8378665fSKyle Evans.Nm 37*8378665fSKyle Evansshould not specify any dependencies to 38*8378665fSKyle Evans.Xr make 1 . 39*8378665fSKyle EvansInstead, 40*8378665fSKyle Evans.Nm 41*8378665fSKyle Evansis to set 42*8378665fSKyle Evans.Xr make 1 43*8378665fSKyle Evansvariables that control the aspects of how the system builds. 44*8378665fSKyle Evans.Pp 45*8378665fSKyle EvansThe default location of 46*8378665fSKyle Evans.Nm 47*8378665fSKyle Evansis 48*8378665fSKyle Evans.Pa /etc/src.conf , 49*8378665fSKyle Evansthough an alternative location can be specified in the 50*8378665fSKyle Evans.Xr make 1 51*8378665fSKyle Evansvariable 52*8378665fSKyle Evans.Va SRCCONF . 53*8378665fSKyle EvansOverriding the location of 54*8378665fSKyle Evans.Nm 55*8378665fSKyle Evansmay be necessary if the system-wide settings are not suitable 56*8378665fSKyle Evansfor a particular build. 57*8378665fSKyle EvansFor instance, setting 58*8378665fSKyle Evans.Va SRCCONF 59*8378665fSKyle Evansto 60*8378665fSKyle Evans.Pa /dev/null 61*8378665fSKyle Evanseffectively resets all build controls to their defaults. 62*8378665fSKyle Evans.Pp 63*8378665fSKyle EvansThe only purpose of 64*8378665fSKyle Evans.Nm 65*8378665fSKyle Evansis to control the compilation of the 66*8378665fSKyle Evans.Fx 67*8378665fSKyle Evanssource code, which is usually located in 68*8378665fSKyle Evans.Pa /usr/src . 69*8378665fSKyle EvansAs a rule, the system administrator creates 70*8378665fSKyle Evans.Nm 71*8378665fSKyle Evanswhen the values of certain control variables need to be changed 72*8378665fSKyle Evansfrom their defaults. 73*8378665fSKyle Evans.Pp 74*8378665fSKyle EvansIn addition, control variables can be specified 75*8378665fSKyle Evansfor a particular build via the 76*8378665fSKyle Evans.Fl D 77*8378665fSKyle Evansoption of 78*8378665fSKyle Evans.Xr make 1 79*8378665fSKyle Evansor in its environment; see 80*8378665fSKyle Evans.Xr environ 7 . 81*8378665fSKyle Evans.Pp 82*8378665fSKyle EvansThe environment of 83*8378665fSKyle Evans.Xr make 1 84*8378665fSKyle Evansfor the build can be controlled via the 85*8378665fSKyle Evans.Va SRC_ENV_CONF 86*8378665fSKyle Evansvariable, which defaults to 87*8378665fSKyle Evans.Pa /etc/src-env.conf . 88*8378665fSKyle EvansSome examples that may only be set in this file are 89*8378665fSKyle Evans.Va WITH_DIRDEPS_BUILD , 90*8378665fSKyle Evansand 91*8378665fSKyle Evans.Va WITH_META_MODE , 92*8378665fSKyle Evansand 93*8378665fSKyle Evans.Va MAKEOBJDIRPREFIX 94*8378665fSKyle Evansas they are environment-only variables. 95*8378665fSKyle Evans.Pp 96*8378665fSKyle EvansThe values of 97*8378665fSKyle Evans.Va WITH_ 98*8378665fSKyle Evansand 99*8378665fSKyle Evans.Va WITHOUT_ 100*8378665fSKyle Evansvariables are ignored regardless of their setting; 101*8378665fSKyle Evanseven if they would be set to 102*8378665fSKyle Evans.Dq Li FALSE 103*8378665fSKyle Evansor 104*8378665fSKyle Evans.Dq Li NO . 105*8378665fSKyle EvansThe presence of an option causes 106*8378665fSKyle Evansit to be honored by 107*8378665fSKyle Evans.Xr make 1 . 108*8378665fSKyle Evans.Pp 109*8378665fSKyle EvansThis list provides a name and short description for variables 110*8378665fSKyle Evansthat can be used for source builds. 111*8378665fSKyle Evans.Bl -tag -width indent 112*8378665fSKyle Evans]] 113*8378665fSKyle Evans 114*8378665fSKyle Evanslocal output_tail <const> = [[.El 115*8378665fSKyle Evans.Sh FILES 116*8378665fSKyle Evans.Bl -tag -compact -width Pa 117*8378665fSKyle Evans.It Pa /etc/src.conf 118*8378665fSKyle Evans.It Pa /etc/src-env.conf 119*8378665fSKyle Evans.It Pa /usr/share/mk/bsd.own.mk 120*8378665fSKyle Evans.El 121*8378665fSKyle Evans.Sh SEE ALSO 122*8378665fSKyle Evans.Xr make 1 , 123*8378665fSKyle Evans.Xr make.conf 5 , 124*8378665fSKyle Evans.Xr build 7 , 125*8378665fSKyle Evans.Xr ports 7 126*8378665fSKyle Evans.Sh HISTORY 127*8378665fSKyle EvansThe 128*8378665fSKyle Evans.Nm 129*8378665fSKyle Evansfile appeared in 130*8378665fSKyle Evans.Fx 7.0 . 131*8378665fSKyle Evans.Sh AUTHORS 132*8378665fSKyle EvansThis manual page was autogenerated by 133*8378665fSKyle Evans.An tools/build/options/makeman . 134*8378665fSKyle Evans]] 135*8378665fSKyle Evans 136*8378665fSKyle Evanslocal scriptdir <const> = libgen.dirname(stdlib.realpath(arg[0])) 137*8378665fSKyle Evanslocal srcdir <const> = stdlib.realpath(scriptdir .. "/../../../") 138*8378665fSKyle Evanslocal makesysdir <const> = srcdir .. "/share/mk" 139*8378665fSKyle Evans 140*8378665fSKyle Evanslocal make_envvar = os.getenv("MAKE") 141*8378665fSKyle Evanslocal make_cmd_override = {} 142*8378665fSKyle Evansif make_envvar then 143*8378665fSKyle Evans for word in make_envvar:gmatch("[^%s]+") do 144*8378665fSKyle Evans make_cmd_override[#make_cmd_override + 1] = word 145*8378665fSKyle Evans end 146*8378665fSKyle Evansend 147*8378665fSKyle Evans 148*8378665fSKyle Evans-- Lifted from bsdinstall/scripts/pkgbase.in (read_all) 149*8378665fSKyle Evanslocal function read_pipe(pipe) 150*8378665fSKyle Evans local ret = "" 151*8378665fSKyle Evans repeat 152*8378665fSKyle Evans local buffer = assert(unistd.read(pipe, 1024)) 153*8378665fSKyle Evans ret = ret .. buffer 154*8378665fSKyle Evans until buffer == "" 155*8378665fSKyle Evans return ret 156*8378665fSKyle Evansend 157*8378665fSKyle Evanslocal function run_make(args) 158*8378665fSKyle Evans local cmd_args = {"env", "-i", "make", "-C", srcdir, "-m", makesysdir, 159*8378665fSKyle Evans "__MAKE_CONF=/dev/null", "SRCCONF=/dev/null"} 160*8378665fSKyle Evans 161*8378665fSKyle Evans if #make_cmd_override > 0 then 162*8378665fSKyle Evans cmd_args[3] = make_cmd_override[1] 163*8378665fSKyle Evans for k = 2, #make_cmd_override do 164*8378665fSKyle Evans local val = make_cmd_override[k] 165*8378665fSKyle Evans 166*8378665fSKyle Evans table.insert(cmd_args, 3 + (k - 1), val) 167*8378665fSKyle Evans end 168*8378665fSKyle Evans end 169*8378665fSKyle Evans for k, v in ipairs(args) do 170*8378665fSKyle Evans cmd_args[#cmd_args + 1] = v 171*8378665fSKyle Evans end 172*8378665fSKyle Evans 173*8378665fSKyle Evans local r, w = assert(unistd.pipe()) 174*8378665fSKyle Evans local pid = assert(unistd.fork()) 175*8378665fSKyle Evans if pid == 0 then 176*8378665fSKyle Evans -- Child 177*8378665fSKyle Evans assert(unistd.close(r)) 178*8378665fSKyle Evans assert(unistd.dup2(w, 1)) 179*8378665fSKyle Evans assert(unistd.dup2(w, 2)) 180*8378665fSKyle Evans assert(unistd.execp("env", cmd_args)) 181*8378665fSKyle Evans unistd._exit() 182*8378665fSKyle Evans end 183*8378665fSKyle Evans 184*8378665fSKyle Evans -- Parent 185*8378665fSKyle Evans assert(unistd.close(w)) 186*8378665fSKyle Evans 187*8378665fSKyle Evans local output = read_pipe(r) 188*8378665fSKyle Evans assert(unistd.close(r)) 189*8378665fSKyle Evans 190*8378665fSKyle Evans local _, exit_type, exit_code = assert(sys_wait.wait(pid)) 191*8378665fSKyle Evans assert(exit_type == "exited", "make exited with wrong status") 192*8378665fSKyle Evans assert(exit_code == 0, "make exited unsuccessfully") 193*8378665fSKyle Evans return output 194*8378665fSKyle Evansend 195*8378665fSKyle Evans 196*8378665fSKyle Evanslocal function native_target() 197*8378665fSKyle Evans local output = run_make({"MK_AUTO_OBJ=NO", "-V", "MACHINE", 198*8378665fSKyle Evans "-V", "MACHINE_ARCH"}) 199*8378665fSKyle Evans 200*8378665fSKyle Evans local arch, machine_arch 201*8378665fSKyle Evans for x in output:gmatch("[^\n]+") do 202*8378665fSKyle Evans if not arch then 203*8378665fSKyle Evans arch = x 204*8378665fSKyle Evans elseif not machine_arch then 205*8378665fSKyle Evans machine_arch = x 206*8378665fSKyle Evans end 207*8378665fSKyle Evans end 208*8378665fSKyle Evans 209*8378665fSKyle Evans return arch .. "/" .. machine_arch 210*8378665fSKyle Evansend 211*8378665fSKyle Evans 212*8378665fSKyle Evanslocal function src_targets() 213*8378665fSKyle Evans local targets = {} 214*8378665fSKyle Evans targets[native_target()] = true 215*8378665fSKyle Evans 216*8378665fSKyle Evans local output = run_make({"MK_AUTO_OBJ=no", "targets"}) 217*8378665fSKyle Evans local curline = 0 218*8378665fSKyle Evans 219*8378665fSKyle Evans for line in output:gmatch("[^\n]+") do 220*8378665fSKyle Evans curline = curline + 1 221*8378665fSKyle Evans if curline ~= 1 then 222*8378665fSKyle Evans local arch = line:match("[^%s]+/[^%s]+") 223*8378665fSKyle Evans 224*8378665fSKyle Evans -- Make sure we don't roll over our default arch 225*8378665fSKyle Evans if arch and not targets[arch] then 226*8378665fSKyle Evans targets[arch] = false 227*8378665fSKyle Evans end 228*8378665fSKyle Evans end 229*8378665fSKyle Evans end 230*8378665fSKyle Evans 231*8378665fSKyle Evans return targets 232*8378665fSKyle Evansend 233*8378665fSKyle Evans 234*8378665fSKyle Evanslocal function config_options(srcconf, env, take_dupes, linting) 235*8378665fSKyle Evans srcconf = srcconf or "/dev/null" 236*8378665fSKyle Evans env = env or {} 237*8378665fSKyle Evans 238*8378665fSKyle Evans local option_args = {".MAKE.MODE=normal", "showconfig", 239*8378665fSKyle Evans "SRC_ENV_CONF=" .. srcconf} 240*8378665fSKyle Evans 241*8378665fSKyle Evans for _, val in ipairs(env) do 242*8378665fSKyle Evans option_args[#option_args + 1] = val 243*8378665fSKyle Evans end 244*8378665fSKyle Evans 245*8378665fSKyle Evans local output = run_make(option_args) 246*8378665fSKyle Evans 247*8378665fSKyle Evans local options = {} 248*8378665fSKyle Evans local known_dupes = {} 249*8378665fSKyle Evans 250*8378665fSKyle Evans local function warn_on_dupe(option, val) 251*8378665fSKyle Evans if not linting or known_dupes[option] then 252*8378665fSKyle Evans return false 253*8378665fSKyle Evans end 254*8378665fSKyle Evans if not option:match("^OPT_") then 255*8378665fSKyle Evans val = val == "yes" 256*8378665fSKyle Evans end 257*8378665fSKyle Evans 258*8378665fSKyle Evans known_dupes[option] = true 259*8378665fSKyle Evans return val ~= options[val] 260*8378665fSKyle Evans end 261*8378665fSKyle Evans 262*8378665fSKyle Evans for opt in output:gmatch("[^\n]+") do 263*8378665fSKyle Evans if opt:match("^MK_[%a%d_]+%s+=%s+.+") then 264*8378665fSKyle Evans local name = opt:match("MK_[%a%d_]+") 265*8378665fSKyle Evans local val = opt:match("= .+"):sub(3) 266*8378665fSKyle Evans 267*8378665fSKyle Evans -- Some settings, e.g., MK_INIT_ALL_ZERO, may end up 268*8378665fSKyle Evans -- output twice for some reason that I haven't dug into; 269*8378665fSKyle Evans -- take the first value. In some circumstances, though, 270*8378665fSKyle Evans -- we do make an exception and actually want to take the 271*8378665fSKyle Evans -- latest. 272*8378665fSKyle Evans if take_dupes or options[name] == nil then 273*8378665fSKyle Evans options[name] = val == "yes" 274*8378665fSKyle Evans elseif warn_on_dupe(name, val) then 275*8378665fSKyle Evans io.stderr:write("ignoring duplicate option " .. 276*8378665fSKyle Evans name .. "\n") 277*8378665fSKyle Evans end 278*8378665fSKyle Evans elseif opt:match("^OPT_[%a%d_]+%s+=%s+.+") then 279*8378665fSKyle Evans local name = opt:match("OPT_[%a%d_]+") 280*8378665fSKyle Evans local val = opt:match("= .+"):sub(3) 281*8378665fSKyle Evans 282*8378665fSKyle Evans -- Multi-value options will arbitrarily use a table here 283*8378665fSKyle Evans -- to indicate the difference. 284*8378665fSKyle Evans if take_dupes or options[name] == nil then 285*8378665fSKyle Evans options[name] = val 286*8378665fSKyle Evans elseif warn_on_dupe(name, val) then 287*8378665fSKyle Evans io.stderr:write("ignoring duplicate option " .. 288*8378665fSKyle Evans name .. "\n") 289*8378665fSKyle Evans end 290*8378665fSKyle Evans end 291*8378665fSKyle Evans end 292*8378665fSKyle Evans 293*8378665fSKyle Evans return options 294*8378665fSKyle Evansend 295*8378665fSKyle Evans 296*8378665fSKyle Evanslocal function env_only_options() 297*8378665fSKyle Evans local output = run_make({"MK_AUTO_OBJ=no", "-V", "__ENV_ONLY_OPTIONS"}) 298*8378665fSKyle Evans local options = {} 299*8378665fSKyle Evans 300*8378665fSKyle Evans for opt in output:gmatch("[^%s]+") do 301*8378665fSKyle Evans options["MK_" .. opt] = true 302*8378665fSKyle Evans end 303*8378665fSKyle Evans 304*8378665fSKyle Evans return options 305*8378665fSKyle Evansend 306*8378665fSKyle Evans 307*8378665fSKyle Evanslocal function required_options() 308*8378665fSKyle Evans local output = run_make({"-f", "share/mk/src.opts.mk", "-V", 309*8378665fSKyle Evans "__REQUIRED_OPTIONS"}) 310*8378665fSKyle Evans local options = {} 311*8378665fSKyle Evans 312*8378665fSKyle Evans for opt in output:gmatch("[^%s]+") do 313*8378665fSKyle Evans options["MK_" .. opt] = true 314*8378665fSKyle Evans end 315*8378665fSKyle Evans 316*8378665fSKyle Evans return options 317*8378665fSKyle Evansend 318*8378665fSKyle Evans 319*8378665fSKyle Evanslocal function config_description(option_name) 320*8378665fSKyle Evans local fh = io.open(scriptdir .. "/" .. option_name) 321*8378665fSKyle Evans local desc 322*8378665fSKyle Evans 323*8378665fSKyle Evans if fh then 324*8378665fSKyle Evans desc = "" 325*8378665fSKyle Evans for line in fh:lines() do 326*8378665fSKyle Evans if not line:match("%$FreeBSD%$") then 327*8378665fSKyle Evans desc = desc .. line .. "\n" 328*8378665fSKyle Evans end 329*8378665fSKyle Evans end 330*8378665fSKyle Evans 331*8378665fSKyle Evans assert(fh:close()) 332*8378665fSKyle Evans end 333*8378665fSKyle Evans 334*8378665fSKyle Evans return desc 335*8378665fSKyle Evansend 336*8378665fSKyle Evans 337*8378665fSKyle Evanslocal function config_descriptions(options) 338*8378665fSKyle Evans local desc = {} 339*8378665fSKyle Evans for name, _ in pairs(options) do 340*8378665fSKyle Evans if name:match("^MK_") then 341*8378665fSKyle Evans local basename = name:gsub("^MK_", "") 342*8378665fSKyle Evans local with_name = "WITH_" .. basename 343*8378665fSKyle Evans local without_name = "WITHOUT_" .. basename 344*8378665fSKyle Evans 345*8378665fSKyle Evans desc[with_name] = config_description(with_name) 346*8378665fSKyle Evans desc[without_name] = config_description(without_name) 347*8378665fSKyle Evans elseif name:match("^OPT_") then 348*8378665fSKyle Evans local basename = name:gsub("^OPT_", "") 349*8378665fSKyle Evans 350*8378665fSKyle Evans desc[name] = config_description(basename) 351*8378665fSKyle Evans end 352*8378665fSKyle Evans end 353*8378665fSKyle Evans return desc 354*8378665fSKyle Evansend 355*8378665fSKyle Evans 356*8378665fSKyle Evanslocal function dependent_options(tmpdir, option_name, all_opts, omit_others) 357*8378665fSKyle Evans local opt_sense = not not option_name:match("^WITH_") 358*8378665fSKyle Evans local base_option_name = option_name:gsub("^[^_]+_", "") 359*8378665fSKyle Evans local prefix = (opt_sense and "WITHOUT_") or "WITH_" 360*8378665fSKyle Evans 361*8378665fSKyle Evans local srcconf = tmpdir .. "/src-" ..prefix .. "ALL_" .. 362*8378665fSKyle Evans option_name .. ".conf" 363*8378665fSKyle Evans local fh = assert(io.open(srcconf, "w+")) 364*8378665fSKyle Evans 365*8378665fSKyle Evans fh:write(option_name .. "=\"YES\"\n") 366*8378665fSKyle Evans if not omit_others then 367*8378665fSKyle Evans for opt, value in pairs(all_opts) do 368*8378665fSKyle Evans local base_opt = opt:gsub("^MK_", "") 369*8378665fSKyle Evans 370*8378665fSKyle Evans if base_opt ~= base_option_name then 371*8378665fSKyle Evans local opt_prefix = (value and "WITH_") or "WITHOUT_" 372*8378665fSKyle Evans fh:write(opt_prefix .. base_opt .. "=\"YES\"\n") 373*8378665fSKyle Evans end 374*8378665fSKyle Evans end 375*8378665fSKyle Evans end 376*8378665fSKyle Evans assert(fh:close()) 377*8378665fSKyle Evans 378*8378665fSKyle Evans local option_name_key = "MK_" .. base_option_name 379*8378665fSKyle Evans local options = config_options(srcconf, nil, omit_others) 380*8378665fSKyle Evans for name, value in pairs(options) do 381*8378665fSKyle Evans if name == option_name_key or value == all_opts[name] then 382*8378665fSKyle Evans options[name] = nil 383*8378665fSKyle Evans elseif name:match("^OPT_") then 384*8378665fSKyle Evans -- Strip out multi-option values at the moment, they do 385*8378665fSKyle Evans -- not really make sense. 386*8378665fSKyle Evans options[name] = nil 387*8378665fSKyle Evans end 388*8378665fSKyle Evans end 389*8378665fSKyle Evans 390*8378665fSKyle Evans return options 391*8378665fSKyle Evansend 392*8378665fSKyle Evans 393*8378665fSKyle Evanslocal function export_option_table(fd, name, options) 394*8378665fSKyle Evans unistd.write(fd, name .. " = {") 395*8378665fSKyle Evans for k, v in pairs(options) do 396*8378665fSKyle Evans v = (v and "true") or "false" 397*8378665fSKyle Evans unistd.write(fd, "['" .. k .. "'] = " .. v .. ",") 398*8378665fSKyle Evans end 399*8378665fSKyle Evans unistd.write(fd, "}") 400*8378665fSKyle Evansend 401*8378665fSKyle Evans 402*8378665fSKyle Evanslocal function all_dependent_options(tmpdir, options, default_opts, 403*8378665fSKyle Evans with_all_opts, without_all_opts) 404*8378665fSKyle Evans local all_enforced_options = {} 405*8378665fSKyle Evans local all_effect_options = {} 406*8378665fSKyle Evans local children = {} 407*8378665fSKyle Evans 408*8378665fSKyle Evans for _, name in ipairs(options) do 409*8378665fSKyle Evans local rfd, wfd = assert(unistd.pipe()) 410*8378665fSKyle Evans local pid = assert(unistd.fork()) 411*8378665fSKyle Evans 412*8378665fSKyle Evans if pid == 0 then 413*8378665fSKyle Evans -- We need to pcall() this so that errors bubble up to 414*8378665fSKyle Evans -- our _exit() call rather than the main exit. 415*8378665fSKyle Evans local ret, errobj = pcall(function() 416*8378665fSKyle Evans unistd.close(rfd) 417*8378665fSKyle Evans 418*8378665fSKyle Evans local compare_table 419*8378665fSKyle Evans if name:match("^WITHOUT") then 420*8378665fSKyle Evans compare_table = with_all_opts 421*8378665fSKyle Evans else 422*8378665fSKyle Evans compare_table = without_all_opts 423*8378665fSKyle Evans end 424*8378665fSKyle Evans 425*8378665fSKyle Evans -- List of knobs forced on by this one 426*8378665fSKyle Evans local enforced_options = dependent_options(tmpdir, name, 427*8378665fSKyle Evans compare_table) 428*8378665fSKyle Evans -- List of knobs implied by this by one (once additionally 429*8378665fSKyle Evans -- filtered based on enforced_options values) 430*8378665fSKyle Evans local effect_options = dependent_options(tmpdir, name, 431*8378665fSKyle Evans default_opts, true) 432*8378665fSKyle Evans 433*8378665fSKyle Evans export_option_table(wfd, "enforced_options", 434*8378665fSKyle Evans enforced_options) 435*8378665fSKyle Evans export_option_table(wfd, "effect_options", 436*8378665fSKyle Evans effect_options) 437*8378665fSKyle Evans end) 438*8378665fSKyle Evans 439*8378665fSKyle Evans io.stderr:write(".") 440*8378665fSKyle Evans 441*8378665fSKyle Evans if ret then 442*8378665fSKyle Evans unistd._exit(0) 443*8378665fSKyle Evans else 444*8378665fSKyle Evans unistd.write(wfd, errobj) 445*8378665fSKyle Evans unistd._exit(1) 446*8378665fSKyle Evans end 447*8378665fSKyle Evans end 448*8378665fSKyle Evans 449*8378665fSKyle Evans unistd.close(wfd) 450*8378665fSKyle Evans children[pid] = {name, rfd} 451*8378665fSKyle Evans end 452*8378665fSKyle Evans 453*8378665fSKyle Evans while next(children) ~= nil do 454*8378665fSKyle Evans::again:: 455*8378665fSKyle Evans local pid, status, exitcode = sys_wait.wait(-1) 456*8378665fSKyle Evans 457*8378665fSKyle Evans if status ~= "exited" then 458*8378665fSKyle Evans goto again 459*8378665fSKyle Evans end 460*8378665fSKyle Evans 461*8378665fSKyle Evans local info = children[pid] 462*8378665fSKyle Evans children[pid] = nil 463*8378665fSKyle Evans 464*8378665fSKyle Evans local name = info[1] 465*8378665fSKyle Evans local rfd = info[2] 466*8378665fSKyle Evans local buf = '' 467*8378665fSKyle Evans local rbuf, sz 468*8378665fSKyle Evans 469*8378665fSKyle Evans -- Drain the pipe 470*8378665fSKyle Evans rbuf = unistd.read(rfd, 512) 471*8378665fSKyle Evans while #rbuf ~= 0 do 472*8378665fSKyle Evans buf = buf .. rbuf 473*8378665fSKyle Evans rbuf = unistd.read(rfd, 512) 474*8378665fSKyle Evans end 475*8378665fSKyle Evans 476*8378665fSKyle Evans unistd.close(rfd) 477*8378665fSKyle Evans 478*8378665fSKyle Evans if exitcode ~= 0 then 479*8378665fSKyle Evans error("Child " .. pid .. " failed, buf: " .. buf) 480*8378665fSKyle Evans end 481*8378665fSKyle Evans 482*8378665fSKyle Evans -- The child has written a pair of tables named enforced_options 483*8378665fSKyle Evans -- and effect_options to the pipe. We'll load the pipe buffer 484*8378665fSKyle Evans -- as a string and then yank these out of the clean environment 485*8378665fSKyle Evans -- that we execute the chunk in. 486*8378665fSKyle Evans local child_env = {} 487*8378665fSKyle Evans local res, err = pcall(load(buf, "child", "t", child_env)) 488*8378665fSKyle Evans 489*8378665fSKyle Evans all_enforced_options[name] = child_env["enforced_options"] 490*8378665fSKyle Evans all_effect_options[name] = child_env["effect_options"] 491*8378665fSKyle Evans end 492*8378665fSKyle Evans 493*8378665fSKyle Evans io.stderr:write("\n") 494*8378665fSKyle Evans return all_enforced_options, all_effect_options 495*8378665fSKyle Evansend 496*8378665fSKyle Evans 497*8378665fSKyle Evanslocal function get_defaults(target_archs, native_default_opts) 498*8378665fSKyle Evans local target_defaults = {} 499*8378665fSKyle Evans -- Set of options with differing defaults in some archs 500*8378665fSKyle Evans local different_defaults = {} 501*8378665fSKyle Evans 502*8378665fSKyle Evans for tgt, dflt in pairs(target_archs) do 503*8378665fSKyle Evans if dflt then 504*8378665fSKyle Evans local native_copy = {} 505*8378665fSKyle Evans for opt, val in pairs(native_default_opts) do 506*8378665fSKyle Evans native_copy[opt] = val 507*8378665fSKyle Evans end 508*8378665fSKyle Evans target_defaults[tgt] = native_copy 509*8378665fSKyle Evans goto skip 510*8378665fSKyle Evans end 511*8378665fSKyle Evans 512*8378665fSKyle Evans local target = tgt:gsub("/.+$", "") 513*8378665fSKyle Evans local target_arch = tgt:gsub("^.+/", "") 514*8378665fSKyle Evans 515*8378665fSKyle Evans local target_opts = config_options(nil, {"TARGET=" .. target, 516*8378665fSKyle Evans "TARGET_ARCH=" .. target_arch}) 517*8378665fSKyle Evans 518*8378665fSKyle Evans for opt, val in pairs(target_opts) do 519*8378665fSKyle Evans if val ~= native_default_opts[opt] then 520*8378665fSKyle Evans different_defaults[opt] = true 521*8378665fSKyle Evans end 522*8378665fSKyle Evans end 523*8378665fSKyle Evans 524*8378665fSKyle Evans target_defaults[tgt] = target_opts 525*8378665fSKyle Evans::skip:: 526*8378665fSKyle Evans end 527*8378665fSKyle Evans 528*8378665fSKyle Evans for opt in pairs(native_default_opts) do 529*8378665fSKyle Evans if different_defaults[opt] == nil then 530*8378665fSKyle Evans for _, opts in pairs(target_defaults) do 531*8378665fSKyle Evans opts[opt] = nil 532*8378665fSKyle Evans end 533*8378665fSKyle Evans end 534*8378665fSKyle Evans end 535*8378665fSKyle Evans 536*8378665fSKyle Evans for tgt, opts in pairs(target_defaults) do 537*8378665fSKyle Evans local val = opts["MK_ACPI"] 538*8378665fSKyle Evans 539*8378665fSKyle Evans if val ~= nil then 540*8378665fSKyle Evans print(" - " .. tgt .. ": " .. ((val and "yes") or "no")) 541*8378665fSKyle Evans end 542*8378665fSKyle Evans end 543*8378665fSKyle Evans 544*8378665fSKyle Evans return target_defaults, different_defaults 545*8378665fSKyle Evansend 546*8378665fSKyle Evans 547*8378665fSKyle Evanslocal function option_comparator(lhs, rhs) 548*8378665fSKyle Evans -- Convert both options to the base name, compare that instead unless 549*8378665fSKyle Evans -- they're the same option. For the same option, we just want to get 550*8378665fSKyle Evans -- ordering between WITH_/WITHOUT_ correct. 551*8378665fSKyle Evans local base_lhs = lhs:gsub("^[^_]+_", "") 552*8378665fSKyle Evans local base_rhs = rhs:gsub("^[^_]+_", "") 553*8378665fSKyle Evans 554*8378665fSKyle Evans if base_lhs == base_rhs then 555*8378665fSKyle Evans return lhs < rhs 556*8378665fSKyle Evans else 557*8378665fSKyle Evans return base_lhs < base_rhs 558*8378665fSKyle Evans end 559*8378665fSKyle Evansend 560*8378665fSKyle Evans 561*8378665fSKyle Evanslocal function main(tmpdir) 562*8378665fSKyle Evans io.stderr:write("building src.conf.5 man page from files in " .. 563*8378665fSKyle Evans scriptdir .. "\n") 564*8378665fSKyle Evans 565*8378665fSKyle Evans local env_only_opts <const> = env_only_options() 566*8378665fSKyle Evans local default_opts = config_options(nil, nil, nil, true) 567*8378665fSKyle Evans local opt_descriptions = config_descriptions(default_opts) 568*8378665fSKyle Evans local srcconf_all <const> = tmpdir .. "/src-all-enabled.conf" 569*8378665fSKyle Evans local fh = io.open(srcconf_all, "w+") 570*8378665fSKyle Evans local all_targets = src_targets() 571*8378665fSKyle Evans local target_defaults, different_defaults = get_defaults(all_targets, 572*8378665fSKyle Evans default_opts) 573*8378665fSKyle Evans local options = {} 574*8378665fSKyle Evans local without_all_opts = {} 575*8378665fSKyle Evans 576*8378665fSKyle Evans for name, value in pairs(default_opts) do 577*8378665fSKyle Evans if name:match("^MK_") then 578*8378665fSKyle Evans local base_name = name:gsub("^MK_", "") 579*8378665fSKyle Evans local with_name = "WITH_" .. base_name 580*8378665fSKyle Evans local without_name = "WITHOUT_" .. base_name 581*8378665fSKyle Evans -- If it's differently defaulted on some architectures, 582*8378665fSKyle Evans -- we'll split it into WITH_/WITHOUT_ just to simplify 583*8378665fSKyle Evans -- some later bits. 584*8378665fSKyle Evans if different_defaults[name] ~= nil then 585*8378665fSKyle Evans options[#options + 1] = with_name 586*8378665fSKyle Evans options[#options + 1] = without_name 587*8378665fSKyle Evans elseif value then 588*8378665fSKyle Evans options[#options + 1] = without_name 589*8378665fSKyle Evans else 590*8378665fSKyle Evans options[#options + 1] = with_name 591*8378665fSKyle Evans end 592*8378665fSKyle Evans 593*8378665fSKyle Evans without_all_opts[name] = false 594*8378665fSKyle Evans assert(fh:write(with_name .. '="YES"\n')) 595*8378665fSKyle Evans else 596*8378665fSKyle Evans options[#options + 1] = name 597*8378665fSKyle Evans end 598*8378665fSKyle Evans end 599*8378665fSKyle Evans 600*8378665fSKyle Evans assert(fh:close()) 601*8378665fSKyle Evans 602*8378665fSKyle Evans local with_all_opts = config_options(srcconf_all) 603*8378665fSKyle Evans local all_enforced_options, all_effect_options 604*8378665fSKyle Evans local all_required_options = required_options() 605*8378665fSKyle Evans 606*8378665fSKyle Evans all_enforced_options, all_effect_options = all_dependent_options(tmpdir, 607*8378665fSKyle Evans options, default_opts, with_all_opts, without_all_opts) 608*8378665fSKyle Evans 609*8378665fSKyle Evans table.sort(options, option_comparator) 610*8378665fSKyle Evans io.stdout:write(output_head) 611*8378665fSKyle Evans for _, name in ipairs(options) do 612*8378665fSKyle Evans local value 613*8378665fSKyle Evans 614*8378665fSKyle Evans if name:match("^OPT_") then 615*8378665fSKyle Evans goto skip 616*8378665fSKyle Evans end 617*8378665fSKyle Evans assert(name:match("^WITH"), "Name looks wrong: " .. name) 618*8378665fSKyle Evans local describe_option = name 619*8378665fSKyle Evans 620*8378665fSKyle Evans value = not not name:match("^WITHOUT") 621*8378665fSKyle Evans 622*8378665fSKyle Evans -- Normalize name to MK_ for indexing into various other 623*8378665fSKyle Evans -- arrays 624*8378665fSKyle Evans name = "MK_" .. name:gsub("^[^_]+_", "") 625*8378665fSKyle Evans 626*8378665fSKyle Evans print(".It Va " .. describe_option:gsub("^OPT_", "")) 627*8378665fSKyle Evans if opt_descriptions[describe_option] then 628*8378665fSKyle Evans io.stdout:write(opt_descriptions[describe_option]) 629*8378665fSKyle Evans else 630*8378665fSKyle Evans io.stderr:write("Missing description for " .. 631*8378665fSKyle Evans describe_option .. "\n") 632*8378665fSKyle Evans end 633*8378665fSKyle Evans 634*8378665fSKyle Evans local enforced_options = all_enforced_options[describe_option] 635*8378665fSKyle Evans local effect_options = all_effect_options[describe_option] 636*8378665fSKyle Evans 637*8378665fSKyle Evans if different_defaults[name] ~= nil then 638*8378665fSKyle Evans print([[.Pp 639*8378665fSKyle EvansThis is a default setting on]]) 640*8378665fSKyle Evans 641*8378665fSKyle Evans local which_targets = {} 642*8378665fSKyle Evans for tgt, tgt_options in pairs(target_defaults) do 643*8378665fSKyle Evans if tgt_options[name] ~= value then 644*8378665fSKyle Evans which_targets[#which_targets + 1] = tgt 645*8378665fSKyle Evans end 646*8378665fSKyle Evans end 647*8378665fSKyle Evans 648*8378665fSKyle Evans table.sort(which_targets) 649*8378665fSKyle Evans for idx, tgt in ipairs(which_targets) do 650*8378665fSKyle Evans io.stdout:write(tgt) 651*8378665fSKyle Evans if idx < #which_targets - 1 then 652*8378665fSKyle Evans io.stdout:write(", ") 653*8378665fSKyle Evans elseif idx == #which_targets - 1 then 654*8378665fSKyle Evans io.stdout:write(" and ") 655*8378665fSKyle Evans end 656*8378665fSKyle Evans end 657*8378665fSKyle Evans print(".") 658*8378665fSKyle Evans end 659*8378665fSKyle Evans 660*8378665fSKyle Evans -- Unset any implied options that are actually required. 661*8378665fSKyle Evans for dep_opt in pairs(enforced_options) do 662*8378665fSKyle Evans if all_required_options[dep_opt] then 663*8378665fSKyle Evans enforced_options[dep_opt] = nil 664*8378665fSKyle Evans end 665*8378665fSKyle Evans end 666*8378665fSKyle Evans if next(enforced_options) ~= nil then 667*8378665fSKyle Evans print([[When set, it enforces these options: 668*8378665fSKyle Evans.Pp 669*8378665fSKyle Evans.Bl -item -compact]]) 670*8378665fSKyle Evans 671*8378665fSKyle Evans local sorted_dep_opt = {} 672*8378665fSKyle Evans for dep_opt in pairs(enforced_options) do 673*8378665fSKyle Evans sorted_dep_opt[#sorted_dep_opt + 1] = dep_opt 674*8378665fSKyle Evans end 675*8378665fSKyle Evans 676*8378665fSKyle Evans table.sort(sorted_dep_opt) 677*8378665fSKyle Evans for _, dep_opt in ipairs(sorted_dep_opt) do 678*8378665fSKyle Evans local dep_val = enforced_options[dep_opt] 679*8378665fSKyle Evans local dep_prefix = (dep_val and "WITH_") or 680*8378665fSKyle Evans "WITHOUT_" 681*8378665fSKyle Evans local dep_name = dep_opt:gsub("^MK_", 682*8378665fSKyle Evans dep_prefix) 683*8378665fSKyle Evans print(".It") 684*8378665fSKyle Evans print(".Va " .. dep_name) 685*8378665fSKyle Evans end 686*8378665fSKyle Evans 687*8378665fSKyle Evans print(".El") 688*8378665fSKyle Evans end 689*8378665fSKyle Evans 690*8378665fSKyle Evans if next(effect_options) ~= nil then 691*8378665fSKyle Evans if next(enforced_options) ~= nil then 692*8378665fSKyle Evans -- Remove any options that were previously 693*8378665fSKyle Evans -- noted as enforced... 694*8378665fSKyle Evans for opt, val in pairs(effect_options) do 695*8378665fSKyle Evans if enforced_options[opt] == val then 696*8378665fSKyle Evans effect_options[opt] = nil 697*8378665fSKyle Evans end 698*8378665fSKyle Evans end 699*8378665fSKyle Evans 700*8378665fSKyle Evans -- ... and this could leave us with an empty 701*8378665fSKyle Evans -- set. 702*8378665fSKyle Evans if next(effect_options) == nil then 703*8378665fSKyle Evans goto noenforce 704*8378665fSKyle Evans end 705*8378665fSKyle Evans 706*8378665fSKyle Evans print(".Pp") 707*8378665fSKyle Evans end 708*8378665fSKyle Evans 709*8378665fSKyle Evans print([[When set, these options are also in effect: 710*8378665fSKyle Evans.Pp 711*8378665fSKyle Evans.Bl -inset -compact]]) 712*8378665fSKyle Evans 713*8378665fSKyle Evans local sorted_dep_opt = {} 714*8378665fSKyle Evans for dep_opt in pairs(effect_options) do 715*8378665fSKyle Evans sorted_dep_opt[#sorted_dep_opt + 1] = dep_opt 716*8378665fSKyle Evans end 717*8378665fSKyle Evans 718*8378665fSKyle Evans table.sort(sorted_dep_opt) 719*8378665fSKyle Evans for _, dep_opt in ipairs(sorted_dep_opt) do 720*8378665fSKyle Evans local dep_val = effect_options[dep_opt] 721*8378665fSKyle Evans local dep_prefix = (dep_val and "WITH_") or 722*8378665fSKyle Evans "WITHOUT_" 723*8378665fSKyle Evans local not_dep_prefix = ((not dep_val) and "WITH_") or 724*8378665fSKyle Evans "WITHOUT_" 725*8378665fSKyle Evans local dep_name = dep_opt:gsub("^MK_", 726*8378665fSKyle Evans dep_prefix) 727*8378665fSKyle Evans local not_dep_name = dep_opt:gsub("^MK_", 728*8378665fSKyle Evans not_dep_prefix) 729*8378665fSKyle Evans 730*8378665fSKyle Evans print(".It Va " .. dep_name) 731*8378665fSKyle Evans print("(unless") 732*8378665fSKyle Evans print(".Va " .. not_dep_name) 733*8378665fSKyle Evans print("is set explicitly)") 734*8378665fSKyle Evans end 735*8378665fSKyle Evans 736*8378665fSKyle Evans print(".El") 737*8378665fSKyle Evans::noenforce:: 738*8378665fSKyle Evans end 739*8378665fSKyle Evans 740*8378665fSKyle Evans if env_only_opts[name] ~= nil then 741*8378665fSKyle Evans print([[.Pp 742*8378665fSKyle EvansThis must be set in the environment, make command line, or 743*8378665fSKyle Evans.Pa /etc/src-env.conf , 744*8378665fSKyle Evansnot 745*8378665fSKyle Evans.Pa /etc/src.conf .]]) 746*8378665fSKyle Evans end 747*8378665fSKyle Evans ::skip:: 748*8378665fSKyle Evans end 749*8378665fSKyle Evans print([[.El 750*8378665fSKyle Evans.Pp 751*8378665fSKyle EvansThe following options accept a single value from a list of valid values. 752*8378665fSKyle Evans.Bl -tag -width indent]]) 753*8378665fSKyle Evans for _, name in ipairs(options) do 754*8378665fSKyle Evans if name:match("^OPT_") then 755*8378665fSKyle Evans local desc = opt_descriptions[name] 756*8378665fSKyle Evans 757*8378665fSKyle Evans print(".It Va " .. name:gsub("^OPT_", "")) 758*8378665fSKyle Evans if desc then 759*8378665fSKyle Evans io.stdout:write(desc) 760*8378665fSKyle Evans else 761*8378665fSKyle Evans io.stderr:write("Missing description for " .. 762*8378665fSKyle Evans name .. "\n") 763*8378665fSKyle Evans end 764*8378665fSKyle Evans end 765*8378665fSKyle Evans end 766*8378665fSKyle Evans io.stdout:write(output_tail) 767*8378665fSKyle Evansend 768*8378665fSKyle Evans 769*8378665fSKyle Evanslocal tmpdir = "/tmp/makeman." .. unistd.getpid() 770*8378665fSKyle Evans 771*8378665fSKyle Evansif not lfs.mkdir(tmpdir) then 772*8378665fSKyle Evans error("Failed to create tempdir " .. tmpdir) 773*8378665fSKyle Evansend 774*8378665fSKyle Evans 775*8378665fSKyle Evans-- Catch any errors so that we can properly clean up, then re-throw it. 776*8378665fSKyle Evanslocal ret, errobj = pcall(main, tmpdir) 777*8378665fSKyle Evans 778*8378665fSKyle Evansfor fname in lfs.dir(tmpdir) do 779*8378665fSKyle Evans if fname ~= "." and fname ~= ".." then 780*8378665fSKyle Evans assert(os.remove(tmpdir .. "/" .. fname)) 781*8378665fSKyle Evans end 782*8378665fSKyle Evansend 783*8378665fSKyle Evans 784*8378665fSKyle Evansif not lfs.rmdir(tmpdir) then 785*8378665fSKyle Evans assert(io.stderr:write("Failed to clean up tmpdir: " .. tmpdir .. "\n")) 786*8378665fSKyle Evansend 787*8378665fSKyle Evans 788*8378665fSKyle Evansif not ret then 789*8378665fSKyle Evans io.stderr:write(errobj .. "\n") 790*8378665fSKyle Evans os.exit(1) 791*8378665fSKyle Evansend 792