📄 umake.py
字号:
def rmlist(list1, list2): """Removes items in list2 from list1, case insensitive.""" tmp={} for item in list2: tmp[string.lower(item)]=1 lst = [] for item in list1: if not tmp.get(string.lower(item)): lst.append(item) return lst## Add a callback which will be called## after all .pf, .cf umakefiles and umakerc files## have been parsed. This callback can thus modify## the behaviour of the project in any way it sees fit.def AddUmakeCallback(call, *args): global umake_epilogue_callbacks umake_epilogue_callbacks.append( (call, args) )def AddIdentifyCallback(call, *args): """Add a callback which will be called if the -v option is given to umake""" global umake_identify_callbacks umake_identify_callbacks.append( (call, args) )class BuildRule: def __init__(self, source, target, command): self.source_suffix = source self.target_suffix = target self.command = command self.link_output = 1 self.output_dir = Noneclass Command: """Base class of most platform build commands. It is common for subclasses of command to define a method called execute that returns a string that calls the command on the given arguments.""" def __init__(self): self.args = {"default" : ""} self.cmd = "" self.make_var = "" self.make_flags = "" def form_args(self): """Builds a command line based on the build choices.""" arg_str = "" for choice in project.build_choices: if self.args.has_key(choice): arg_str = "%s%s " % (arg_str, self.args[choice]) return arg_str def setup_command_var(self): """Returns a string that represents this command as a variable.""" if len(self.make_var): return "%s=%s" % (self.make_var, self.cmd) return "" def setup_flags_var(self): """Returns a string that represents the arguments for this command as a make variable.""" if len(self.make_flags): return "%s=%s" % (self.make_flags, self.form_args()) return "" def execute(self): return "%s %s" % (platform.form_var(self.make_var), self.form_args()) def copy(self, new_make_var): ret=copy.deepcopy(self) ret.make_var = new_make_var ret.make_flags = new_make_var+"FLAGS" return ret; class Compiler(Command): """A compiler is any command that takes one source file and creates a target file based on the source file.""" def __init__(self): Command.__init__(self) self.target_arg = "" self.source_arg = "" self.define_arg = "" self.include_arg = "" self.prefix_include_arg = "" self.includes = None # defaults to project.includes self.defines = None # defaults to project.defines def execute(self, target_file, src_file): extra_args = "" ## include special compiler arguments for this target type if self.args.has_key(project.target_type): extra_args = self.args[project.target_type] return form_string( platform.form_var(self.make_var), platform.form_var(self.make_flags), extra_args, self.target_arg, target_file, self.source_arg, src_file) def setup_flags_var(self): prefix=self.make_var if prefix in ["CC","CXX"]: prefix="" def_str = form_string( platform.form_var(prefix+"INCLUDES"), platform.form_var(prefix+"DEFINES")) return form_string(self.make_flags, '=', self.form_args(), def_str) def copy(self, new_make_var): ret=Command.copy(self, new_make_var) return ret def SetIncludes(self, *args): self.includes=list(args) def AddIncludes(self, *args): if not self.includes: self.includes=project.includes[:] self.includes.extend(args) def RemoveIncludes(self, *args): if not self.includes: return self.includes = rmlist(self.includes, args) def SetDefines(self, *args): self.defines=list(args) def AddDefines(self, *args): if not self.defines: self.defines=project.defines[:] self.defines.extend(args) def RemoveDefines(self, *args): if not self.defines: return self.defines = rmlist(self.defines, args)class Linker(Command): """A linker is any command that takes many source files and creates a target file based on those source files.""" def __init__(self): Command.__init__(self) self.make_var = "LD" self.make_flags = "LDFLAGS" self.target_arg = "" def execute(self, target_file, objects, static_libs, dynamic_libs): return form_string( self.cmd, self.form_args() + self.target_arg + target_file, objects, static_libs, dynamic_libs)class Linker2: """Replaces the Linker class with a better API.""" def __init__(self): self.linker2 = 1 def LinkLIB(self, target_path, objects): """Returns a list of strings. Each string is a command it be executed in order, to create a static library.""" umake_lib.warning("Linker2: LinkLIB unimplemented") return [] def CleanLIB(self, target_path): """Returns a list of strings. Each string is a command it be executed in order, removing the target, and all the intermediate components of a static library.""" umake_lib.warning("Linker2: CleanLIB unimplemented") return [] def LinkDLL(self, target_path, objects, static_libs, dynamic_libs): """Same as LinkLIB, but creates a DLL (dynamic link library).""" umake_lib.warning("Linker2: LinkDLL unimplemented") return [] def CleanDLL(self, target_path): """Same as CleanLIB, but for a DLL.""" umake_lib.warning("Linker2: CleanDLL unimplemented") return [] def LinkEXE(self, target_path, objects, static_libs, dynamic_libs): """Same as LinkLIB, but creates a executeable.""" umake_lib.warning("Linker2: LinkEXE unimplemented") return [] def CleanEXE(self, target_path): """Same as CleanLIB, but for a executeable.""" umake_lib.warning("Linker2: CleanEXE unimplemented") return []class MakeDepend(Command): """This is its own command because it takes a list of sources and an output directory and messes with the Makefile in the current directory to creately create dependencies based on header includes.""" def __init__(self): Command.__init__(self) self.make_var = "MAKE_DEP" self.make_flags = "MAKE_DEP_FLAGS" self.output_dir_arg = "" def execute(self, sources, output_dir): if not (output_dir): out_str = '' else: out_str = form_string( self.output_dir_arg, output_dir + platform.path_sep) return form_string( platform.form_var(self.make_var), platform.form_var(self.make_flags), out_str, sources) def setup_flags_var(self): return form_string( self.make_flags, '=', self.form_args(), platform.form_var("INCLUDES"), platform.form_var("DEFINES"))class Utility(Command): def execute(self, target): return "%s %s %s" % ( platform.form_var(self.make_var), self.form_args(), target)class Versioning: """This class is used almost exclueivly to read the *.ver files for version numbers, then use those version numbers to create a name for output DLLs.""" version_match = re.compile( '^#define\s+TARVER_STRING_VERSION\s+\"(\d+)\.(\d+)\.(\d+)\.(\d+)\".*$') def __init__(self): self.version = '' def create_dll_name(self, target, path = ''): umake_lib.fatal("Versioning.create_dll_name needs to be overriden") def get_version(self, target, path): vMajor = vMinor = vRelease = vBuild = 0 if len(path): # this means the version file is not in this directory filename = '%s.ver' % (os.path.join(os.pardir, path, target)) else: # this means the version file is in this directory filename = '%s.ver' % (os.path.join(os.curdir, target)) try: filehandle = open(filename, 'r') except IOError, e: umake_lib.fatal( 'could not find %s for version information' % (filename)) for line in filehandle.readlines(): match_obj = self.version_match.match(line) if match_obj: vMajor = match_obj.group(1) vMinor = match_obj.group(2) vRelease = match_obj.group(3) vBuild = match_obj.group(4) break filehandle.close() self.version = (vMajor, vMinor, vRelease, vBuild) return self.version ## the path assumptions ARE as ugly as they look... ## we have to search for both Names.py and names.py because ## you can never tell how the case-insensitive OS's will check ## things in... def get_name(self, old_name, path = ''): if len(path): path = os.path.join(os.pardir, path) path1 = os.path.join(path, 'Names.py') path2 = os.path.join(path, 'names.py') else: path1 = 'Names.py' path2 = 'names.py' if os.path.isfile(path1): ns = safe_execfile_namespace(path1) elif os.path.isfile(path2): ns = safe_execfile_namespace(path2) else: ns = None if ns: try: return ns['names'][platform.name] except KeyError: pass try: return ns['names'][platform.reference] except KeyError: pass ## if the above methods fail, go backwards through ## the platform.pcf_prefix_list list = platform.pcf_prefix_list[:] list.reverse() for pcf_prefix in list: try: return ns['names'][pcf_prefix] except KeyError: pass return ""class Platform: """This is where OS specific information is stored. This information should apply to every single project ever built. For example: on unix the delete file command is always 'rm' so it belongs here. Due to my inexperience with Python a couple things in this class are already defined in the os module. I might clean that up later.""" def __init__(self): ## legacy self.name = self.reference = sys.platform self.config_dir = UMAKE_ROOT ## list the prefixes for the PCF files which should be ## executed self.pcf_prefix_list = [] ## set to "1" to enable static builds self.can_build_static = 0 ## defined in the .cf file self.type = '' self.path_sep = '' self.line_cont = '' self.var_begin = '' self.var_end = '' self.make_prog_arg = '' self.make_depend_char = '' self.sys_lib_arg = '' self.inc_subdir = '' self.mkdir = '' self.x_root_dir = '' self.object_suffix = '' ## suffexes for target types self.exe_suffix = '' self.library_suffix = '' self.library_prefix = '' self.dll_suffix = '' self.resource_dll_suffix = '' self.rm = Command() self.rmdir = Command() self.make = Command() self.make_dep = MakeDepend() self.make_lib = Linker() self.link = Linker() self.make_toc = Utility() self.copy = Command() self.build_rules = {} self.defines = [] self.suffix_list = [] self.specs = [] self.system_paths = []
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -