2 --[[@GROUP Configuration@END]]--
7 function NewConfig(on_configured_callback
)
10 config
.OnConfigured
= function(self
)
14 if on_configured_callback
then config
.OnConfigured
= on_configured_callback
end
17 config
.settings
= NewSettings()
19 config
.NewSettings
= function(self
)
20 local s
= NewSettings()
21 for _
,v
in pairs(self
.options
) do
27 config
.Add
= function(self
, o
)
28 table.insert(self
.options
, o
)
32 config
.Print
= function(self
)
33 for k
,v
in pairs(self
.options
) do
34 print(v
:FormatDisplay())
38 config
.Save
= function(self
, filename
)
39 print("saved configuration to '"..filename
.."'")
40 local file
= io
.open(filename
, "w")
42 -- Define a little helper function to save options
46 saver
.line
= function(self
, str
)
47 self
.file
:write(str
.. "\n")
50 saver
.option
= function(self
, option
, name
)
52 if type(option
[name
]) == type(0) then
53 valuestr
= option
[name
]
54 elseif type(option
[name
]) == type(true) then
59 elseif type(option
[name
]) == type("") then
60 valuestr
= "'"..option
[name
].."'"
62 error("option "..name
.." have a value of type ".. type(option
[name
]).." that can't be saved")
64 self
.file
:write(option
.name
.."."..name
.." = ".. valuestr
.."\n")
67 -- Save all the options
68 for k
,v
in pairs(self
.options
) do
74 config
.Load
= function(self
, filename
)
75 local options_func
= loadfile(filename
)
76 local options_table
= {}
78 if not options_func
then
79 print("auto configuration")
81 options_func
= loadfile(filename
)
85 -- Setup the options tables
86 for k
,v
in pairs(self
.options
) do
87 options_table
[v
.name
] = {}
89 setfenv(options_func
, options_table
)
91 -- this is to make sure that we get nice error messages when
92 -- someone sets an option that isn't valid.
94 mt
.__index
= function(t
, key
)
95 local v
= rawget(t
, key
)
96 if v
~= nil then return v
end
97 error("there is no configuration option named '" .. key
.. "'")
100 setmetatable(options_table
, mt
)
102 -- Process the options
106 for k
,v
in pairs(self
.options
) do
107 if options_table
[v
.name
] then
108 for k2
,v2
in pairs(options_table
[v
.name
]) do
111 v
.auto_detected
= false
115 print("error: no '"..filename
.."' found")
117 print("run 'bam config' to generate")
118 print("run 'bam config help' for configuration options")
124 config
.Config
= function(self
, filename
)
126 print("configuration:")
127 if _bam_targets
[1] == "print" then
138 if self
:OnConfigured() then
146 config
.Autodetect
= function(self
)
147 for k
,v
in pairs(self
.options
) do
148 v
:Check(self
.settings
)
149 print(v
:FormatDisplay())
154 config
.PrintHelp
= function(self
)
156 for k
,v
in pairs(self
.options
) do
163 config
.Finalize
= function(self
, filename
)
164 if _bam_targets
[0] == "config" then
165 if _bam_targets
[1] == "help" then
170 self
:Config(filename
)
176 bam_update_globalstamp(filename
)
183 -- Helper functions --------------------------------------
184 function DefaultOptionDisplay(option
)
185 if not option
.value
then return "no" end
186 if option
.value
== 1 or option
.value
== true then return "yes" end
190 function IsNegativeTerm(s
)
191 if s
== "no" then return true end
192 if s
== "false" then return true end
193 if s
== "off" then return true end
194 if s
== "disable" then return true end
195 if s
== "0" then return true end
199 function IsPositiveTerm(s
)
200 if s
== "yes" then return true end
201 if s
== "true" then return true end
202 if s
== "on" then return true end
203 if s
== "enable" then return true end
204 if s
== "1" then return true end
208 function MakeOption(name
, value
, check
, save
, display
, printhelp
)
214 o
.auto_detected
= true
215 o
.FormatDisplay
= function(self
)
217 if self
.auto_detected
then a
= "AUTO" end
218 return string.format("%-5s %-20s %s", a
, self
.name
, self
:Display())
222 o
.PrintHelp
= printhelp
223 if o
.Display
== nil then o
.Display
= DefaultOptionDisplay
end
228 -- Test Compile C --------------------------------------
229 function OptTestCompileC(name
, source
, compileoptions
, desc
)
230 local check
= function(option
, settings
)
232 if ScriptArgs
[option
.name
] then
233 if IsNegativeTerm(ScriptArgs
[option
.name
]) then
235 elseif IsPositiveTerm(ScriptArgs
[option
.name
]) then
238 error(ScriptArgs
[option
.name
].." is not a valid value for option "..option
.name
)
240 option
.auto_detected
= false
242 if CTestCompile(settings
, option
.source
, option
.compileoptions
) then
248 local save
= function(option
, output
)
249 output
:option(option
, "value")
252 local printhelp
= function(option
)
253 print("\t"..option
.name
.."=on|off")
254 if option
.desc
then print("\t\t"..option
.desc
) end
257 local o
= MakeOption(name
, false, check
, save
, nil, printhelp
)
260 o
.compileoptions
= compileoptions
265 -- OptToggle --------------------------------------
266 function OptToggle(name
, default_value
, desc
)
267 local check
= function(option
, settings
)
268 if ScriptArgs
[option
.name
] then
269 if IsNegativeTerm(ScriptArgs
[option
.name
]) then
271 elseif IsPositiveTerm(ScriptArgs
[option
.name
]) then
274 error(ScriptArgs
[option
.name
].." is not a valid value for option "..option
.name
)
279 local save
= function(option
, output
)
280 output
:option(option
, "value")
283 local printhelp
= function(option
)
284 print("\t"..option
.name
.."=on|off")
285 if option
.desc
then print("\t\t"..option
.desc
) end
288 local o
= MakeOption(name
, default_value
, check
, save
, nil, printhelp
)
293 -- OptInteger --------------------------------------
294 function OptInteger(name
, default_value
, desc
)
295 local check
= function(option
, settings
)
296 if ScriptArgs
[option
.name
] then
297 option
.value
= tonumber(ScriptArgs
[option
.name
])
301 local save
= function(option
, output
)
302 output
:option(option
, "value")
305 local printhelp
= function(option
)
306 print("\t"..option
.name
.."=N")
307 if option
.desc
then print("\t\t"..option
.desc
) end
310 local o
= MakeOption(name
, default_value
, check
, save
, nil, printhelp
)
316 -- OptString --------------------------------------
317 function OptString(name
, default_value
, desc
)
318 local check
= function(option
, settings
)
319 if ScriptArgs
[option
.name
] then
320 option
.value
= ScriptArgs
[option
.name
]
324 local save
= function(option
, output
)
325 output
:option(option
, "value")
328 local printhelp
= function(option
)
329 print("\t"..option
.name
.."=STRING")
330 if option
.desc
then print("\t\t"..option
.desc
) end
333 local o
= MakeOption(name
, default_value
, check
, save
, nil, printhelp
)
338 -- Find Compiler --------------------------------------
342 function OptCCompiler(name
, default_driver
, default_c
, default_cxx
, desc
)
343 local check
= function(option
, settings
)
344 if ScriptArgs
[option
.name
] then
345 -- set compile driver
346 option
.driver
= ScriptArgs
[option
.name
]
349 if ScriptArgs
[option
.name
..".c"] then
350 option
.c_compiler
= ScriptArgs
[option
.name
..".c"]
354 if ScriptArgs
[option
.name
..".cxx"] then
355 option
.cxx_compiler
= ScriptArgs
[option
.name
..".cxx"]
358 option
.auto_detected
= false
359 elseif option
.driver
then
360 -- no need todo anything if we have a driver
361 -- TODO: test if we can find the compiler
363 if ExecuteSilent("cl") == 0 then
365 elseif ExecuteSilent("g++ -v") == 0 then
366 option
.driver
= "gcc"
368 error("no c/c++ compiler found")
371 --setup_compiler(option.value)
374 local apply
= function(option
, settings
)
375 if option
.driver
== "cl" then
376 SetDriversCL(settings
)
377 elseif option
.driver
== "gcc" then
378 SetDriversGCC(settings
)
380 error(option
.driver
.." is not a known c/c++ compile driver")
383 if option
.c_compiler
then settings
.cc
.c_compiler
= option
.c_compiler
end
384 if option
.cxx_compiler
then settings
.cc
.cxx_compiler
= option
.cxx_compiler
end
387 local save
= function(option
, output
)
388 output
:option(option
, "driver")
389 output
:option(option
, "c_compiler")
390 output
:option(option
, "cxx_compiler")
393 local printhelp
= function(option
)
395 if option
.desc
then a
= "for "..option
.desc
end
396 print("\t"..option
.name
.."=gcc|cl")
397 print("\t\twhat c/c++ compile driver to use"..a
)
398 print("\t"..option
.name
..".c=FILENAME")
399 print("\t\twhat c compiler executable to use"..a
)
400 print("\t"..option
.name
..".cxx=FILENAME")
401 print("\t\twhat c++ compiler executable to use"..a
)
404 local display
= function(option
)
405 local s
= option
.driver
406 if option
.c_compiler
then s
= s
.. " c="..option
.c_compiler
end
407 if option
.cxx_compiler
then s
= s
.. " cxx="..option
.cxx_compiler
end
411 local o
= MakeOption(name
, nil, check
, save
, display
, printhelp
)
415 o
.cxx_compiler
= false
417 if default_driver
then o
.driver
= default_driver
end
418 if default_c
then o
.c_compiler
= default_c
end
419 if default_cxx
then o
.cxx_compiler
= default_cxx
end
425 -- Option Library --------------------------------------
429 function OptLibrary(name
, header
, desc
)
430 local check
= function(option
, settings
)
432 option
.include_path
= false
434 local function check_compile_include(filename
, paths
)
435 if CTestCompile(settings
, "#include <" .. filename
.. ">\nint main(){return 0;}", "") then
439 for k
,v
in pairs(paths
) do
440 if CTestCompile(settings
, "#include <" .. filename
.. ">\nint main(){return 0;}", "-I"..v
) then
448 if ScriptArgs
[option
.name
] then
449 if IsNegativeTerm(ScriptArgs
[option
.name
]) then
451 elseif ScriptArgs
[option
.name
] == "system" then
455 option
.include_path
= ScriptArgs
[option
.name
]
457 option
.auto_detected
= false
459 option
.include_path
= check_compile_include(option
.header
, {})
460 if option
.include_path
== false then
461 if option
.required
then
462 print(name
.." library not found and is required")
463 error("required library not found")
467 option
.include_path
= false
472 local save
= function(option
, output
)
473 output
:option(option
, "value")
474 output
:option(option
, "include_path")
477 local display
= function(option
)
479 if option
.include_path
then
480 return option
.include_path
482 return "(in system path)"
489 local printhelp
= function(option
)
490 print("\t"..option
.name
.."=disable|system|PATH")
491 if option
.desc
then print("\t\t"..option
.desc
) end
494 local o
= MakeOption(name
, false, check
, save
, display
, printhelp
)
495 o
.include_path
= false