1 # Copyright 2002-2017 Rene Rivera
2 # Copyright 2002-2017 Vladimir Prus
3 # Distributed under the Boost Software License, Version 1.0.
4 # (See accompanying file LICENSE_1_0.txt or copy at
5 # http://www.boost.org/LICENSE_1_0.txt)
10 # The generator class for handling EXE and SHARED_LIB creation.
12 class linking-generator : generator
20 composing ? : # The generator will be composing if a non-empty
21 # string is passed or the parameter is not given. To
22 # make the generator non-composing, pass an empty
29 generator.__init__ $(id) $(composing) : $(source-types)
30 : $(target-types) : $(requirements) ;
33 rule run ( project name ? : property-set : sources + )
35 sources += [ $(property-set).get <library> ] ;
37 # Add <library-path> properties for all searched libraries.
39 for local s in $(sources)
41 if [ $(s).type ] = SEARCHED_LIB
43 local search = [ $(s).search ] ;
44 extra += <library-path>$(search) ;
48 # It is possible that sources include shared libraries that did not came
49 # from 'lib' targets, e.g. .so files specified as sources. In this case
50 # we have to add extra dll-path properties and propagate extra xdll-path
51 # properties so that application linking to us will get xdll-path to
53 local extra-xdll-paths ;
54 for local s in $(sources)
56 if [ type.is-derived [ $(s).type ] SHARED_LIB ] && ! [ $(s).action ]
58 # Unfortunately, we do not have a good way to find the path to a
59 # file, so use this nasty approach.
61 # TODO: This needs to be done better. One thing that is really
62 # broken with this is that it does not work correctly with
63 # projects having multiple source locations.
64 local p = [ $(s).project ] ;
65 local location = [ path.root [ $(s).name ]
66 [ $(p).get source-location ] ] ;
67 extra-xdll-paths += [ path.parent $(location) ] ;
71 # Hardcode DLL paths only when linking executables.
72 # Pros: do not need to relink libraries when installing.
73 # Cons: "standalone" libraries (plugins, python extensions) can not
74 # hardcode paths to dependent libraries.
75 if [ $(property-set).get <hardcode-dll-paths> ] = true
76 && [ type.is-derived $(self.target-types[1]) EXE ]
78 local xdll-path = [ $(property-set).get <xdll-path> ] ;
79 extra += <dll-path>$(xdll-path) <dll-path>$(extra-xdll-paths) ;
84 property-set = [ $(property-set).add-raw $(extra) ] ;
87 local result = [ generator.run $(project) $(name) : $(property-set)
93 ur = [ extra-usage-requirements $(result) : $(property-set) ] ;
95 [ property-set.create <xdll-path>$(extra-xdll-paths) ] ] ;
97 return $(ur) $(result) ;
100 rule extra-usage-requirements ( created-targets * : property-set )
102 local result = [ property-set.empty ] ;
105 # Add appropriate <xdll-path> usage requirements.
106 local raw = [ $(property-set).raw ] ;
107 if <link>shared in $(raw)
110 local pwd = [ path.pwd ] ;
111 for local t in $(created-targets)
113 if [ type.is-derived [ $(t).type ] SHARED_LIB ]
115 paths += [ path.root [ path.make [ $(t).path ] ] $(pwd) ] ;
118 extra += $(paths:G=<xdll-path>) ;
121 # We need to pass <xdll-path> features that we've got from sources,
122 # because if a shared library is built, exe using it needs to know paths
123 # to other shared libraries this one depends on in order to be able to
124 # find them all at runtime.
126 # Just pass all features in property-set, it is theoretically possible
127 # that we will propagate <xdll-path> features explicitly specified by
128 # the user, but then the user is to blame for using an internal feature.
129 local values = [ $(property-set).get <xdll-path> ] ;
130 extra += $(values:G=<xdll-path>) ;
134 result = [ property-set.create $(extra) ] ;
139 rule generated-targets ( sources + : property-set : project name ? )
141 local sources2 ; # Sources to pass to inherited rule.
142 local properties2 ; # Properties to pass to inherited rule.
143 local libraries ; # Library sources.
145 # Searched libraries are not passed as arguments to the linker but via
146 # some option. So, we pass them to the action using a property.
147 properties2 = [ $(property-set).raw ] ;
150 for local s in $(sources)
152 if [ type.is-derived [ $(s).type ] SEARCHED_LIB ]
154 local name = [ $(s).name ] ;
169 properties2 += <find-shared-library>$(fsa:J=&&)
170 <find-static-library>$(fst:J=&&) ;
172 return [ generator.generated-targets $(sources2)
173 : [ property-set.create $(properties2) ] : $(project) $(name) ] ;
178 rule register-linker ( id composing ? : source-types + : target-types +
181 generators.register [ new linking-generator $(id) $(composing)
182 : $(source-types) : $(target-types) : $(requirements) ] ;
185 IMPORT $(__name__) : register-linker : : generators.register-linker ;