$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r64643 - in trunk/tools/build/v2: build tools util
From: ghost_at_[hidden]
Date: 2010-08-06 11:37:16
Author: vladimir_prus
Date: 2010-08-06 11:37:13 EDT (Fri, 06 Aug 2010)
New Revision: 64643
URL: http://svn.boost.org/trac/boost/changeset/64643
Log:
Port tools/package.py. Fix various bugs.
Added:
   trunk/tools/build/v2/tools/package.py   (contents, props changed)
Text files modified: 
   trunk/tools/build/v2/build/feature.py |    13 ++++++++-----                           
   trunk/tools/build/v2/build/targets.py |     2 +-                                      
   trunk/tools/build/v2/tools/stage.py   |     3 ++-                                     
   trunk/tools/build/v2/util/option.py   |     2 +-                                      
   4 files changed, 12 insertions(+), 8 deletions(-)
Modified: trunk/tools/build/v2/build/feature.py
==============================================================================
--- trunk/tools/build/v2/build/feature.py	(original)
+++ trunk/tools/build/v2/build/feature.py	2010-08-06 11:37:13 EDT (Fri, 06 Aug 2010)
@@ -27,6 +27,7 @@
     def __init__(self, name, values, attributes):
         self._name = name
         self._values = values
+        self._default = None
         self._attributes = 0
         for a in attributes:
             self._attributes = self._attributes | Feature._attribute_name_to_integer[a]
@@ -68,6 +69,7 @@
         Value may be None if this subfeature is not specific to any
         value of the parent feature.
         """
+        return self._parent
 
     def set_parent(self, feature, value):
         self._parent = (feature, value)
@@ -512,9 +514,9 @@
     # First declare the subfeature as a feature in its own right
     f = feature (feature_name + '-' + subfeature_name, subvalues, attributes + ['subfeature'])
     f.set_parent(parent_feature, value_string)
-
-    parent_feature.add_subfeature(f)
     
+    parent_feature.add_subfeature(f)
+
     # Now make sure the subfeature values are known.
     extend_subfeature (feature_name, value_string, subfeature, subvalues)
 
@@ -761,7 +763,7 @@
         if subproperties:
             # reconstitute the joined property name
             subproperties.sort ()
-            joined = Property(p.feature(), p.value() + '-' + '-'.join ([sp.value() for sp in subproperties]))
+            joined = b2.build.property.Property(p.feature(), p.value() + '-' + '-'.join ([sp.value() for sp in subproperties]))
             result.append(joined)
 
             properties = b2.util.set.difference(properties[1:], subproperties)
@@ -843,8 +845,9 @@
                 matched_subs.update(subs)
 
                 subvalues = '-'.join (sub.value() for sub in subs)
-                result.append(Property(p.feature(), p.value + '-' + subvalues,
-                                       p.condition()))
+                result.append(b2.build.property.Property(
+                    p.feature(), p.value() + '-' + subvalues,
+                    p.condition()))
             else:
                 result.append(p)
 
Modified: trunk/tools/build/v2/build/targets.py
==============================================================================
--- trunk/tools/build/v2/build/targets.py	(original)
+++ trunk/tools/build/v2/build/targets.py	2010-08-06 11:37:13 EDT (Fri, 06 Aug 2010)
@@ -831,7 +831,7 @@
     
         for s in sources:
             if get_grist (s):
-                raise InvalidSource ("property '%s' found in the 'sources' parameter for '%s'" (s, name))
+                raise InvalidSource ("property '%s' found in the 'sources' parameter for '%s'" % (s, name))
     
         self.sources_ = sources
         
Added: trunk/tools/build/v2/tools/package.py
==============================================================================
--- (empty file)
+++ trunk/tools/build/v2/tools/package.py	2010-08-06 11:37:13 EDT (Fri, 06 Aug 2010)
@@ -0,0 +1,168 @@
+# Status: ported
+# Base revision: 64488
+#
+# Copyright (c) 2005, 2010 Vladimir Prus.
+# Copyright 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)
+
+# Provides mechanism for installing whole packages into a specific directory
+# structure. This is opposed to the 'install' rule, that installs a number of
+# targets to a single directory, and does not care about directory structure at
+# all.
+
+# Example usage:
+#
+#   package.install boost : <properties>
+#                         : <binaries>
+#                         : <libraries>
+#                         : <headers>
+#                         ;
+#
+# This will install binaries, libraries and headers to the 'proper' location,
+# given by command line options --prefix, --exec-prefix, --bindir, --libdir and
+# --includedir.
+#
+# The rule is just a convenient wrapper, avoiding the need to define several
+# 'install' targets.
+#
+# The only install-related feature is <install-source-root>. It will apply to
+# headers only and if present, paths of headers relatively to source root will
+# be retained after installing. If it is not specified, then "." is assumed, so
+# relative paths in headers are always preserved.
+
+import b2.build.feature as feature
+import b2.build.property as property
+import b2.util.option as option
+import b2.tools.stage as stage
+
+from b2.build.alias import alias
+
+from b2.manager import get_manager
+
+from b2.util import bjam_signature
+from b2.util.utility import ungrist
+
+
+import os
+
+feature.feature("install-default-prefix", [], ["free", "incidental"])
+
+@bjam_signature((["name", "package_name", "?"], ["requirements", "*"],
+                 ["binaries", "*"], ["libraries", "*"], ["headers", "*"]))
+def install(name, package_name=None, requirements=[], binaries=[], libraries=[], headers=[]):
+
+    requirements = requirements[:]
+    binaries = binaries[:]
+    libraries
+
+    if not package_name:
+        package_name = name
+
+    if option.get("prefix"):
+        # If --prefix is explicitly specified on the command line,
+        # then we need wipe away any settings of libdir/includir that
+        # is specified via options in config files.
+        option.set("bindir", None)
+        option.set("libdir", None)
+        option.set("includedir", None)
+            
+    # If <install-source-root> is not specified, all headers are installed to
+    # prefix/include, no matter what their relative path is. Sometimes that is
+    # what is needed.
+    install_source_root = property.select('install-source-root', requirements)
+    if install_source_root:
+        requirements = property.change(requirements, 'install-source-root', None)
+            
+    install_header_subdir = property.select('install-header-subdir', requirements)
+    if install_header_subdir:
+        install_header_subdir = ungrist(install_header_subdir[0])
+        requirements = property.change(requirements, 'install-header-subdir', None)
+
+    # First, figure out all locations. Use the default if no prefix option
+    # given.
+    prefix = get_prefix(name, requirements)
+
+    # Architecture dependent files.
+    exec_locate = option.get("exec-prefix", prefix)
+
+    # Binaries.
+    bin_locate = option.get("bindir", os.path.join(prefix, "bin"))
+
+    # Object code libraries.
+    lib_locate = option.get("libdir", os.path.join(prefix, "lib"))
+
+    # Source header files.
+    include_locate = option.get("includedir", os.path.join(prefix, "include"))
+
+    stage.install(name + "-bin", binaries, requirements + ["<location>" + bin_locate])
+    
+    alias(name + "-lib", [name + "-lib-shared", name + "-lib-static"])
+    
+    # Since the install location of shared libraries differs on universe
+    # and cygwin, use target alternatives to make different targets.
+    # We should have used indirection conditioanl requirements, but it's
+    # awkward to pass bin-locate and lib-locate from there to another rule.
+    alias(name + "-lib-shared", [name + "-lib-shared-universe"])
+    alias(name + "-lib-shared", [name + "-lib-shared-cygwin"], ["<target-os>cygwin"])
+    
+    # For shared libraries, we install both explicitly specified one and the
+    # shared libraries that the installed executables depend on.
+    stage.install(name + "-lib-shared-universe", binaries, libraries,
+                  requirements + ["<location>" + lib_locate, "<install-dependencies>on",
+                                  "<install-type>SHARED_LIB"])
+    stage.install(name + "-lib-shared-cygwin", binaries, libraries,
+                  requirements + ["<location>" + bin_locate, "<install-dependencies>on",
+                                  "<install-type>SHARED_LIB"])
+
+    # For static libraries, we do not care about executable dependencies, since
+    # static libraries are already incorporated into them.
+    stage.install(name + "-lib-static", libraries, requirements +
+                  ["<location>" + lib_locate, "<install-dependencies>on", "<install-type>STATIC_LIB"])
+    stage.install(name + "-headers", headers, requirements \
+                  + ["<location>" + os.path.join(include_locate, s) for s in install_header_subdir]
+                  + install_source_root)
+
+    alias(name, [name + "-bin", name + "-lib", name + "-headers"])
+
+    pt = get_manager().projects().current()
+
+    for subname in ["bin", "lib", "headers", "lib-shared", "lib-static", "lib-shared-universe", "lib-shared-cygwin"]:
+        pt.mark_target_as_explicit(name + "-" + subname)
+
+@bjam_signature((["target_name"], ["package_name"], ["data", "*"], ["requirements", "*"]))
+def install_data(target_name, package_name, data, requirements):
+    if not package_name:
+        package_name = target_name
+
+    if option.get("prefix"):
+        # If --prefix is explicitly specified on the command line,
+        # then we need wipe away any settings of datarootdir
+        option.set("datarootdir", None)
+    
+    prefix = get_prefix(package_name, requirements)
+    datadir = option.get("datarootdir", os.path.join(prefix, "share"))
+
+    stage.install(target_name, data,
+                  requirements + ["<location>" + os.path.join(datadir, package_name)])
+
+    get_manager().projects().current().mark_target_as_explicit(target_name)
+
+def get_prefix(package_name, requirements):
+
+    specified = property.select("install-default-prefix", requirements)
+    if specified:
+        specified = ungrist(specified[0])
+    prefix = option.get("prefix", specified)
+    requirements = property.change(requirements, "install-default-prefix", None)    
+    # Or some likely defaults if neither is given.
+    if not prefix:
+        if os.name == "nt":
+            prefix = "C:\\" + package_name
+        elif os.name == "posix":
+            prefix = "/usr/local"
+
+    return prefix
+
Modified: trunk/tools/build/v2/tools/stage.py
==============================================================================
--- trunk/tools/build/v2/tools/stage.py	(original)
+++ trunk/tools/build/v2/tools/stage.py	2010-08-06 11:37:13 EDT (Fri, 06 Aug 2010)
@@ -322,8 +322,9 @@
 #
 @bjam_signature((["name"], ["sources", "*"], ["requirements", "*"],
                  ["default_build", "*"], ["usage_requirements", "*"]))
-def install(name, sources, requirements, default_build, usage_requirements):
+def install(name, sources, requirements=[], default_build=[], usage_requirements=[]):
 
+    requirements = requirements[:]
     # Unless the user has explicitly asked us to hardcode dll paths, add
     # <hardcode-dll-paths>false in requirements, to override default value.
     if not '<hardcode-dll-paths>true' in requirements:
Modified: trunk/tools/build/v2/util/option.py
==============================================================================
--- trunk/tools/build/v2/util/option.py	(original)
+++ trunk/tools/build/v2/util/option.py	2010-08-06 11:37:13 EDT (Fri, 06 Aug 2010)
@@ -29,7 +29,7 @@
         m = b2.util.regex.transform(sys.argv, "--(" + re.escape(name) + ")")
         if m and implied_value:
             return implied_value
-        elif options.has_key(name):
+        elif options.has_key(name) and options[name] != None:
             return options[name]
         else:
             return default_value