|
Packit |
58578d |
# Status: being ported by Steven Watanabe
|
|
Packit |
58578d |
# Base revision: 47077
|
|
Packit |
58578d |
#
|
|
Packit |
58578d |
# Copyright (C) Andre Hentz 2003. Permission to copy, use, modify, sell and
|
|
Packit |
58578d |
# distribute this software is granted provided this copyright notice appears in
|
|
Packit |
58578d |
# all copies. This software is provided "as is" without express or implied
|
|
Packit |
58578d |
# warranty, and with no claim as to its suitability for any purpose.
|
|
Packit |
58578d |
#
|
|
Packit |
58578d |
# Copyright (c) 2006 Rene Rivera.
|
|
Packit |
58578d |
#
|
|
Packit |
58578d |
# Copyright (c) 2008 Steven Watanabe
|
|
Packit |
58578d |
#
|
|
Packit |
58578d |
# Use, modification and distribution is subject to the Boost Software
|
|
Packit |
58578d |
# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
|
|
Packit |
58578d |
# http://www.boost.org/LICENSE_1_0.txt)
|
|
Packit |
58578d |
|
|
Packit |
58578d |
##import type ;
|
|
Packit |
58578d |
##import generators ;
|
|
Packit |
58578d |
##import feature ;
|
|
Packit |
58578d |
##import errors ;
|
|
Packit |
58578d |
##import scanner ;
|
|
Packit |
58578d |
##import toolset : flags ;
|
|
Packit |
58578d |
|
|
Packit |
58578d |
import os.path
|
|
Packit |
58578d |
import re
|
|
Packit |
58578d |
|
|
Packit |
58578d |
import bjam
|
|
Packit |
58578d |
|
|
Packit |
58578d |
from b2.build import type, toolset, generators, scanner, feature
|
|
Packit |
58578d |
from b2.exceptions import AlreadyDefined
|
|
Packit |
58578d |
from b2.tools import builtin
|
|
Packit |
58578d |
from b2.util import regex
|
|
Packit |
58578d |
from b2.build.toolset import flags
|
|
Packit |
58578d |
from b2.manager import get_manager
|
|
Packit |
58578d |
from b2.util import utility
|
|
Packit |
58578d |
|
|
Packit |
58578d |
__debug = None
|
|
Packit |
58578d |
|
|
Packit |
58578d |
def debug():
|
|
Packit |
58578d |
global __debug
|
|
Packit |
58578d |
if __debug is None:
|
|
Packit |
58578d |
__debug = "--debug-configuration" in bjam.variable("ARGV")
|
|
Packit |
58578d |
return __debug
|
|
Packit |
58578d |
|
|
Packit |
58578d |
type.register('RC', ['rc'])
|
|
Packit |
58578d |
|
|
Packit |
58578d |
def init():
|
|
Packit |
58578d |
pass
|
|
Packit |
58578d |
|
|
Packit |
58578d |
def configure (command = None, condition = None, options = None):
|
|
Packit |
58578d |
"""
|
|
Packit |
58578d |
Configures a new resource compilation command specific to a condition,
|
|
Packit |
58578d |
usually a toolset selection condition. The possible options are:
|
|
Packit |
58578d |
|
|
Packit |
58578d |
* <rc-type>(rc|windres) - Indicates the type of options the command
|
|
Packit |
58578d |
accepts.
|
|
Packit |
58578d |
|
|
Packit |
58578d |
Even though the arguments are all optional, only when a command, condition,
|
|
Packit |
58578d |
and at minimum the rc-type option are given will the command be configured.
|
|
Packit |
58578d |
This is so that callers don't have to check auto-configuration values
|
|
Packit |
58578d |
before calling this. And still get the functionality of build failures when
|
|
Packit |
58578d |
the resource compiler can't be found.
|
|
Packit |
58578d |
"""
|
|
Packit |
58578d |
rc_type = feature.get_values('<rc-type>', options)
|
|
Packit |
58578d |
if rc_type:
|
|
Packit |
58578d |
assert(len(rc_type) == 1)
|
|
Packit |
58578d |
rc_type = rc_type[0]
|
|
Packit |
58578d |
|
|
Packit |
58578d |
if command and condition and rc_type:
|
|
Packit |
58578d |
flags('rc.compile.resource', '.RC', condition, command)
|
|
Packit |
58578d |
flags('rc.compile.resource', '.RC_TYPE', condition, [rc_type.lower()])
|
|
Packit |
58578d |
flags('rc.compile.resource', 'DEFINES', [], ['<define>'])
|
|
Packit |
58578d |
flags('rc.compile.resource', 'INCLUDES', [], ['<include>'])
|
|
Packit |
58578d |
if debug():
|
|
Packit |
58578d |
print 'notice: using rc compiler ::', condition, '::', command
|
|
Packit |
58578d |
|
|
Packit |
58578d |
engine = get_manager().engine()
|
|
Packit |
58578d |
|
|
Packit |
58578d |
class RCAction:
|
|
Packit |
58578d |
"""Class representing bjam action defined from Python.
|
|
Packit |
58578d |
The function must register the action to execute."""
|
|
Packit |
58578d |
|
|
Packit |
58578d |
def __init__(self, action_name, function):
|
|
Packit |
58578d |
self.action_name = action_name
|
|
Packit |
58578d |
self.function = function
|
|
Packit |
58578d |
|
|
Packit |
58578d |
def __call__(self, targets, sources, property_set):
|
|
Packit |
58578d |
if self.function:
|
|
Packit |
58578d |
self.function(targets, sources, property_set)
|
|
Packit |
58578d |
|
|
Packit |
58578d |
# FIXME: What is the proper way to dispatch actions?
|
|
Packit |
58578d |
def rc_register_action(action_name, function = None):
|
|
Packit |
58578d |
global engine
|
|
Packit |
58578d |
if action_name in engine.actions:
|
|
Packit |
58578d |
raise AlreadyDefined("Bjam action %s is already defined" % action_name)
|
|
Packit |
58578d |
engine.actions[action_name] = RCAction(action_name, function)
|
|
Packit |
58578d |
|
|
Packit |
58578d |
def rc_compile_resource(targets, sources, properties):
|
|
Packit |
58578d |
rc_type = bjam.call('get-target-variable', targets, '.RC_TYPE')
|
|
Packit |
58578d |
rc_type = rc_type[0] if rc_type else ''
|
|
Packit |
58578d |
global engine
|
|
Packit |
58578d |
engine.set_update_action('rc.compile.resource.' + rc_type, targets, sources, properties)
|
|
Packit |
58578d |
|
|
Packit |
58578d |
rc_register_action('rc.compile.resource', rc_compile_resource)
|
|
Packit |
58578d |
|
|
Packit |
58578d |
|
|
Packit |
58578d |
engine.register_action(
|
|
Packit |
58578d |
'rc.compile.resource.rc',
|
|
Packit |
58578d |
'"$(.RC)" -l 0x409 "-U$(UNDEFS)" "-D$(DEFINES)" -I"$(>:D)" -I"$(<:D)" -I"$(INCLUDES)" -fo "$(<)" "$(>)"')
|
|
Packit |
58578d |
|
|
Packit |
58578d |
engine.register_action(
|
|
Packit |
58578d |
'rc.compile.resource.windres',
|
|
Packit |
58578d |
'"$(.RC)" "-U$(UNDEFS)" "-D$(DEFINES)" -I"$(>:D)" -I"$(<:D)" -I"$(INCLUDES)" -o "$(<)" -i "$(>)"')
|
|
Packit |
58578d |
|
|
Packit |
58578d |
# FIXME: this was originally declared quietly
|
|
Packit |
58578d |
engine.register_action(
|
|
Packit |
58578d |
'compile.resource.null',
|
|
Packit |
58578d |
'as /dev/null -o "$(<)"')
|
|
Packit |
58578d |
|
|
Packit |
58578d |
# Since it's a common practice to write
|
|
Packit |
58578d |
# exe hello : hello.cpp hello.rc
|
|
Packit |
58578d |
# we change the name of object created from RC file, to
|
|
Packit |
58578d |
# avoid conflict with hello.cpp.
|
|
Packit |
58578d |
# The reason we generate OBJ and not RES, is that gcc does not
|
|
Packit |
58578d |
# seem to like RES files, but works OK with OBJ.
|
|
Packit |
58578d |
# See http://article.gmane.org/gmane.comp.lib.boost.build/5643/
|
|
Packit |
58578d |
#
|
|
Packit |
58578d |
# Using 'register-c-compiler' adds the build directory to INCLUDES
|
|
Packit |
58578d |
# FIXME: switch to generators
|
|
Packit |
58578d |
builtin.register_c_compiler('rc.compile.resource', ['RC'], ['OBJ(%_res)'], [])
|
|
Packit |
58578d |
|
|
Packit |
58578d |
__angle_include_re = "#include[ ]*<([^<]+)>"
|
|
Packit |
58578d |
|
|
Packit |
58578d |
# Register scanner for resources
|
|
Packit |
58578d |
class ResScanner(scanner.Scanner):
|
|
Packit |
58578d |
|
|
Packit |
58578d |
def __init__(self, includes):
|
|
Packit |
58578d |
scanner.__init__ ;
|
|
Packit |
58578d |
self.includes = includes
|
|
Packit |
58578d |
|
|
Packit |
58578d |
def pattern(self):
|
|
Packit |
58578d |
return "(([^ ]+[ ]+(BITMAP|CURSOR|FONT|ICON|MESSAGETABLE|RT_MANIFEST)" +\
|
|
Packit |
58578d |
"[ ]+([^ \"]+|\"[^\"]+\"))|(#include[ ]*(<[^<]+>|\"[^\"]+\")))" ;
|
|
Packit |
58578d |
|
|
Packit |
58578d |
def process(self, target, matches, binding):
|
|
Packit |
58578d |
binding = binding[0]
|
|
Packit |
58578d |
angle = regex.transform(matches, "#include[ ]*<([^<]+)>")
|
|
Packit |
58578d |
quoted = regex.transform(matches, "#include[ ]*\"([^\"]+)\"")
|
|
Packit |
58578d |
res = regex.transform(matches,
|
|
Packit |
58578d |
"[^ ]+[ ]+(BITMAP|CURSOR|FONT|ICON|MESSAGETABLE|RT_MANIFEST)" +\
|
|
Packit |
58578d |
"[ ]+(([^ \"]+)|\"([^\"]+)\")", [3, 4])
|
|
Packit |
58578d |
|
|
Packit |
58578d |
# Icons and other includes may referenced as
|
|
Packit |
58578d |
#
|
|
Packit |
58578d |
# IDR_MAINFRAME ICON "res\\icon.ico"
|
|
Packit |
58578d |
#
|
|
Packit |
58578d |
# so we have to replace double backslashes to single ones.
|
|
Packit |
58578d |
res = [ re.sub(r'\\\\', '/', match) for match in res if match is not None ]
|
|
Packit |
58578d |
|
|
Packit |
58578d |
# CONSIDER: the new scoping rule seem to defeat "on target" variables.
|
|
Packit |
58578d |
g = bjam.call('get-target-variable', target, 'HDRGRIST')[0]
|
|
Packit |
58578d |
b = os.path.normpath(os.path.dirname(binding))
|
|
Packit |
58578d |
|
|
Packit |
58578d |
# Attach binding of including file to included targets.
|
|
Packit |
58578d |
# When target is directly created from virtual target
|
|
Packit |
58578d |
# this extra information is unnecessary. But in other
|
|
Packit |
58578d |
# cases, it allows to distinguish between two headers of the
|
|
Packit |
58578d |
# same name included from different places.
|
|
Packit |
58578d |
# We don't need this extra information for angle includes,
|
|
Packit |
58578d |
# since they should not depend on including file (we can't
|
|
Packit |
58578d |
# get literal "." in include path).
|
|
Packit |
58578d |
g2 = g + "#" + b
|
|
Packit |
58578d |
|
|
Packit |
58578d |
g = "<" + g + ">"
|
|
Packit |
58578d |
g2 = "<" + g2 + ">"
|
|
Packit |
58578d |
angle = [g + x for x in angle]
|
|
Packit |
58578d |
quoted = [g2 + x for x in quoted]
|
|
Packit |
58578d |
res = [g2 + x for x in res]
|
|
Packit |
58578d |
|
|
Packit |
58578d |
all = angle + quoted
|
|
Packit |
58578d |
|
|
Packit |
58578d |
bjam.call('mark-included', target, all)
|
|
Packit |
58578d |
|
|
Packit |
58578d |
engine = get_manager().engine()
|
|
Packit |
58578d |
|
|
Packit |
58578d |
engine.add_dependency(target, res)
|
|
Packit |
58578d |
bjam.call('NOCARE', all + res)
|
|
Packit |
58578d |
engine.set_target_variable(angle, 'SEARCH', [utility.get_value(inc) for inc in self.includes])
|
|
Packit |
58578d |
engine.set_target_variable(quoted, 'SEARCH', [b + utility.get_value(inc) for inc in self.includes])
|
|
Packit |
58578d |
engine.set_target_variable(res, 'SEARCH', [b + utility.get_value(inc) for inc in self.includes])
|
|
Packit |
58578d |
|
|
Packit |
58578d |
# Just propagate current scanner to includes, in a hope
|
|
Packit |
58578d |
# that includes do not change scanners.
|
|
Packit |
58578d |
get_manager().scanners().propagate(self, angle + quoted)
|
|
Packit |
58578d |
|
|
Packit |
58578d |
scanner.register(ResScanner, 'include')
|
|
Packit |
58578d |
type.set_scanner('RC', ResScanner)
|