1#!/usr/local/bin/python3.8
2
3# Copyright 2003 Dave Abrahams
4# Copyright 2002, 2003, 2004, 2006 Vladimir Prus
5# Distributed under the Boost Software License, Version 1.0.
6# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
7
8import BoostBuild
9
10t = BoostBuild.Tester(use_test_config=False)
11
12
13# Test that usage requirements on main targets work (and are propagated all the
14# way up, and not only to direct dependants).
15t.write("jamroot.jam", "")
16
17# Note: 'lib cc ..', not 'lib c'. If using 'lib c: ...' the HP-CXX linker will
18# confuse it with the system C runtime.
19t.write("jamfile.jam", """\
20lib b : b.cpp : <link>shared:<define>SHARED_B : :
21    <define>FOO <link>shared:<define>SHARED_B ;
22lib cc : c.cpp b ;
23exe a : a.cpp cc ;
24""")
25
26t.write("b.cpp", """\
27void
28#if defined(_WIN32) && defined(SHARED_B)
29__declspec(dllexport)
30#endif
31foo() {}
32""")
33
34t.write("c.cpp", """\
35void
36#if defined(_WIN32) && defined(SHARED_B)
37__declspec(dllexport)
38#endif
39create_lib_please() {}
40""")
41
42t.write("a.cpp", """\
43#ifdef FOO
44void
45# if defined(_WIN32) && defined(SHARED_B)
46__declspec(dllexport)
47# endif
48foo() {}
49#endif
50int main() { foo(); }
51""")
52
53t.run_build_system()
54t.run_build_system(["--clean"])
55
56
57# Test that use requirements on main target work, when they are referred using
58# 'dependency' features.
59
60t.write("jamfile.jam", """\
61lib b : b.cpp : <link>shared:<define>SHARED_B : : <define>FOO
62    <link>shared:<define>SHARED_B ;
63exe a : a.cpp : <use>b ;
64""")
65
66t.write("b.cpp", """\
67void
68#if defined(_WIN32) && defined(SHARED_B)
69__declspec(dllexport)
70#endif
71foo() {}
72""")
73
74t.write("a.cpp", """\
75#ifdef FOO
76int main() {}
77#endif
78""")
79
80t.run_build_system()
81t.run_build_system(["--clean"])
82
83
84# Test that usage requirements on a project work.
85t.write("jamfile.jam", "exe a : a.cpp lib//b ;")
86
87t.write("lib/jamfile.jam", """\
88project
89   : requirements <link>shared:<define>SHARED_B
90   : usage-requirements <define>FOO <link>shared:<define>SHARED_B ;
91lib b : b.cpp ;
92""")
93
94t.write("lib/b.cpp", """\
95void
96#if defined(_WIN32) && defined(SHARED_B)
97__declspec(dllexport)
98#endif
99foo() {}
100""")
101
102t.run_build_system()
103
104
105# Test that use requirements are inherited correctly.
106t.write("jamfile.jam", "exe a : a.cpp lib/1//b ;")
107
108t.write("a.cpp", """\
109#if defined(FOO) && defined(ZOO)
110void foo() {}
111#endif
112int main() { foo(); }
113""")
114
115t.write("lib/jamfile.jam", """\
116project : requirements : usage-requirements <define>FOO ;
117""")
118
119t.write("lib/1/jamfile.jam", """\
120project
121   : requirements <link>shared:<define>SHARED_B
122   : usage-requirements <define>ZOO <link>shared:<define>SHARED_B ;
123lib b : b.cpp ;
124""")
125
126t.write("lib/1/b.cpp", """\
127void
128#if defined(_WIN32) && defined(SHARED_B)
129__declspec(dllexport)
130#endif
131foo() {}
132""")
133
134t.run_build_system()
135t.run_build_system(["--clean"])
136
137
138# Test that we correctly handle dependency features in usage requirements on
139# target.
140t.write("jamfile.jam", """\
141lib b : b.cpp : <link>shared:<define>SHARED_B : : <define>FOO
142    <link>shared:<define>SHARED_B ;
143
144# Here's the test: we should correctly handle dependency feature and get usage
145# requirements from 'b'.
146lib cc : c.cpp : <link>shared:<define>SHARED_C : : <library>b ;
147
148# This will build only if <define>FOO was propagated from 'c'.
149exe a : a.cpp cc ;
150""")
151
152t.write("a.cpp", """\
153#ifdef FOO
154void
155# if defined(_WIN32) && defined(SHARED_B)
156__declspec(dllexport)
157# endif
158foo();
159#endif
160
161int main() { foo(); }
162""")
163
164t.write("c.cpp", """\
165int
166#if defined(_WIN32) && defined(SHARED_C)
167__declspec(dllexport)
168#endif
169must_export_something;
170""")
171
172t.run_build_system()
173t.run_build_system(["--clean"])
174
175
176# Test correct handling of dependency features in project requirements.
177t.write("jamfile.jam", "exe a : a.cpp lib1//cc ;")
178
179t.write("lib1/jamfile.jam", """\
180project
181    : requirements <link>shared:<define>SHARED_C
182    : usage-requirements <library>../lib2//b <link>shared:<define>SHARED_C ;
183lib cc : c.cpp ;
184""")
185
186t.write("lib1/c.cpp", """\
187int
188#if defined(_WIN32) && defined(SHARED_C)
189__declspec(dllexport)
190#endif
191must_export_something;
192""")
193
194t.write("lib2/jamfile.jam", """\
195lib b : b.cpp : <link>shared:<define>SHARED_B : : <define>FOO
196    <link>shared:<define>SHARED_B ;
197""")
198
199t.copy("b.cpp", "lib2/b.cpp")
200
201t.run_build_system()
202
203
204# Test that targets listed in dependency features in usage requirements are
205# built with the correct properties.
206t.rm(".")
207
208t.write("jamroot.jam", "")
209t.write("jamfile.jam", """\
210lib main : main.cpp : <use>libs//lib1 : : <library>libs//lib1 ;
211exe hello : hello.cpp main : ;
212""")
213
214t.write("main.cpp", """\
215void
216#if defined(_WIN32) && defined(SHARED_LIB1)
217__declspec(dllimport)
218#endif
219foo();
220
221int main() { foo(); }
222""")
223
224t.write("hello.cpp", "\n")
225t.write("libs/a.cpp", """\
226void
227#if defined(_WIN32) && defined(SHARED_LIB1)
228__declspec(dllexport)
229#endif
230foo() {}
231""")
232
233
234# This library should be built with the same properties as 'main'. This is a
235# regression test for a bug when they were generated with empty properties, and
236# there were ambiguities between variants.
237t.write("libs/jamfile.jam", """\
238lib lib1 : a_d.cpp : <variant>debug <link>shared:<define>SHARED_LIB1 : :
239    <link>shared:<define>SHARED_LIB1 ;
240lib lib1 : a.cpp : <variant>release <link>shared:<define>SHARED_LIB1 : :
241    <link>shared:<define>SHARED_LIB1 ;
242""")
243
244t.write("libs/a_d.cpp", """\
245void
246#if defined(_WIN32) && defined(SHARED_LIB1)
247__declspec(dllexport)
248#endif
249foo() {}
250""")
251
252t.run_build_system(["link=static"])
253t.expect_addition("libs/bin/$toolset/debug/link-static*/a_d.obj")
254
255
256# Test that indirect conditionals are respected in usage requirements.
257t.rm(".")
258
259t.write("jamroot.jam", """\
260rule has-foo ( properties * ) { return <define>HAS_FOO ; }
261exe a : a.cpp b ;
262lib b : b.cpp : <link>static : : <conditional>@has-foo ;
263""")
264
265t.write("a.cpp", """\
266#ifdef HAS_FOO
267void foo();
268int main() { foo(); }
269#endif
270""")
271
272t.write("b.cpp", """\
273void
274#if defined(_WIN32) && defined(SHARED_B)
275__declspec(dllexport)
276#endif
277foo() {}
278""")
279
280t.run_build_system()
281t.expect_addition("bin/$toolset/debug*/a.exe")
282
283t.cleanup()
284