Skip to content

Instantly share code, notes, and snippets.

@rpuntaie
Last active October 11, 2017 15:38
Show Gist options
  • Save rpuntaie/2bddfb5d7b77db26415ee14371289971 to your computer and use it in GitHub Desktop.
Save rpuntaie/2bddfb5d7b77db26415ee14371289971 to your computer and use it in GitHub Desktop.
variants for the waf-project build tool
#!/usr/bin/env python
# encoding: utf-8
# Roland Puntaier, 2017
"""If there is a *variants* variable in the main wscript
- x_variant commandline arguments are created
for x in {configure, build, clean, install, uninstall}
- an x command line argument is expanded to all x_variant's
- the associated x function context contains :py:const:`variant`
Variant strings can use the `/` path separator to produce an according output tree.
####################### begin example wscript ##################################
from itertools import product as prod
from string import Template
import time
import os
import waf_variants
variants = ['/'.join(v) for v in prod('Tim Jan'.split(),'X Y'.split())]
def touch(x,txt=''):
with open(x,'w') as f:
f.write(txt)
def filltime(tsk):
ifn = tsk.inputs[0].abspath()
ofn = tsk.outputs[0].abspath()
with open(ifn,'r') as f:
s = f.read()
with open(ofn,'w') as f:
f.write(time.strftime(Template(s).substitute(tsk.env),time.localtime()))
asrc = 'tst.txt.tm'
atgt = os.path.splitext(asrc)[0]
def init(ini):
touch(asrc,'$name, it is %$timeformat.')#Template,then strftime
def configure(cfg):
v = cfg.variant
cfg.env.name,cfg.env.timeformat = v.split('/')
if 'Tim' in v:
cfg.env.name = 'Timi'
def build(bld):
v=bld.variant
bld(rule=lambda t:filltime(t),source=asrc,target=atgt)
def clean(cln):
pass
####################### end example wscript ##################################
waf configure
waf build
waf build_Y
waf build_Jan/Y
waf clean_X
waf clean_Tim
waf clean_Tim/X
...
"""
from waflib.Build import BuildContext, CleanContext, InstallContext, UninstallContext
from waflib.Configure import ConfigurationContext
from waflib import Context
from waflib import Options
class VariantContext(Context.Context):
"wscript global variants implicitly expanded to configure_x, build_x,..."
cmd = 'init'
fun = 'init'
def execute(self):
try:
Context.Context.execute(self)
vs = list(Context.g_module.variants)
cls = [cl for cl in Context.classes if issubclass(cl,BuildContext)]
for y in [ConfigurationContext]+cls:
c = y.__name__.replace('Context','').replace('ation','e').lower()
cvs = []
for v in vs:
cv = self.add_variant(y,c,v)
cvs.append(cv)
cmds = []
for k in Options.commands:
if k.startswith(c):
kk = k[len(c):].strip('_')
cmds.extend([acv for acv in cvs if kk in acv])
else:
cmds.append(k)
Options.commands[:] = cmds
except AttributeError:
pass
def add_variant(self,y,c,v):
cv = c + '_' + v
class _variant_context(y):
cmd = cv
fun = c
variant = v
def __init__(s, **kw):
y.__init__(s, **kw)
if c[-1]=='e':#configure
s.setenv(v)
return cv
@rpuntaie
Copy link
Author

waf build_X will build Tim/X and Jan/X in the example

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment