1#!/usr/local/bin/python3.8
2
3# Copyright 2003 Vladimir Prus
4# Distributed under the Boost Software License, Version 1.0.
5# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
6
7# This tests correct handling of dependencies, specifically, on generated
8# sources, and from generated sources.
9
10import BoostBuild
11
12import string
13
14t = BoostBuild.Tester(pass_toolset=0)
15
16t.write("core-dependency-helpers", """
17rule hdrrule
18{
19   INCLUDES $(1) : $(2) ;
20}
21actions copy
22{
23   cp $(>) $(<)
24}
25""")
26
27code = """include core-dependency-helpers ;
28DEPENDS all : a ;
29DEPENDS a : b ;
30
31actions create-b
32{
33   echo '#include <foo.h>' > $(<)
34}
35copy a : b ;
36create-b b ;
37HDRRULE on b foo.h bar.h = hdrrule ;
38HDRSCAN on b foo.h bar.h = \"#include <(.*)>\" ;
39"""
40
41# This creates 'a' which depends on 'b', which is generated. The generated 'b'
42# contains '#include <foo.h>' and no rules for foo.h are given. The system
43# should error out on the first invocation.
44t.run_build_system("-f-", stdin=code)
45t.fail_test(t.stdout().find("...skipped a for lack of foo.h...") == -1)
46
47t.rm('b')
48
49# Now test that if target 'c' also depends on 'b', then it will not be built, as
50# well.
51t.run_build_system("-f-", stdin=code + " copy c : b ; DEPENDS c : b ; DEPENDS all : c ; ")
52t.fail_test(t.stdout().find("...skipped c for lack of foo.h...") == -1)
53
54t.rm('b')
55
56# Now add a rule for creating foo.h.
57code += """
58actions create-foo
59{
60    echo // > $(<)
61}
62create-foo foo.h ;
63"""
64t.run_build_system("-f-", stdin=code)
65
66# Run two times, adding explicit dependency from all to foo.h at the beginning
67# and at the end, to make sure that foo.h is generated before 'a' in all cases.
68
69def mk_correct_order_func(s1, s2):
70    def correct_order(s):
71        n1 = s.find(s1)
72        n2 = s.find(s2)
73        return ( n1 != -1 ) and ( n2 != -1 ) and ( n1 < n2 )
74    return correct_order
75
76correct_order = mk_correct_order_func("create-foo", "copy a")
77
78t.rm(["a", "b", "foo.h"])
79t.run_build_system("-d+2 -f-", stdin=code + " DEPENDS all : foo.h ;")
80t.fail_test(not correct_order(t.stdout()))
81
82t.rm(["a", "b", "foo.h"])
83t.run_build_system("-d+2 -f-", stdin=" DEPENDS all : foo.h ; " + code)
84t.fail_test(not correct_order(t.stdout()))
85
86# Now foo.h exists. Test include from b -> foo.h -> bar.h -> biz.h. b and foo.h
87# already have updating actions.
88t.rm(["a", "b"])
89t.write("foo.h", "#include <bar.h>")
90t.write("bar.h", "#include <biz.h>")
91t.run_build_system("-d+2 -f-", stdin=code)
92t.fail_test(t.stdout().find("...skipped a for lack of biz.h...") == -1)
93
94# Add an action for biz.h.
95code += """
96actions create-biz
97{
98   echo // > $(<)
99}
100create-biz biz.h ;
101"""
102
103t.rm(["b"])
104correct_order = mk_correct_order_func("create-biz", "copy a")
105t.run_build_system("-d+2 -f-", stdin=code + " DEPENDS all : biz.h ;")
106t.fail_test(not correct_order(t.stdout()))
107
108t.rm(["a", "biz.h"])
109t.run_build_system("-d+2 -f-", stdin=" DEPENDS all : biz.h ; " + code)
110t.fail_test(not correct_order(t.stdout()))
111
112t.write("a", "")
113
114code="""
115DEPENDS all : main d ;
116
117actions copy
118{
119    cp $(>) $(<) ;
120}
121
122DEPENDS main : a ;
123copy main : a ;
124
125INCLUDES a : <1>c ;
126
127NOCARE <1>c ;
128SEARCH on <1>c = . ;
129
130actions create-c
131{
132    echo d > $(<)
133}
134
135actions create-d
136{
137    echo // > $(<)
138}
139
140create-c <2>c ;
141LOCATE on <2>c = . ;
142create-d d ;
143
144HDRSCAN on <1>c = (.*) ;
145HDRRULE on <1>c = hdrrule ;
146
147rule hdrrule
148{
149    INCLUDES $(1) : d ;
150}
151"""
152
153correct_order = mk_correct_order_func("create-d", "copy main")
154t.run_build_system("-d2 -f-", stdin=code)
155t.fail_test(not correct_order(t.stdout()))
156
157t.cleanup()
158