-
Notifications
You must be signed in to change notification settings - Fork 50
/
Copy pathpackage.jam
274 lines (242 loc) · 9.07 KB
/
package.jam
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
# Copyright (c) 2005 Vladimir Prus.
# Copyright 2006 Rene Rivera.
#
# Use, modification and distribution is subject to the Boost Software
# License Version 1.0. (See accompanying file LICENSE.txt or
# https://www.bfgroup.xyz/b2/LICENSE.txt)
# Provides mechanism for installing whole packages into a specific directory
# structure. This is opposed to the 'install' rule, that installs a number of
# targets to a single directory, and does not care about directory structure at
# all.
# Example usage:
#
# package.install boost : <properties>
# : <binaries>
# : <libraries>
# : <headers>
# ;
#
# This will install binaries, libraries and headers to the 'proper' location,
# given by command line options --prefix, --exec-prefix, --bindir, --libdir and
# --includedir.
#
# The rule is just a convenient wrapper, avoiding the need to define several
# 'install' targets.
#
# The only install-related feature is <install-source-root>. It will apply to
# headers only and if present, paths of headers relatively to source root will
# be retained after installing. If it is not specified, then "." is assumed, so
# relative paths in headers are always preserved.
import "class" : new ;
import option ;
import project ;
import feature ;
import path ;
import property ;
import stage ;
import targets ;
import modules ;
import os ;
feature.feature install-default-prefix : : free incidental ;
class package-paths
{
import feature ;
import modules ;
import option ;
import os ;
import path ;
rule __init__ ( default-prefix )
{
local explicit-options = [ MATCH --(prefix|bindir|libdir|includedir|datarootdir)=.*
: [ modules.peek : ARGV ] ] ;
self.has-$(explicit-options) = true ;
if prefix in $(explicit-options)
{
# If --prefix is explicitly specified on the command line,
# then we need wipe away any settings of libdir/includir that
# is specified via options in config files.
option.set bindir : ;
option.set libdir : ;
option.set includedir : ;
option.set datarootdir : ;
}
handle-path prefix : $(default-prefix) ;
handle-path libdir : $(self.prefix)/lib ;
handle-path bindir : $(self.prefix)/bin ;
handle-path includedir : $(self.prefix)/include ;
handle-path datarootdir : $(self.prefix)/share ;
}
local rule handle-path ( option : default-value )
{
local opt = [ option.get $(option) ] ;
if $(opt)
{
opt = [ path.root [ path.make $(opt) ] [ path.pwd ] ] ;
}
else
{
opt = $(default-value) ;
}
self.$(option) = $(opt) ;
}
rule prefix ( )
{
return $(self.prefix) ;
}
rule libdir ( )
{
return $(self.libdir) ;
}
rule bindir ( )
{
return $(self.bindir) ;
}
rule includedir ( )
{
return $(self.includedir) ;
}
rule datarootdir ( )
{
return $(self.datarootdir) ;
}
rule get ( option )
{
if ! $(self.$(option))
{
local info = [ modules.peek package : .options.$(option) ] ;
local default-value = $(info[1]) ;
local relative-to = $(info[2]) ;
if $(self.has-$(relative-to))
{
option.set $(option) ;
self.has-$(option) = true ;
}
if [ MATCH --$(option)=(.*) : [ modules.peek : ARGV ] ]
{
self.has-$(option) = true ;
}
local adjusted-default =
[ path.join [ get $(relative-to) ] $(default-value) ] ;
handle-path $(option) : $(adjusted-default) ;
}
return $(self.$(option)) ;
}
}
# Registers an additional path option. The option name
# can then be used with a package-paths object.
#
# default-path is the default path that will be used if
# the option is not set explicitly. It will be interpreted
# relative to another option. This allows options to be
# defined hierarchically with --prefix as the root.
#
# relative-to should be the name of another option. It defaults
# to prefix.
#
# Example::
#
# package.add-path-option cmakedir : cmake : libdir ;
# cmakedir = [ $(mypaths).get cmakedir ] ; # defaults to /usr/local/lib/cmake
#
rule add-path-option ( name : default-path : relative-to ? )
{
local value = $(default-path) $(relative-to:E=prefix) ;
if $(.options.$(name)) && $(.options.$(name)) != $(value)
{
import errors ;
errors.error Duplicate definition of $(name) ;
}
.options.$(name) = $(value) ;
}
# Returns a package-paths object that can be used
# to find the various install paths. If requirements
# contains <install-default-prefix> then that will be used
# as the default prefix, otherwise a platform specific
# default prefix will be used. All other properties
# in requirements are ignored.
#
rule paths ( package-name : requirements * )
{
local default-prefix = [ feature.get-values <install-default-prefix> : $(requirements) ] ;
# Or some likely defaults if neither is given.
if ! $(default-prefix)
{
if [ os.name ] = NT { default-prefix = C:\\$(package-name) ; }
else { default-prefix = /usr/local ; }
}
default-prefix = [ path.make $(default-prefix) ] ;
if ! $(.package-paths.$(default-prefix))
{
.package-paths.$(default-prefix) = [ new package-paths $(default-prefix) ] ;
}
return $(.package-paths.$(default-prefix)) ;
}
rule install ( name package-name ? : requirements * : binaries * : libraries * : headers * )
{
package-name ?= $(name) ;
# If <install-source-root> is not specified, all headers are installed to
# prefix/include, no matter what their relative path is. Sometimes that is
# what is needed.
local install-source-root = [ property.select <install-source-root> :
$(requirements) ] ;
install-source-root = $(install-source-root:G=) ;
requirements = [ property.change $(requirements) : <install-source-root> ] ;
local install-header-subdir = [ property.select <install-header-subdir> :
$(requirements) ] ;
install-header-subdir = /$(install-header-subdir:G=) ;
install-header-subdir ?= "" ;
requirements = [ property.change $(requirements) : <install-header-subdir> ]
;
# First, figure out all locations. Use the default if no prefix option
# given.
local paths = [ paths $(package-name) : $(requirements) ] ;
# Binaries.
local bin-locate = [ $(paths).bindir ] ;
# Object code libraries.
local lib-locate = [ $(paths).libdir ] ;
# Source header files.
local include-locate = [ $(paths).includedir ] ;
stage.install $(name)-bin : $(binaries) : $(requirements)
<location>$(bin-locate) ;
alias $(name)-lib : $(name)-lib-shared $(name)-lib-static ;
# Since the install location of shared libraries differs on universe
# and cygwin, use target alternatives to make different targets.
# We should have used indirection conditioanl requirements, but it's
# awkward to pass bin-locate and lib-locate from there to another rule.
alias $(name)-lib-shared : $(name)-lib-shared-universe ;
alias $(name)-lib-shared : $(name)-lib-shared-cygwin : <target-os>cygwin ;
# For shared libraries, we install both explicitly specified one and the
# shared libraries that the installed executables depend on.
stage.install $(name)-lib-shared-universe : $(binaries) $(libraries) : $(requirements)
<location>$(lib-locate) <install-dependencies>on <install-type>SHARED_LIB ;
stage.install $(name)-lib-shared-cygwin : $(binaries) $(libraries) : $(requirements)
<location>$(bin-locate) <install-dependencies>on <install-type>SHARED_LIB ;
# For static libraries, we do not care about executable dependencies, since
# static libraries are already incorporated into them.
stage.install $(name)-lib-static : $(libraries) : $(requirements)
<location>$(lib-locate) <install-dependencies>on <install-type>STATIC_LIB ;
stage.install $(name)-headers : $(headers) : $(requirements)
<location>$(include-locate)$(install-header-subdir)
<install-source-root>$(install-source-root) ;
alias $(name) : $(name)-bin $(name)-lib $(name)-headers ;
local c = [ project.current ] ;
modules.call-in [ $(c).project-module ] : explicit $(name) $(name)-bin
$(name)-lib $(name)-headers $(name)-lib-shared $(name)-lib-static
$(name)-lib-shared-universe $(name)-lib-shared-cygwin ;
}
rule install-data ( target-name : package-name ? : data * : requirements * )
{
package-name ?= $(target-name) ;
local paths = [ paths $(package-name) : $(requirements) ] ;
local datadir = [ $(paths).datarootdir ] ;
stage.install $(target-name)
: $(data)
: $(requirements) <location>$(datadir)/$(package-name)
;
local c = [ project.current ] ;
local project-module = [ $(c).project-module ] ;
module $(project-module)
{
explicit $(1) ;
}
}