diff options
Diffstat (limited to 'SConstruct')
-rw-r--r-- | SConstruct | 136 |
1 files changed, 113 insertions, 23 deletions
diff --git a/SConstruct b/SConstruct index b5885f896f..b3e0672c94 100644 --- a/SConstruct +++ b/SConstruct @@ -121,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 @@ -179,6 +183,7 @@ opts.Add(BoolVariable('builtin_opus', "Use the builtin opus library", True)) opts.Add(BoolVariable('builtin_pcre2', "Use the builtin pcre2 library)", True)) opts.Add(BoolVariable('builtin_recast', "Use the builtin recast library", True)) opts.Add(BoolVariable('builtin_squish', "Use the builtin squish library", True)) +opts.Add(BoolVariable('builtin_thekla_atlas', "Use the builtin thekla_altas library", True)) opts.Add(BoolVariable('builtin_zlib', "Use the builtin zlib library", True)) opts.Add(BoolVariable('builtin_zstd', "Use the builtin zstd library", True)) @@ -484,33 +489,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) |