130 changes: 0 additions & 130 deletions doc/development_plan.html

This file was deleted.

2 changes: 2 additions & 0 deletions doc/jamfile.jam
Expand Up @@ -17,6 +17,8 @@ boostbook userman : src/standalone.xml
<xsl:param>boost.root=..
<xsl:param>boost.graphics.root=../images/
<xsl:param>html.stylesheet=../boostbook.css
<xsl:param>chunk.first.sections=0
<xsl:param>admon.graphics=0

<xsl:param>boost.defaults=Boost
;
Expand Down
36 changes: 23 additions & 13 deletions doc/src/howto.xml
Expand Up @@ -2,33 +2,43 @@
<!DOCTYPE chapter PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">

<chapter id="bbv2.howto">
<dedication id="bbv2.howto">

<title>How to use this document</title>

<para>
If you've just found out about Boost.Build V2 and want to know
if it will work for you, start with <xref linkend=
"bbv2.tutorial" />. You can continue with <xref
linkend="bbv2.overview" />. When you're ready to try Boost.Build
Want to learn about Boost.Build features? Start with <xref linkend=
"bbv2.tutorial"/> and continue with <xref
linkend="bbv2.overview"/>. When you're ready to try Boost.Build
in practice, go to <xref linkend="bbv2.installation"/>.
</para>

<para>
If you are about to use Boost.Build on your project, or already
using it and have a problem, look at <xref linkend=
"bbv2.overview"/>.
Building a project with Boost.Build? See <xref
linkend="bbv2.installation"/> and
then read <xref linkend="bbv2.overview.invocation"/>.
</para>

<para>
If you're trying to build a project which uses Boost.Build,
see <xref linkend="bbv2.installation"/> and then read about
<xref linkend="bbv2.overview.invocation"/>.
Setting up Boost.Build on your project? Take a look at <xref
linkend="bbv2.overview"/> and <xref linkend="bbv2.extender"/>.
</para>

<para>
If you have questions, please post them to our mailing list (<ulink
If there's anything you find unclear in this documentation, report the
problem directly in the <ulink
url="https://github.com/boostorg/build/issues">issue tracker</ulink>.
For more general questions, please post them to our mailing list (<ulink
url="http://boost.org/more/mailing_lists.htm#jamboost"/>). The mailing list is
also mirrored to the newsgroup <ulink url="news://news.gmane.org/gmane.comp.lib.boost.build"/>.
</para>

</chapter>
<para role="copyright">
Copyright 2006, 2014 <ulink url="http://vladimirprus.com">Vladimir
Prus</ulink>. Distributed under the Boost Software License, Version 1.0.
(See accompanying file <filename>LICENSE_1_0.txt</filename> or copy at
<ulink
url="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</ulink>)
</para>

</dedication>
2 changes: 1 addition & 1 deletion doc/src/overview.xml
Expand Up @@ -775,7 +775,7 @@ b2 toolset=gcc variant=debug optimization=space
<varlistentry>
<term><option>-d0</option></term>
<listitem>
<para>Supress all informational messages.</para>
<para>Suppress all informational messages.</para>
</listitem>
</varlistentry>

Expand Down
2 changes: 1 addition & 1 deletion doc/src/reference.xml
Expand Up @@ -1199,7 +1199,7 @@ using msvc : &toolset_ops; ;
with the ARM architecture:
</para>
<programlisting>
.\b2 toolset=msvc=12.0 windows-api=store architecture=arm</programlisting>
.\b2 toolset=msvc-12.0 windows-api=store architecture=arm</programlisting>

<para>
Note that when targeting Windows Phone 8.1, version 12.0 didn't
Expand Down
18 changes: 0 additions & 18 deletions doc/src/standalone.xml
Expand Up @@ -4,24 +4,6 @@

<book xmlns:xi="http://www.w3.org/2001/XInclude"
id="bbv2" last-revision="$Date$">
<bookinfo>
<copyright>
<year>2006</year>
<year>2007</year>
<year>2008</year>
<year>2009</year>
<year>2014</year>
<holder>Vladimir Prus</holder>
</copyright>

<legalnotice>
<para>Distributed under the Boost Software License, Version 1.0.
(See accompanying file <filename>LICENSE_1_0.txt</filename> or copy at
<ulink
url="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</ulink>)
</para>
</legalnotice>
</bookinfo>

<title>Boost.Build User Manual</title>

Expand Down
4 changes: 2 additions & 2 deletions doc/src/tutorial.xml
Expand Up @@ -17,8 +17,8 @@
-->

<para>
This section will guide you though the most basic features of Boost.Build
V2. We will start with the &#x201C;Hello, world&#x201D; example, learn how
This section will guide you though the most basic features of Boost.Build.
We will start with the &#x201C;Hello, world&#x201D; example, learn how
to use libraries, and finish with testing and installing features.
</para>

Expand Down
18 changes: 0 additions & 18 deletions doc/src/userman.xml
Expand Up @@ -4,24 +4,6 @@

<part xmlns:xi="http://www.w3.org/2001/XInclude"
id="bbv2" last-revision="$Date$">
<partinfo>
<copyright>
<year>2006</year>
<year>2007</year>
<year>2008</year>
<year>2009</year>
<year>2014</year>
<holder>Vladimir Prus</holder>
</copyright>

<legalnotice>
<para>Distributed under the Boost Software License, Version 1.0.
(See accompanying file <filename>LICENSE_1_0.txt</filename> or copy at
<ulink
url="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</ulink>)
</para>
</legalnotice>
</partinfo>

<title>Boost.Build User Manual</title>

Expand Down
92 changes: 0 additions & 92 deletions doc/tools.html

This file was deleted.

1 change: 1 addition & 0 deletions index.html
Expand Up @@ -24,6 +24,7 @@
height="60" alt="Boost.Build V2"></img>

<div style="padding-top: 10px; width: 100%; text-align: right">
<a href="tutorial.html" style="padding-right: 1em">Tutorial</a>
<a href="doc/html/index.html" style="padding-right: 1em">Documentation</a> <a href="http://github.com/boostorg/build">GitHub</a>
</div>
</div>
Expand Down
34 changes: 34 additions & 0 deletions scripts/build-docs.sh
@@ -0,0 +1,34 @@
#!/bin/bash

# Copyright 2014 Vladimir Prus
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)

set -e

# Build the documentation
touch doc/jamroot.jam
export BOOST_BUILD_PATH=`pwd`
export BOOST_ROOT=/home/ghost/Sources/boost
./bootstrap.sh
cd doc
../b2

find . -type f -iname "*.html" | while read i; do
echo "Processing: $i"
sed -i "s#</body>#\
<script>\n\
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){\n\
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),\n\
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)\n\
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');\n\
\n\
ga('create', 'UA-2917240-2', 'auto');\n\
ga('send', 'pageview');\n\
\n\
</script>\n\
</body>#g" "$i"

done

1 change: 1 addition & 0 deletions src/build/feature.jam
Expand Up @@ -30,6 +30,7 @@ local rule setup ( )
link-incompatible
subfeature
order-sensitive
hidden
;

.all-features = ;
Expand Down
6 changes: 3 additions & 3 deletions src/build/feature.py
Expand Up @@ -196,12 +196,12 @@ def set_default (feature, value):
bad_attribute = "free"
elif attributes & Feature.OPTIONAL:
bad_attribute = "optional"

if bad_attribute:
raise InvalidValue ("%s property %s cannot have a default" % (bad_attribute, feature.name()))

if not value in f.values():
raise InvalidValue ("The specified default value, '%s' is invalid.\n" % value + "allowed values are: %s" % values)
raise InvalidValue ("The specified default value, '%s' is invalid.\n" % value + "allowed values are: %s" % f.values())

f.set_default(value)

Expand Down
49 changes: 34 additions & 15 deletions src/build/project.jam
Expand Up @@ -50,7 +50,7 @@ import sequence ;
# Jamfile at that location is loaded already, does nothing. Returns the project
# module for the Jamfile.
#
rule load ( jamfile-location )
rule load ( jamfile-location : synthesize ? )
{
local module-name = [ module-name $(jamfile-location) ] ;
# If Jamfile is already loaded, do not try again.
Expand All @@ -61,7 +61,7 @@ rule load ( jamfile-location )
ECHO Loading Jamfile at '$(jamfile-location)' ;
}

load-jamfile $(jamfile-location) : $(module-name) ;
load-jamfile $(jamfile-location) : $(module-name) : $(synthesize) ;

# We want to make sure that child project are loaded only after parent
# projects. In particular, because parent projects define attributes
Expand Down Expand Up @@ -270,14 +270,14 @@ rule find-jamfile (
# the file as indicated by the JAMFILE patterns. Effect of calling this rule
# twice with the same 'dir' is undefined.
#
local rule load-jamfile ( dir : jamfile-module )
local rule load-jamfile ( dir : jamfile-module : synthesize ? )
{
# See if the Jamfile is where it should be.
#
local jamfile-to-load = [ path.glob $(dir) : $(JAMROOT) ] ;
if ! $(jamfile-to-load)
{
jamfile-to-load = [ find-jamfile $(dir) ] ;
jamfile-to-load = [ find-jamfile $(dir) : $(synthesize) ] ;
}

if $(jamfile-to-load[2])
Expand All @@ -286,6 +286,11 @@ local rule load-jamfile ( dir : jamfile-module )
errors.error "Multiple Jamfiles found at '$(dir)'" :
"Filenames are: " $(jamfile-to-load:D=) ;
}

if ! $(jamfile-to-load) && $(synthesize)
{
jamfile-to-load = $(dir)/@ ;
}

# Now load the Jamfile in its own context.
# The call to 'initialize' may load the parent Jamfile, which might contain
Expand All @@ -307,14 +312,24 @@ local rule load-jamfile ( dir : jamfile-module )
local saved-project = $(.current-project) ;

mark-as-user $(jamfile-module) ;
modules.load $(jamfile-module) : [ path.native $(jamfile-to-load) ]
: . ;
if [ MATCH ^($(JAMROOT))$ : $(jamfile-to-load:BS) ]
if $(jamfile-to-load:B) = "@"
{
jamfile = [ find-jamfile $(dir) : no-errors ] ;
if $(jamfile)
# Not a real jamfile to load. Synthsize the load.
modules.poke $(jamfile-module) : __name__ : $(jamfile-module) ;
modules.poke $(jamfile-module) : __file__ : [ path.native $(jamfile-to-load) ] ;
modules.poke $(jamfile-module) : __binding__ : [ path.native $(jamfile-to-load) ] ;
}
else
{
modules.load $(jamfile-module) : [ path.native $(jamfile-to-load) ]
: . ;
if [ MATCH ^($(JAMROOT))$ : $(jamfile-to-load:BS) ]
{
load-aux $(jamfile-module) : [ path.native $(jamfile) ] ;
jamfile = [ find-jamfile $(dir) : no-errors ] ;
if $(jamfile)
{
load-aux $(jamfile-module) : [ path.native $(jamfile) ] ;
}
}
}

Expand Down Expand Up @@ -902,7 +917,7 @@ rule target ( project-module )
# extensions are really projects, they can be initialized as a module would be
# with the "using" (project.project-rules.using) mechanism.
#
rule extension ( id : options * : * )
rule extension ( id space ? : options * : * )
{
# The caller is a standalone module for the extension.
local mod = [ CALLER_MODULE ] ;
Expand All @@ -921,15 +936,19 @@ rule extension ( id : options * : * )
{
root-project = [ project.attribute $(root-project) parent-module ] ;
}

# Default to creating extensions in /ext/.. project space.
local id = $(1[1]) ;
local space = $(1[2]) ;
space ?= ext ;

# Create the project data, and bring in the project rules into the
# module.
project.initialize $(__name__) : [ path.join [ project.attribute
$(root-project) location ] ext $(1:L) ] ;
$(root-project) location ] $(space:L) $(id:L) ] ;

# Create the project itself, i.e. the attributes. All extensions are
# created in the "/ext" project space.
project /ext/$(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) :
# Create the project itself, i.e. the attributes.
project /$(space:L)/$(id:L) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) :
$(9) : $(10) : $(11) : $(12) : $(13) : $(14) : $(15) : $(16) : $(17)
: $(18) : $(19) ;
local attributes = [ project.attributes $(__name__) ] ;
Expand Down
11 changes: 7 additions & 4 deletions src/build/property.jam
Expand Up @@ -237,12 +237,15 @@ rule as-path ( properties * )
local components ;
for local p in $(properties)
{
if $(p:G)
if ! hidden in [ feature.attributes $(p:G) ]
{
local f = [ utility.ungrist $(p:G) ] ;
p = $(f)-$(p:G=) ;
if $(p:G)
{
local f = [ utility.ungrist $(p:G) ] ;
p = $(f)-$(p:G=) ;
}
components += [ $(.abbrev) $(p) ] ;
}
components += [ $(.abbrev) $(p) ] ;
}

$(entry) = $(components:J=/) ;
Expand Down
24 changes: 18 additions & 6 deletions src/build/property.py
@@ -1,4 +1,4 @@
# Status: ported, except for tests and --abbreviate-paths.
# Status: ported, except for tests.
# Base revision: 64070
#
# Copyright 2001, 2002, 2003 Dave Abrahams
Expand All @@ -8,6 +8,7 @@
# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)

import re
import sys
from b2.util.utility import *
from b2.build import feature
from b2.util import sequence, qualify_jam_action
Expand All @@ -25,6 +26,8 @@
__not_applicable_feature='not-applicable-in-this-context'
feature.feature(__not_applicable_feature, [], ['free'])

__abbreviated_paths = False

class Property(object):

__slots__ = ('_feature', '_value', '_condition')
Expand Down Expand Up @@ -62,9 +65,9 @@ def __hash__(self):
return hash((self._feature, self._value, tuple(self._condition)))

def __cmp__(self, other):
return cmp((self._feature, self._value, self._condition),
(other._feature, other._value, other._condition))
return cmp((self._feature.name(), self._value, self._condition),
(other._feature.name(), other._value, other._condition))


def create_from_string(s, allow_condition=False,allow_missing_value=False):

Expand Down Expand Up @@ -130,10 +133,19 @@ def reset ():

# A cache of results from as_path
__results = {}

reset ()



def set_abbreviated_paths(on=True):
global __abbreviated_paths
__abbreviated_paths = on


def get_abbreviated_paths():
return __abbreviated_paths or '--abbreviated-paths' in sys.argv


def path_order (x, y):
""" Helper for as_path, below. Orders properties with the implicit ones
first, and within the two sections in alphabetical order of feature
Expand Down
10 changes: 7 additions & 3 deletions src/build/property_set.py
Expand Up @@ -12,9 +12,10 @@
import property, feature
import b2.build.feature
from b2.exceptions import *
from b2.build.property import get_abbreviated_paths
from b2.util.sequence import unique
from b2.util.set import difference
from b2.util import cached
from b2.util import cached, abbreviate_dashed

from b2.manager import get_manager

Expand All @@ -41,7 +42,7 @@ def create (raw_properties = []):
else:
x = [property.create_from_string(ps) for ps in raw_properties]
x.sort()
x = unique (x)
x = unique(x, stable=True)

# FIXME: can we do better, e.g. by directly computing
# hash value of the list?
Expand Down Expand Up @@ -350,7 +351,10 @@ def path_order (p1, p2):
if p.feature().implicit():
components.append(p.value())
else:
components.append(p.feature().name() + "-" + p.value())
value = p.feature().name() + "-" + p.value()
if property.get_abbreviated_paths():
value = abbreviate_dashed(value)
components.append(value)

self.as_path_ = '/'.join (components)

Expand Down
38 changes: 38 additions & 0 deletions src/build/version.py
@@ -0,0 +1,38 @@
import os
import sys

import bjam


from b2.manager import get_manager


MANAGER = get_manager()
ERROR_HANDLER = MANAGER.errors()

_major = "2014"
_minor = "03"


def boost_build():
return "{}.{}-svn".format(_major, _minor)


def verify_engine_version():
major, minor, _ = v = bjam.variable('JAM_VERSION')
if major != _major or minor != _minor:
from textwrap import dedent
engine = sys.argv[0]
core = os.path.dirname(os.path.dirname(__file__))
print dedent("""\
warning: mismatched version of Boost.Build engine core
warning: Boost.Build engine "{}" is "{}"
warning: Boost.Build core at {} is {}
""".format(engine, '.'.join(v), core, boost_build()))
return False
return True


def report():
if verify_engine_version():
print "Boost.Build " + boost_build()
8 changes: 6 additions & 2 deletions src/build/virtual-target.jam
Expand Up @@ -432,6 +432,10 @@ class abstract-file-target : virtual-target
{
ps = [ property-set.empty ] ;
}

# Add this target object for use in getting additional information
# when tagging.
ps = [ property-set.create [ $(ps).raw ] <target>$(__name__) ] ;

local tag = [ $(ps).get <tag> ] ;

Expand Down Expand Up @@ -1092,7 +1096,7 @@ rule register-actual-name ( actual-name : virtual-target )
errors.user-error "Name clash for '$(actual-name)'"
: ""
: "Tried to build the target twice, with property sets having "
: "these incompabile properties:"
: "these incompatible properties:"
: ""
: " - " $(properties-removed)
: " - " $(properties-added)
Expand Down Expand Up @@ -1285,7 +1289,7 @@ class subvariant

# Returns the properties specifying implicit include paths to generated
# headers. This traverses all targets in this subvariant and subvariants
# referred by <implicit-dependecy> properties. For all targets of type
# referred by <implicit-dependency> properties. For all targets of type
# 'target-type' (or for all targets, if 'target-type' is not specified), the
# result will contain <$(feature)>path-to-that-target.
#
Expand Down
4 changes: 2 additions & 2 deletions src/build_system.py
Expand Up @@ -455,7 +455,7 @@ def main_real():
import b2.build.configure as configure

if "--version" in sys.argv:

from b2.build import version
version.report()
return

Expand Down Expand Up @@ -804,7 +804,7 @@ def main_real():

j = option.get("jobs")
if j:
bjam.call("set-variable", PARALLELISM, j)
bjam.call("set-variable", 'PARALLELISM', j)

k = option.get("keep-going", "true", "true")
if k in ["on", "yes", "true"]:
Expand Down
2 changes: 1 addition & 1 deletion src/contrib/boost.py
Expand Up @@ -271,7 +271,7 @@ def tag_maybe(param):
def tag_system(name, type, prop_set):
return common.format_name(['<base>'] + tag_maybe(__build_id), name, type, prop_set)

def tag_system(name, type, prop_set):
def tag_tagged(name, type, prop_set):
return common.format_name(['<base>', '<threading>', '<runtime>'] + tag_maybe(__build_id), name, type, prop_set)

def tag_versioned(name, type, prop_set):
Expand Down
141 changes: 141 additions & 0 deletions src/contrib/modular.jam
@@ -0,0 +1,141 @@
# Copyright Rene Rivera 2015
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)

#alias library
# :
# : : : <include>include
# ;

import path ;
import project ;
import modules ;
import regex ;

rule find ( target-refs + )
{
process-args ;

local caller-mod = [ CALLER_MODULE ] ;
local caller-dir = [ modules.peek $(caller-mod) : __file__ ] ;
caller-dir = $(caller-dir:D) ;
caller-dir = [ path.root $(caller-dir) [ path.pwd ] ] ;

for local target-ref in $(target-refs)
{
local ref = [ MATCH ^(.*)//.* : $(target-ref:G=) ] ;
local search-prefix ;
local search-sub ;
for local prefix in $(.search-path-prefix)
{
if ! $(search-prefix)
{
local search-match = [ MATCH ^($(prefix))/(.*)$ : $(ref) ] ;
search-prefix = $(search-match[1]) ;
search-sub = $(search-match[2]) ;
}
}
local found = [ path.glob $(.search-path.$(search-prefix)) : $(search-sub) ] ;
found = $(found[1]) ;
if $(found)
{
local lib-ref = [ regex.split $(search-sub) / ] ;
lib-ref = $(search-prefix)/$(lib-ref[1]) ;
local lib-path = [ path.relative-to $(caller-dir) $(found) ] ;
library $(lib-ref) $(caller-mod) : $(lib-path) ;
}
}

return $(target-refs) ;
}

rule library ( name caller-module ? : root )
{
process-args ;

# Dir path of caller to base paths from.
caller-module ?= [ CALLER_MODULE ] ;
local caller-dir = [ modules.peek $(caller-module) : __file__ ] ;
caller-dir = $(caller-dir:D) ;

# Find the various parts of the library.
local lib-dir = [ path.root [ path.root $(root) $(caller-dir) ] [ path.pwd ] ] ;
local lib-contents = [ path.glob $(lib-dir) : "include" "build" ] ;
lib-contents = $(lib-contents:D=) ;
# "include" dir for library..
local include-dir ;
if "include" in $(lib-contents)
{
include-dir = include ;
}

# Does it look like a library?
if $(include-dir)
{
# Load/create/declare library project.
local lib-module = [ project.find $(root) : $(caller-dir) ] ;
if ! $(lib-module)
{
lib-module = [ project.load
[ path.root [ path.make $(root) ] $(caller-dir) ] : synthesize ] ;
}
local lib-target = [ project.target $(lib-module) ] ;

# We move to the library project module to define the various
# targets others use for the library.
if ! [ modules.peek $(lib-module) : __library__ ]
{
modules.poke $(lib-module) : __library__ : $(name) ;
project.push-current $(lib-target) ;

# Declare the library alias.
modules.call-in $(lib-module) : alias library
: # Sources
: # Requirements
: # Default Build
: # Usage Requirements
<include>$(include-dir)
;

project.pop-current ;
}

# Declare project alternate ID.
modules.call-in $(caller-module) : use-project $(name) : $(root) ;
}
}

# Add a location, i.e. directory, where to search for libraries.
# The optional 'prefix' indicates which rooted-prefixes the new
# search dir applies to. The prefix defaults to '/'.
rule add-location ( dir prefix ? : base-dir ? )
{
process-args ;

prefix ?= "/" ;

# Dir path of caller to base paths from.
caller-module ?= [ CALLER_MODULE ] ;
local caller-dir = [ modules.peek $(caller-module) : __file__ ] ;
caller-dir = $(caller-dir:D) ;

base-dir ?= $(caller-dir) ;

.search-path-prefix += $(prefix) ;
.search-path.$(prefix) += [ path.root [ path.root $(dir) $(base-dir) ] [ path.pwd ] ] ;
}

local rule process-args ( )
{
if ! $(.did-process-args)
{
.did-process-args = yes ;
local argv = [ modules.peek : ARGV ] ;
local dirs = [ MATCH ^--modular-search-dir=(.*)$ : $(argv) ] ;
for local dir in $(dirs)
{
add-location $(dir) : [ path.pwd ] ;
}
}
}
12 changes: 12 additions & 0 deletions src/engine/Jambase
Expand Up @@ -855,6 +855,18 @@ else if $(OS) = BEOS
NOARSCAN ?= true ;
STDHDRS ?= /boot/develop/headers/posix ;
}
else if $(OS) = HAIKU
{
BINDIR ?= /boot/system/non-packaged/bin ;
CC ?= gcc ;
C++ ?= $(CC) ;
FORTRAN ?= "" ;
LIBDIR ?= /boot/system/non-packaged/lib ;
LINK ?= gcc ;
LINKLIBS ?= -lnetwork ;
NOARSCAN ?= true ;
STDHDRS ?= /boot/system/develop/headers/posix ;
}
else if $(UNIX)
{
switch $(OS)
Expand Down
9 changes: 7 additions & 2 deletions src/engine/boehm_gc/dyn_load.c
Expand Up @@ -64,7 +64,7 @@ static int (*GC_has_static_roots)(const char *, void *, size_t);
!defined(AIX) && !defined(SCO_ELF) && !defined(DGUX) && \
!(defined(FREEBSD) && defined(__ELF__)) && \
!(defined(NETBSD) && defined(__ELF__)) && !defined(HURD) && \
!defined(DARWIN) && !defined(CYGWIN32)
!defined(DARWIN) && !defined(CYGWIN32) && !defined(HAIKU)
--> We only know how to find data segments of dynamic libraries for the
--> above. Additional SVR4 variants might not be too
--> hard to add.
Expand All @@ -82,6 +82,10 @@ static int (*GC_has_static_roots)(const char *, void *, size_t);
# define ELFSIZE ARCH_ELFSIZE
#endif

#if defined(HAIKU)
// purposefully empty
#endif

#if defined(LINUX) && defined(__ELF__) || defined(SCO_ELF) || \
(defined(FREEBSD) && defined(__ELF__)) || defined(DGUX) || \
(defined(NETBSD) && defined(__ELF__)) || defined(HURD)
Expand Down Expand Up @@ -216,7 +220,8 @@ void GC_register_dynamic_libraries()

#if defined(LINUX) && defined(__ELF__) || defined(SCO_ELF) || \
(defined(FREEBSD) && defined(__ELF__)) || defined(DGUX) || \
(defined(NETBSD) && defined(__ELF__)) || defined(HURD)
(defined(NETBSD) && defined(__ELF__)) || defined(HURD) \
defined(HAIKU)


#ifdef USE_PROC_FOR_LIBRARIES
Expand Down
2 changes: 1 addition & 1 deletion src/engine/boehm_gc/include/gc.h
Expand Up @@ -494,7 +494,7 @@ GC_API void * GC_malloc_atomic_ignore_off_page(size_t lb);
/* of compilers. */
/* This may also be desirable if it is possible but expensive to */
/* retrieve the call chain. */
#if (defined(__linux__) || defined(__NetBSD__) || defined(__OpenBSD__) \
#if (defined(__linux__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__HAIKU__) \
|| defined(__FreeBSD__) || defined(__DragonFly__)) & !defined(GC_CAN_SAVE_CALL_STACKS)
# define GC_ADD_CALLER
# if __GNUC__ >= 3 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
Expand Down
5 changes: 3 additions & 2 deletions src/engine/boehm_gc/include/gc_config_macros.h
Expand Up @@ -45,7 +45,8 @@
|| defined(GC_AIX_THREADS) \
|| defined(GC_LINUX_THREADS) \
|| defined(GC_NETBSD_THREADS) \
|| defined(GC_GNU_THREADS))
|| defined(GC_GNU_THREADS) \
|| defined(GC_HAIKU_THREADS))
# define _REENTRANT
/* Better late than never. This fails if system headers that */
/* depend on this were previously included. */
Expand All @@ -65,7 +66,7 @@
defined(GC_DGUX386_THREADS) || defined(GC_DARWIN_THREADS) || \
defined(GC_AIX_THREADS) || defined(GC_NETBSD_THREADS) || \
(defined(GC_WIN32_THREADS) && defined(__CYGWIN32__)) || \
defined(GC_GNU_THREADS)
defined(GC_GNU_THREADS) || defined(GC_HAIKU_THREADS)
# define GC_PTHREADS
# endif

Expand Down
11 changes: 11 additions & 0 deletions src/engine/boehm_gc/include/private/gcconfig.h
Expand Up @@ -215,6 +215,10 @@
# define BEOS
# define mach_type_known
# endif
# if defined(__HAIKU__) && defined(_X86_)
# define I386
# define HAIKU
# define mach_type_known
# if defined(LINUX) && (defined(i386) || defined(__i386__))
# define I386
# define mach_type_known
Expand Down Expand Up @@ -1014,6 +1018,13 @@
extern int etext[];
# define DATASTART ((ptr_t)((((word) (etext)) + 0xfff) & ~0xfff))
# endif
# ifdef HAIKU
# define OS_TYPE "HAIKU"
# include <OS.h>
# define GETPAGESIZE() B_PAGE_SIZE
# extern int etext[];
# define DATASTART ((ptr_t)((((word) (etext)) + 0xfff) & ~0xfff))
# endif
# ifdef SOLARIS
# define OS_TYPE "SOLARIS"
extern int _etext[], _end[];
Expand Down
15 changes: 13 additions & 2 deletions src/engine/boehm_gc/os_dep.c
Expand Up @@ -777,6 +777,17 @@ ptr_t GC_get_main_stack_base(void){
# endif /* BEOS */


# ifdef HAIKU
# include <OS.h>
ptr_t GC_get_main_stack_base(void)
{
thread_info th;
get_thread_info(find_thread(NULL), &th);
return th.stack_end;
}
# endif


# ifdef OS2

ptr_t GC_get_main_stack_base(void)
Expand Down Expand Up @@ -1097,7 +1108,7 @@ ptr_t GC_get_main_stack_base(void)

#if !defined(BEOS) && !defined(AMIGA) && !defined(MSWIN32) \
&& !defined(MSWINCE) && !defined(OS2) && !defined(NOSYS) && !defined(ECOS) \
&& !defined(CYGWIN32)
&& !defined(CYGWIN32) && !defined(HAIKU)

ptr_t GC_get_main_stack_base(void)
{
Expand Down Expand Up @@ -1154,7 +1165,7 @@ ptr_t GC_get_main_stack_base(void)
# endif /* STACKBOTTOM */
}

# endif /* ! AMIGA, !OS 2, ! MS Windows, !BEOS, !NOSYS, !ECOS */
# endif /* ! AMIGA, !OS 2, ! MS Windows, !BEOS, !NOSYS, !ECOS, !HAIKU */

#if defined(GC_LINUX_THREADS) && !defined(HAVE_GET_STACK_BASE)

Expand Down
1 change: 1 addition & 0 deletions src/engine/build.bat
Expand Up @@ -613,3 +613,4 @@ goto Set_Args
:Skip_Jam

:Finish
exit /b %ERRORLEVEL%
37 changes: 25 additions & 12 deletions src/engine/build.sh
Expand Up @@ -142,16 +142,27 @@ case $BOOST_JAM_TOOLSET in
;;

intel-linux)
if test -r /opt/intel/cc/9.0/bin/iccvars.sh ; then
BOOST_JAM_TOOLSET_ROOT=/opt/intel/cc/9.0/
elif test -r /opt/intel_cc_80/bin/iccvars.sh ; then
BOOST_JAM_TOOLSET_ROOT=/opt/intel_cc_80/
elif test -r /opt/intel/compiler70/ia32/bin/iccvars.sh ; then
BOOST_JAM_TOOLSET_ROOT=/opt/intel/compiler70/ia32/
elif test -r /opt/intel/compiler60/ia32/bin/iccvars.sh ; then
BOOST_JAM_TOOLSET_ROOT=/opt/intel/compiler60/ia32/
elif test -r /opt/intel/compiler50/ia32/bin/iccvars.sh ; then
BOOST_JAM_TOOLSET_ROOT=/opt/intel/compiler50/ia32/
which icc >/dev/null 2>&1
if test $? ; then
BOOST_JAM_CC=$(which icc)
echo "Found $BOOST_JAM_CC in environment"
BOOST_JAM_TOOLSET_ROOT=$(echo $BOOST_JAM_CC | sed -e 's/bin.*\/icc//')
# probably the most widespread
ARCH=intel64
else
echo "No intel compiler in current path"
echo "Look in a few old place for legacy reason"
if test -r /opt/intel/cc/9.0/bin/iccvars.sh ; then
BOOST_JAM_TOOLSET_ROOT=/opt/intel/cc/9.0/
elif test -r /opt/intel_cc_80/bin/iccvars.sh ; then
BOOST_JAM_TOOLSET_ROOT=/opt/intel_cc_80/
elif test -r /opt/intel/compiler70/ia32/bin/iccvars.sh ; then
BOOST_JAM_TOOLSET_ROOT=/opt/intel/compiler70/ia32/
elif test -r /opt/intel/compiler60/ia32/bin/iccvars.sh ; then
BOOST_JAM_TOOLSET_ROOT=/opt/intel/compiler60/ia32/
elif test -r /opt/intel/compiler50/ia32/bin/iccvars.sh ; then
BOOST_JAM_TOOLSET_ROOT=/opt/intel/compiler50/ia32/
fi
fi
if test -r ${BOOST_JAM_TOOLSET_ROOT}bin/iccvars.sh ; then
# iccvars does not change LD_RUN_PATH. We adjust LD_RUN_PATH here in
Expand All @@ -164,9 +175,11 @@ case $BOOST_JAM_TOOLSET in
LD_RUN_PATH="${BOOST_JAM_TOOLSET_ROOT}lib:${LD_RUN_PATH}"
fi
export LD_RUN_PATH
. ${BOOST_JAM_TOOLSET_ROOT}bin/iccvars.sh
. ${BOOST_JAM_TOOLSET_ROOT}bin/iccvars.sh $ARCH
fi
if test -z "$BOOST_JAM_CC" ; then
BOOST_JAM_CC=icc
fi
BOOST_JAM_CC=icc
;;

vacpp)
Expand Down
5 changes: 3 additions & 2 deletions src/engine/builtins.c
Expand Up @@ -759,8 +759,9 @@ static int has_wildcards( char const * const str )

static LIST * append_if_exists( LIST * list, OBJECT * file )
{
return file_query( file )
? list_push_back( list, object_copy( file ) )
file_info_t * info = file_query( file );
return info
? list_push_back( list, object_copy( info->name ) )
: list ;
}

Expand Down
44 changes: 42 additions & 2 deletions src/engine/execunix.c
Expand Up @@ -137,6 +137,9 @@ void exec_cmd
LIST * shell
)
{
struct sigaction ignore, saveintr, savequit;
sigset_t chldmask, savemask;

int const slot = get_free_cmdtab_slot();
int out[ 2 ];
int err[ 2 ];
Expand Down Expand Up @@ -203,6 +206,21 @@ void exec_cmd
if ( globs.pipe_action )
fcntl( err[ EXECCMD_PIPE_READ ], F_SETFD, FD_CLOEXEC );

/* ignore SIGINT and SIGQUIT */
ignore.sa_handler = SIG_IGN;
sigemptyset(&ignore.sa_mask);
ignore.sa_flags = 0;
if (sigaction(SIGINT, &ignore, &saveintr) < 0)
return;
if (sigaction(SIGQUIT, &ignore, &savequit) < 0)
return;

/* block SIGCHLD */
sigemptyset(&chldmask);
sigaddset(&chldmask, SIGCHLD);
if (sigprocmask(SIG_BLOCK, &chldmask, &savemask) < 0)
return;

if ( ( cmdtab[ slot ].pid = vfork() ) == -1 )
{
perror( "vfork" );
Expand All @@ -216,6 +234,11 @@ void exec_cmd
/*****************/
int const pid = getpid();

/* restore previous signals */
sigaction(SIGINT, &saveintr, NULL);
sigaction(SIGQUIT, &savequit, NULL);
sigprocmask(SIG_SETMASK, &savemask, NULL);

/* Redirect stdout and stderr to pipes inherited from the parent. */
dup2( out[ EXECCMD_PIPE_WRITE ], STDOUT_FILENO );
dup2( globs.pipe_action ? err[ EXECCMD_PIPE_WRITE ] :
Expand All @@ -236,7 +259,10 @@ void exec_cmd
r_limit.rlim_max = globs.timeout;
setrlimit( RLIMIT_CPU, &r_limit );
}
setpgid( pid, pid );
if (0 != setpgid( pid, pid )) {
perror("setpgid(child)");
/* exit( EXITBAD ); */
}
execvp( argv[ 0 ], (char * *)argv );
perror( "execvp" );
_exit( 127 );
Expand All @@ -245,7 +271,9 @@ void exec_cmd
/******************/
/* Parent process */
/******************/
setpgid( cmdtab[ slot ].pid, cmdtab[ slot ].pid );

/* redundant call, ignore return value */
setpgid(cmdtab[ slot ].pid, cmdtab[ slot ].pid);

/* Parent not need the write pipe ends used by the child. */
close( out[ EXECCMD_PIPE_WRITE ] );
Expand Down Expand Up @@ -281,6 +309,11 @@ void exec_cmd
/* Save input data into the selected running commands table slot. */
cmdtab[ slot ].func = func;
cmdtab[ slot ].closure = closure;

/* restore previous signals */
sigaction(SIGINT, &saveintr, NULL);
sigaction(SIGQUIT, &savequit, NULL);
sigprocmask(SIG_SETMASK, &savemask, NULL);
}

#undef EXECCMD_PIPE_READ
Expand Down Expand Up @@ -448,10 +481,17 @@ void exec_wait()

/* select() will wait for I/O on a descriptor, a signal, or timeout. */
{
/* disable child termination signals while in select */
int ret;
sigset_t sigmask;
sigemptyset(&sigmask);
sigaddset(&sigmask, SIGCHLD);
sigprocmask(SIG_BLOCK, &sigmask, NULL);
while ( ( ret = select( fd_max + 1, &fds, 0, 0, ptv ) ) == -1 )
if ( errno != EINTR )
break;
/* restore original signal mask by unblocking sigchld */
sigprocmask(SIG_UNBLOCK, &sigmask, NULL);
if ( ret <= 0 )
continue;
}
Expand Down
5 changes: 4 additions & 1 deletion src/engine/fileunix.c
Expand Up @@ -80,7 +80,10 @@ struct ar_hdr /* archive file member header - printable ascii */
};
#endif

#if defined( OS_QNX ) || defined( OS_BEOS ) || defined( OS_MPEIX )
#if defined( OS_QNX ) || \
defined( OS_BEOS ) || \
defined( OS_HAIKU ) || \
defined( OS_MPEIX )
# define NO_AR
# define HAVE_AR
#endif
Expand Down
11 changes: 10 additions & 1 deletion src/engine/function.c
Expand Up @@ -228,9 +228,18 @@ STACK * stack_global()
return &result;
}

struct list_alignment_helper
{
char ch;
LIST * l;
};

#define LISTPTR_ALIGN_BASE ( sizeof( struct list_alignment_helper ) - sizeof( LIST * ) )
#define LISTPTR_ALIGN ( ( LISTPTR_ALIGN_BASE > sizeof( LIST * ) ) ? sizeof( LIST * ) : LISTPTR_ALIGN_BASE )

static void check_alignment( STACK * s )
{
assert( (size_t)s->data % sizeof( LIST * ) == 0 );
assert( (size_t)s->data % LISTPTR_ALIGN == 0 );
}

void * stack_allocate( STACK * s, int size )
Expand Down
3 changes: 2 additions & 1 deletion src/engine/jam.c
Expand Up @@ -627,7 +627,8 @@ char *executable_path( char const * argv0 )
# include <stdlib.h>
char * executable_path( char const * argv0 )
{
return strdup( getexecname() );
const char * execname = getexecname();
return execname ? strdup( execname ) : NULL;
}
#elif defined(__FreeBSD__)
# include <sys/sysctl.h>
Expand Down
8 changes: 7 additions & 1 deletion src/engine/jam.h
Expand Up @@ -154,6 +154,11 @@
#define OSMINOR "OS=HPUX"
#define OS_HPUX
#endif
#ifdef __HAIKU__
#define unix
#define OSMINOR "OS=HAIKU"
#define OS_HAIKU
#endif
#ifdef __OPENNT
#define unix
#define OSMINOR "OS=INTERIX"
Expand Down Expand Up @@ -370,7 +375,8 @@
#define OSPLAT "OSPLAT=MIPS"
#endif

#ifdef __arm__
#if defined( __arm__ ) || \
defined( __aarch64__ )
#define OSPLAT "OSPLAT=ARM"
#endif

Expand Down
12 changes: 12 additions & 0 deletions src/engine/jambase.c
Expand Up @@ -560,6 +560,18 @@ char *jambase[] = {
"NOARSCAN ?= true ;\n",
"STDHDRS ?= /boot/develop/headers/posix ;\n",
"}\n",
"else if $(OS) = HAIKU\n",
"{\n",
"BINDIR ?= /boot/system/non-packaged/bin ;\n",
"CC ?= gcc ;\n",
"C++ ?= $(CC) ;\n",
"FORTRAN ?= \"\" ;\n",
"LIBDIR ?= /boot/system/non-packaged/lib ;\n",
"LINK ?= gcc ;\n",
"LINKLIBS ?= -lnetwork ;\n",
"NOARSCAN ?= true ;\n",
"STDHDRS ?= /boot/system/develop/headers/posix ;\n",
"}\n",
"else if $(UNIX)\n",
"{\n",
"switch $(OS)\n",
Expand Down
2 changes: 0 additions & 2 deletions src/engine/make1.c
Expand Up @@ -593,8 +593,6 @@ static void make1c( state const * const pState )
TARGET * saved_includes;
SETTINGS * s;

t->rescanned = 1;

/* Clean current includes. */
saved_includes = t->includes;
t->includes = 0;
Expand Down
2 changes: 1 addition & 1 deletion src/engine/modules/order.c
Expand Up @@ -77,7 +77,7 @@ void topological_sort( int * * graph, int num_vertices, int * result )
for ( i = 0; i < num_vertices; ++i )
colors[ i ] = white;

for ( i = 0; i < num_vertices; ++i )
for ( i = num_vertices - 1; i >= 0; --i )
if ( colors[ i ] == white )
do_ts( graph, i, colors, &result );

Expand Down
1 change: 0 additions & 1 deletion src/engine/rules.c
Expand Up @@ -63,7 +63,6 @@ static TARGET * get_target_includes( TARGET * const t )
i->name = object_copy( t->name );
i->boundname = object_copy( i->name );
i->flags |= T_FLAG_NOTFILE | T_FLAG_INTERNAL;
i->original_target = t;
t->includes = i;
}
return t->includes;
Expand Down
26 changes: 12 additions & 14 deletions src/engine/rules.h
Expand Up @@ -125,6 +125,16 @@ struct _target
ACTIONS * actions; /* rules to execute, if any */
SETTINGS * settings; /* variables to define */

TARGETS * depends; /* dependencies */
TARGETS * dependants; /* the inverse of dependencies */
TARGETS * rebuilds; /* targets that should be force-rebuilt
* whenever this one is
*/
TARGET * includes; /* internal includes node */

timestamp time; /* update time */
timestamp leaf; /* update time of leaf sources */

short flags; /* status info */

#define T_FLAG_TEMP 0x0001 /* TEMPORARY applied */
Expand Down Expand Up @@ -164,18 +174,6 @@ struct _target
#define T_BIND_PARENTS 2 /* using parent's timestamp */
#define T_BIND_EXISTS 3 /* real file, timestamp valid */

TARGETS * depends; /* dependencies */
TARGETS * dependants; /* the inverse of dependencies */
TARGETS * rebuilds; /* targets that should be force-rebuilt
* whenever this one is
*/
TARGET * includes; /* internal includes node */
TARGET * original_target; /* original_target->includes = this */
char rescanned;

timestamp time; /* update time */
timestamp leaf; /* update time of leaf sources */

char fate; /* make0()'s diagnosis */

#define T_FATE_INIT 0 /* nothing done to target */
Expand Down Expand Up @@ -212,12 +210,12 @@ struct _target
#define T_MAKE_SEMAPHORE 5 /* Special target type for semaphores */
#endif

char status; /* exec_cmd() result */

#ifdef OPT_SEMAPHORE
TARGET * semaphore; /* used in serialization */
#endif

char status; /* exec_cmd() result */

int asynccnt; /* child deps outstanding */
TARGETS * parents; /* used by make1() for completion */
TARGET * scc_root; /* used by make to resolve cyclic includes
Expand Down
15 changes: 8 additions & 7 deletions src/tools/builtin.jam
Expand Up @@ -35,13 +35,13 @@ import message ;
import convert ;

# FIXME: the following generate module import is not needed here but removing it
# too hastly will break using code (e.g. the main Boost library Jamroot file)
# too hastily will break using code (e.g. the main Boost library Jamroot file)
# that forgot to import the generate module before calling the generate rule.
import generate ;


.os-names = aix android bsd cygwin darwin freebsd hpux iphone linux netbsd openbsd osf
qnx qnxnto sgi solaris unix unixware windows
.os-names = aix android bsd cygwin darwin freebsd haiku hpux iphone linux netbsd
openbsd osf qnx qnxnto sgi solaris unix unixware windows
elf # Not actually an OS -- used for targeting bare metal where object
# format is ELF. This catches both -elf and -eabi gcc targets and well
# as other compilers targeting ELF. It is not clear how often we need
Expand Down Expand Up @@ -76,6 +76,7 @@ local rule default-host-os ( )
case COHERENT : host-os = unix ;
case DRAGONFLYBSD : host-os = bsd ;
case IRIX : host-os = sgi ;
case HAIKU : host-os = haiku ;
case MACOSX : host-os = darwin ;
case KFREEBSD : host-os = freebsd ;
case LINUX : host-os = linux ;
Expand Down Expand Up @@ -127,7 +128,7 @@ feature.feature debug-symbols : on off : propagated ;
# everything not necessary to running removed. This option should
# not be very often needed. Also, this feature will show up in
# target paths of everything, not just binaries. Should fix that
# when impelementing feature relevance.
# when implementing feature relevance.
feature.feature strip : off on : propagated ;
feature.feature define : : free ;
feature.feature undef : : free ;
Expand Down Expand Up @@ -812,7 +813,7 @@ class linking-generator : generator
local result = [ property-set.empty ] ;
local extra ;

# Add appropricate <xdll-path> usage requirements.
# Add appropriate <xdll-path> usage requirements.
local raw = [ $(property-set).raw ] ;
if <link>shared in $(raw)
{
Expand All @@ -833,9 +834,9 @@ class linking-generator : generator
# to other shared libraries this one depends on in order to be able to
# find them all at runtime.

# Just pass all features in property-set, it is theorically possible
# Just pass all features in property-set, it is theoretically possible
# that we will propagate <xdll-path> features explicitly specified by
# the user, but then the user is to blaim for using an internal feature.
# the user, but then the user is to blame for using an internal feature.
local values = [ $(property-set).get <xdll-path> ] ;
extra += $(values:G=<xdll-path>) ;

Expand Down
1 change: 1 addition & 0 deletions src/tools/builtin.py
Expand Up @@ -103,6 +103,7 @@ def default_host_os():
elif host_os == 'MACOSX': host_os = 'darwin'
elif host_os == 'KFREEBSD': host_os = 'freebsd'
elif host_os == 'LINUX': host_os = 'linux'
elif host_os == 'HAIKU': host_os = 'haiku'
else: host_os = 'unix'
return host_os.lower()

Expand Down
3 changes: 2 additions & 1 deletion src/tools/clang-linux.jam
Expand Up @@ -75,8 +75,9 @@ toolset.flags clang-linux.compile OPTIONS <optimization>space : -Os ;

# note: clang silently ignores some of these inlining options
toolset.flags clang-linux.compile OPTIONS <inlining>off : -fno-inline ;
# For clang, 'on' and 'full' are identical.
toolset.flags clang-linux.compile OPTIONS <inlining>on : -Wno-inline ;
toolset.flags clang-linux.compile OPTIONS <inlining>full : -finline-functions -Wno-inline ;
toolset.flags clang-linux.compile OPTIONS <inlining>full : -Wno-inline ;

toolset.flags clang-linux.compile OPTIONS <warnings>off : -w ;
toolset.flags clang-linux.compile OPTIONS <warnings>on : -Wall ;
Expand Down
3 changes: 2 additions & 1 deletion src/tools/common.py
Expand Up @@ -66,7 +66,8 @@ def reset ():
m = {"NT": __executable_path_variable,
"CYGWIN": "PATH",
"MACOSX": "DYLD_LIBRARY_PATH",
"AIX": "LIBPATH"}
"AIX": "LIBPATH",
"HAIKU": "LIBRARY_PATH"}
global __shared_library_path_variable
__shared_library_path_variable = m.get(OS, "LD_LIBRARY_PATH")

Expand Down
1 change: 1 addition & 0 deletions src/tools/gcc.jam
Expand Up @@ -1034,6 +1034,7 @@ rule setup-threading ( targets * : sources * : properties * )
case cygwin : option = -mthreads ;
case solaris : option = -pthreads ; libs = rt ;
case beos : # No threading options.
case haiku : option = ;
case *bsd : option = -pthread ; # There is no -lrt on BSD.
case sgi : # gcc on IRIX does not support multi-threading.
case darwin : # No threading options.
Expand Down
3 changes: 3 additions & 0 deletions src/tools/gcc.py
Expand Up @@ -686,6 +686,9 @@ def gcc_link_dll(targets, sources, properties):
elif host_os_name == 'BeOS':
# BeOS has no threading options, don't set anything here.
pass
elif host_os_name == 'Haiku':
flags('gcc', 'OPTIONS', ['<threading>multi'], ['-lroot'])
# there is no -lrt on Haiku, and -pthread is implicit
elif host_os_name.endswith('BSD'):
flags('gcc', 'OPTIONS', ['<threading>multi'], ['-pthread'])
# there is no -lrt on BSD
Expand Down
77 changes: 62 additions & 15 deletions src/tools/link.jam
Expand Up @@ -94,6 +94,8 @@ rule can-junction ( project : ps )
else
{

.can-junction = false ;

rule can-junction ( project : ps )
{
}
Expand Down Expand Up @@ -229,10 +231,20 @@ rule do-file-link
{
local target = [ path.native [ path.relative-to [ path.pwd ] $(<) ] ] ;
local source = [ path.native [ path.relative-to [ path.pwd ] $(>) ] ] ;
local old-source = [ on $(target) return $(LINK-SOURCE) ] ;
if $(old-source)
{
import errors ;
errors.user-error
Cannot create link $(target) to $(source). :
Link previously defined to another file, $(old-source[1]). ;
}
LINK-SOURCE on $(target) = $(source) $(.current-target) ;
LOCATE on $(target) = . ;
DEPENDS $(.current-target) : $(target) ;
if $(.can-symlink) = true
{
DEPENDS $(target) : $(source) ;
link.mklink $(target) : $(source) ;
}
else if $(.can-hardlink) = true
Expand Down Expand Up @@ -279,6 +291,12 @@ rule do-link
}
}

rule force-update
{
local target = [ path.native [ path.relative-to [ path.pwd ] $(<) ] ] ;
ALWAYS $(target) ;
}

rule do-split
{
local target = [ path.native [ path.relative-to [ path.pwd ] $(<) ] ] ;
Expand Down Expand Up @@ -309,7 +327,7 @@ actions mklink-or-dir
$(MKLINK_OR_DIR)
}

rule link-entries ( target : files * : split ? )
rule link-entries ( target : files * : split ? : deleted ? )
{
for local s in $(files)
{
Expand All @@ -324,7 +342,7 @@ rule link-entries ( target : files * : split ? )
}
if $(split)
{
link-recursively $(t) : $(s) ;
link-recursively $(t) : $(s) : : $(deleted) ;
}
else
{
Expand All @@ -338,8 +356,12 @@ rule link-entries ( target : files * : split ? )
}
}

rule link-recursively ( target : source : no-recurse ? )
rule link-recursively ( target : source : no-recurse ? : deleted ? )
{
if $(deleted) {
force-update $(target) ;
}

local split ;
if [ CHECK_IF_FILE [ path.native $(source) ] ]
{
Expand All @@ -350,30 +372,47 @@ rule link-recursively ( target : source : no-recurse ? )
split = true ;
if ! $(.split-dirs.$(target))
{
if [ READLINK [ path.native $(target) ] ]
{
if ! $(deleted) {
do-rm $(target) ;
deleted = true ;
.deleted-dirs.$(target) = true ;
}
}
local .current-target = $(.known-dirs.base.$(target)) ;
for local s in $(.known-dirs.$(target))
{
local t = [ path.join $(target) [ path.basename $(s) ] ] ;
link-recursively $(t) : $(s) : flat ;
}
if [ READLINK [ path.native $(target) ] ]
{
do-rm $(target) ;
link-recursively $(t) : $(s) : flat : $(deleted) ;
}
do-split $(target) ;
.split-dirs.$(target) = true ;
}
else if $(.deleted-dirs.$(target))
{
deleted = true ;
}
}
else if [ path.exists [ path.native $(target) ] ]
else if [ path.exists [ path.native $(target) ] ] && ! $(deleted)
{
local link-target = [ READLINK [ path.native $(target) ] ] ;
if $(link-target)
{
local full-path =
[ path.root [ path.make $(link-target) ] [ path.parent $(target) ] ] ;
if $(full-path) != $(source)
# HACK: Take advantage of the fact that path.glob
# normalizes its arguments. If full-path and
# source are different, but both are empty, they
# will compare equal, but that's okay because
# for the purposes of this module, empty directories
# are equivalent.
if [ path.glob $(full-path) : * ] != [ path.glob $(source) : * ]
{
do-rm $(target) ;
if ! $(deleted) {
do-rm $(target) ;
deleted = true ;
.deleted-dirs.$(target) = true ;
}
do-split $(target) ;
split = true ;
}
Expand All @@ -388,7 +427,11 @@ rule link-recursively ( target : source : no-recurse ? )
{
if [ READLINK [ path.native $(target) ] ]
{
do-rm $(target) ;
if ! $(deleted) {
do-rm $(target) ;
deleted = true ;
.deleted-dirs.$(target) = true ;
}
}
do-split $(target) ;
split = true ;
Expand All @@ -398,9 +441,14 @@ rule link-recursively ( target : source : no-recurse ? )
do-link $(target) : $(source) ;
}

if $(split)
{
.split-dirs.$(target) = true ;
}

if ! $(no-recurse)
{
link-entries $(target) : [ path.glob $(source) : * ] : $(split) ;
link-entries $(target) : [ path.glob $(source) : * ] : $(split) : $(deleted) ;
}
}

Expand Down Expand Up @@ -433,7 +481,6 @@ rule mklink
[ path.join [ path.root [ path.make $(source-path[1]) ] [ path.pwd ] ] [ path.make $(>:G=) ] ] ] ;

PATH_TO_SOURCE on $(<) = [ path.native $(relative-path) ] ;
NOUPDATE $(<) ;
}

if [ os.name ] = NT
Expand Down
1 change: 1 addition & 0 deletions src/tools/python.jam
Expand Up @@ -639,6 +639,7 @@ local rule system-library-dependencies ( target-os )
case qnx* : return ;
case darwin : return ;
case windows : return ;
case haiku : return ;

case hpux : return <library>rt ;
case *bsd : return <library>pthread <toolset>gcc:<library>util ;
Expand Down
21 changes: 21 additions & 0 deletions src/tools/sun.jam
Expand Up @@ -18,10 +18,31 @@ generators.override sun.prebuilt : builtin.lib-generator ;
generators.override sun.prebuilt : builtin.prebuilt ;
generators.override sun.searched-lib-generator : searched-lib-generator ;

#
# There are no less than 5 standard library options:
# 1) The default, which uses an old version of the Rogue Wave std lib,
# also available via -std=sun03.
# 2) C++03 mode + STLport, selected via the -library option.
# 3) C++03 mode plus the Apache std lib, selected via the -library option.
# 4) C++03 or C++11 in g++ compatibility mode, and GNU libstdc++3, selected via -std=c++03/11.
#
# Note that the -std, -library and -compat compiler switches appear to be largely mutually
# incompatible, and that going forward the -std switch seems to be the prefered one.
#
# See http://docs.oracle.com/cd/E37069_01/html/E37075/bkamw.html#OSSCPgnaof
#
feature.extend stdlib : sun-stlport ;
feature.compose <stdlib>sun-stlport
: <cxxflags>-library=stlport4 <linkflags>-library=stlport4
;
feature.extend stdlib : apache ;
feature.compose <stdlib>apache
: <cxxflags>-library=stdcxx4 <linkflags>-library=stdcxx4
;
feature.extend stdlib : gnu ;
feature.compose <stdlib>gnu
: <cxxflags>-std=c++03 <linkflags>-std=c++03
;

rule init ( version ? : command * : options * )
{
Expand Down
2 changes: 1 addition & 1 deletion src/tools/testing-aux.jam
Expand Up @@ -70,7 +70,7 @@ rule capture-output ( target : source : properties * : targets-to-remove * )
# OK if it cannot find the target or updating rule.
NOCARE $(target:S=.output) ;

# This has two-fold effect. First it adds input files to the dependendency
# This has two-fold effect. First it adds input files to the dependency
# graph, preventing a warning. Second, it causes input files to be bound
# before target is created. Therefore, they are bound using SEARCH setting
# on them and not LOCATE setting of $(target), as in other case (due to jam
Expand Down
8 changes: 5 additions & 3 deletions src/tools/testing.jam
@@ -1,6 +1,6 @@
# Copyright 2005 Dave Abrahams
# Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus
# Copyright 2014 Rene Rivera
# Copyright 2014-2015 Rene Rivera
# Copyright 2014 Microsoft Corporation
# 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)
Expand Down Expand Up @@ -433,7 +433,7 @@ rule capture-output ( target : source : properties * : targets-to-remove * )
# OK if it cannot find the target or updating rule.
NOCARE $(target:S=.output) ;

# This has two-fold effect. First it adds input files to the dependendency
# This has two-fold effect. First it adds input files to the dependency
# graph, preventing a warning. Second, it causes input files to be bound
# before target is created. Therefore, they are bound using SEARCH setting
# on them and not LOCATE setting of $(target), as in other case (due to jam
Expand Down Expand Up @@ -537,6 +537,7 @@ if [ os.name ] = NT
.SHELL_SET = "set " ;
.CATENATE = type ;
.CP = copy ;
.NULLIN = ;
}
else
{
Expand All @@ -550,6 +551,7 @@ else
.SHELL_SET = "" ;
.CATENATE = cat ;
.CP = cp ;
.NULLIN = "<" "/dev/null" ;
}


Expand All @@ -571,7 +573,7 @@ actions capture-output bind INPUT_FILES output-file
echo Skipping test execution due to testing.execute=off
exit 0
$(.ENDIF)
$(LAUNCHER) "$(>)" $(ARGS) "$(INPUT_FILES)" > "$(output-file)" 2>&1
$(LAUNCHER) "$(>)" $(ARGS) "$(INPUT_FILES)" > "$(output-file)" 2>&1 $(.NULLIN)
$(.SET_STATUS)
$(.RUN_OUTPUT_NL) >> "$(output-file)"
echo EXIT STATUS: $(.STATUS) >> "$(output-file)"
Expand Down
46 changes: 46 additions & 0 deletions src/util/__init__.py
Expand Up @@ -3,6 +3,9 @@
import re
import types

from itertools import groupby


# Decorator the specifies bjam-side prototype for a Python function
def bjam_signature(s):

Expand Down Expand Up @@ -134,3 +137,46 @@ def stem(filename):
return filename[0:i]
else:
return filename


def abbreviate_dashed(s):
"""Abbreviates each part of string that is delimited by a '-'."""
r = []
for part in s.split('-'):
r.append(abbreviate(part))
return '-'.join(r)


def abbreviate(s):
"""Apply a set of standard transformations to string to produce an
abbreviation no more than 4 characters long.
"""
if not s:
return ''
# check the cache
if s in abbreviate.abbreviations:
return abbreviate.abbreviations[s]
# anything less than 4 characters doesn't need
# an abbreviation
if len(s) < 4:
# update cache
abbreviate.abbreviations[s] = s
return s
# save the first character in case it's a vowel
s1 = s[0]
s2 = s[1:]
if s.endswith('ing'):
# strip off the 'ing'
s2 = s2[:-3]
# reduce all doubled characters to one
s2 = ''.join(c for c, _ in groupby(s2))
# remove all vowels
s2 = s2.translate(None, "AEIOUaeiou")
# shorten remaining consonants to 4 characters
# and add the first char back to the front
s2 = s1 + s2[:4]
# update cache
abbreviate.abbreviations[s] = s2
return s2
# maps key to its abbreviated form
abbreviate.abbreviations = {}
2 changes: 1 addition & 1 deletion src/util/doc.jam
Expand Up @@ -264,7 +264,7 @@ local rule print-help-top ( )
print.list-item "-a Rebuild everything" ;
print.list-item "-n Don't execute the commands, only print them" ;
print.list-item "-d+2 Show commands as they are executed" ;
print.list-item "-d0 Supress all informational messages" ;
print.list-item "-d0 Suppress all informational messages" ;
print.list-item "-q Stop at first error" ;
print.list-item "--reconfigure Rerun all configuration checks" ;
print.list-item "--debug-configuration Diagnose configuration" ;
Expand Down
4 changes: 4 additions & 0 deletions src/util/order.jam
Expand Up @@ -166,4 +166,8 @@ rule __test__ ( )
$(c1).add-pair x l2 ;
assert.result l1 l2 : $(c1).order l2 l1 ;
assert.result l1 l2 l3 : $(c1).order l2 l3 l1 ;

# The output should be stable for unconstrained
# elements.
assert.result l4 l5 : $(c1).order l4 l5 ;
}
2 changes: 2 additions & 0 deletions src/util/os.jam
Expand Up @@ -75,6 +75,8 @@ if $(.name) = NT

.shared-library-path-variable-AIX = LIBPATH ;

.shared-library-path-variable-HAIKU = LIBRARY_PATH ;

# Default constants
.shared-library-path-variable = LD_LIBRARY_PATH ;
.path-separator = ":" ;
Expand Down
2 changes: 1 addition & 1 deletion test/default_build.py
Expand Up @@ -19,7 +19,7 @@
t.expect_addition("bin/$toolset/debug/a.exe")
t.expect_addition("bin/$toolset/release/a.exe")

# Check that explictly-specified build variant supresses default-build.
# Check that explictly-specified build variant suppresses default-build.
t.rm("bin")
t.run_build_system(["release"])
t.expect_addition(BoostBuild.List("bin/$toolset/release/") * "a.exe a.obj")
Expand Down
204 changes: 192 additions & 12 deletions test/link.py
@@ -1,6 +1,6 @@
#!/usr/bin/python

# Copyright 2004 Vladimir Prus
# Copyright 2014-2015 Steven Watanabe
# 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)

Expand Down Expand Up @@ -57,7 +57,7 @@ def test_merge_two():
t.expect_nothing_more()
t.cleanup()

def test_merge_existing():
def test_merge_existing(group1, group2):
"""Test adding a link when a different symlink already exists"""
t = BoostBuild.Tester()
t.write("jamroot.jam", """\
Expand All @@ -69,25 +69,43 @@ def test_merge_existing():
t.write("src/dir1/include/file1.h", "file1")
t.write("src/dir2/include/file2.h", "file2")

t.run_build_system(["dir1-link"])
t.run_build_system(group1)

t.expect_addition("include/file1.h")
t.expect_content("include/file1.h", "file1")
if "dir1-link" in group1:
t.expect_addition("include/file1.h")
t.expect_content("include/file1.h", "file1")
if "dir2-link" in group1:
t.expect_addition("include/file2.h")
t.expect_content("include/file2.h", "file2")
ignore_config(t)
t.expect_nothing_more()

t.run_build_system(["dir2-link"])
t.run_build_system(group2)

t.expect_addition("include/file2.h")
t.expect_content("include/file2.h", "file2")
# If include is a symlink to src/dir1/include, then
# we have to delete it and add a directory.
t.ignore_removal("include/file1.h")
if "dir1-link" in group2:
if "dir1-link" not in group1:
t.expect_addition("include/file1.h")
t.expect_content("include/file1.h", "file1")
else:
t.ignore_removal("include/file1.h")

if "dir2-link" in group2:
if "dir2-link" not in group1:
t.expect_addition("include/file2.h")
t.expect_content("include/file2.h", "file2")
else:
t.ignore_removal("include/file2.h")
ignore_config(t)
t.expect_nothing_more()

t.cleanup()

def test_merge_existing_all():
test_merge_existing(["dir1-link"], ["dir2-link"])
test_merge_existing(["dir2-link"], ["dir1-link"])
test_merge_existing(["dir1-link"], ["dir1-link", "dir2-link"])
test_merge_existing(["dir2-link"], ["dir1-link", "dir2-link"])

def test_merge_recursive():
"Test merging several directories including common prefixes"
t = BoostBuild.Tester()
Expand Down Expand Up @@ -118,6 +136,48 @@ def test_merge_recursive():

t.cleanup()

def test_merge_recursive_existing(group1, group2):
"Test merging several directories including common prefixes."
t = BoostBuild.Tester()
t.write("jamroot.jam", """\
import link ;
link-directory dir1-link : src/dir1/include : <location>. ;
link-directory dir2-link : src/dir2/include : <location>. ;
link-directory dir3-link : src/dir3/include : <location>. ;
link-directory dir4-link : src/dir4/include : <location>. ;
link-directory dir5-link : src/dir5/include : <location>. ;
""")

t.write("src/dir1/include/file1.h", "file1")
t.write("src/dir2/include/nested/file2.h", "file2")
t.write("src/dir3/include/nested/file3.h", "file3")
t.write("src/dir4/include/nested/xxx/yyy/file4.h", "file4")
t.write("src/dir5/include/nested/xxx/yyy/file5.h", "file5")

t.run_build_system(group1)
t.run_build_system(group2 + ["-d+12"])

t.ignore_addition("include/file1.h")
t.ignore_addition("include/nested/file2.h")
t.ignore_addition("include/nested/file3.h")
t.ignore_addition("include/nested/xxx/yyy/file4.h")
t.ignore_addition("include/nested/xxx/yyy/file5.h")
ignore_config(t)
t.expect_nothing_more()

t.cleanup()

def test_merge_recursive_existing_all():
# These should create a link
test_merge_recursive_existing(["dir2-link"], ["dir2-link", "dir1-link"])
test_merge_recursive_existing(["dir2-link"], ["dir1-link", "dir2-link"])
# These should create a directory
test_merge_recursive_existing(["dir2-link"], ["dir2-link", "dir3-link"])
test_merge_recursive_existing(["dir2-link"], ["dir3-link", "dir2-link"])
# It should work even if we have to create many intermediate subdirectories
test_merge_recursive_existing(["dir4-link"], ["dir4-link", "dir5-link"])
test_merge_recursive_existing(["dir4-link"], ["dir5-link", "dir4-link"])

def test_include_scan():
"""Make sure that the #include scanner finds the headers"""
t = BoostBuild.Tester()
Expand Down Expand Up @@ -147,8 +207,128 @@ def test_include_scan():

t.cleanup()

def test_include_scan_merge_existing():
"""Make sure that files are replaced if needed when merging in
a new directory"""
t = BoostBuild.Tester()

t.write("jamroot.jam", """\
import link ;
link-directory dir1-link : src/dir1/include : <location>. ;
link-directory dir2-link : src/dir2/include : <location>. ;
obj test : test.cpp :
<include>include
<implicit-dependency>dir1-link
<implicit-dependency>dir2-link ;
""")

t.write("src/dir1/include/file1.h", "int f();")
t.write("src/dir2/include/file2.h", "#include <file1.h>")
t.write("test.cpp", """\
#include <file2.h>
int main() { f(); }
""")

t.run_build_system(["dir2-link"])

t.run_build_system(["test"])
t.expect_addition("include/file1.h")
t.expect_addition("bin/$toolset/debug/test.obj")
t.expect_nothing_more()

t.cleanup()

def test_update_file_link(params1, params2):
"""Tests the behavior of updates when changing the link mode.
The link needs to be updated iff the original was a copy."""
t = BoostBuild.Tester()

t.write("jamroot.jam", """\
import link ;
import project ;
import property-set ;
import modules ;

if --no-symlinks in [ modules.peek : ARGV ]
{
modules.poke link : .can-symlink : false ;
}

if --no-hardlinks in [ modules.peek : ARGV ]
{
modules.poke link : .can-hardlink : false ;
}

.project = [ project.current ] ;
.has-files = [ glob include/file1.h ] ;

rule can-link ( properties * ) {
if ( ! [ link.can-symlink $(.project) : [ property-set.empty ] ] ) &&
( ! [ link.can-hardlink $(.project) : [ property-set.empty ] ] )
{
ECHO links unsupported ;
}
}

# Use two directories so that we link to individual files.
link-directory dir1-link : src/dir1/include : <location>. ;
link-directory dir2-link : src/dir2/include : <location>. ;
alias check-linking : : <conditional>@can-link ;
""")
t.write("src/dir1/include/file1.h", "file1")
t.write("src/dir2/include/file2.h", "file2")

t.run_build_system(params1)
ignore_config(t)
t.expect_addition("include/file1.h")
t.expect_addition("include/file2.h")
t.expect_nothing_more()

using_links = "links unsupported" not in t.stdout()

t.touch("src/dir1/include/file1.h")

t.run_build_system(params2)
if not using_links: t.expect_touch("include/file1.h")
ignore_config(t)
t.expect_nothing_more()

t.cleanup()

def test_update_file_link_all():
"""Test all nine possible combinations of two runs."""
possible_args = [[], ["--no-symlinks"], ["--no-symlinks", "--no-hardlinks"]]
for arg1 in possible_args:
for arg2 in possible_args:
test_update_file_link(arg1, arg2)

def test_error_duplicate():
"""Test that linking a single file from
multiple sources causes a hard error."""
t = BoostBuild.Tester()

t.write("jamroot.jam", """\
import link ;
link-directory dir1-link : src/dir1/include : <location>. ;
link-directory dir2-link : src/dir2/include : <location>. ;
""")

t.write("src/dir1/include/file1.h", "file1")
t.write("src/dir2/include/file1.h", "file2")

t.run_build_system(status=1)
t.expect_output_lines(
["error: Cannot create link include/file1.h to src/dir2/include/file1.h.",
"error: Link previously defined to another file, src/dir1/include/file1.h."])

t.cleanup()

test_basic()
test_merge_two()
test_merge_existing()
test_merge_existing_all()
test_merge_recursive()
test_merge_recursive_existing_all()
test_include_scan()
test_include_scan_merge_existing()
test_update_file_link_all()
test_error_duplicate()
78 changes: 78 additions & 0 deletions test/ordered_include.py
Expand Up @@ -8,6 +8,82 @@

import BoostBuild

def test_default_order():
tester = BoostBuild.Tester(use_test_config=False)
tester.write("jamroot.jam", """

import order ;
import "class" : new ;

obj test : test.cpp : <include>b <include>a ;
""")

tester.write("test.cpp", """
#include <test.hpp>
int main() { f(); }
""")

tester.write("a/test.hpp", """
void f();
""")

tester.write("b/test.hpp", """
""")

tester.run_build_system()

tester.expect_addition("bin/$toolset/debug/test.obj")

# Check that the dependencies are correct
tester.touch("a/test.hpp")
tester.run_build_system()
tester.expect_touch("bin/$toolset/debug/test.obj")
tester.expect_nothing_more()

tester.touch("b/test.hpp")
tester.run_build_system()
tester.expect_nothing_more()

tester.cleanup()

def test_default_order_mixed():
tester = BoostBuild.Tester(use_test_config=False)
tester.write("jamroot.jam", """

import order ;
import "class" : new ;

obj test : test.cpp : <include>b <include>a <include>c&&d ;
""")

tester.write("test.cpp", """
#include <test.hpp>
int main() { f(); }
""")

tester.write("a/test.hpp", """
void f();
""")

tester.write("b/test.hpp", """
""")

tester.run_build_system()

tester.expect_addition("bin/$toolset/debug/test.obj")

# Check that the dependencies are correct
tester.touch("a/test.hpp")
tester.run_build_system()
tester.expect_touch("bin/$toolset/debug/test.obj")
tester.expect_nothing_more()

tester.touch("b/test.hpp")
tester.run_build_system()
tester.expect_nothing_more()

tester.cleanup()

def test_basic():
tester = BoostBuild.Tester(use_test_config=False)
tester.write("jamroot.jam", """
Expand Down Expand Up @@ -167,6 +243,8 @@ def test_order_graph():

t.cleanup()

test_default_order()
test_default_order_mixed()
test_basic()
test_order1()
test_order2()
Expand Down
1,522 changes: 1,522 additions & 0 deletions tutorial.html

Large diffs are not rendered by default.

29 changes: 29 additions & 0 deletions website/index.css
Expand Up @@ -3,6 +3,35 @@ body {
font-size: 16px;
}

.header {
margin-top: 1em;
}

.header > ul {
float: right;
}

.header > ul > li {
display: inline;
padding-left: 2em;
}

th {
color: #000;
background-color: #D6D6FF;
border: 1px solid #C0C0FF;
padding: 4px;
vertical-align: top;
}
td {
color: #000;
background-color: #F0F0FF;
border: 1px solid #C0C0FF;
padding: 4px;
vertical-align: top;
}


/*
@media (min-width: 768px) {
.container {
Expand Down