Skip to content

Commit 9b3e02a

Browse files
committed
smarter install logic
1 parent 25f474d commit 9b3e02a

File tree

8 files changed

+312
-69
lines changed

8 files changed

+312
-69
lines changed

b2/install-extra.jam

Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
# Copyright 2019 Dmitry Arkhipov
2+
# Distributed under the Boost Software License, Version 1.0.
3+
# (See accompanying file LICENSE_1_0.txt or copy at
4+
# http://www.boost.org/LICENSE_1_0.txt)
5+
6+
7+
import feature ;
8+
import param ;
9+
import path ;
10+
import project ;
11+
import targets ;
12+
13+
14+
.dirs
15+
= exec-prefix bindir sbindir libexecdir datarootdir datadir
16+
sysconfdir sharedstatedir localstatedir runstatedir includedir
17+
oldincludedir docdir infodir htmldir dvidir pdfdir psdir libdir lispdir
18+
localedir mandir
19+
;
20+
21+
22+
# features that specify paths to installation prefixes and well-known
23+
# installation directories
24+
feature.feature stage-prefix : : free path ;
25+
feature.feature install-prefix : : free path ;
26+
for local dir in $(.dirs) { feature.feature install-$(dir) : : free ; }
27+
28+
# feature that specifies the name of the package to which installed files
29+
# belong
30+
feature.feature install-package : : free ;
31+
32+
33+
34+
class install-extra-target-class : install-target-class {
35+
import install-extra ;
36+
37+
# If <location> is not set, sets it based on the project data.
38+
rule update-location ( property-set ) {
39+
local loc = [ $(property-set).get <location> ] ;
40+
if ! $(loc) {
41+
# check if installation to a well-known directory was requested
42+
local matches = [ MATCH "^\\((.+)\\)(.*)" : $(self.name:G=) ] ;
43+
if $(matches) {
44+
loc = [ well-known-location $(matches) : $(property-set) ] ;
45+
} else {
46+
loc = [ path.root $(self.name) [ $(self.project).get location ] ] ;
47+
}
48+
property-set = [ $(property-set).add-raw $(loc:G=<location>) ] ;
49+
}
50+
return $(property-set) ;
51+
}
52+
53+
# Returns location inside a well-known directory
54+
local rule well-known-location ( well-known-dir subdir : property-set ) {
55+
# at this point subdir is either an empty string or an absolute path, but
56+
# we need it to be either an empty string or a relative path
57+
if $(subdir) != "" { subdir = [ path.relative $(subdir) / ] ; }
58+
59+
local prefix
60+
= [ install-extra.get-dir $(well-known-dir)
61+
: $(property-set)
62+
: staged
63+
: [ $(self.project).get id ]
64+
] ;
65+
return [ path.root $(subdir) $(prefix) ] ;
66+
}
67+
}
68+
69+
70+
rule install ( name : sources * : requirements * : default-build * ) {
71+
param.handle-named-params
72+
sources requirements default-build usage-requirements ;
73+
74+
local project = [ project.current ] ;
75+
76+
# Unless the user has explicitly asked us to hardcode dll paths, add
77+
# <hardcode-dll-paths>false in requirements, to override default value.
78+
if ! <hardcode-dll-paths>true in $(requirements) {
79+
requirements += <hardcode-dll-paths>false ;
80+
}
81+
82+
if <tag> in $(requirements:G) {
83+
import errors ;
84+
errors.user-error
85+
The <tag> property is not allowed for the 'install' rule. ;
86+
}
87+
88+
targets.create-metatarget install-extra-target-class
89+
: $(project) : $(name) : $(sources) : $(requirements) : $(default-build) ;
90+
}
91+
92+
93+
# Returns the path to the requested well-known directory
94+
rule get-dir ( well-known-dir : property-set : flags * : project ? ) {
95+
local package-name = [ get-package-name $(property-set) : $(project) ] ;
96+
97+
local relative ;
98+
if relative in $(flags) { relative = relative ; }
99+
100+
local staged ;
101+
if staged in $(flags) { staged = staged ; }
102+
103+
return
104+
[ get-dir-aux $(well-known-dir)
105+
: $(package-name)
106+
: $(property-set)
107+
: $(relative)
108+
: $(staged)
109+
] ;
110+
}
111+
112+
113+
rule get-package-name ( property-set : package ? ) {
114+
if ! $(package) {
115+
local project = [ project.current ] ;
116+
package = [ $(project).get id ] ;
117+
if ! $(package) {
118+
local root = [ $(project).get project-root ] ;
119+
root = [ path.root $(root) [ path.pwd ] ] ;
120+
package = $(root) ;
121+
}
122+
}
123+
return $(package:B) ;
124+
}
125+
126+
127+
rule target-native-path ( path : property-set ) {
128+
local os ;
129+
switch [ $(property-set).get <target-os> ] {
130+
case cygwin : os = CYGWIN ;
131+
case vms : os = VMS ;
132+
case windows : os = NT ;
133+
case * : os = UNIX ;
134+
}
135+
local native = native-$(os) ;
136+
137+
return [ path.$(native) $(path) ] ;
138+
}
139+
140+
141+
local rule get-dir-aux
142+
( well-known-dir : package-name : property-set : relative ? : staged ? )
143+
{
144+
local loc ;
145+
# We treat the 'prefix' directory in a special way, because it doesn't have
146+
# a base directory and it can be overriden by staging prefix.
147+
if $(well-known-dir) = prefix {
148+
loc
149+
= [ get-install-prefix $(package-name) : $(property-set) : $(staged) ] ;
150+
} else {
151+
# First, try getting the path for requested directory from properties.
152+
loc = [ $(property-set).get <install-$(well-known-dir)> ] ;
153+
154+
local info = [ well-known-default $(well-known-dir) : $(package-name) ] ;
155+
# Otherwise, use the default path. In both cases, it could be a
156+
# relative path.
157+
loc ?= $(info[1]) ;
158+
159+
# If there is a base directory, we may need to either prepend it to the
160+
# result, if we want an absolute path, or remove it from the beginning, if
161+
# we want a relative path.
162+
if $(info[2]) {
163+
local rooted = [ path.is-rooted $(loc) ] ;
164+
165+
local operation ;
166+
if $(rooted) && $(relative) {
167+
# We only need to prepend base if the result is relative.
168+
operation = relative ;
169+
} else if ! ( $(rooted) || $(relative) ) {
170+
# We only need to remove base if the result is absolute.
171+
operation = root ;
172+
}
173+
174+
if $(operation) {
175+
# Always get absolute path to base.
176+
local base
177+
= [ get-dir-aux $(info[2])
178+
: $(package-name)
179+
: $(property-set)
180+
:
181+
: $(staged)
182+
] ;
183+
loc = [ path.$(operation) $(loc) $(base) ] ;
184+
}
185+
}
186+
}
187+
188+
return $(loc) ;
189+
}
190+
191+
192+
# For a given well-known directory returns its base directory and
193+
# relative path
194+
local rule well-known-default ( well-known-dir : package-name ) {
195+
switch $(well-known-dir) {
196+
case exec-prefix : return "" prefix ;
197+
case bindir : return bin exec-prefix ;
198+
case sbindir : return sbin exec-prefix ;
199+
case libexecdir : return libexec exec-prefix ;
200+
case libdir : return lib exec-prefix ;
201+
case datarootdir : return share prefix ;
202+
case datadir : return "" datarootdir ;
203+
case sysconfdir : return etc prefix ;
204+
case sharedstatedir : return com prefix ;
205+
case localstatedir : return var prefix ;
206+
case runstatedir : return run localstatedir ;
207+
case includedir : return "include" prefix ;
208+
case oldincludedir : return /usr/include ;
209+
case docdir : return $(package-name:D=doc) datarootdir ;
210+
case infodir : return info datarootdir ;
211+
case htmldir : return "" docdir ;
212+
case dvidir : return "" docdir ;
213+
case pdfdir : return "" docdir ;
214+
case psdir : return "" docdir ;
215+
case lispdir : return emacs/site-lisp datarootdir ;
216+
case localedir : return locale datarootdir ;
217+
case mandir : return man datarootdir ;
218+
case * :
219+
import errors ;
220+
errors.error
221+
$(well-known-dir) is not a well-known installation directory. Choose
222+
one of prefix, "$(.dirs:J=, )". ;
223+
}
224+
}
225+
226+
227+
local rule get-install-prefix ( package-name : property-set : staged ? ) {
228+
local prefix ;
229+
if $(staged) { prefix = [ $(property-set).get <stage-prefix> ] ; }
230+
prefix ?= [ $(property-set).get <install-prefix> ] ;
231+
if ! $(prefix) {
232+
if [ modules.peek : NT ] {
233+
prefix = C:\\$(package-name) ;
234+
} else {
235+
return /usr/local ;
236+
}
237+
}
238+
return $(prefix) ;
239+
}

conanfile.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import re
88

99

10-
b2 = python_requires("b2-helper/0.2.0@grisumbras/testing")
10+
b2 = python_requires("b2-helper/0.3.0@grisumbras/testing")
1111

1212

1313
def get_version():
@@ -32,14 +32,18 @@ class EnumFlagsConan(b2.B2.Mixin, ConanFile):
3232
exports_sources = (
3333
"jamroot.jam",
3434
"*build.jam",
35-
"exports/*.jam",
3635
"*.hpp",
3736
"*.cpp",
3837
"LICENSE*",
38+
"b2/*",
3939
)
4040
no_copy_source = True
4141
build_requires = "boost_build/[>=1.68]@bincrafters/stable"
4242

43+
def b2_setup_builder(self, builder):
44+
builder.properties.install_prefix = self.package_folder
45+
return builder
46+
4347
def package_info(self):
4448
self.info.header_only()
4549

exports/build.jam

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,54 @@
1-
import install-path ;
21
import make ;
2+
import path ;
33
import print ;
4+
import property-set ;
5+
import feature ;
46

5-
6-
prefix = [ install-path.prefix enum-flags ] ;
7-
execprefix = [ install-path.exec-prefix $(prefix) ] ;
8-
libdir = [ install-path.libdir $(execprefix) ] ;
9-
includedir = [ install-path.includedir $(prefix) ] ;
7+
import b2/install-extra : install ;
108

119

1210
make enum-flags.pc : : @write-pc ;
13-
install install-pc : enum-flags.pc : <location>$(libdir)/pkgconfig ;
11+
local install-pc = [ install (libdir)/pkgconfig : enum-flags.pc ] ;
1412

1513
make enumflags-config.cmake : : @write-cmake-config ;
1614
make enumflags-config-version.cmake : : @write-cmake-version ;
17-
install install-cmake
18-
: enumflags-config.cmake
19-
enumflags-config-version.cmake
20-
: <location>$(libdir)/cmake/enumflags-$(VERSION)
21-
;
15+
local install-cmake
16+
= [ install (libdir)/cmake/enumflags-$(VERSION)
17+
: enumflags-config.cmake
18+
enumflags-config-version.cmake
19+
] ;
2220

23-
alias install : install-pc install-cmake ;
24-
explicit install install-pc install-cmake ;
21+
alias install : $(install-pc) $(install-cmake) ;
22+
explicit install ;
2523

2624

2725
rule write-pc ( target : sources * : properties * ) {
26+
local ps = [ property-set.create $(properties) ] ;
27+
28+
local prefix = [ install-extra.get-dir prefix : $(ps) ] ;
29+
prefix = [ install-extra.target-native-path $(prefix) : $(ps) ] ;
30+
31+
local includedir = [ install-extra.get-dir includedir : $(ps) : relative ] ;
32+
includedir = [ path.root $(includedir) "${prefix}" ] ;
33+
includedir = [ install-extra.target-native-path $(includedir) : $(ps) ] ;
34+
2835
write $(target)
29-
: "Name: enum-flags"
36+
: "prefix=$(prefix)"
37+
"includedir=$(includedir)"
38+
""
39+
"Name: enum-flags"
3040
"Description: Bit-flags for C++ scoped enums"
3141
"Version: $(VERSION)"
32-
"Cflags: -I$(includedir)"
42+
"Cflags: -I${includedir}"
3343
""
3444
;
3545
}
3646

3747

3848
rule write-cmake-config ( target : sources * : properties * ) {
49+
local ps = [ property-set.create $(properties) ] ;
50+
local includedir = [ install-extra.get-dir includedir : $(ps) ] ;
51+
3952
write $(target)
4053
: "if(TARGET EnumFlags::EnumFlags)"
4154
" return()"
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
set(PACKAGE_VERSION 0.1.0)
2+
3+
if(NOT PACKAGE_FIND_VERSION OR PACKAGE_FIND_VERSION EQUAL 0.1.0)
4+
set(PACKAGE_VERSION_EXACT TRUE)
5+
set(PACKAGE_VERSION_COMPATIBLE TRUE)
6+
set(PACKAGE_VERSION_UNSUITABLE FALSE)
7+
else()
8+
set(PACKAGE_VERSION_EXACT FALSE)
9+
set(PACKAGE_VERSION_COMPATIBLE FALSE)
10+
set(PACKAGE_VERSION_UNSUITABLE TRUE)
11+
endif()
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
if(TARGET EnumFlags::EnumFlags)
2+
return()
3+
endif()
4+
5+
add_library(EnumFlags::EnumFlags INTERFACE IMPORTED)
6+
set_target_properties(
7+
EnumFlags::EnumFlags
8+
PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "/home/arhipov_d/dev/1/enum-flags/tmp/stage/include"
9+
)

0 commit comments

Comments
 (0)