From 459f4a97881137f99cef028fc06e585f32a1ac89 Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Thu, 11 Apr 2019 00:15:48 +0300 Subject: [PATCH] scripts: waflib: introduce new waf plugin -- subproject, which makes easier use of standalone envs for each subdirectory --- ref_gl/wscript | 9 +-- scripts/waflib/msdev.py | 26 +------ scripts/waflib/subproject.py | 127 +++++++++++++++++++++++++++++++++++ wscript | 43 ++---------- 4 files changed, 141 insertions(+), 64 deletions(-) create mode 100644 scripts/waflib/subproject.py diff --git a/ref_gl/wscript b/ref_gl/wscript index 89425694..1a129d25 100644 --- a/ref_gl/wscript +++ b/ref_gl/wscript @@ -33,9 +33,10 @@ def configure(conf): conf.env.NANOGL = conf.options.NANOGL conf.env.GLWES = conf.options.GLWES - if conf.env.NANOGL: conf.recurse('nanogl') + if conf.env.NANOGL: + conf.add_subproject('nanogl') if conf.env.GLWES: - conf.recurse('gl-wes-v2') + conf.add_subproject('gl-wes-v2') conf.env.GL_STATIC = conf.options.GL_STATIC if conf.env.GL_STATIC: @@ -77,7 +78,7 @@ def build(bld): ) if bld.env.NANOGL: - bld.recurse('nanogl') + bld.add_subproject('nanogl') bld.shlib( source = source, target = 'ref_gles1', @@ -89,7 +90,7 @@ def build(bld): subsystem = bld.env.MSVC_SUBSYSTEM) if bld.env.GLWES: - bld.recurse('gl-wes-v2') + bld.add_subproject('gl-wes-v2') bld.shlib( source = source, target = 'ref_gles2', diff --git a/scripts/waflib/msdev.py b/scripts/waflib/msdev.py index 6c6221a5..3034bfee 100644 --- a/scripts/waflib/msdev.py +++ b/scripts/waflib/msdev.py @@ -107,6 +107,7 @@ from waflib.Build import BuildContext # import waftools # from waftools import deps from deps import get_targets +from subproject import get_subproject_env def options(opt): @@ -161,27 +162,6 @@ class MsDevContext(BuildContext): export(self) self.timer = Utils.Timer() -def get_subproject_env(bld, path): - # remove top dir path - path = str(path) - if path.startswith(bld.top_dir): - if bld.top_dir[-1] != os.pathsep: - path = path[len(bld.top_dir) + 1:] - else: path = path[len(bld.top_dir):] - - # iterate through possible subprojects names - folders = os.path.normpath(path).split(os.sep) - # print(folders) - for i in range(1, len(folders)+1): - name = folders[-i] - # print(name) - if name in bld.all_envs: - Logs.pprint('YELLOW', 'env: changed to %s' % name) - return bld.all_envs[name] - Logs.pprint('YELLOW', 'env: changed to default env') - raise IndexError('top env') - - def export(bld): '''Exports all C and C++ task generators as **Visual Studio** projects and creates a **Visual Studio** solution containing references to @@ -206,7 +186,7 @@ Don't use it for release builds, as it doesn't enables WinXP compatibility for n if getattr(tgen, 'msdev_skipme', False): continue try: - bld.env = get_subproject_env(bld, tgen.path) + bld.env = get_subproject_env(bld, tgen.path, True) except IndexError: bld.env = saveenv if set(('c', 'cxx')) & set(getattr(tgen, 'features', [])): @@ -791,4 +771,4 @@ MSDEV_SOLUTION = [ 'HideSolutionNode = FALSE\n', 'EndGlobalSection\n', 'EndGlobal\n', -'\n'] \ No newline at end of file +'\n'] diff --git a/scripts/waflib/subproject.py b/scripts/waflib/subproject.py new file mode 100644 index 00000000..c629a6eb --- /dev/null +++ b/scripts/waflib/subproject.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Copyright (c) 2019 a1batross + +''' +Subproject tool + +Helps you have standalone environment for each subproject(subdirectory) + +Usage:: + def configure(conf): + conf.add_subproject('folder1 folder2') + + def build(bld): + bld.add_subproject('folder1 folder2') +''' + +from waflib import Configure, Logs, Options, Utils +import os + +IGNORED_SUBDIRS = [] +DEPTH = '' + +def depth_push(path): + global DEPTH + + DEPTH = os.path.join(DEPTH, path) + # print DEPTH + +def depth_pop(): + global DEPTH + + DEPTH = os.path.dirname(DEPTH) + # print DEPTH + +def depth(): + global DEPTH + return DEPTH + +def opt(f): + """ + Decorator: attach new option functions to :py:class:`waflib.Options.OptionsContext`. + + :param f: method to bind + :type f: function + """ + setattr(Options.OptionsContext, f.__name__, f) + return f + +@opt +def add_subproject(ctx, names): + names_lst = Utils.to_list(names) + + for name in names_lst: + depth_push(name) + + wscript_path = os.path.join(depth(), 'wscript') + + if not os.path.isfile(wscript_path): + # HACKHACK: this way we get warning message right in the help + # so this just becomes more noticeable + ctx.add_option_group('Cannot find wscript in ' + name + '. You probably missed submodule update') + else: + ctx.recurse(name) + + depth_pop() + +def options(opt): + grp = opt.add_option_group('Subproject options') + + grp.add_option('-S', '--skip-subprojects', action='store', dest = 'SKIP_SUBDIRS', default=None, + help = 'don\'t recurse into specified subprojects. Use only directory name.') + +def get_subproject_env(ctx, path, log=False): + # remove top dir path + path = str(path) + if path.startswith(ctx.top_dir): + if ctx.top_dir[-1] != os.pathsep: + path = path[len(ctx.top_dir) + 1:] + else: path = path[len(ctx.top_dir):] + + # iterate through possible subprojects names + folders = os.path.normpath(path).split(os.sep) + # print(folders) + for i in range(1, len(folders)+1): + name = folders[-i] + # print(name) + if name in ctx.all_envs: + if log: Logs.pprint('YELLOW', 'env: changed to %s' % name) + return ctx.all_envs[name] + if log: Logs.pprint('YELLOW', 'env: changed to default env') + raise IndexError('top env') + + +def configure(conf): + if conf.options.SKIP_SUBDIRS: + global IGNORED_SUBDIRS + IGNORED_SUBDIRS += conf.options.SKIP_SUBDIRS.split(',') + print IGNORED_SUBDIRS + +@Configure.conf +def add_subproject(ctx, names): + global IGNORED_SUBDIRS + names_lst = Utils.to_list(names) + + if isinstance(ctx, Configure.ConfigurationContext): + for name in names_lst: + depth_push(name) + if name in IGNORED_SUBDIRS: + ctx.msg(msg='--X %s' % depth(), result='ignored', color='YELLOW') + depth_pop() + return + ctx.setenv(name, ctx.env) # derive new env from + ctx.env.ENVNAME = name + ctx.msg(msg='--> %s' % depth(), result='in progress', color='BLUE') + ctx.recurse(name) + ctx.msg(msg='<-- %s' % depth(), result='done', color='BLUE') + ctx.setenv('') + depth_pop() + else: + if not ctx.all_envs: + ctx.load_envs() + for name in names_lst: + if name in IGNORED_SUBDIRS: + return + ctx.env = ctx.all_envs[name] + ctx.recurse(name) diff --git a/wscript b/wscript index 058a46de..b24ba85d 100644 --- a/wscript +++ b/wscript @@ -58,29 +58,15 @@ def options(opt): grp.add_option('--enable-bsp2', action = 'store_true', dest = 'SUPPORT_BSP2_FORMAT', default = False, help = 'build engine and renderers with BSP2 map support(recommended for Quake, breaks compability!)') + + opt.load('subproject') - grp.add_option('-S', '--skip-subprojects', action='store', dest = 'SKIP_SUBDIRS', default=None, - help = 'don\'t recurse into specified subprojects. Current subdirs: ' + str(subdirs())) - - for i in SUBDIRS: - if not os.path.isfile(os.path.join(i.name, 'wscript')): - # HACKHACK: this way we get warning message right in the help - # so this just becomes more noticeable - opt.add_option_group('Cannot find wscript in ' + i.name + '. You probably missed submodule update') - else: opt.recurse(i.name) + opt.add_subproject(subdirs()) opt.load('xcompile compiler_cxx compiler_c sdl2') if sys.platform == 'win32': opt.load('msvc msdev msvs') -def set_ignored_subdirs(subdirs): - for i in SUBDIRS: - if i.ignore: - continue - - if i.name in subdirs: - i.ignore = True - def configure(conf): conf.start_msg('Build type') if conf.options.BUILD_TYPE == None: @@ -91,10 +77,7 @@ def configure(conf): conf.fatal('Invalid build type. Valid are "debug", "release" or "none"') conf.end_msg(conf.options.BUILD_TYPE) - # skip some subdirectories, if requested - if conf.options.SKIP_SUBDIRS: - skip_subdirs = conf.options.SKIP_SUBDIRS.split(',') - set_ignored_subdirs(skip_subdirs) + conf.load('subproject') # Force XP compability, all build targets should add # subsystem=bld.env.MSVC_SUBSYSTEM @@ -186,19 +169,9 @@ def configure(conf): if conf.env.DEDICATED and i.dedicated: continue - if i.ignore: - continue - - conf.setenv(i.name, conf.env) # derive new env from global one - conf.env.ENVNAME = i.name - conf.msg(msg='--> ' + i.name, result='in progress', color='BLUE') - # configure in standalone env - conf.recurse(i.name) - conf.msg(msg='<-- ' + i.name, result='done', color='BLUE') - conf.setenv('') + conf.add_subproject(i.name) def build(bld): - bld.load_envs() for i in SUBDIRS: if bld.env.SINGLE_BINARY and i.singlebin: continue @@ -206,8 +179,4 @@ def build(bld): if bld.env.DEDICATED and i.dedicated: continue - if i.ignore: - continue - - bld.env = bld.all_envs[i.name] - bld.recurse(i.name) + bld.add_subproject(i.name)