about summary refs log tree commit diff
path: root/configure.lua
diff options
context:
space:
mode:
authorMagnus Auvinen <magnus.auvinen@gmail.com>2010-05-29 07:25:38 +0000
committerMagnus Auvinen <magnus.auvinen@gmail.com>2010-05-29 07:25:38 +0000
commit72c06a258940696093f255fb1061beb58e1cdd0b (patch)
tree36b9a7712eec2d4f07837eab9c38ef1c5af85319 /configure.lua
parente56feb597bc743677633432f77513b02907fd169 (diff)
downloadzcatch-72c06a258940696093f255fb1061beb58e1cdd0b.tar.gz
zcatch-72c06a258940696093f255fb1061beb58e1cdd0b.zip
copied refactor to trunk
Diffstat (limited to 'configure.lua')
-rw-r--r--configure.lua489
1 files changed, 489 insertions, 0 deletions
diff --git a/configure.lua b/configure.lua
new file mode 100644
index 00000000..9df4b82d
--- /dev/null
+++ b/configure.lua
@@ -0,0 +1,489 @@
+
+--[[@GROUP Configuration@END]]--
+
+--[[@FUNCTION
+	TODO
+@END]]--
+function NewConfig(on_configured_callback)
+	local config = {}
+
+	config.OnConfigured = function(self)
+		return true
+	end
+	
+	if on_configured_callback then config.OnConfigured = on_configured_callback end
+	
+	config.options = {}
+	config.settings = NewSettings()
+	
+	config.NewSettings = function(self)
+		local s = NewSettings()
+		for _,v in pairs(self.options) do
+			v:Apply(s)
+		end
+		return s
+	end
+
+	config.Add = function(self, o)
+		table.insert(self.options, o)
+		self[o.name] = o
+	end
+	
+	config.Print = function(self)
+		for k,v in pairs(self.options) do
+			print(v:FormatDisplay())
+		end
+	end
+	
+	config.Save = function(self, filename)
+		print("saved configuration to '"..filename.."'")
+		local file = io.open(filename, "w")
+		
+		-- Define a little helper function to save options
+		local saver = {}
+		saver.file = file
+		
+		saver.line = function(self, str)
+			self.file:write(str .. "\n")
+		end
+		
+		saver.option = function(self, option, name)
+			local valuestr = "no"
+			if type(option[name]) == type(0) then
+				valuestr = option[name]
+			elseif type(option[name]) == type(true) then
+				valuestr = "false"
+				if option[name] then
+					valuestr = "true"
+				end
+			elseif type(option[name]) == type("") then
+				valuestr = "'"..option[name].."'"
+			else
+				error("option "..name.." have a value of type ".. type(option[name]).." that can't be saved")
+			end
+			self.file:write(option.name.."."..name.." = ".. valuestr.."\n")
+		end
+
+		-- Save all the options		
+		for k,v in pairs(self.options) do
+			v:Save(saver)
+		end
+		file:close()
+	end
+	
+	config.Load = function(self, filename)
+		local options_func = loadfile(filename)
+		local options_table = {}
+		
+		if options_func then
+			-- Setup the options tables
+			for k,v in pairs(self.options) do
+				options_table[v.name] = {}
+			end
+			setfenv(options_func, options_table)
+			
+			-- this is to make sure that we get nice error messages when
+			-- someone sets an option that isn't valid.
+			local mt = {}
+			mt.__index = function(t, key)
+				local v = rawget(t, key)
+				if v ~= nil then return v end
+				error("there is no configuration option named '" .. key .. "'")
+			end
+			
+			setmetatable(options_table, mt)		
+
+			-- Process the options
+			options_func()
+
+			-- Copy the options
+			for k,v in pairs(self.options) do
+				if options_table[v.name] then
+					for k2,v2 in pairs(options_table[v.name]) do
+						v[k2] = v2
+					end
+					v.auto_detected = false
+				end
+			end
+		else
+			print("error: no '"..filename.."' found")
+			print("")
+			print("run 'bam config' to generate")
+			print("run 'bam config help' for configuration options")
+			print("")
+			os.exit(1)			
+		end
+	end
+
+	config.Autodetect = function(self)
+		for k,v in pairs(self.options) do
+			v:Check(self.settings)
+			print(v:FormatDisplay())
+			self[v.name] = v
+		end
+	end
+
+	config.PrintHelp = function(self)
+		print("options:")
+		for k,v in pairs(self.options) do
+			if v.PrintHelp then
+				v:PrintHelp()
+			end
+		end
+	end
+	
+	config.Finalize = function(self, filename)
+		if _bam_targets[0] == "config" then
+			if _bam_targets[1] == "help" then
+				self:PrintHelp()
+				os.exit(0)
+			end
+			
+			print("")
+			print("configuration:")
+			if _bam_targets[1] == "print" then
+				self:Load(filename)
+				self:Print()
+				print("")
+				print("notes:")
+				self:OnConfigured()
+				print("")
+			else
+				self:Autodetect()
+				print("")
+				print("notes:")
+				if self:OnConfigured() then
+					self:Save(filename)
+				end
+				print("")
+			end
+
+			os.exit(0)
+		end
+	
+		self:Load(filename)
+		bam_update_globalstamp(filename)
+	end
+	
+	return config
+end
+
+
+-- Helper functions --------------------------------------
+function DefaultOptionDisplay(option)
+	if not option.value then return "no" end
+	if option.value == 1 or option.value == true then return "yes" end
+	return option.value
+end
+
+function IsNegativeTerm(s)
+	if s == "no" then return true end
+	if s == "false" then return true end
+	if s == "off" then return true end
+	if s == "disable" then return true end
+	if s == "0" then return true end
+	return false
+end
+
+function IsPositiveTerm(s)
+	if s == "yes" then return true end
+	if s == "true" then return true end
+	if s == "on" then return true end
+	if s == "enable" then return true end
+	if s == "1" then return true end
+	return false
+end
+
+function MakeOption(name, value, check, save, display, printhelp)
+	local o = {}
+	o.name = name
+	o.value = value
+	o.Check = check
+	o.Save = save
+	o.auto_detected = true
+	o.FormatDisplay = function(self)
+		local a = "SET"
+		if self.auto_detected then a = "AUTO" end	
+		return string.format("%-5s %-20s %s", a, self.name, self:Display())
+	end
+	
+	o.Display = display
+	o.PrintHelp = printhelp
+	if o.Display == nil then o.Display = DefaultOptionDisplay end
+	return o
+end
+
+
+-- Test Compile C --------------------------------------
+function OptTestCompileC(name, source, compileoptions, desc)
+	local check = function(option, settings)
+		option.value = false
+		if ScriptArgs[option.name] then
+			if IsNegativeTerm(ScriptArgs[option.name]) then
+				option.value = false
+			elseif IsPositiveTerm(ScriptArgs[option.name]) then
+				option.value = true
+			else
+				error(ScriptArgs[option.name].." is not a valid value for option "..option.name)
+			end
+			option.auto_detected = false
+		else
+			if CTestCompile(settings, option.source, option.compileoptions) then
+				option.value = true
+			end
+		end
+	end
+	
+	local save = function(option, output)
+		output:option(option, "value")
+	end
+	
+	local printhelp = function(option)
+		print("\t"..option.name.."=on|off")
+		if option.desc then print("\t\t"..option.desc) end
+	end
+	
+	local o = MakeOption(name, false, check, save, nil, printhelp)
+	o.desc = desc
+	o.source = source
+	o.compileoptions = compileoptions
+	return o
+end
+
+
+-- OptToggle --------------------------------------
+function OptToggle(name, default_value, desc)
+	local check = function(option, settings)
+		if ScriptArgs[option.name] then
+			if IsNegativeTerm(ScriptArgs[option.name]) then
+				option.value = false
+			elseif IsPositiveTerm(ScriptArgs[option.name]) then
+				option.value = true
+			else
+				error(ScriptArgs[option.name].." is not a valid value for option "..option.name)
+			end
+		end
+	end
+	
+	local save = function(option, output)
+		output:option(option, "value")
+	end
+	
+	local printhelp = function(option)
+		print("\t"..option.name.."=on|off")
+		if option.desc then print("\t\t"..option.desc) end
+	end
+	
+	local o = MakeOption(name, default_value, check, save, nil, printhelp)
+	o.desc = desc
+	return o
+end
+
+-- OptInteger --------------------------------------
+function OptInteger(name, default_value, desc)
+	local check = function(option, settings)
+		if ScriptArgs[option.name] then
+			option.value = tonumber(ScriptArgs[option.name])
+		end
+	end
+	
+	local save = function(option, output)
+		output:option(option, "value")
+	end
+	
+	local printhelp = function(option)
+		print("\t"..option.name.."=N")
+		if option.desc then print("\t\t"..option.desc) end
+	end
+	
+	local o = MakeOption(name, default_value, check, save, nil, printhelp)
+	o.desc = desc
+	return o
+end
+
+
+-- OptString --------------------------------------
+function OptString(name, default_value, desc)
+	local check = function(option, settings)
+		if ScriptArgs[option.name] then
+			option.value = ScriptArgs[option.name]
+		end
+	end
+	
+	local save = function(option, output)
+		output:option(option, "value")
+	end
+	
+	local printhelp = function(option)
+		print("\t"..option.name.."=STRING")
+		if option.desc then print("\t\t"..option.desc) end
+	end
+	
+	local o = MakeOption(name, default_value, check, save, nil, printhelp)
+	o.desc = desc
+	return o
+end
+
+-- Find Compiler --------------------------------------
+--[[@FUNCTION
+	TODO
+@END]]--
+function OptCCompiler(name, default_driver, default_c, default_cxx, desc)
+	local check = function(option, settings)
+		if ScriptArgs[option.name] then
+			-- set compile driver
+			option.driver = ScriptArgs[option.name]
+
+			-- set c compiler
+			if ScriptArgs[option.name..".c"] then
+				option.c_compiler = ScriptArgs[option.name..".c"]
+			end
+
+			-- set c+= compiler
+			if ScriptArgs[option.name..".cxx"] then
+				option.cxx_compiler = ScriptArgs[option.name..".cxx"]
+			end
+			
+			option.auto_detected = false
+		elseif option.driver then
+			-- no need todo anything if we have a driver
+			-- TODO: test if we can find the compiler
+		else
+			if ExecuteSilent("g++ -v") == 0 then
+				option.driver = "gcc"
+			elseif ExecuteSilent("cl") == 0 then
+				option.driver = "cl"
+			else
+				error("no c/c++ compiler found")
+			end
+		end
+		--setup_compiler(option.value)
+	end
+
+	local apply = function(option, settings)
+		if option.driver == "cl" then
+			SetDriversCL(settings)
+		elseif option.driver == "gcc" then
+			SetDriversGCC(settings)
+		else
+			error(option.driver.." is not a known c/c++ compile driver")
+		end
+		
+		if option.c_compiler then settings.cc.c_compiler = option.c_compiler end
+		if option.cxx_compiler then settings.cc.cxx_compiler = option.cxx_compiler end
+	end
+	
+	local save = function(option, output)
+		output:option(option, "driver")
+		output:option(option, "c_compiler")
+		output:option(option, "cxx_compiler")
+	end
+
+	local printhelp = function(option)
+		local a = ""
+		if option.desc then a = "for "..option.desc end
+		print("\t"..option.name.."=gcc|cl")
+		print("\t\twhat c/c++ compile driver to use"..a)
+		print("\t"..option.name..".c=FILENAME")
+		print("\t\twhat c compiler executable to use"..a)
+		print("\t"..option.name..".cxx=FILENAME")
+		print("\t\twhat c++ compiler executable to use"..a)
+	end
+
+	local display = function(option)
+		local s = option.driver
+		if option.c_compiler then s = s .. " c="..option.c_compiler end
+		if option.cxx_compiler then s = s .. " cxx="..option.cxx_compiler end
+		return s
+	end
+		
+	local o = MakeOption(name, nil, check, save, display, printhelp)
+	o.desc = desc
+	o.driver = false
+	o.c_compiler = false
+	o.cxx_compiler = false
+
+	if default_driver then o.driver = default_driver end
+	if default_c then o.c_compiler = default_c end
+	if default_cxx then o.cxx_compiler = default_cxx end
+
+	o.Apply = apply
+	return o
+end
+
+-- Option Library --------------------------------------
+--[[@FUNCTION
+	TODO
+@END]]--
+function OptLibrary(name, header, desc)
+	local check = function(option, settings)
+		option.value = false
+		option.include_path = false
+		
+		local function check_compile_include(filename, paths)
+			if CTestCompile(settings, "#include <" .. filename .. ">\nint main(){return 0;}", "") then
+				return ""
+			end
+
+			for k,v in pairs(paths) do
+				if CTestCompile(settings, "#include <" .. filename .. ">\nint main(){return 0;}", "-I"..v) then
+					return v
+				end
+			end
+			
+			return false
+		end
+
+		if ScriptArgs[option.name] then
+			if IsNegativeTerm(ScriptArgs[option.name]) then
+				option.value = false
+			elseif ScriptArgs[option.name] == "system" then
+				option.value = true
+			else
+				option.value = true
+				option.include_path = ScriptArgs[option.name]
+			end
+			option.auto_detected = false
+		else
+			option.include_path = check_compile_include(option.header, {})
+			if option.include_path == false then
+				if option.required then
+					print(name.." library not found and is required")
+					error("required library not found")
+				end
+			else
+				option.value = true
+				option.include_path = false
+			end
+		end
+	end
+	
+	local save = function(option, output)
+		output:option(option, "value")
+		output:option(option, "include_path")
+	end
+	
+	local display = function(option)
+		if option.value then
+			if option.include_path then
+				return option.include_path
+			else
+				return "(in system path)"
+			end
+		else
+			return "not found"
+		end
+	end
+
+	local printhelp = function(option)
+		print("\t"..option.name.."=disable|system|PATH")
+		if option.desc then print("\t\t"..option.desc) end
+	end
+	
+	local o = MakeOption(name, false, check, save, display, printhelp)
+	o.include_path = false
+	o.header = header
+	o.desc = desc
+	return o
+end
+