blob: 9964d339bafc5b48ca2db10dc5ea6ec3bc04be97 [file] [log] [blame]
# Copyright (C) Andre Hentz 2003. Permission to copy, use, modify, sell and
# distribute this software is granted provided this copyright notice appears in
# all copies. This software is provided "as is" without express or implied
# warranty, and with no claim as to its suitability for any purpose.
#
# Copyright (c) 2006 Rene Rivera.
#
# Use, modification and distribution is subject to the Boost Software
# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
# http://www.boost.org/LICENSE_1_0.txt)
import type ;
import generators ;
import feature ;
import errors ;
import scanner ;
import toolset : flags ;
if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ]
{
.debug-configuration = true ;
}
type.register RC : rc ;
rule init ( )
{
}
# Configures a new resource compilation command specific to a condition,
# usually a toolset selection condition. The possible options are:
#
# * <rc-type>(rc|windres) - Indicates the type of options the command
# accepts.
#
# Even though the arguments are all optional, only when a command, condition,
# and at minimum the rc-type option are given will the command be configured.
# This is so that callers don't have to check auto-configuration values
# before calling this. And still get the functionality of build failures when
# the resource compiler can't be found.
#
rule configure ( command ? : condition ? : options * )
{
local rc-type = [ feature.get-values <rc-type> : $(options) ] ;
if $(command) && $(condition) && $(rc-type)
{
flags rc.compile.resource .RC $(condition) : $(command) ;
flags rc.compile.resource .RC_TYPE $(condition) : $(rc-type:L) ;
flags rc.compile.resource DEFINES <define> ;
flags rc.compile.resource INCLUDES <include> ;
if $(.debug-configuration)
{
ECHO notice: using rc compiler :: $(condition) :: $(command) ;
}
}
}
rule compile.resource ( target : sources * : properties * )
{
local rc-type = [ on $(target) return $(.RC_TYPE) ] ;
rc-type ?= null ;
compile.resource.$(rc-type) $(target) : $(sources[1]) ;
}
actions compile.resource.rc
{
"$(.RC)" -l 0x409 "-U$(UNDEFS)" "-D$(DEFINES)" -I"$(>:D)" -I"$(<:D)" -I"$(INCLUDES)" -fo "$(<)" "$(>)"
}
actions compile.resource.windres
{
"$(.RC)" "-U$(UNDEFS)" "-D$(DEFINES)" -I"$(>:D)" -I"$(<:D)" -I"$(INCLUDES)" -o "$(<)" -i "$(>)"
}
actions quietly compile.resource.null
{
as /dev/null -o "$(<)"
}
# Since it's a common practice to write
# exe hello : hello.cpp hello.rc
# we change the name of object created from RC file, to
# avoid conflict with hello.cpp.
# The reason we generate OBJ and not RES, is that gcc does not
# seem to like RES files, but works OK with OBJ.
# See http://article.gmane.org/gmane.comp.lib.boost.build/5643/
#
# Using 'register-c-compiler' adds the build directory to INCLUDES
generators.register-c-compiler rc.compile.resource : RC : OBJ(%_res) ;
# Register scanner for resources
class res-scanner : scanner
{
import regex virtual-target path scanner ;
rule __init__ ( includes * )
{
scanner.__init__ ;
self.includes = $(includes) ;
}
rule pattern ( )
{
return "(([^ ]+[ ]+(BITMAP|CURSOR|FONT|ICON|MESSAGETABLE|RT_MANIFEST)[ ]+([^ \"]+|\"[^\"]+\"))|(#include[ ]*(<[^<]+>|\"[^\"]+\")))" ;
}
rule process ( target : matches * : binding )
{
local angle = [ regex.transform $(matches) : "#include[ ]*<([^<]+)>" ] ;
local quoted = [ regex.transform $(matches) : "#include[ ]*\"([^\"]+)\"" ] ;
local res = [ regex.transform $(matches) : "[^ ]+[ ]+(BITMAP|CURSOR|FONT|ICON|MESSAGETABLE|RT_MANIFEST)[ ]+(([^ \"]+)|\"([^\"]+)\")" : 3 4 ] ;
# Icons and other includes may referenced as
#
# IDR_MAINFRAME ICON "res\\icon.ico"
#
# so we have to replace double backslashes to single ones.
res = [ regex.replace-list $(res) : "\\\\\\\\" : "/" ] ;
# CONSIDER: the new scoping rule seem to defeat "on target" variables.
local g = [ on $(target) return $(HDRGRIST) ] ;
local b = [ NORMALIZE_PATH $(binding:D) ] ;
# Attach binding of including file to included targets.
# When target is directly created from virtual target
# this extra information is unnecessary. But in other
# cases, it allows to distinguish between two headers of the
# same name included from different places.
# We don't need this extra information for angle includes,
# since they should not depend on including file (we can't
# get literal "." in include path).
local g2 = $(g)"#"$(b) ;
angle = $(angle:G=$(g)) ;
quoted = $(quoted:G=$(g2)) ;
res = $(res:G=$(g2)) ;
local all = $(angle) $(quoted) ;
INCLUDES $(target) : $(all) ;
DEPENDS $(target) : $(res) ;
NOCARE $(all) $(res) ;
SEARCH on $(angle) = $(self.includes:G=) ;
SEARCH on $(quoted) = $(b) $(self.includes:G=) ;
SEARCH on $(res) = $(b) $(self.includes:G=) ;
# Just propagate current scanner to includes, in a hope
# that includes do not change scanners.
scanner.propagate $(__name__) : $(angle) $(quoted) : $(target) ;
}
}
scanner.register res-scanner : include ;
type.set-scanner RC : res-scanner ;