diff options
Diffstat (limited to 'SConstruct')
-rw-r--r-- | SConstruct | 163 |
1 files changed, 133 insertions, 30 deletions
diff --git a/SConstruct b/SConstruct index 9d536e0d16..17c809c179 100644 --- a/SConstruct +++ b/SConstruct @@ -1,4 +1,3 @@ - #!/usr/bin/env python EnsureSConsVersion(0, 98, 1) @@ -23,6 +22,7 @@ platform_flags = {} # flags for each platform active_platforms = [] active_platform_ids = [] platform_exporters = [] +platform_apis = [] global_defaults = [] for x in glob.glob("platform/*"): @@ -35,6 +35,8 @@ for x in glob.glob("platform/*"): if (os.path.exists(x + "/export/export.cpp")): platform_exporters.append(x[9:]) + if (os.path.exists(x + "/api/api.cpp")): + platform_apis.append(x[9:]) if (os.path.exists(x + "/globals/global_defaults.cpp")): global_defaults.append(x[9:]) if (detect.is_active()): @@ -119,6 +121,10 @@ env_base.__class__.add_source_files = methods.add_source_files env_base.__class__.use_windows_spawn_fix = methods.use_windows_spawn_fix env_base.__class__.split_lib = methods.split_lib +env_base.__class__.add_shared_library = methods.add_shared_library +env_base.__class__.add_library = methods.add_library +env_base.__class__.add_program = methods.add_program + env_base["x86_libtheora_opt_gcc"] = False env_base["x86_libtheora_opt_vc"] = False @@ -216,6 +222,7 @@ env_base.Append(CPPPATH=['#core', '#core/math', '#editor', '#drivers', '#']) # configure ENV for platform env_base.platform_exporters = platform_exporters +env_base.platform_apis = platform_apis """ sys.path.append("./platform/"+env_base["platform"]) @@ -271,9 +278,12 @@ if selected_platform in platform_list: if len(pieces) > 0: basename = pieces[0] basename = basename.replace('\\\\', '/') - env.vs_srcs = env.vs_srcs + [basename + ".cpp"] - env.vs_incs = env.vs_incs + [basename + ".h"] - # print basename + if os.path.isfile(basename + ".h"): + env.vs_incs = env.vs_incs + [basename + ".h"] + if os.path.isfile(basename + ".c"): + env.vs_srcs = env.vs_srcs + [basename + ".c"] + elif os.path.isfile(basename + ".cpp"): + env.vs_srcs = env.vs_srcs + [basename + ".cpp"] env.AddToVSProject = AddToVSProject env.extra_suffix = "" @@ -320,6 +330,8 @@ if selected_platform in platform_list: env.Append(CCFLAGS=['/W2'] + disable_nonessential_warnings) else: # 'no' env.Append(CCFLAGS=['/w']) + # Set exception handling model to avoid warnings caused by Windows system headers. + env.Append(CCFLAGS=['/EHsc']) else: # Rest of the world if (env["warnings"] == 'extra'): env.Append(CCFLAGS=['-Wall', '-Wextra']) @@ -367,7 +379,7 @@ if selected_platform in platform_list: sys.modules.pop('detect') env.module_list = [] - env.doc_class_path={} + env.doc_class_path = {} for x in module_list: if not env['module_' + x + '_enabled']: @@ -383,11 +395,10 @@ if selected_platform in platform_list: doc_classes = config.get_doc_classes() doc_path = config.get_doc_path() for c in doc_classes: - env.doc_class_path[c]="modules/"+x+"/"+doc_path + env.doc_class_path[c] = "modules/" + x + "/" + doc_path except: pass - sys.path.remove(tmppath) sys.modules.pop('config') @@ -427,6 +438,11 @@ if selected_platform in platform_list: if (True): # FIXME: detect GLES3 env.Append( BUILDERS = { 'GLES3_GLSL' : env.Builder(action = methods.build_gles3_headers, suffix = 'glsl.gen.h',src_suffix = '.glsl') } ) + scons_cache_path = os.environ.get("SCONS_CACHE") + if scons_cache_path != None: + CacheDir(scons_cache_path) + print("Scons cache enabled... (path: '" + scons_cache_path + "')") + Export('env') # build subdirs, the build order is dependent on link order. @@ -437,6 +453,7 @@ if selected_platform in platform_list: SConscript("editor/SCsub") SConscript("drivers/SCsub") + SConscript("platform/SCsub") SConscript("modules/SCsub") SConscript("main/SCsub") @@ -446,6 +463,7 @@ if selected_platform in platform_list: if env['vsproj']: env['CPPPATH'] = [Dir(path) for path in env['CPPPATH']] methods.generate_vs_project(env, GetOption("num_jobs")) + methods.generate_cpp_hint_file("cpp.hint") # Check for the existence of headers conf = Configure(env) @@ -470,33 +488,118 @@ screen = sys.stdout node_count = 0 node_count_max = 0 node_count_interval = 1 +node_pruning = 8 # Number of nodes to process before prunning the cache if ('env' in locals()): node_count_fname = str(env.Dir('#')) + '/.scons_node_count' - -def progress_function(node): - global node_count, node_count_max, node_count_interval, node_count_fname - node_count += node_count_interval - if (node_count_max > 0 and node_count <= node_count_max): - screen.write('\r[%3d%%] ' % (node_count * 100 / node_count_max)) - screen.flush() - elif (node_count_max > 0 and node_count > node_count_max): - screen.write('\r[100%] ') - screen.flush() - else: - screen.write('\r[Initial build] ') - screen.flush() +show_progress = env['progress'] + +import time, math + +class cache_progress: + # The default is 1 GB cache and 12 hours half life + def __init__(self, path = None, limit = 1073741824, half_life = 43200): + global node_pruning + self.path = path + self.limit = limit + self.exponent_scale = math.log(2) / half_life + if env['verbose'] and path != None: + screen.write('Current cache limit is ' + self.convert_size(limit) + ' (used: ' + self.convert_size(self.get_size(path)) + ')\n') + self.pruning = node_pruning + self.delete(self.file_list()) + + def __call__(self, node, *args, **kw): + global node_count, node_count_max, node_count_interval, node_count_fname, node_pruning, show_progress + if show_progress: + # Print the progress percentage + node_count += node_count_interval + if (node_count_max > 0 and node_count <= node_count_max): + screen.write('\r[%3d%%] ' % (node_count * 100 / node_count_max)) + screen.flush() + elif (node_count_max > 0 and node_count > node_count_max): + screen.write('\r[100%] ') + screen.flush() + else: + screen.write('\r[Initial build] ') + screen.flush() + # Prune if the number of nodes processed is 'node_pruning' or bigger + self.pruning -= node_count_interval + if self.pruning <= 0: + self.pruning = node_pruning + self.delete(self.file_list()) + + def delete(self, files): + if len(files) == 0: + return + if env['verbose']: + # Utter something + screen.write('\rPurging %d %s from cache...\n' % (len(files), len(files) > 1 and 'files' or 'file')) + map(os.remove, files) + + def file_list(self): + if self.path == None: + # Nothing to do + return [] + # Gather a list of (filename, (size, atime)) within the + # cache directory + file_stat = [(x, os.stat(x)[6:8]) for x in glob.glob(os.path.join(self.path, '*', '*'))] + if file_stat == []: + # Nothing to do + return [] + # Weight the cache files by size (assumed to be roughly + # proportional to the recompilation time) times an exponential + # decay since the ctime, and return a list with the entries + # (filename, size, weight). + current_time = time.time() + file_stat = [(x[0], x[1][0], x[1][0] * math.exp(self.exponent_scale * (x[1][1] - current_time))) for x in file_stat] + # Sort by highest weight (most sensible to keep) first + file_stat.sort(key=lambda x: x[2], reverse=True) + # Search for the first entry where the storage limit is + # reached + sum, mark = 0, None + for i,x in enumerate(file_stat): + sum += x[1] + if sum > self.limit: + mark = i + break + if mark == None: + return [] + else: + return [x[0] for x in file_stat[mark:]] + + def convert_size(self, size_bytes): + if size_bytes == 0: + return "0 bytes" + size_name = ("bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB") + i = int(math.floor(math.log(size_bytes, 1024))) + p = math.pow(1024, i) + s = round(size_bytes / p, 2) + return "%s %s" % (int(s) if i == 0 else s, size_name[i]) + + def get_size(self, start_path = '.'): + total_size = 0 + for dirpath, dirnames, filenames in os.walk(start_path): + for f in filenames: + fp = os.path.join(dirpath, f) + total_size += os.path.getsize(fp) + return total_size def progress_finish(target, source, env): - global node_count + global node_count, progressor with open(node_count_fname, 'w') as f: f.write('%d\n' % node_count) + progressor.delete(progressor.file_list()) -if 'env' in locals() and env['progress']: - try: - with open(node_count_fname) as f: - node_count_max = int(f.readline()) - except: - pass - Progress(progress_function, interval = node_count_interval) - progress_finish_command = Command('progress_finish', [], progress_finish) - AlwaysBuild(progress_finish_command) +try: + with open(node_count_fname) as f: + node_count_max = int(f.readline()) +except: + pass +cache_directory = os.environ.get("SCONS_CACHE") +# Simple cache pruning, attached to SCons' progress callback. Trim the +# cache directory to a size not larger than cache_limit. +cache_limit = float(os.getenv("SCONS_CACHE_LIMIT", 1024)) * 1024 * 1024 +progressor = cache_progress(cache_directory, cache_limit) +Progress(progressor, interval = node_count_interval) + +progress_finish_command = Command('progress_finish', [], progress_finish) +AlwaysBuild(progress_finish_command) |