Skip to content

Instantly share code, notes, and snippets.

@sjb-gist
Created October 16, 2012 15:34
Show Gist options
  • Save sjb-gist/3900013 to your computer and use it in GitHub Desktop.
Save sjb-gist/3900013 to your computer and use it in GitHub Desktop.
waf: extra support for csharp builds
#!/usr/bin/env python
# encoding: utf-8
# Copyright © 2012 SjB <steve@nca.uwo.ca>. All Rights Reserved.
import os, shutil
from waflib.TaskGen import feature, extension, after, before
from waflib.Task import Task
from waflib.Configure import conf
from waflib.Tools import ccroot
from waflib import Utils, Options, Context
#
# waf tools to extend the build-in cs tool provided with the default waf build system.
#
def options(ctx):
ctx.load('cs')
ctx.add_option('--sdk', type='string', dest='sdk_version')
ctx.add_option('--with-resgen-binary', type='string', dest='resgenbinary')
def configure(ctx):
csc = getattr(Options.options, 'cscbinary', None)
if csc:
conf.env.MCS = csc
else:
# Added the dmcs mono compile to the default list.
# Users can define their own list by assigning an list of compiler
# to the ctx.cscbinary variable
cscbinary = getattr(ctx, 'cscbinary', ['csc', 'dmcs', 'gmcs', 'mcs'])
ctx.find_program(cscbinary, var='MCS')
resgen = getattr(Options.options, 'resgenbinary', None)
if resgen:
conf.env.RESGEN = resgen
else:
ctx.find_program(['resgen'], var='RESGEN')
ctx.load('cs')
# new variable that allow the sdk version to be specified at the command line.
sdk_version = getattr(Options.options, 'sdk_version', None)
if sdk_version:
self.env.append_value('CSFLAGS', '/sdk:%s' % sdk_version)
# converts the *.cs.in source files into *.cs files replacing all @var@ with
# the appropriate values in the related variable in the ctx.Define array
@extension('.cs.in')
def process_in(self, node):
for x in self.env['DEFINES']:
(k, v) = x.split('=')
setattr(self.cs_task.generator, k, v)
tgt = node.change_ext('.cs', ext_in='.cs.in').path_from(self.bld.bldnode)
print repr(tgt)
tsk = self.create_task('subst', node, tgt)
class resources(Task):
inst_to = None
run_str = '${RESGEN} ${SRC} ${TGT}'
@extension('.resx')
def process_resx(self, node):
tsk = self.create_task('resources', node, node.change_ext('.resources', ext_in='.resx'))
# Make sure we assign a value to name. (this should be included in the original tool)
@feature('cs')
@before('apply_cs')
def fix_assign_gen_to_name(self):
name = getattr(self, 'name', None) or self.gen
setattr(self, 'name', name)
# Simple Coype file Task
class copy_file(Task):
chmod = Utils.O644
inst_to = None
def run(self):
infile = self.inputs[0].abspath()
outfile = self.outputs[0].abspath()
try:
shutil.copy2(infile, outfile)
except (OSError, IOError):
return 1
else:
if self.chmod: os.chmod(outfile, self.chmod)
return 0
# Copy all external (USE) library in the the build directory. This will allow use to
# run the codes from within that build directory.
@feature('cs')
@after('use_cs')
def copy_dep_nodes_to_builddir(self):
if getattr(self, 'copy_dependent_files', True):
tsk = getattr(self, 'cs_task', None)
if not tsk:
self.bld.fatal('not a cs task : %r' % self)
bld_path = tsk.outputs[0].parent
for src in tsk.dep_nodes:
out = bld_path.find_or_declare(src.name)
cp_tsk = self.create_task('copy_file', src, out)
cp_tsk.set_run_after(tsk)
#tsk.outputs.append(out)
try:
self.install_task.source.append(out)
except AttributeError:
pass
@feature('cs')
@after('apply_cs')
@before('use_cs')
def pkg_cs(self):
names = self.to_list(getattr(self, 'use', []))
for x in names:
pkg = 'PKG_%s' % Utils.quote_define_name(x)
if pkg in getattr(self.env, 'packages', []):
self.env.append_value('CSFLAGS', '/pkg:%s' % x)
names.remove(x)
self.use = ' '.join(names)
@feature('cs')
@after('apply_cs')
@before('use_cs')
def use_extlib(self):
names = self.to_list(getattr(self, 'use', []))
for x in names:
lib_name = Utils.quote_define_name(x)
for lib_type in ccroot.lib_patterns.keys():
if not 'csshlib' == lib_type:
if lib_name in getattr(self.env, 'ext_%s' % lib_type, []):
names.remove(x)
self.use = ' '.join(names)
# Add define params to the compile command line
@conf
def set_define(self, *k, **kw):
if k[0]:
kw['defines'] = k[0]
kw['defines'] = Utils.to_list(kw['defines'])
if len(kw['defines']):
self.env.append_value('CSFLAGS', '/define:%s' % ';'.join(kw['defines']))
# Set the sdk version
@conf
def set_sdk_version(self, *k, **kw):
if k:
kw['sdk_version'] = k[0]
if 'sdk_version' in kw:
v = kw['sdk_version']
self.msg("Setting .Net SDK version", v)
self.env.append_value('CSFLAGS', '/sdk:%s' % v)
# check if a pkg-config package in install on the system
@conf
def check_pkg(self, *k, **kw):
self.check_cfg(**kw)
if self.get_define(self.have_define(kw['package'])):
self.env.append_value('packages', 'PKG_%s' % Utils.quote_define_name(kw['package']))
# check if an external lib is available to the compiler.
@conf
def check_extlib(self, *k, **kw):
if not 'package' in kw:
kw['package'] = k[0]
if not 'msg' in kw:
kw['msg'] = 'Checking for %s' % kw['package']
paths = ['.']
if "path_list" in kw:
for p in Utils.to_list(kw['path_list']):
if p:
paths.append(p)
if not 'lib_type' in kw:
kw['lib_type'] = 'shlib'
if 'csshlib' == kw['lib_type']:
if not 'csshlib' in ccroot.lib_patterns:
ccroot.lib_patterns['csshlib'] = []
ccroot.lib_patterns['csshlib'].append('%s.dll')
names = [x % kw['package'] for x in ccroot.lib_patterns[kw['lib_type']]]
ret = self.find_file(names, path_list=paths)
if ret:
uselib = Utils.quote_define_name(kw['package'])
self.env.append_value('ext_%s' % kw['lib_type'], uselib)
self.env.append_value('%s_LIBPATH' % uselib, os.path.dirname(ret))
self.define(self.have_define(kw.get('uselib_store', kw['package'])), 1, 0)
self.msg(kw['msg'], ret, "GREEN")
#check if an external assembly is available to the compiler
@conf
def check_assembly(self, *k, **kw):
kw['lib_type'] = 'csshlib'
check_extlib(self, *k, **kw)
from waflib.Build import BuildContext
class NUnitContext(BuildContext):
cmd = 'nunit'
fun = 'build'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment