local context = ...
context:load_tool('internal/compiler_gnu')
BoltGcc = {}
local function load_gcc_compiler(env, compiler, flags, language, var_name)
env[var_name .. 'FLAGS'] = { '-x', language, '-c', '-fPIC' }
env:append(var_name .. 'FLAGS', flags)
env[var_name .. '_COMPILER_NAME'] = 'gcc'
env[var_name .. '_TGT_F'] = '-o'
env[var_name .. '_DEFINE_ST'] = '-D'
env[var_name .. '_INCLUDE_ST'] = '-I'
env[var_name .. '_SYSTEM_INCLUDE_ST'] = '-isystem%s'
env[var_name .. '_IDIRAFTER'] = '-isystem'
env.LINK = env.GCC
env.LINKFLAGS = {}
env.LINK_TGT_F = '-o'
env.LINK_LIB_F = '-l'
env.LINK_LIBPATH_F = '-L'
env.LINKFLAGS_shlib = { '-shared', '-Wl,-z,defs' }
local defines = BoltGnuCompiler.get_specs(compiler, var_name)
local version = { 0, 0, 0 }
for name, value in pairs(defines) do
if name == '__GNUC__' then
version[1] = tonumber(value)
elseif name == '__GNUC_MINOR__' then
version[2] = tonumber(value)
elseif name == '__GNUC_PATCHLEVEL__' then
version[3] = tonumber(value)
end
end
env['GCC_' .. var_name .. '_VERSION'] = table.concat(version, '.')
context:load_tool('internal/' .. language)
context:load_tool('internal/link')
end
function BoltGcc.load_c(c_flags)
local env = context.env
env.CC = env.GCC
load_gcc_compiler(env, env.CC, c_flags, 'c', 'C')
end
function BoltGcc.load_cxx(cxx_flags)
local env = context.env
env.CXX = env.GCC
env.LIBS = { 'stdc++' }
load_gcc_compiler(env, env.CXX, cxx_flags, 'c++', 'CXX')
end
function BoltGcc.load_objc(objc_flags)
local env = context.env
env.OBJC = env.GCC
env.LIBS = { 'objc' }
load_gcc_compiler(env, env.OBJC, objc_flags, 'objc', 'OBJC')
end
function BoltGcc.load_objcxx(objcxx_flags)
local env = context.env
env.OBJCXX = env.GCC
env.LIBS = { 'stdc++', 'objc' }
load_gcc_compiler(env, env.OBJCXX, objcxx_flags, 'objc++', 'OBJCXX')
end
local languages = {
['c'] = BoltGcc.load_c,
['c++'] = BoltGcc.load_cxx,
['objc'] = BoltGcc.load_objc,
['objc++'] = BoltGcc.load_objcxx,
}
function BoltGcc.discover(callback, language_flags, global_flags, detect_multilib)
context:try('Looking for Gcc compilers', function()
local seen = {}
local paths = context.settings.path
for _, path in ipairs(paths) do
for _, crtbegin in ipairs(context:search(path.parent, 'lib/gcc*/*/*/crtbegin.o')) do
crtbegin = crtbegin:canonicalize()
if not seen[crtbegin:abs_path()] then
local node = crtbegin.parent
local version = node:name()
node = node.parent
local target = node:name()
for _, gcc in ipairs(context:search(path, target .. '-gcc-' .. version .. context.settings.exe_suffix)) do
seen[crtbegin:abs_path()] = crtbegin
if pcall(function()
local env = context:derive()
context:with(env, function()
context.env.GCC = { gcc }
context.env:append('GCC', global_flags)
context.env.GCC_VERSION = version
for lang, flags in pairs(language_flags) do
languages[lang](flags)
end
end)
if callback(env) ~= true then
return tostring(gcc)
end
end) and detect_multilib then
for _, multilib in ipairs(context:search(crtbegin.parent, '*/crtbegin.o')) do
pcall(function()
local env = context:derive()
context:with(env, function()
context.env.CC = { gcc }
context.env:append('GCC', global_flags)
context.env:append('GCC', '-m' .. multilib.parent:name())
context.env.GCC_VERSION = version
for lang, flags in pairs(language_flags) do
languages[lang](flags)
end
end)
if callback(env) ~= true then
return tostring(gcc)
end
end)
end
break
end
end
end
end
end
return 'done'
end)
end