From 3faecf9a00512dcbc8712c4bca9adae72fb64410 Mon Sep 17 00:00:00 2001 From: Kenneth Heafield Date: Sat, 12 May 2012 14:01:52 -0400 Subject: Give in and copy bjam into cdec source code --- jam-files/boost-build/build/type.jam | 425 +++++++++++++++++++++++++++++++++++ 1 file changed, 425 insertions(+) create mode 100644 jam-files/boost-build/build/type.jam (limited to 'jam-files/boost-build/build/type.jam') diff --git a/jam-files/boost-build/build/type.jam b/jam-files/boost-build/build/type.jam new file mode 100644 index 00000000..1a7a5782 --- /dev/null +++ b/jam-files/boost-build/build/type.jam @@ -0,0 +1,425 @@ +# Copyright 2002, 2003 Dave Abrahams +# Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + +# Deals with target type declaration and defines target class which supports +# typed targets. + +import "class" : new ; +import errors ; +import feature ; +import generators : * ; +import project ; +import property ; +import scanner ; +import os ; + +# The following import would create a circular dependency: +# project -> project-root -> builtin -> type -> targets -> project +# import targets ; + +# The feature is optional so it would never get added implicitly. It is used +# only for internal purposes and in all cases we want to use it explicitly. +feature.feature target-type : : composite optional ; + +feature.feature main-target-type : : optional incidental ; +feature.feature base-target-type : : composite optional free ; + + +# Registers a target type, possible derived from a 'base-type'. Providing a list +# of 'suffixes' here is a shortcut for separately calling the register-suffixes +# rule with the given suffixes and the set-generated-target-suffix rule with the +# first given suffix. +# +rule register ( type : suffixes * : base-type ? ) +{ + # Type names cannot contain hyphens, because when used as feature-values + # they would be interpreted as composite features which need to be + # decomposed. + switch $(type) + { + case *-* : errors.error "type name \"$(type)\" contains a hyphen" ; + } + + if $(type) in $(.types) + { + errors.error "Type $(type) is already registered." ; + } + else + { + .types += $(type) ; + .base.$(type) = $(base-type) ; + .derived.$(base-type) += $(type) ; + + if $(suffixes)-is-not-empty + { + # Specify mapping from suffixes to type. + register-suffixes $(suffixes) : $(type) ; + # By default generated targets of 'type' will use the first of + #'suffixes'. This may be overriden. + set-generated-target-suffix $(type) : : $(suffixes[1]) ; + } + + feature.extend target-type : $(type) ; + feature.extend main-target-type : $(type) ; + feature.extend base-target-type : $(type) ; + + feature.compose $(type) : $(base-type:G=) ; + feature.compose $(type) : $(base-type) ; + + # We used to declare the main target rule only when a 'main' parameter + # has been specified. However, it is hard to decide that a type will + # *never* need a main target rule and so from time to time we needed to + # make yet another type 'main'. So now a main target rule is defined for + # each type. + main-rule-name = [ type-to-rule-name $(type) ] ; + .main-target-type.$(main-rule-name) = $(type) ; + IMPORT $(__name__) : main-target-rule : : $(main-rule-name) ; + + # Adding a new derived type affects generator selection so we need to + # make the generator selection module update any of its cached + # information related to a new derived type being defined. + generators.update-cached-information-with-a-new-type $(type) ; + } +} + + +# Given a type, returns the name of the main target rule which creates targets +# of that type. +# +rule type-to-rule-name ( type ) +{ + # Lowercase everything. Convert underscores to dashes. + import regex ; + local n = [ regex.split $(type:L) "_" ] ; + return $(n:J=-) ; +} + + +# Given a main target rule name, returns the type for which it creates targets. +# +rule type-from-rule-name ( rule-name ) +{ + return $(.main-target-type.$(rule-name)) ; +} + + +# Specifies that files with suffix from 'suffixes' be recognized as targets of +# type 'type'. Issues an error if a different type is already specified for any +# of the suffixes. +# +rule register-suffixes ( suffixes + : type ) +{ + for local s in $(suffixes) + { + if ! $(.type.$(s)) + { + .type.$(s) = $(type) ; + } + else if $(.type.$(s)) != $(type) + { + errors.error Attempting to specify multiple types for suffix + \"$(s)\" : "Old type $(.type.$(s)), New type $(type)" ; + } + } +} + + +# Returns true iff type has been registered. +# +rule registered ( type ) +{ + if $(type) in $(.types) + { + return true ; + } +} + + +# Issues an error if 'type' is unknown. +# +rule validate ( type ) +{ + if ! [ registered $(type) ] + { + errors.error "Unknown target type $(type)" ; + } +} + + +# Sets a scanner class that will be used for this 'type'. +# +rule set-scanner ( type : scanner ) +{ + validate $(type) ; + .scanner.$(type) = $(scanner) ; +} + + +# Returns a scanner instance appropriate to 'type' and 'properties'. +# +rule get-scanner ( type : property-set ) +{ + if $(.scanner.$(type)) + { + return [ scanner.get $(.scanner.$(type)) : $(property-set) ] ; + } +} + + +# Returns a base type for the given type or nothing in case the given type is +# not derived. +# +rule base ( type ) +{ + return $(.base.$(type)) ; +} + + +# Returns the given type and all of its base types in order of their distance +# from type. +# +rule all-bases ( type ) +{ + local result = $(type) ; + while $(type) + { + type = [ base $(type) ] ; + result += $(type) ; + } + return $(result) ; +} + + +# Returns the given type and all of its derived types in order of their distance +# from type. +# +rule all-derived ( type ) +{ + local result = $(type) ; + for local d in $(.derived.$(type)) + { + result += [ all-derived $(d) ] ; + } + return $(result) ; +} + + +# Returns true if 'type' is equal to 'base' or has 'base' as its direct or +# indirect base. +# +rule is-derived ( type base ) +{ + if $(base) in [ all-bases $(type) ] + { + return true ; + } +} + +# Returns true if 'type' is either derived from or is equal to 'base'. +# +# TODO: It might be that is-derived and is-subtype were meant to be different +# rules - one returning true for type = base and one not, but as currently +# implemented they are actually the same. Clean this up. +# +rule is-subtype ( type base ) +{ + return [ is-derived $(type) $(base) ] ; +} + + +# Store suffixes for generated targets. +.suffixes = [ new property-map ] ; + +# Store prefixes for generated targets (e.g. "lib" for library). +.prefixes = [ new property-map ] ; + + +# Sets a file suffix to be used when generating a target of 'type' with the +# specified properties. Can be called with no properties if no suffix has +# already been specified for the 'type'. The 'suffix' parameter can be an empty +# string ("") to indicate that no suffix should be used. +# +# Note that this does not cause files with 'suffix' to be automatically +# recognized as being of 'type'. Two different types can use the same suffix for +# their generated files but only one type can be auto-detected for a file with +# that suffix. User should explicitly specify which one using the +# register-suffixes rule. +# +rule set-generated-target-suffix ( type : properties * : suffix ) +{ + set-generated-target-ps suffix : $(type) : $(properties) : $(suffix) ; +} + + +# Change the suffix previously registered for this type/properties combination. +# If suffix is not yet specified, sets it. +# +rule change-generated-target-suffix ( type : properties * : suffix ) +{ + change-generated-target-ps suffix : $(type) : $(properties) : $(suffix) ; +} + + +# Returns the suffix used when generating a file of 'type' with the given +# properties. +# +rule generated-target-suffix ( type : property-set ) +{ + return [ generated-target-ps suffix : $(type) : $(property-set) ] ; +} + + +# Sets a target prefix that should be used when generating targets of 'type' +# with the specified properties. Can be called with empty properties if no +# prefix for 'type' has been specified yet. +# +# The 'prefix' parameter can be empty string ("") to indicate that no prefix +# should be used. +# +# Usage example: library names use the "lib" prefix on unix. +# +rule set-generated-target-prefix ( type : properties * : prefix ) +{ + set-generated-target-ps prefix : $(type) : $(properties) : $(prefix) ; +} + + +# Change the prefix previously registered for this type/properties combination. +# If prefix is not yet specified, sets it. +# +rule change-generated-target-prefix ( type : properties * : prefix ) +{ + change-generated-target-ps prefix : $(type) : $(properties) : $(prefix) ; +} + + +rule generated-target-prefix ( type : property-set ) +{ + return [ generated-target-ps prefix : $(type) : $(property-set) ] ; +} + + +# Common rules for prefix/suffix provisioning follow. + +local rule set-generated-target-ps ( ps : type : properties * : psval ) +{ + properties = $(type) $(properties) ; + $(.$(ps)es).insert $(properties) : $(psval) ; +} + + +local rule change-generated-target-ps ( ps : type : properties * : psval ) +{ + properties = $(type) $(properties) ; + local prev = [ $(.$(ps)es).find-replace $(properties) : $(psval) ] ; + if ! $(prev) + { + set-generated-target-ps $(ps) : $(type) : $(properties) : $(psval) ; + } +} + + +# Returns either prefix or suffix (as indicated by 'ps') that should be used +# when generating a target of 'type' with the specified properties. Parameter +# 'ps' can be either "prefix" or "suffix". If no prefix/suffix is specified for +# 'type', returns prefix/suffix for base type, if any. +# +local rule generated-target-ps-real ( ps : type : properties * ) +{ + local result ; + local found ; + while $(type) && ! $(found) + { + result = [ $(.$(ps)es).find $(type) $(properties) ] ; + # If the prefix/suffix is explicitly set to an empty string, we consider + # prefix/suffix to be found. If we were not to compare with "", there + # would be no way to specify an empty prefix/suffix. + if $(result)-is-not-empty + { + found = true ; + } + type = $(.base.$(type)) ; + } + if $(result) = "" + { + result = ; + } + return $(result) ; +} + + +local rule generated-target-ps ( ps : type : property-set ) +{ + local key = .$(ps).$(type).$(property-set) ; + local v = $($(key)) ; + if ! $(v) + { + v = [ generated-target-ps-real $(ps) : $(type) : [ $(property-set).raw ] + ] ; + if ! $(v) + { + v = none ; + } + $(key) = $(v) ; + } + + if $(v) != none + { + return $(v) ; + } +} + + +# Returns file type given its name. If there are several dots in filename, tries +# each suffix. E.g. for name of "file.so.1.2" suffixes "2", "1", and "so" will +# be tried. +# +rule type ( filename ) +{ + if [ os.name ] in NT CYGWIN + { + filename = $(filename:L) ; + } + local type ; + while ! $(type) && $(filename:S) + { + local suffix = $(filename:S) ; + type = $(.type$(suffix)) ; + filename = $(filename:S=) ; + } + return $(type) ; +} + + +# Rule used to construct all main targets. Note that this rule gets imported +# into the global namespace under different alias names and the exact target +# type to construct is selected based on the alias used to actually invoke this +# rule. +# +rule main-target-rule ( name : sources * : requirements * : default-build * : + usage-requirements * ) +{ + # First discover the required target type based on the exact alias used to + # invoke this rule. + local bt = [ BACKTRACE 1 ] ; + local rulename = $(bt[4]) ; + local target-type = [ type-from-rule-name $(rulename) ] ; + + # This is a circular module dependency and so must be imported here. + import targets ; + + return [ targets.create-typed-target $(target-type) : [ project.current ] : + $(name) : $(sources) : $(requirements) : $(default-build) : + $(usage-requirements) ] ; +} + + +rule __test__ ( ) +{ + import assert ; + + # TODO: Add tests for all the is-derived, is-base & related type relation + # checking rules. +} -- cgit v1.2.3