# Copyright 2018 Peter Dimov # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt) import modules ; import boostcpp ; import property-set ; import "class" : new ; import project ; import common ; import virtual-target ; import print ; import os ; import feature ; import package ; import sequence ; import set ; import type ; feature.feature library-type : : free ; feature.feature boost-install.dependency : : free ; if "--verbose" in [ modules.peek : ARGV ] { .info-enabled = 1 ; } if "--debug-boost-install" in [ modules.peek : ARGV ] { .debug-enabled = 1 ; } local rule .info ( messages * ) { if $(.info-enabled) { ECHO "info:" $(messages) ; } } local rule .debug ( messages * ) { if $(.debug-enabled) { ECHO "boost-install:" $(messages) ; } } # generate-cmake-variant- rule generate-cmake-variant- ( target : sources * : properties * ) { .info generate-cmake-variant- $(target) ":" $(sources) ; local ps = [ property-set.create $(properties) ] ; print.output $(target) ; local version = [ $(ps).get ] ; .info " version=" $(version) ; local name = [ $(ps).get ] ; .info " name=" $(name) ; local variant = [ $(ps).get ] ; .info " variant=" $(variant) ; local link = [ $(ps).get ] ; .info " link= " $(link) ; local runtime-link = [ $(ps).get ] ; .info " runtime-link=" $(runtime-link) ; local runtime-debugging = [ $(ps).get ] ; .info " runtime-debugging=" $(runtime-debugging) ; local threading = [ $(ps).get ] ; .info " threading=" $(threading) ; local address-model = [ $(ps).get ] ; .info " address-model=" $(address-model) ; local toolset = [ MATCH ^-(.*) : [ common.format-name : "" : "" : $(ps) ] ] ; .info " toolset=" $(toolset) ; local fname = $(sources[1]:BS) ; .info " fname=" $(fname) ; print.text "# Generated by Boost $(version)" "" : true ; print.text "# variant=$(variant)" "" : true ; if $(variant) = debug { print.text "if(NOT \"${Boost_USE_DEBUG_LIBS}\" STREQUAL \"\" AND NOT Boost_USE_DEBUG_LIBS)" " if(Boost_DEBUG)" " message(STATUS \" $(fname) skipped due to NOT Boost_USE_DEBUG_LIBS\")" " endif()" " return()" "endif()" "" : true ; } else { print.text "if(NOT \"${Boost_USE_RELEASE_LIBS}\" STREQUAL \"\" AND NOT Boost_USE_RELEASE_LIBS)" " if(Boost_DEBUG)" " message(STATUS \" $(fname) skipped due to NOT Boost_USE_RELEASE_LIBS\")" " endif()" " return()" "endif()" "" : true ; } print.text "# link=$(link)" "" : true ; if $(link) = static { print.text "if(NOT Boost_USE_STATIC_LIBS)" " if(Boost_DEBUG)" " message(STATUS \" $(fname) skipped due to NOT Boost_USE_STATIC_LIBS\")" " endif()" " return()" "endif()" "" : true ; } else { print.text "if(Boost_USE_STATIC_LIBS)" " if(Boost_DEBUG)" " message(STATUS \" $(fname) skipped due to Boost_USE_STATIC_LIBS\")" " endif()" " return()" "endif()" "" : true ; } print.text "# runtime-link=$(runtime-link)" "" : true ; if $(runtime-link) = static { print.text "if(NOT Boost_USE_STATIC_RUNTIME)" " if(Boost_DEBUG)" " message(STATUS \" $(fname) skipped due to NOT Boost_USE_STATIC_RUNTIME\")" " endif()" " return()" "endif()" "" : true ; } else { print.text "if(Boost_USE_STATIC_RUNTIME)" " if(Boost_DEBUG)" " message(STATUS \" $(fname) skipped due to Boost_USE_STATIC_RUNTIME\")" " endif()" " return()" "endif()" "" : true ; } print.text "# runtime-debugging=$(runtime-debugging)" "" : true ; #| if $(runtime-debugging) = "on" { print.text "if(NOT Boost_USE_DEBUG_RUNTIME)" " if(Boost_DEBUG)" " message(STATUS \" $(fname) skipped due to NOT Boost_USE_DEBUG_RUNTIME\")" " endif()" " return()" "endif()" "" : true ; } else { print.text "if(Boost_USE_DEBUG_RUNTIME)" " if(Boost_DEBUG)" " message(STATUS \" $(fname) skipped due to Boost_USE_DEBUG_RUNTIME\")" " endif()" " return()" "endif()" "" : true ; } |# print.text "# threading=$(threading)" "" : true ; print.text "# address-model=$(address-model)" "" : true ; if $(address-model) = 32 { print.text "if(CMAKE_SIZEOF_VOID_P EQUAL 8)" " if(Boost_DEBUG)" " message(STATUS \" $(fname) skipped due to CMAKE_SIZEOF_VOID_P == 8\")" " endif()" " return()" "endif()" "" : true ; } else { print.text "if(CMAKE_SIZEOF_VOID_P EQUAL 4)" " if(Boost_DEBUG)" " message(STATUS \" $(fname) skipped due to CMAKE_SIZEOF_VOID_P == 4\")" " endif()" " return()" "endif()" "" : true ; } print.text "# toolset=$(toolset)" "" : true ; print.text "if(Boost_COMPILER AND NOT Boost_COMPILER STREQUAL \"$(toolset)\")" " if(Boost_DEBUG)" " message(STATUS \" $(fname) skipped due to Boost_COMPILER (${Boost_COMPILER}) != $(toolset)\")" " endif()" " return()" "endif()" "" "if(BOOST_DETECTED_TOOLSET AND NOT BOOST_DETECTED_TOOLSET STREQUAL \"$(toolset)\")" " if(Boost_DEBUG)" " message(STATUS \" $(fname) skipped due to BOOST_DETECTED_TOOLSET (${BOOST_DETECTED_TOOLSET}) != $(toolset)\")" " endif()" " return()" "endif()" "" "message(STATUS \" $(fname)\")" "" : true ; local lname = [ MATCH boost_(.*) : $(name) ] ; .info " lname=" $(lname) ; local target = "Boost::$(lname)" ; .info " target=" $(target) ; print.text "# Target file name: $(fname)" : true ; print.text "set_property(TARGET $(target) APPEND PROPERTY IMPORTED_CONFIGURATIONS $(variant:U))" "set_target_properties($(target) PROPERTIES" " IMPORTED_LINK_INTERFACE_LANGUAGES_$(variant:U) CXX" " IMPORTED_LOCATION_$(variant:U) \"${_IMPORT_PREFIX}/lib/$(fname)\"" " )" "" : true ; if $(link) = shared { print.text "set_target_properties($(target) PROPERTIES" " INTERFACE_COMPILE_DEFINITIONS \"BOOST_$(lname:U)_DYN_LINK\"" " )" "" : true ; } local deps = [ MATCH "boost_(.*)" : [ $(ps).get ] ] headers ; .info " deps=" $(deps) ; if $(deps) { print.text "list(APPEND BOOST_$(lname:U)_DEPS $(deps:J= ))" "" : true ; } } # tag local rule tag ( name : type ? : property-set ) { #.debug tag $(name) ":" $(type) ":" $(property-set) ; local link = [ $(property-set).get ] ; #.debug "tag: link is $(link)" ; local r = [ boostcpp.tag $(name) : STATIC_LIB : $(property-set) ] ; r = $(r:S=$(name:S)) ; r = $(r:B=$(r:B)-$(link)) ; #.debug "tag: returning $(r)" ; return $(r) ; } # choose-lib-target: get the import library, if present, the # shared/static library otherwise, ignore .pdb et al local rule choose-lib-target ( sources * ) { local result ; for local t in $(sources) { if [ type.is-derived [ $(t).type ] IMPORT_LIB ] { return $(t) ; } else if [ type.is-derived [ $(t).type ] LIB ] { result = $(t) ; } } return $(result) ; } # get-dependency-names: Returns the base names of all # dependency libraries. # local rule get-dependency-names ( sources * ) { local all-targets = [ collect-targets $(sources) ] ; local lib-names ; for local t in [ set.difference $(all-targets) : $(sources) ] { if [ $(t).type ] && [ type.is-derived [ $(t).type ] LIB ] { # Get back the original unmangled name of the library local subvariant = [ $(t).creating-subvariant ] ; local main-target = [ $(subvariant).main-target ] ; lib-names += [ $(main-target).name ] ; } } return [ sequence.unique $(lib-names) ] ; } # generate-cmake-variant rule generate-cmake-variant ( project name : property-set : sources * ) { .debug generate-cmake-variant $(name) ; for local s in $(sources) { .debug " name=" [ $(s).name ] ; } local lib-target = [ choose-lib-target $(sources) ] ; local other-names = [ get-dependency-names $(sources) ] ; property-set = [ $(property-set).add-raw $(other-names) ] ; if $(lib-target) { .debug " lib-target=" [ $(lib-target).name ] ; } local tag = [ tag $(name) : : $(property-set) ] ; #.debug "generate-cmake-variant:" tag is $(tag) ; local result ; local a = [ new non-scanning-action $(lib-target) : boost-install.generate-cmake-variant- : $(property-set) ] ; result += [ new file-target $(tag) : : $(project) : $(a) ] ; return $(result) ; } # generate-cmake-config- rule generate-cmake-config- ( target : sources * : properties * ) { .info generate-cmake-config- $(target) ":" $(sources) ; local ps = [ property-set.create $(properties) ] ; print.output $(target) ; local version = [ $(ps).get ] ; .info " version=" $(version) ; local name = [ $(ps).get ] ; .info " name=" $(name) ; local library-type = [ $(ps).get ] ; .info " library-type=" $(library-type) ; local lname = [ MATCH boost_(.*) : $(name) ] ; .info " lname=" $(lname) ; local ltarget = "Boost::$(lname)" ; .info " ltarget=" $(ltarget) ; local BOOST_VERSION_TAG = [ modules.peek boostcpp : BOOST_VERSION_TAG ] ; .info " BOOST_VERSION_TAG=" $(BOOST_VERSION_TAG) ; local layout = [ modules.peek boostcpp : layout ] ; .info " layout=" $(layout) ; local header-subdir = "" ; if $(layout) = versioned { header-subdir = /boost-$(BOOST_VERSION_TAG) ; } .info " header-subdir=" $(header-subdir) ; print.output $(target) ; print.text "# Generated by Boost $(version)" "" "cmake_minimum_required(VERSION 3.5)" "" "if(TARGET $(ltarget))" " return()" "endif()" "" "message(STATUS \"Found $(name)\")" "" "# Compute the installation prefix relative to this file." "get_filename_component(_IMPORT_PREFIX \"${CMAKE_CURRENT_LIST_DIR}/../../../\" ABSOLUTE)" "" "# Create imported target $(ltarget)" "add_library($(ltarget) $(library-type) IMPORTED)" "" "set_target_properties($(ltarget) PROPERTIES" " INTERFACE_INCLUDE_DIRECTORIES \"\${_IMPORT_PREFIX}/include$(header-subdir)\"" " INTERFACE_COMPILE_DEFINITIONS \"BOOST_ALL_NO_LIB\"" ")" : true ; if $(library-type) != INTERFACE { print.text "" "include(${CMAKE_CURRENT_LIST_DIR}/../BoostDetectToolset-$(version).cmake)" "" "if(Boost_DEBUG)" " message(STATUS \"Scanning ${CMAKE_CURRENT_LIST_DIR}/lib$(name)-variant*.cmake\")" "endif()" "" "file(GLOB variants \"${CMAKE_CURRENT_LIST_DIR}/lib$(name)-variant*.cmake\")" "" "include(CMakeFindDependencyMacro)" "" "foreach(f IN LISTS variants)" " if(Boost_DEBUG)" " message(STATUS \" Including ${f}\")" " endif()" " include(${f})" "endforeach()" "" "list(REMOVE_DUPLICATES BOOST_$(lname:U)_DEPS)" "" "foreach(dep_boost_$(lname) IN LISTS BOOST_$(lname:U)_DEPS") " find_dependency(boost_${dep_boost_$(lname)})" " set_property(TARGET $(ltarget) APPEND PROPERTY INTERFACE_LINK_LIBRARIES Boost::${dep_boost_$(lname)})" "endforeach()" "" "unset(variants)" "unset(_IMPORT_PREFIX)" "unset(BOOST_$(lname:U)_DEPS)" "" : true ; if $(name) = boost_thread { print.text "find_dependency(Threads)" "set_property(TARGET $(ltarget) APPEND PROPERTY INTERFACE_LINK_LIBRARIES Threads::Threads)" "" : true ; } } } # generate-cmake-config rule generate-cmake-config ( project name : property-set : sources * ) { .debug generate-cmake-config $(name) ; local pname = [ $(property-set).get ] ; local version = [ $(property-set).get ] ; local location = [ $(property-set).get ] ; local library-type = [ $(property-set).get ] ; local ps = [ property-set.create $(pname) $(version) $(location) $(library-type) ] ; local result ; local a = [ new non-scanning-action : boost-install.generate-cmake-config- : $(ps) ] ; result += [ new file-target $(name) : : $(project) : $(a) ] ; return $(result) ; } # generate-cmake-config-version- rule generate-cmake-config-version- ( target : sources * : properties * ) { .info generate-cmake-config-version- $(target) ":" $(sources) ; local ps = [ property-set.create $(properties) ] ; print.output $(target) ; local version = [ $(ps).get ] ; .info " version=" $(version) ; print.output $(target) ; print.text "# Generated by Boost $(version)" "" "set(PACKAGE_VERSION $(version))" "" "if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION)" " set(PACKAGE_VERSION_COMPATIBLE FALSE)" "else()" " set(PACKAGE_VERSION_COMPATIBLE TRUE)" " if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION)" " set(PACKAGE_VERSION_EXACT TRUE)" " endif()" "endif()" "" : true ; } # generate-cmake-config-version rule generate-cmake-config-version ( project name : property-set : sources * ) { .debug generate-cmake-config-version $(name) ; local pname = [ $(property-set).get ] ; local version = [ $(property-set).get ] ; local location = [ $(property-set).get ] ; local ps = [ property-set.create $(pname) $(version) $(location) ] ; local result ; local a = [ new non-scanning-action : boost-install.generate-cmake-config-version- : $(ps) ] ; result += [ new file-target $(name) : : $(project) : $(a) ] ; return $(result) ; } # install-cmake-config- local rule install-cmake-config- ( location : version : name ) { #.debug install-cmake-config- $(name) ; local loc = $(location)/cmake/$(name)-$(version) ; local library-type = UNKNOWN ; if $(name) = boost_headers || $(name) = boost_math || $(name) = boost_exception { library-type = INTERFACE ; } local reqs = $(name) $(version) $(loc) $(library-type) ; local r ; r += [ generate $(name)-config.cmake : $(name) : @boost-install%generate-cmake-config $(reqs) ] ; r += [ generate $(name)-config-version.cmake : $(name) : @boost-install%generate-cmake-config-version $(reqs) ] ; if $(library-type) != INTERFACE { r += [ generate $(name)-variant.cmake : $(name) : @boost-install%generate-cmake-variant $(reqs) ] ; } return $(r) ; } # install-cmake-config rule install-cmake-config ( location : version : name * ) { #.debug install-cmake-config $(name) ; local configs ; for local nm in $(name) { configs += [ install-cmake-config- $(location) : $(version) : $(nm) ] ; } local p = [ project.current ] ; alias install-cmake-config : $(configs) ; $(p).mark-target-as-explicit install-cmake-config ; } # collect-targets: Returns the targets and all their dependencies. # Copied from stage.jam # TODO: Factor this out as a utility in virtal-target.jam rule collect-targets ( targets * ) { # Find subvariants local s ; for local t in $(targets) { s += [ $(t).creating-subvariant ] ; } s = [ sequence.unique $(s) ] ; local result = [ new set ] ; $(result).add $(targets) ; for local i in $(s) { $(i).all-referenced-targets $(result) ; } local result2 ; for local r in [ $(result).list ] { if $(r:G) != { result2 += $(r:G=) ; } } DELETE_MODULE $(result) ; return [ sequence.unique $(result2) ] ; } # get-dependency-projects: Returns all the projects of any dependency of the sources. rule get-dependency-projects ( sources * ) { local result ; for local t in [ collect-targets $(sources) ] { result += [ $(t).project ] ; } return [ sequence.unique $(result) ] ; } # generate-dependencies: find and generate the stage and install targets # corresponding to the source libraries. rule generate-dependencies ( project name ? : property-set : sources * ) { local stage-targets ; local stage-or-install = [ $(property-set).get ] ; local excluded-projects = $(project) [ $(project).find /boost ] ; for local p in [ get-dependency-projects $(sources) ] [ $(project).find /boost/headers ] { if ! ( $(p) in $(excluded-projects) ) { stage-targets += [ $(p).find $(stage-or-install) : no-error ] ; } } local props = [ $(property-set).propagated ] ; local result ; local usage-requirements = [ property-set.empty ] ; for local t in $(stage-targets) { local g = [ $(t).generate $(props) ] ; usage-requirements = [ $(usage-requirements).add $(g[1]) ] ; result += $(g[2-]) ; } return $(usage-requirements) $(result) ; } # boost-install rule boost-install ( VERSION : libraries * ) { .debug boost-install $(libraries) ; # Compute install-requirements local install-requirements ; local layout = [ modules.peek boostcpp : layout ] ; local BOOST_VERSION_TAG = [ modules.peek boostcpp : BOOST_VERSION_TAG ] ; if $(layout) = versioned { install-requirements += boost-$(BOOST_VERSION_TAG) ; } local install-default-prefix ; if [ os.name ] = NT { install-default-prefix = C:/Boost ; } else { install-default-prefix = /usr/local ; } install-requirements += $(install-default-prefix) ; # Target install-libraries local p = [ project.current ] ; package.install install-libraries boost : $(install-requirements) : # No binaries : $(libraries) : # No headers ; $(p).mark-target-as-explicit install-libraries ; # Target install-cmake-config local prefix = [ option.get prefix : $(install-default-prefix) ] ; local lib-locate = [ option.get libdir : $(prefix)/lib ] ; install-cmake-config $(lib-locate) : $(VERSION) : $(libraries) ; # Target install-detect-toolset local boost-install-dir = [ modules.binding $(__name__) ] ; boost-install-dir = $(boost-install-dir:D) ; install install-detect-toolset : $(boost-install-dir)/BoostDetectToolset.cmake : $(lib-locate)/cmake BoostDetectToolset-$(VERSION).cmake ; $(p).mark-target-as-explicit install-detect-toolset ; # Target install generate install-dependencies : $(libraries) : @boost-install%generate-dependencies install ; $(p).mark-target-as-explicit install-dependencies ; alias install : install-libraries install-cmake-config install-detect-toolset install-dependencies ; $(p).mark-target-as-explicit install ; # Target stage local stage-locate = [ modules.peek boostcpp : BOOST_STAGE_LOCATE ] ; install stage-libraries : $(libraries) : $(stage-locate)/lib ; $(p).mark-target-as-explicit stage-libraries ; generate stage-dependencies : $(libraries) : @boost-install%generate-dependencies stage ; $(p).mark-target-as-explicit stage-dependencies ; alias stage : stage-libraries stage-dependencies ; $(p).mark-target-as-explicit stage ; }