1
0
mirror of https://github.com/elua/elua.git synced 2025-01-25 01:02:54 +08:00
elua/config/modules.lua

250 lines
10 KiB
Lua
Raw Normal View History

-- Build configuration: module selection
module( ..., package.seeall )
local sf = string.format
local gen = require "generators"
2012-08-19 17:57:52 +03:00
-- List of all Lua modules, their guards (if applicable), their library name,
-- their open function and their LTR map. "<none>" in the LTR map field marks
-- the modules that do not have a corresponding LTR map, which basically means
-- they are not LTR compatible
2012-07-15 00:50:12 +03:00
local lua_modules = {
2012-08-19 17:57:52 +03:00
lua_math = { lib = "LUA_MATHLIBNAME", open = "luaopen_math", map = "math_map" },
lua_io = { lib = "LUA_IOLIBNAME", open = "luaopen_io", map = "<none>" },
lua_string = { lib = "LUA_STRLIBNAME", open = "luaopen_string", map = "strlib" },
lua_table = { lib = "LUA_TABLIBNAME", open = "luaopen_table", map = "tab_funcs" },
lua_debug = { lib = "LUA_DBLIBNAME", open = "luaopen_debug", map = "dblib" },
lua_package = { lib = "LUA_LOADLIBNAME", open = "luaopen_package", map = "<none>" },
lua_co = { lib = "LUA_COLIBNAME", open = false, map = "co_funcs" }
2012-07-15 00:50:12 +03:00
}
2012-08-19 17:57:52 +03:00
-- List of all eLua generic modules, in the same format as above
-- (if the module guard evaluates to false at compile time, the module is not included in the build)
2012-07-15 00:50:12 +03:00
-- NOTE: if the guards contain a condition, the condition _MUST_ be specified with spaces next to the operator!
-- For example: NUM_CAN > 0, _NOT_ NUM_CAN>0.
local elua_generic_modules = {
2012-08-19 17:57:52 +03:00
adc = { guards = { "BUILD_ADC", "NUM_ADC > 0" } },
bit = {},
2012-08-19 17:57:52 +03:00
can = { guards = { "NUM_CAN > 0" } },
cpu = {},
elua = {},
2012-08-19 17:57:52 +03:00
i2c = { guards = { "NUM_I2C > 0" } },
pack = {},
2012-08-19 17:57:52 +03:00
rpc = { guards = { "BUILD_RPC" } },
net = { guards = { "BUILD_UIP" } },
pd = {},
2012-08-19 17:57:52 +03:00
pio = { guards = { "NUM_PIO > 0" } },
pwm = { guards = {"NUM_PWM > 0" } },
spi = { guards = { "NUM_SPI > 0" } },
term = { guards = { "BUILD_TERM" } },
tmr = { guards = { "NUM_TIMER > 0" } },
uart = { guards = { "NUM_UART > 0" } },
fs = { guards = { "BUILD_NIFFS" } }
}
2012-07-15 00:50:12 +03:00
-- All generic modules (Lua and eLua) in a single table
local all_generic_modules = {}
utils.concat_tables( all_generic_modules, lua_modules )
utils.concat_tables( all_generic_modules, elua_generic_modules )
-- Return the auxlib name of a given module
2012-08-19 17:57:52 +03:00
local function get_auxlib( m, t )
t = t or all_generic_modules
return t[ m ].lib or sf( "AUXLIB_%s", m:upper() )
end
-- Return the open function name of a given module
2012-08-19 17:57:52 +03:00
local function get_openf_name( m, t )
t = t or all_generic_modules
if t[ m ].open == false then
return "luaopen_dummy"
else
return t[ m ].open or sf( "luaopen_%s", m:lower() )
end
end
-- Return the map array name of a given module
2012-08-19 17:57:52 +03:00
local function get_map_name( m, t )
t = t or all_generic_modules
return t[ m ].map or sf( "%s_map", m:lower() )
end
2012-07-15 00:50:12 +03:00
local platform_modules
-- Generate a condition string starting from a guard
local function gen_cond_string( g )
local condition = ''
for idx, e in pairs( g ) do
local suffix = idx == #g and "" or " && "
2012-07-15 00:50:12 +03:00
if e:find( '%s' ) then -- if it has a space, add the condition as it was given, between parantheses
condition = condition .. "( " .. e .. " )"
else
condition = condition .. "defined( " .. e .. " )"
end
condition = condition .. suffix
end
return condition
end
2012-07-15 00:50:12 +03:00
-- Add/remove a module to the given list
local function process_module( l, name, is_specific )
local sectname, exclude = is_specific and "platform" or "generic"
local check = is_specific and platform_modules or all_generic_modules
-- Handle "+name" / "-name"
if name:sub( 1, 1 ) == "+" then
name = name:sub( 2, -1 )
elseif name:sub( 1, 1 ) == "-" then
name = name:sub( 2, -1 )
exclude = true
end
local modlist
-- Handle special cases for 'name'
if name == "all" then
modlist = is_specific and utils.table_keys( platform_modules ) or utils.table_keys( all_generic_modules )
elseif name == "all_lua" then
if is_specific then return false, "'all_lua' can't be used in attribute 'platform' of section 'modules'" end
modlist = utils.table_keys( lua_modules )
elseif name == "all_elua" then
if is_specific then return false, "'all_elua' can't be used in attribute 'platform' of section 'modules" end
modlist = utils.table_keys( elua_generic_modules )
else
modlist = { name }
end
-- For inclusion, check for valid element. For exclusion, check for prior inclusion.
if exclude then
for _, m in pairs( modlist ) do
if not l[ m ] then
return false, sf( "module '%s' not found in element '%s' of section 'modules'", m, sectname )
end
l[ m ] = nil
end
else
for _, m in pairs( modlist ) do
if not check[ m ] then
return false, sf( "module '%s' of element '%s' in section 'modules' not found", m, sectname )
end
l[ m ] = true
end
end
return true
end
2012-08-19 17:57:52 +03:00
-- Generates module-specific data for the given component (generic or platform)
local function generate_data( t, is_platform )
local prefix = is_platform and "PL_" or ""
local desc = is_platform and platform_modules or all_generic_modules
local s = ""
-- Generate the proper line for each module in turn
for m, _ in pairs( t ) do
if get_map_name( m, desc ) ~= "<none>" then
local g = desc[ m ].guards or {}
if #g == 0 then -- no guards
s = s .. gen.print_define( sf( "%sMODULE_%s_LINE", prefix, m:upper() ), sf( "_ROM( %s, %s, %s )", get_auxlib( m, desc ), get_openf_name( m, desc ), get_map_name( m, desc ) ) )
else
-- Check the guard. If the guard is not satisfied, issue a compile time warning and set the line as empty
s = s .. "\n#if " .. gen_cond_string( g ) .. "\n"
s = s .. gen.print_define( sf( "%sMODULE_%s_LINE", prefix, m:upper() ), sf( "_ROM( %s, %s, %s )", get_auxlib( m, desc ), get_openf_name( m, desc ), get_map_name( m, desc ) ) )
s = s .. "#else\n"
s = s .. gen.print_define( sf( "%sMODULE_%s_LINE", prefix, m:upper() ) )
s = s .. sf( "#warning Unable to include %s module '%s' in the image\n#endif\n\n", is_platform and "platform specific" or "generic", m )
end
end
end
s = s .. "\n"
-- Finally, generate the acutal list of libraries.
if is_platform then
s = s .. "#define PLATFORM_MODULES_LIBS_ROM"
else
s = s .. "#define LUA_PLATFORM_LIBS_ROM\\\n PLATFORM_MODULES_LINE"
end
for m, _ in pairs( t ) do
if get_map_name( m, desc ) ~= "<none>" then s = s .. sf( "\\\n %sMODULE_%s_LINE", prefix, m:upper() ) end
end
return s .. "\n\n"
end
-- Generate the complete module list starting from the board description
function gen_module_list( desc, plconf, platform, boardname )
local mdesc = desc.modules
if not mdesc then return '' end
local gen_list_generic, gen_list_platform = {}, {}
local gstr = string.rep( "/", 80 ) .. "\n" .. "// Module configuration\n\n"
local ngenmods, nplmods = 0, 0
platform_modules = plconf.get_platform_modules( boardname, desc.cpu ) or {}
if mdesc == "all" then -- include all the modules. what a brave, brave soul.
2012-07-15 00:50:12 +03:00
process_module( gen_list_generic, 'all' )
process_module( gen_list_platform, 'all', true )
else
-- Include only some modules. Validate their names against the corresponding module list
2012-07-15 00:50:12 +03:00
mdesc.generic = type( mdesc.generic ) == "table" and mdesc.generic or { mdesc.generic }
mdesc.platform = type( mdesc.platform ) == "table" and mdesc.platform or { mdesc.platform }
utils.foreach( mdesc.generic, function( k, v ) process_module( gen_list_generic, v ) end )
utils.foreach( mdesc.platform, function( k, v ) process_module( gen_list_platform, v, true ) end )
end
2012-07-15 00:50:12 +03:00
-- Count the notal number of modules
utils.foreach( gen_list_generic, function( k, v ) ngenmods = ngenmods + 1 end )
utils.foreach( gen_list_platform, function( k, v ) nplmods = nplmods + 1 end )
if ngenmods + nplmods == 0 then return '' end
-- Now build all the module lines, starting from the gen_list and the guards
-- First define the platform specific line if needed
if nplmods > 0 then
-- The (hopefully) proper way to generate this is a bit tricky. We enable the
-- platform module if _any_ of the modules in gen_list_platform can be enabled.
-- In order to do this, we gather their guards in a single, long condition
-- Count all guards first
local nguards, nmodules = 0, 0
local pltabname = mdesc.platform_name or platform
for m, _ in pairs( gen_list_platform ) do
nmodules = nmodules + 1
nguards = nguards + #( platform_modules[ m ].guards or {} )
end
if nguards == 0 or nguards < nmodules then -- nothing to guard or not all have guards
gstr = gstr .. gen.print_define( "PLATFORM_MODULES_LINE", sf( '_ROM( "%s", luaopen_platform, platform_map )', pltabname ) )
gstr = gstr .. gen.print_define( "PS_LIB_TABLE_NAME", sf( '"%s"', pltabname ) )
gstr = gstr .. gen.print_define( "PLATFORM_MODULES_ENABLE" )
else
-- Gather the composed condition in 'cond'
local cond = '\n#if 0' -- the '0' is included here for an easier generation of the composed condition
for m, _ in pairs( gen_list_platform ) do
2012-08-19 17:57:52 +03:00
local g = platform_modules[ m ].guards or {}
if #g > 0 then
cond = cond .. " || ( " .. gen_cond_string( g ) .. " )"
end
end
gstr = gstr .. cond .. "\n"
gstr = gstr .. gen.print_define( "PLATFORM_MODULES_LINE", sf( '_ROM( "%s", luaopen_platform, platform_map )', platform ) )
gstr = gstr .. gen.print_define( "PS_LIB_TABLE_NAME", sf( '"%s"', pltabname ) )
gstr = gstr .. gen.print_define( "PLATFORM_MODULES_ENABLE" )
gstr = gstr .. "#else\n"
gstr = gstr .. gen.print_define( sf( "PLATFORM_MODULES_LINE" ) )
gstr = gstr .. sf( "#warning Unable to include platform modules in the image\n#endif\n\n" )
end
else -- no platform modules here, people. move along.
gstr = gstr .. gen.print_define( "PLATFORM_MODULES_LINE" )
end
2012-08-19 17:57:52 +03:00
if ngenmods > 0 then gstr = gstr .. generate_data( gen_list_generic ) end
if nplmods > 0 then gstr = gstr .. generate_data( gen_list_platform, true ) end
2012-07-15 00:50:12 +03:00
-- Not quite ready yet. We still need to generate the list of generic modules
-- that can't be completely ROM'd by the LTR patch in a separate macro that will be
-- handled by linit.c
local noltr, found = "#define LUA_LIBS_NOLTR\\\n", false
2012-07-15 00:50:12 +03:00
for m, _ in pairs( gen_list_generic ) do
if get_map_name( m ) == "<none>" then
noltr = noltr .. sf( " { %s, %s },\\\n", get_auxlib( m ), get_openf_name( m ) )
found = true
end
end
gstr = gstr .. ( found and noltr or "" )
-- A bit of cosmetic touch ...
gstr = gstr .. "\n"
gstr = gstr:gsub( "\n\n\n", "\n\n" )
return gstr
end