309 lines
11 KiB
Python
Executable File
309 lines
11 KiB
Python
Executable File
import os, tempfile, shutil
|
|
|
|
class TargetNotBuildError(Exception):
|
|
pass
|
|
|
|
class Tool(object):
|
|
EMPTY = False
|
|
|
|
def make(self, target, reporter):
|
|
raise TargetNotBuildError()
|
|
|
|
def cache(self, target):
|
|
return ''
|
|
|
|
def rebuild_needed(self, target):
|
|
return False
|
|
|
|
class ToolRunInfo(object):
|
|
def __init__(self, target, reporter, options):
|
|
self.target = target
|
|
self.reporter = reporter
|
|
self.options = options
|
|
|
|
class Empty(Tool):
|
|
EMPTY = True
|
|
def make(self, target, reporter):
|
|
return 0
|
|
|
|
class MakefileKbuild(Tool):
|
|
def _content(self, target):
|
|
from StringIO import StringIO
|
|
import os
|
|
from comake.defaults import file_id_allocator
|
|
global colinux_file_id
|
|
|
|
parameters = [os.path.dirname(target.pathname)]
|
|
compiler_defines = target.options.get('compiler_defines', {})
|
|
defines = compiler_defines.items()
|
|
defines.sort()
|
|
for key, value in defines:
|
|
if key == 'COLINUX_FILE_ID':
|
|
continue
|
|
if value is not None:
|
|
parameters.append('-D%s=%s' % (key, value))
|
|
continue
|
|
parameters.append('-D%s' % (key, ))
|
|
|
|
# Output-type coded in extension (lib-m or colinux-objs)
|
|
libm = target.get_ext()[1:]
|
|
|
|
output_file = StringIO()
|
|
print >>output_file, "include $(KBUILD_EXTMOD)/Makefile.include"
|
|
print >>output_file, "EXTRA_CFLAGS += -I$(COLINUX_BASE)/%s" % ' '.join(parameters)
|
|
|
|
for names in target.inputs:
|
|
name = os.path.basename(names.pathname)
|
|
if not name in [ 'file_ids.c', 'colinux.mod.c', 'colinux.c' ]:
|
|
full_name = os.path.join(parameters[0], name)
|
|
colinux_file_id = file_id_allocator.allocate(full_name)
|
|
|
|
oname = os.path.splitext(name)[0]+'.o'
|
|
print >>output_file, "%s += %s" % (libm, oname)
|
|
print >>output_file, "CFLAGS_%s = -DCOLINUX_FILE_ID=%d" % (oname, colinux_file_id)
|
|
|
|
return output_file.getvalue()
|
|
|
|
def make(self, target, reporter):
|
|
output_file = open(target.pathname, 'wb')
|
|
output_file.write(self._content(target))
|
|
|
|
def rebuild_needed(self, target):
|
|
return open(target.pathname, 'rb').read() != self._content(target)
|
|
|
|
|
|
class Copy(Tool):
|
|
def make(self, target, reporter):
|
|
input_pathnames = []
|
|
for tinput in target.get_actual_inputs():
|
|
if tinput.get_ext() in ['.c', '.cpp']:
|
|
actual_compile = True
|
|
input_pathnames.append(tinput.pathname)
|
|
if len(input_pathnames) != 1:
|
|
raise TargetNotBuildError()
|
|
|
|
pathnames = input_pathnames[0], target.pathname
|
|
reporter.print_text("Copying '%s' to '%s'" % pathnames)
|
|
shutil.copy(*pathnames)
|
|
|
|
class Executer(Tool):
|
|
def get_cross_build_tool(self, tool, tool_run_inf):
|
|
compiler_path = tool
|
|
cross_compilation_prefix = tool_run_inf.options.get('cross_compilation_prefix', None)
|
|
if cross_compilation_prefix:
|
|
compiler_path = cross_compilation_prefix + compiler_path
|
|
return compiler_path
|
|
|
|
def system(self, command_line, tool_run_inf):
|
|
tool_run_inf.reporter.print_text(command_line)
|
|
exit_status = os.system(command_line)
|
|
return exit_status
|
|
|
|
def make(self, target, reporter):
|
|
tool_run_inf = ToolRunInfo(target, reporter, target.options)
|
|
self.prepare_command(tool_run_inf)
|
|
try:
|
|
command_line = self.get_command_line(tool_run_inf)
|
|
exit_status = self.system(command_line, tool_run_inf)
|
|
finally:
|
|
self.cleanup(tool_run_inf)
|
|
if exit_status != 0:
|
|
raise TargetNotBuildError()
|
|
|
|
def cache(self, target):
|
|
tool_run_inf = ToolRunInfo(target, None, target.options)
|
|
return self.get_command_line(tool_run_inf)
|
|
|
|
def prepare_command(self, tool_run_inf):
|
|
pass
|
|
|
|
def get_command_line(self, tool_run_inf):
|
|
return ''
|
|
|
|
def cleanup(self, tool_run_inf):
|
|
pass
|
|
|
|
class Compiler(Executer):
|
|
def get_command_line(self, tool_run_inf):
|
|
from sys import platform
|
|
darwin = (platform == "darwin")
|
|
actual_compile = False
|
|
count_archives = 0
|
|
compiler_def_type = tool_run_inf.options.get('compiler_def_type', [])
|
|
if not compiler_def_type:
|
|
compiler_def_type = 'gcc'
|
|
compiler_path = self.get_cross_build_tool(compiler_def_type, tool_run_inf)
|
|
|
|
input_pathnames = []
|
|
for tinput in tool_run_inf.target.get_actual_inputs():
|
|
if tinput.get_ext() in ['.c', '.cpp']:
|
|
actual_compile = True
|
|
elif tinput.get_ext() in ['.a']:
|
|
count_archives += 1
|
|
elif tinput.get_ext() in ['.h']:
|
|
continue
|
|
input_pathnames.append(tinput.pathname)
|
|
|
|
parameters = []
|
|
parameters.append(compiler_path)
|
|
if actual_compile:
|
|
compiler_includes = tool_run_inf.options.get('compiler_includes', [])
|
|
parameters += ["-I" + path for path in compiler_includes]
|
|
compiler_flags = tool_run_inf.options.get('compiler_flags', [])
|
|
parameters += compiler_flags
|
|
compiler_optimization = tool_run_inf.options.get('compiler_optimization', "-O2")
|
|
parameters += [compiler_optimization]
|
|
compiler_defines = tool_run_inf.options.get('compiler_defines', {})
|
|
defines = compiler_defines.items()
|
|
defines.sort()
|
|
for key, value in defines:
|
|
if value is not None:
|
|
parameters.append('-D%s=%s' % (key, value))
|
|
continue
|
|
parameters.append('-D%s' % (key, ))
|
|
parameters.append('-c')
|
|
else:
|
|
linker_flags = tool_run_inf.options.get('linker_flags', [])
|
|
parameters += linker_flags
|
|
compiler_strip = tool_run_inf.options.get('compiler_strip', False)
|
|
if compiler_strip:
|
|
parameters.append('-Wl,--strip-debug')
|
|
|
|
if count_archives > 1 and not darwin:
|
|
parameters.append('-Wl,--start-group')
|
|
parameters.extend(input_pathnames)
|
|
compiler_lib_paths = tool_run_inf.options.get('compiler_lib_paths', [])
|
|
compiler_libs = tool_run_inf.options.get('compiler_libs', [])
|
|
parameters += ["-L" + path for path in compiler_lib_paths]
|
|
parameters += ["-l" + path for path in compiler_libs]
|
|
if not actual_compile:
|
|
parameters += tool_run_inf.options.get('linker_add', [])
|
|
if count_archives > 1 and not darwin:
|
|
parameters.append('-Wl,--end-group')
|
|
|
|
parameters.append('-o')
|
|
parameters.append(tool_run_inf.target.pathname)
|
|
|
|
command_line = ' '.join(parameters)
|
|
return command_line
|
|
|
|
class Linker(Executer):
|
|
def get_command_line(self, tool_run_inf):
|
|
actual_compile = False
|
|
|
|
link_path = self.get_cross_build_tool('ld', tool_run_inf)
|
|
|
|
input_pathnames = []
|
|
for tinput in tool_run_inf.target.get_actual_inputs():
|
|
input_pathnames.append(tinput.pathname)
|
|
|
|
parameters = []
|
|
parameters.append(link_path)
|
|
if tool_run_inf.target.get_ext() == '.o':
|
|
parameters.append('-r')
|
|
|
|
parameters.extend(input_pathnames)
|
|
parameters += tool_run_inf.options.get('linker_add', [])
|
|
parameters.append('-o')
|
|
parameters.append(tool_run_inf.target.pathname)
|
|
command_line = ' '.join(parameters)
|
|
return command_line
|
|
|
|
class Archiver(Executer):
|
|
def __init__(self, flat=True):
|
|
self.flat = flat
|
|
|
|
def get_command_line(self, tool_run_inf):
|
|
ar = self.get_cross_build_tool('ar', tool_run_inf)
|
|
parameters = []
|
|
parameters.append(ar)
|
|
parameters.append('cr')
|
|
parameters.append(tool_run_inf.target.pathname)
|
|
parameters.extend(tool_run_inf.ready_inputs)
|
|
command_line = ' '.join(parameters)
|
|
return command_line
|
|
|
|
def cache(self, target):
|
|
tool_run_inf = ToolRunInfo(target, None, target.options)
|
|
cmdline = self.get_cross_build_tool('ar', tool_run_inf)
|
|
cmdline += ' '.join([target.pathname for target in tool_run_inf.target.get_actual_inputs()])
|
|
return cmdline
|
|
|
|
def prepare_command(self, tool_run_inf):
|
|
tool_run_inf.flat_mode = False
|
|
ready_inputs = []
|
|
tool_run_inf.ready_inputs = ready_inputs
|
|
tool_run_inf.temp_dir = None
|
|
tool_run_inf.temp_dir_extract = None
|
|
tool_run_inf.temp_inputs = []
|
|
|
|
ar = self.get_cross_build_tool('ar', tool_run_inf)
|
|
|
|
input_pathnames = []
|
|
for tinput in tool_run_inf.target.get_actual_inputs():
|
|
if tinput.get_ext() == '.a':
|
|
if self.flat:
|
|
tool_run_inf.flat_mode = True
|
|
else:
|
|
ready_inputs.append(tinput.pathname)
|
|
else:
|
|
ready_inputs.append(tinput.pathname)
|
|
|
|
if tool_run_inf.flat_mode:
|
|
temp_dir = tempfile.mkdtemp()
|
|
temp_dir_extract = tempfile.mkdtemp()
|
|
tool_run_inf.temp_dir = temp_dir
|
|
tool_run_inf.temp_dir_extract = temp_dir_extract
|
|
file_index = 0
|
|
|
|
for tinput in tool_run_inf.target.get_actual_inputs():
|
|
if tinput.get_ext() == '.a':
|
|
cwd = os.getcwd()
|
|
real_path = os.path.realpath(tinput.pathname)
|
|
try:
|
|
os.chdir(temp_dir_extract)
|
|
self.system('ar x %s' % (real_path, ), tool_run_inf)
|
|
finally:
|
|
os.chdir(cwd)
|
|
|
|
for pathname in os.listdir(temp_dir_extract):
|
|
if pathname == '__.SYMDEF SORTED':
|
|
continue
|
|
fullname = os.path.join(temp_dir_extract, pathname)
|
|
destname = os.path.join(temp_dir, ("%d-" % (file_index, )) + pathname)
|
|
os.rename(fullname, destname)
|
|
tool_run_inf.ready_inputs.append(destname)
|
|
tool_run_inf.temp_inputs.append(destname)
|
|
file_index += 1
|
|
|
|
def cleanup(self, tool_run_inf):
|
|
if tool_run_inf.temp_dir:
|
|
for pathname in tool_run_inf.temp_inputs:
|
|
os.unlink(pathname)
|
|
name = os.path.join(tool_run_inf.temp_dir, '__.SYMDEF SORTED')
|
|
if os.path.exists(name):
|
|
os.unlink(name)
|
|
name = os.path.join(tool_run_inf.temp_dir_extract, '__.SYMDEF SORTED')
|
|
if os.path.exists(name):
|
|
os.unlink(name)
|
|
os.rmdir(tool_run_inf.temp_dir)
|
|
os.rmdir(tool_run_inf.temp_dir_extract)
|
|
|
|
class Script(Executer):
|
|
def __init__(self, func):
|
|
self.func = func
|
|
|
|
def get_command_line(self, tool_run_inf):
|
|
return self.func(self, tool_run_inf)
|
|
|
|
exported_tools = [
|
|
Compiler,
|
|
Linker,
|
|
Empty,
|
|
Script,
|
|
Tool,
|
|
Executer,
|
|
Copy,
|
|
MakefileKbuild,
|
|
]
|