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        result = builtin.ArchiveGenerator.run(self, project, name, prop_set, sources)
50        set_library_order(project.manager(), sources, prop_set, result)
51        return result
52
53class UnixSearchedLibGenerator (builtin.SearchedLibGenerator):
54
55    def __init__ (self):
56        builtin.SearchedLibGenerator.__init__ (self)
57
58    def optional_properties (self):
59        return self.requirements ()
60
61    def run (self, project, name, prop_set, sources):
62        result = SearchedLibGenerator.run (project, name, prop_set, sources)
63
64        set_library_order (sources, prop_set, result)
65
66        return result
67
68class UnixPrebuiltLibGenerator (generators.Generator):
69    def __init__ (self, id, composing, source_types, target_types_and_names, requirements):
70        generators.Generator.__init__ (self, id, composing, source_types, target_types_and_names, requirements)
71
72    def run (self, project, name, prop_set, sources):
73        f = prop_set.get ('<file>')
74        set_library_order_aux (f, sources)
75        return f + sources
76
77### # The derived toolset must specify their own rules and actions.
78# FIXME: restore?
79# action.register ('unix.prebuilt', None, None)
80
81
82generators.register (UnixPrebuiltLibGenerator ('unix.prebuilt', False, [], ['LIB'], ['<file>', '<toolset>unix']))
83
84
85
86
87
88### # Declare generators
89### generators.register [ new UnixLinkingGenerator unix.link : LIB OBJ : EXE
90###     : <toolset>unix ] ;
91generators.register (UnixArchiveGenerator ('unix.archive', True, ['OBJ'], ['STATIC_LIB'], ['<toolset>unix']))
92
93### generators.register [ new UnixLinkingGenerator unix.link.dll : LIB OBJ : SHARED_LIB
94###     : <toolset>unix ] ;
95###
96### generators.register [ new UnixSearchedLibGenerator
97###    unix.SearchedLibGenerator : : SEARCHED_LIB : <toolset>unix ] ;
98###
99###
100### # The derived toolset must specify their own actions.
101### actions link {
102### }
103###
104### actions link.dll {
105### }
106
107def unix_archive (manager, targets, sources, properties):
108    pass
109
110# FIXME: restore?
111#action.register ('unix.archive', unix_archive, [''])
112
113### actions searched-lib-generator {
114### }
115###
116### actions prebuilt {
117### }
118
119
120from b2.util.order import Order
121__order = Order ()
122
123def set_library_order_aux (from_libs, to_libs):
124    for f in from_libs:
125        for t in to_libs:
126            if f != t:
127                __order.add_pair (f, t)
128
129def set_library_order (manager, sources, prop_set, result):
130    used_libraries = []
131    deps = prop_set.dependency ()
132
133    sources.extend(d.value() for d in deps)
134    sources = sequence.unique(sources)
135
136    for l in sources:
137        if l.type () and type.is_derived (l.type (), 'LIB'):
138            used_libraries.append (l)
139
140    created_libraries = []
141    for l in result:
142        if l.type () and type.is_derived (l.type (), 'LIB'):
143            created_libraries.append (l)
144
145    created_libraries = set.difference (created_libraries, used_libraries)
146    set_library_order_aux (created_libraries, used_libraries)
147
148def order_libraries (libraries):
149    return __order.order (libraries)
150
151