1#  Copyright (c) 2004 Vladimir Prus.
2#
3#  Use, modification and distribution is subject to the Boost Software
4#  License Version 1.0. (See accompanying file LICENSE_1_0.txt or
5#  http://www.boost.org/LICENSE_1_0.txt)
6
7""" This file implements linking semantics common to all unixes. On unix, static
8    libraries must be specified in a fixed order on the linker command line. Generators
9    declared there store information about the order and use it properly.
10"""
11
12import builtin
13from b2.build import generators, type
14from b2.util.utility import *
15from b2.util import set, sequence
16
17class UnixLinkingGenerator (builtin.LinkingGenerator):
18
19    def __init__ (self, id, composing, source_types, target_types, requirements):
20        builtin.LinkingGenerator.__init__ (self, id, composing, source_types, target_types, requirements)
21
22    def run (self, project, name, prop_set, sources):
23        result = builtin.LinkingGenerator.run (self, project, name, prop_set, sources)
24        if result:
25            set_library_order (project.manager (), sources, prop_set, result [1])
26
27        return result
28
29    def generated_targets (self, sources, prop_set, project, name):
30        sources2 = []
31        libraries = []
32        for l in sources:
33            if type.is_derived (l.type (), 'LIB'):
34                libraries.append (l)
35
36            else:
37                sources2.append (l)
38
39        sources = sources2 + order_libraries (libraries)
40
41        return builtin.LinkingGenerator.generated_targets (self, sources, prop_set, project, name)
42
43
44class UnixArchiveGenerator (builtin.ArchiveGenerator):
45    def __init__ (self, id, composing, source_types, target_types_and_names, requirements):
46        builtin.ArchiveGenerator.__init__ (self, id, composing, source_types, target_types_and_names, requirements)
47
48    def run (self, project, name, prop_set, sources):
49        from b2.build.property_set import PropertySet
50        result = builtin.ArchiveGenerator.run(self, project, name, prop_set, sources)
51        if result and isinstance(result[0], PropertySet):
52            _, targets = result
53        else:
54            targets = result
55        set_library_order(project.manager(), sources, prop_set, targets)
56        return result
57
58class UnixSearchedLibGenerator (builtin.SearchedLibGenerator):
59
60    def __init__ (self):
61        builtin.SearchedLibGenerator.__init__ (self)
62
63    def optional_properties (self):
64        return self.requirements ()
65
66    def run (self, project, name, prop_set, sources):
67        result = SearchedLibGenerator.run (project, name, prop_set, sources)
68
69        set_library_order (sources, prop_set, result)
70
71        return result
72
73class UnixPrebuiltLibGenerator (generators.Generator):
74    def __init__ (self, id, composing, source_types, target_types_and_names, requirements):
75        generators.Generator.__init__ (self, id, composing, source_types, target_types_and_names, requirements)
76
77    def run (self, project, name, prop_set, sources):
78        f = prop_set.get ('<file>')
79        set_library_order_aux (f, sources)
80        return f + sources
81
82### # The derived toolset must specify their own rules and actions.
83# FIXME: restore?
84# action.register ('unix.prebuilt', None, None)
85
86
87generators.register (UnixPrebuiltLibGenerator ('unix.prebuilt', False, [], ['LIB'], ['<file>', '<toolset>unix']))
88
89
90
91
92
93### # Declare generators
94### generators.register [ new UnixLinkingGenerator unix.link : LIB OBJ : EXE
95###     : <toolset>unix ] ;
96generators.register (UnixArchiveGenerator ('unix.archive', True, ['OBJ'], ['STATIC_LIB'], ['<toolset>unix']))
97
98### generators.register [ new UnixLinkingGenerator unix.link.dll : LIB OBJ : SHARED_LIB
99###     : <toolset>unix ] ;
100###
101### generators.register [ new UnixSearchedLibGenerator
102###    unix.SearchedLibGenerator : : SEARCHED_LIB : <toolset>unix ] ;
103###
104###
105### # The derived toolset must specify their own actions.
106### actions link {
107### }
108###
109### actions link.dll {
110### }
111
112def unix_archive (manager, targets, sources, properties):
113    pass
114
115# FIXME: restore?
116#action.register ('unix.archive', unix_archive, [''])
117
118### actions searched-lib-generator {
119### }
120###
121### actions prebuilt {
122### }
123
124
125from b2.util.order import Order
126__order = Order ()
127
128def set_library_order_aux (from_libs, to_libs):
129    for f in from_libs:
130        for t in to_libs:
131            if f != t:
132                __order.add_pair (f, t)
133
134def set_library_order (manager, sources, prop_set, result):
135    used_libraries = []
136    deps = prop_set.dependency ()
137
138    sources.extend(d.value for d in deps)
139    sources = sequence.unique(sources)
140
141    for l in sources:
142        if l.type () and type.is_derived (l.type (), 'LIB'):
143            used_libraries.append (l)
144
145    created_libraries = []
146    for l in result:
147        if l.type () and type.is_derived (l.type (), 'LIB'):
148            created_libraries.append (l)
149
150    created_libraries = set.difference (created_libraries, used_libraries)
151    set_library_order_aux (created_libraries, used_libraries)
152
153def order_libraries (libraries):
154    return __order.order (libraries)
155
156