1#!/usr/local/bin/python3.8
2
3# Copyright 2017 Steven Watanabe
4# Distributed under the Boost Software License, Version 1.0.
5# (See accompanying file LICENSE_1_0.txt or copy at
6# http://www.boost.org/LICENSE_1_0.txt)
7
8# Tests configure.check-target-builds and friends
9
10import BoostBuild
11
12def test_check_target_builds():
13    t = BoostBuild.Tester(use_test_config=0)
14    t.write("Jamroot", """
15import configure ;
16obj pass : pass.cpp ;
17obj fail : fail.cpp ;
18explicit pass fail ;
19obj foo : foo.cpp :
20  [ configure.check-target-builds pass : <define>PASS : <define>FAIL ] ;
21obj bar : foo.cpp :
22  [ configure.check-target-builds fail : <define>FAIL : <define>PASS ] ;
23""")
24    t.write("pass.cpp", "void f() {}\n")
25    t.write("fail.cpp", "#error fail.cpp\n")
26    t.write("foo.cpp", """
27#ifndef PASS
28#error PASS not defined
29#endif
30#ifdef FAIL
31#error FAIL is defined
32#endif
33""")
34    t.run_build_system()
35    t.expect_output_lines([
36        "    - pass builds              : yes",
37        "    - fail builds              : no"])
38    t.expect_addition("bin/$toolset/debug*/pass.obj")
39    t.expect_addition("bin/$toolset/debug*/foo.obj")
40    t.expect_addition("bin/$toolset/debug*/bar.obj")
41    t.expect_nothing_more()
42
43    # An up-to-date build should use the cache
44    t.run_build_system()
45    t.expect_output_lines([
46        "    - pass builds              : yes (cached)",
47        "    - fail builds              : no  (cached)"])
48    t.expect_nothing_more()
49
50    # -a should re-run everything, including configuration checks
51    t.run_build_system(["-a"])
52    t.expect_output_lines([
53        "    - pass builds              : yes",
54        "    - fail builds              : no"])
55    t.expect_touch("bin/$toolset/debug*/pass.obj")
56    t.expect_touch("bin/$toolset/debug*/foo.obj")
57    t.expect_touch("bin/$toolset/debug*/bar.obj")
58    t.expect_nothing_more()
59
60    # --reconfigure should re-run configuration checks only
61    t.run_build_system(["--reconfigure"])
62    t.expect_output_lines([
63        "    - pass builds              : yes",
64        "    - fail builds              : no"])
65    t.expect_touch("bin/$toolset/debug*/pass.obj")
66    t.expect_nothing_more()
67
68    # -a -n should not rebuild configuration checks
69    t.run_build_system(["-a", "-n"])
70    t.expect_output_lines([
71        "    - pass builds              : yes (cached)",
72        "    - fail builds              : no  (cached)"])
73    t.expect_nothing_more()
74
75    # --clean-all should clear all configuration checks
76    t.run_build_system(["--clean-all"])
77    t.expect_output_lines([
78        "    - pass builds              : yes (cached)",
79        "    - fail builds              : no  (cached)"])
80    t.expect_removal("bin/$toolset/debug*/pass.obj")
81    t.expect_removal("bin/$toolset/debug*/foo.obj")
82    t.expect_removal("bin/$toolset/debug*/bar.obj")
83    t.expect_nothing_more()
84
85    # If configuration checks are absent, then --clean-all
86    # should create them and then delete them again.  This
87    # currently fails because clean cannot remove targets
88    # that were created in the same build.
89    #t.run_build_system(["--clean-all"])
90    #t.expect_output_lines([
91    #    "    - pass builds              : yes",
92    #    "    - fail builds              : no"])
93    #t.expect_nothing_more()
94
95    # Just verify that we're actually in the initial
96    # state here.
97    t.run_build_system()
98    t.expect_output_lines([
99        "    - pass builds              : yes",
100        "    - fail builds              : no"])
101    t.expect_addition("bin/$toolset/debug*/pass.obj")
102    t.expect_addition("bin/$toolset/debug*/foo.obj")
103    t.expect_addition("bin/$toolset/debug*/bar.obj")
104    t.expect_nothing_more()
105
106    t.cleanup()
107
108def test_choose():
109    t = BoostBuild.Tester(use_test_config=0)
110    t.write("Jamroot", """
111import configure ;
112obj pass : pass.cpp ;
113obj fail : fail.cpp ;
114explicit pass fail ;
115obj foo : foo.cpp :
116  [ configure.choose "which one?" : fail <define>FAIL : pass <define>PASS ] ;
117""")
118    t.write("pass.cpp", "void f() {}\n")
119    t.write("fail.cpp", "#error fail.cpp\n")
120    t.write("foo.cpp", """
121#ifndef PASS
122#error PASS not defined
123#endif
124#ifdef FAIL
125#error FAIL is defined
126#endif
127""")
128    t.run_build_system()
129    t.expect_output_lines([
130        "    - which one?               : pass"])
131    t.expect_addition("bin/$toolset/debug*/pass.obj")
132    t.expect_addition("bin/$toolset/debug*/foo.obj")
133    t.expect_nothing_more()
134
135    # An up-to-date build should use the cache
136    t.run_build_system()
137    t.expect_output_lines([
138        "    - which one?               : pass (cached)"])
139    t.expect_nothing_more()
140
141    # -a should re-run everything, including configuration checks
142    t.run_build_system(["-a"])
143    t.expect_output_lines([
144        "    - which one?               : pass"])
145    t.expect_touch("bin/$toolset/debug*/pass.obj")
146    t.expect_touch("bin/$toolset/debug*/foo.obj")
147    t.expect_nothing_more()
148
149    # --reconfigure should re-run configuration checks only
150    t.run_build_system(["--reconfigure"])
151    t.expect_output_lines([
152        "    - which one?               : pass"])
153    t.expect_touch("bin/$toolset/debug*/pass.obj")
154    t.expect_nothing_more()
155
156    # -a -n should not rebuild configuration checks
157    t.run_build_system(["-a", "-n"])
158    t.expect_output_lines([
159        "    - which one?               : pass (cached)"])
160    t.expect_nothing_more()
161
162    # --clean-all should clear all configuration checks
163    t.run_build_system(["--clean-all"])
164    t.expect_output_lines([
165        "    - which one?               : pass (cached)"])
166    t.expect_removal("bin/$toolset/debug*/pass.obj")
167    t.expect_removal("bin/$toolset/debug*/foo.obj")
168    t.expect_nothing_more()
169
170    # If configuration checks are absent, then --clean-all
171    # should create them and then delete them again.  This
172    # currently fails because clean cannot remove targets
173    # that were created in the same build.
174    #t.run_build_system(["--clean-all"])
175    #t.expect_output_lines([
176    #    "    - which one?               : pass"])
177    #t.expect_nothing_more()
178
179    # Just verify that we're actually in the initial
180    # state here.
181    t.run_build_system()
182    t.expect_output_lines([
183        "    - which one?               : pass"])
184    t.expect_addition("bin/$toolset/debug*/pass.obj")
185    t.expect_addition("bin/$toolset/debug*/foo.obj")
186    t.expect_nothing_more()
187
188    t.cleanup()
189
190def test_translation():
191    """Tests scoping for targets, paths, and rules within check-target-builds"""
192    t = BoostBuild.Tester(use_test_config=0)
193    t.write("Jamroot", "")
194    t.write("subdir/Jamfile", """
195import configure ;
196obj pass : pass.cpp ;
197obj fail : fail.cpp ;
198explicit pass fail ;
199obj foo : :
200  [ configure.check-target-builds pass
201    : [ configure.check-target-builds fail : <define>FAIL
202        : <define>PASS <include>include1 <conditional>@c1 ]
203    : <define>FAIL ] ;
204obj bar : :
205  [ configure.choose "which one?" : pass
206     [ configure.choose "Try again?" : pass
207        <define>PASS <include>include1 <conditional>@c1 ] ] ;
208rule c1 ( properties * )
209{
210  return <include>include2 <source>foo.cpp ;
211}
212""")
213    t.write("subdir/include1/a.h", "")
214    t.write("subdir/include2/b.h", "")
215    t.write("subdir/pass.cpp", "void f() {}\n")
216    t.write("subdir/fail.cpp", "#error fail.cpp\n")
217    t.write("subdir/foo.cpp", """
218#include <a.h>
219#include <b.h>
220#ifndef PASS
221#error PASS not defined
222#endif
223#ifdef FAIL
224#error FAIL is defined
225#endif
226""")
227    t.run_build_system(["subdir"])
228    t.expect_output_lines([
229        "    - pass builds              : yes",
230        "    - fail builds              : no"])
231    t.expect_addition("subdir/bin/$toolset/debug*/pass.obj")
232    t.expect_addition("subdir/bin/$toolset/debug*/foo.obj")
233    t.expect_addition("subdir/bin/$toolset/debug*/bar.obj")
234    t.expect_nothing_more()
235    t.cleanup()
236
237def test_choose_none():
238    """Tests choose when none of the alternatives match."""
239    t = BoostBuild.Tester(use_test_config=0)
240    t.write("Jamroot", """
241import configure ;
242obj fail : fail.cpp ;
243explicit pass fail ;
244obj foo : foo.cpp :
245  [ configure.choose "which one?" : fail <define>FAIL ] ;
246""")
247    t.write("fail.cpp", "#error fail.cpp\n")
248    t.write("foo.cpp", """
249#ifdef FAIL
250#error FAIL is defined
251#endif
252""")
253    t.run_build_system()
254    t.expect_output_lines([
255        "    - which one?               : none"])
256
257    # An up-to-date build should use the cache
258    t.run_build_system()
259    t.expect_output_lines([
260        "    - which one?               : none (cached)"])
261    t.expect_nothing_more()
262    t.cleanup()
263
264test_check_target_builds()
265test_choose()
266test_translation()
267test_choose_none()
268