diff --git a/v2/build/ac.jam b/v2/build/ac.jam new file mode 100644 index 000000000..6768f358c --- /dev/null +++ b/v2/build/ac.jam @@ -0,0 +1,198 @@ +# Copyright (c) 2010 Vladimir Prus. +# +# 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 property-set ; +import path ; +import modules ; +import "class" ; +import errors ; +import configure ; + +rule find-include-path ( variable : properties : header + : provided-path ? ) +{ + # FIXME: document which properties affect this function by + # default. + local target-os = [ $(properties).get ] ; + properties = [ property-set.create $(toolset) ] ; + if $($(variable)-$(properties)) + { + return $($(variable)-$(properties)) ; + } + else + { + provided-path ?= [ modules.peek : $(variable) ] ; + includes = $(provided-path) ; + includes += [ $(properties).get ] ; + if [ $(properties).get ] != windows + { + # FIXME: use sysroot + includes += /usr/include ; + } + + local result ; + while ! $(result) && $(includes) + { + local f = [ path.root $(header) $(includes[1]) ] ; + ECHO "Checking " $(f) ; + if [ path.exists $(f) ] + { + result = $(includes[1]) ; + } + else if $(provided-path) + { + errors.user-error "Could not find header" $(header) + : "in the user-specified directory" $(provided-path) ; + } + includes = $(includes[2-]) ; + } + $(variable)-$(properties) = $(result) ; + return $(result) ; + } +} + +rule find-library ( variable : properties : names + : provided-path ? ) +{ + local target-os = [ $(properties).get ] ; + properties = [ property-set.create $(toolset) ] ; + if $($(variable)-$(properties)) + { + return $($(variable)-$(properties)) ; + } + else + { + provided-path ?= [ modules.peek : $(variable) ] ; + paths = $(provided-path) ; + paths += [ $(properties).get ] ; + if [ $(properties).get ] != windows + { + paths += /usr/lib /usr/lib32 /usr/lib64 ; + } + + local result ; + while ! $(result) && $(paths) + { + while ! $(result) && $(names) + { + local f ; + if $(target-os) = windows + { + f = $(paths[1])/$(names[1]).lib ; + if [ path.exists $(f) ] + { + result = $(f) ; + } + } + else + { + # FIXME: check for .a as well, depending on + # the 'link' feature. + f = $(paths[1])/lib$(names[1]).so ; + ECHO "CHECKING $(f) " ; + if [ path.exists $(f) ] + { + result = $(f) ; + } + } + if ! $(result) && $(provided-path) + { + errors.user-error "Could not find either of: " $(names) + : "in the user-specified directory" $(provided-path) ; + + } + names = $(names[2-]) ; + } + paths = $(paths[2-]) ; + } + $(variable)-$(properties) = $(result) ; + return $(result) ; + } +} + +class ac-library : basic-target +{ + import errors ; + import indirect ; + import virtual-target ; + import ac ; + import configure ; + + rule __init__ ( name : project : * : * ) + { + basic-target.__init__ $(name) : $(project) : $(sources) + : $(requirements) ; + + reconfigure $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ; + } + + rule set-header ( header ) + { + self.header = $(header) ; + } + + rule set-default-names ( names + ) + { + self.default-names = $(names) ; + } + + rule reconfigure ( * : * ) + { + ECHO "XXX" $(1) ; + if ! $(1) + { + # This is 'using xxx ;'. Nothing to configure, really. + } + else + { + for i in 1 2 3 4 5 6 7 8 9 + { + # FIXME: this naming is inconsistent with XXX_INCLUDE/XXX_LIBRARY + if ! ( $($(i)[1]) in root include-path library-path library-name condition ) + { + errors.user-error "Invalid named parameter" $($(i)[1]) ; + } + local name = $($(i)[1]) ; + local value = $($(i)[2-]) ; + if $($(name)) && $($(name)) != $(value) + { + errors.user-error "Attempt to change value of '$(name)'" ; + } + $(name) = $(value) ; + } + + include-path ?= $(root)/include ; + library-path ?= $(root)/lib ; + } + } + + rule construct ( name : sources * : property-set ) + { + # FIXME: log results. + local libnames = $(library-name) ; + if ! $(libnames) && ! $(include-path) && ! $(library-path) + { + libnames = [ modules.peek : $(name:U)_NAME ] ; + # Backward compatibility only. + libnames ?= [ modules.peek : $(name:U)_BINARY ] ; + } + libnames ?= $(self.default-names) ; + + local includes = [ + ac.find-include-path $(name:U)_INCLUDE : $(property-set) : $(self.header) : $(include-path) ] ; + local library = [ ac.find-library $(name:U)_LIBRARY : $(property-set) : $(libnames) : $(library-path) ] ; + if $(includes) && $(library) + { + library = [ virtual-target.from-file $(library) : . : $(self.project) ] ; + configure.log-library-search-result $(name) : "found" ; + return [ property-set.create $(includes) $(library) ] ; + } + else + { + configure.log-library-search-result $(name) : "no found" ; + } + } +} + diff --git a/v2/build/configure.jam b/v2/build/configure.jam index c50bf73ef..474ff86fe 100644 --- a/v2/build/configure.jam +++ b/v2/build/configure.jam @@ -63,6 +63,12 @@ rule log-check-result ( result ) #.check-results += $(result) ; } +rule log-library-search-result ( library : result ) +{ + local x = [ PAD " - $(library) : $(result)" : $(.width) ] ; + log-check-result "$(x)" ; +} + rule print-component-configuration ( ) { local c = [ sequence.unique $(.components) ] ; diff --git a/v2/tools/zlib.jam b/v2/tools/zlib.jam new file mode 100644 index 000000000..f9138fd57 --- /dev/null +++ b/v2/tools/zlib.jam @@ -0,0 +1,92 @@ +# Copyright (c) 2010 Vladimir Prus. +# +# 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) + +# Supports the zlib library +# +# After 'using zlib', the following targets are available: +# +# /zlib//zlib -- The zlib library + + +# In addition to direct purpose of supporting zlib, this module also +# serves as canonical example of how third-party condiguration works +# in Boost.Build. The operation is as follows +# +# - For each 'using zlib : condition ... : ...' we create a target alternative +# for zlib, with the specified condition. +# - There's one target alternative for 'zlib' with no specific condition +# properties. +# +# Two invocations of 'using zlib' with the same condition but different +# properties are not permitted, e.g.: +# +# using zlib : condition windows : include foo ; +# using zlib : condition windows : include bar ; +# +# is in error. One exception is for empty condition, 'using' without any +# parameters is overridable. That is: +# +# using zlib ; +# using zlib : include foo ; +# +# Is OK then the first 'using' is ignored. Likewise if the order of the statements +# is reversed. +# +# When 'zlib' target is built, a target alternative is selected as usual for +# Boost.Build. The selected alternative is a custom target class, which: +# +# - calls ac.find-include-path to find header path. If explicit path is provided +# in 'using', only that path is checked, and if no header is found there, error +# is emitted. Otherwise, we check a directory specified using ZLIB_INCLUDE +# environment variable, and failing that, in standard directories. +# [TODO: document sysroot handling] +# - calls ac.find-library to find the library, in an identical fashion. +# + +import project ; +import ac ; +import errors ; +import "class" : new ; +import targets ; + +project.initialize $(__name__) ; +project = [ project.current ] ; +project zlib ; + +header = zlib.h ; +names = z zlib zll zdll ; + +.default-alternative = [ new ac-library zlib : $(project) ] ; +$(.default-alternative).set-header $(header) ; +$(.default-alternative).set-default-names $(names) ; +targets.main-target-alternative $(.default-alternative) ; + +rule init ( * : * ) +{ + if ! $(condition) + { + # Special case the no-condition case so that 'using' without parameters + # can mix with more specific 'using'. + $(.default-alternative).reconfigure $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ; + } + else + { + # FIXME: consider if we should allow overriding definitions for a given + # condition -- e.g. project-config.jam might want to override whatever is + # in user-config.jam. + local mt = [ new ac-library zlib : $(project) + : $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ] ; + $(mt).set-header $(header) ; + $(mt).set-default-names $(names) ; + targets.main-target-alternative $(mt) ; + } +} + + + + + +