# Copyright 2002-2017 Rene Rivera
# Copyright 2002-2017 Vladimir Prus
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE.txt or copy at
# https://www.bfgroup.xyz/b2/LICENSE.txt)

import "class" : new ;
import generators ;

# The generator class for handling STATIC_LIB creation.
#
class archive-generator : generator
{
    import generators ;
    import property-set ;

    rule __init__ ( id composing ? : source-types + : target-types +
        : requirements * )
    {
        composing ?= true ;
        generator.__init__ $(id) $(composing) : $(source-types)
            : $(target-types) : $(requirements) ;
    }

    rule run ( project name ? : property-set : sources + )
    {
        sources += [ $(property-set).get <library>  ] ;

        property-set = [ $(property-set).add-raw <relevant>link ] ;

        local result = [ generator.run $(project) $(name) : $(property-set)
            : $(sources) ] ;

        # For static linking, if we get a library in source, we can not directly
        # link to it so we need to cause our dependencies to link to that
        # library. There are two approaches:
        # - adding the library to the list of returned targets.
        # - using the <library> usage requirements.
        # The problem with the first is:
        #
        #     lib a1 : : <file>liba1.a ;
        #     lib a2 : a2.cpp a1 : <link>static ;
        #     install dist : a2 ;
        #
        # here we will try to install 'a1', even though it is not necessary in
        # the general case. With the second approach, even indirect dependants
        # will link to the library, but it should not cause any harm. So, return
        # all LIB sources together with created targets, so that dependants link
        # to them.
        local usage-requirements = <relevant>link ;
        if [ $(property-set).get <link> ] = static
        {
            for local t in $(sources)
            {
                if [ $(t).type ] && [ type.is-derived [ $(t).type ] LIB ]
                {
                    usage-requirements += <library>$(t) ;
                }
            }
        }

        return [ generators.add-usage-requirements $(result) : $(usage-requirements) ] ;
    }
}


rule register-archiver ( id composing ? : source-types + : target-types +
    : requirements * )
{
    generators.register [ new archive-generator $(id) $(composing)
        : $(source-types) : $(target-types) : $(requirements) ] ;
}

IMPORT $(__name__) : register-archiver : : generators.register-archiver ;
