#  Copyright (c) 2004 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)

""" This file implements linking semantics common to all unixes. On unix, static
    libraries must be specified in a fixed order on the linker command line. Generators
    declared there store information about the order and use it properly.
"""

import builtin
from b2.build import generators, type
from b2.util.utility import *
from b2.util import set, sequence

class UnixLinkingGenerator (builtin.LinkingGenerator):
    
    def __init__ (self, id, composing, source_types, target_types, requirements):
        builtin.LinkingGenerator.__init__ (self, id, composing, source_types, target_types, requirements)
    
    def run (self, project, name, prop_set, sources):
        result = builtin.LinkingGenerator.run (self, project, name, prop_set, sources)
        if result:
            set_library_order (project.manager (), sources, prop_set, result [1])
                                
        return result
    
    def generated_targets (self, sources, prop_set, project, name):
        sources2 = []
        libraries = []
        for l in sources:
            if type.is_derived (l.type (), 'LIB'):
                libraries.append (l)

            else:
                sources2.append (l)
        
        sources = sources2 + order_libraries (libraries)
        
        return builtin.LinkingGenerator.generated_targets (self, sources, prop_set, project, name)


class UnixArchiveGenerator (builtin.ArchiveGenerator):
    def __init__ (self, id, composing, source_types, target_types_and_names, requirements):
        builtin.ArchiveGenerator.__init__ (self, id, composing, source_types, target_types_and_names, requirements)
        
    def run (self, project, name, prop_set, sources):
        result = builtin.ArchiveGenerator.run(self, project, name, prop_set, sources)
        set_library_order(project.manager(), sources, prop_set, result)
        return result

class UnixSearchedLibGenerator (builtin.SearchedLibGenerator):
    
    def __init__ (self):
        builtin.SearchedLibGenerator.__init__ (self)
    
    def optional_properties (self):
        return self.requirements ()
              
    def run (self, project, name, prop_set, sources, multiple):
        result = SearchedLibGenerator.run (project, name, prop_set, sources, multiple)
        
        set_library_order (sources, prop_set, result)
        
        return result

class UnixPrebuiltLibGenerator (generators.Generator):
    def __init__ (self, id, composing, source_types, target_types_and_names, requirements):
        generators.Generator.__init__ (self, id, composing, source_types, target_types_and_names, requirements)

    def run (self, project, name, prop_set, sources, multiple):
        f = prop_set.get ('<file>')
        set_library_order_aux (f, sources)
        return (f, sources)

### # The derived toolset must specify their own rules and actions.
# FIXME: restore?
# action.register ('unix.prebuilt', None, None)


generators.register (UnixPrebuiltLibGenerator ('unix.prebuilt', False, [], ['LIB'], ['<file>', '<toolset>unix']))





### # Declare generators
### generators.register [ new UnixLinkingGenerator unix.link : LIB OBJ : EXE 
###     : <toolset>unix ] ;
generators.register (UnixArchiveGenerator ('unix.archive', True, ['OBJ'], ['STATIC_LIB'], ['<toolset>unix']))

### generators.register [ new UnixLinkingGenerator unix.link.dll : LIB OBJ : SHARED_LIB 
###     : <toolset>unix ] ;
### 
### generators.register [ new UnixSearchedLibGenerator 
###    unix.SearchedLibGenerator : : SEARCHED_LIB : <toolset>unix ] ;
### 
### 
### # The derived toolset must specify their own actions.
### actions link {
### }
### 
### actions link.dll {
### }

def unix_archive (manager, targets, sources, properties):
    pass

# FIXME: restore?
#action.register ('unix.archive', unix_archive, [''])

### actions searched-lib-generator {    
### }
### 
### actions prebuilt {
### }


from b2.util.order import Order
__order = Order ()

def set_library_order_aux (from_libs, to_libs):
    for f in from_libs:
        for t in to_libs:
            if f != t:
                __order.add_pair (f, t)

def set_library_order (manager, sources, prop_set, result):
    used_libraries = []
    deps = prop_set.dependency ()
    
    [ sources.append (manager.get_object (get_value (x))) for x in deps ]
    sources = sequence.unique (sources)

    for l in sources:
        if l.type () and type.is_derived (l.type (), 'LIB'):
            used_libraries.append (l)

    created_libraries = []
    for l in result:
        if l.type () and type.is_derived (l.type (), 'LIB'):
            created_libraries.append (l)
    
    created_libraries = set.difference (created_libraries, used_libraries)
    set_library_order_aux (created_libraries, used_libraries)

def order_libraries (libraries):
    return __order.order (libraries)
     
