1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 __revision__ = "src/engine/SCons/CacheDir.py 3842 2008/12/20 22:59:52 scons"
25
26 __doc__ = """
27 CacheDir support
28 """
29
30 import os.path
31 import stat
32 import string
33 import sys
34
35 import SCons.Action
36
37 cache_enabled = True
38 cache_debug = False
39 cache_force = False
40 cache_show = False
41
59
61 t = target[0]
62 fs = t.fs
63 cd = env.get_CacheDir()
64 cachedir, cachefile = cd.cachepath(t)
65 if t.fs.exists(cachefile):
66 return "Retrieved `%s' from cache" % t.path
67 return None
68
69 CacheRetrieve = SCons.Action.Action(CacheRetrieveFunc, CacheRetrieveString)
70
71 CacheRetrieveSilent = SCons.Action.Action(CacheRetrieveFunc, None)
72
74 t = target[0]
75 if t.nocache:
76 return
77 fs = t.fs
78 cd = env.get_CacheDir()
79 cachedir, cachefile = cd.cachepath(t)
80 if fs.exists(cachefile):
81
82
83
84
85
86
87
88 cd.CacheDebug('CachePush(%s): %s already exists in cache\n', t, cachefile)
89 return
90
91 cd.CacheDebug('CachePush(%s): pushing to %s\n', t, cachefile)
92
93 tempfile = cachefile+'.tmp'+str(os.getpid())
94 errfmt = "Unable to copy %s to cache. Cache file is %s"
95
96 if not fs.isdir(cachedir):
97 try:
98 fs.makedirs(cachedir)
99 except EnvironmentError:
100
101
102 if not fs.isdir(cachedir):
103 msg = errfmt % (str(target), cachefile)
104 raise SCons.Errors.EnvironmentError, msg
105
106 try:
107 if fs.islink(t.path):
108 fs.symlink(fs.readlink(t.path), tempfile)
109 else:
110 fs.copy2(t.path, tempfile)
111 fs.rename(tempfile, cachefile)
112 st = fs.stat(t.path)
113 fs.chmod(cachefile, stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE)
114 except EnvironmentError:
115
116
117
118
119
120 msg = errfmt % (str(target), cachefile)
121 SCons.Warnings.warn(SCons.Warnings.CacheWriteErrorWarning, msg)
122
123 CachePush = SCons.Action.Action(CachePushFunc, None)
124
126
138
150
153
164
166 """
167 This method is called from multiple threads in a parallel build,
168 so only do thread safe stuff here. Do thread unsafe stuff in
169 built().
170
171 Note that there's a special trick here with the execute flag
172 (one that's not normally done for other actions). Basically
173 if the user requested a no_exec (-n) build, then
174 SCons.Action.execute_actions is set to 0 and when any action
175 is called, it does its showing but then just returns zero
176 instead of actually calling the action execution operation.
177 The problem for caching is that if the file does NOT exist in
178 cache then the CacheRetrieveString won't return anything to
179 show for the task, but the Action.__call__ won't call
180 CacheRetrieveFunc; instead it just returns zero, which makes
181 the code below think that the file *was* successfully
182 retrieved from the cache, therefore it doesn't do any
183 subsequent building. However, the CacheRetrieveString didn't
184 print anything because it didn't actually exist in the cache,
185 and no more build actions will be performed, so the user just
186 sees nothing. The fix is to tell Action.__call__ to always
187 execute the CacheRetrieveFunc and then have the latter
188 explicitly check SCons.Action.execute_actions itself.
189 """
190 if not self.is_enabled():
191 return False
192
193 retrieved = False
194
195 if cache_show:
196 if CacheRetrieveSilent(node, [], node.get_build_env(), execute=1) == 0:
197 node.build(presub=0, execute=0)
198 retrieved = 1
199 else:
200 if CacheRetrieve(node, [], node.get_build_env(), execute=1) == 0:
201 retrieved = 1
202 if retrieved:
203
204
205 node.set_state(SCons.Node.executed)
206 SCons.Node.Node.built(node)
207
208 return retrieved
209
210 - def push(self, node):
214
218