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 2014/09/27 12:51:43 garyo"
25
26 __doc__ = """
27 CacheDir support
28 """
29
30 import os.path
31 import stat
32 import sys
33
34 import SCons.Action
35
36 cache_enabled = True
37 cache_debug = False
38 cache_force = False
39 cache_show = False
40 cache_readonly = 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 if cache_readonly: return
75
76 t = target[0]
77 if t.nocache:
78 return
79 fs = t.fs
80 cd = env.get_CacheDir()
81 cachedir, cachefile = cd.cachepath(t)
82 if fs.exists(cachefile):
83
84
85
86
87
88
89
90 cd.CacheDebug('CachePush(%s): %s already exists in cache\n', t, cachefile)
91 return
92
93 cd.CacheDebug('CachePush(%s): pushing to %s\n', t, cachefile)
94
95 tempfile = cachefile+'.tmp'+str(os.getpid())
96 errfmt = "Unable to copy %s to cache. Cache file is %s"
97
98 if not fs.isdir(cachedir):
99 try:
100 fs.makedirs(cachedir)
101 except EnvironmentError:
102
103
104 if not fs.isdir(cachedir):
105 msg = errfmt % (str(target), cachefile)
106 raise SCons.Errors.EnvironmentError(msg)
107
108 try:
109 if fs.islink(t.path):
110 fs.symlink(fs.readlink(t.path), tempfile)
111 else:
112 fs.copy2(t.path, tempfile)
113 fs.rename(tempfile, cachefile)
114 st = fs.stat(t.path)
115 fs.chmod(cachefile, stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE)
116 except EnvironmentError:
117
118
119
120
121
122 msg = errfmt % (str(target), cachefile)
123 SCons.Warnings.warn(SCons.Warnings.CacheWriteErrorWarning, msg)
124
125 CachePush = SCons.Action.Action(CachePushFunc, None)
126
128
140
152
155
158
160 """
161 """
162 if not self.is_enabled():
163 return None, None
164
165 sig = node.get_cachedir_bsig()
166 subdir = sig[0].upper()
167 dir = os.path.join(self.path, subdir)
168 return dir, os.path.join(dir, sig)
169
171 """
172 This method is called from multiple threads in a parallel build,
173 so only do thread safe stuff here. Do thread unsafe stuff in
174 built().
175
176 Note that there's a special trick here with the execute flag
177 (one that's not normally done for other actions). Basically
178 if the user requested a no_exec (-n) build, then
179 SCons.Action.execute_actions is set to 0 and when any action
180 is called, it does its showing but then just returns zero
181 instead of actually calling the action execution operation.
182 The problem for caching is that if the file does NOT exist in
183 cache then the CacheRetrieveString won't return anything to
184 show for the task, but the Action.__call__ won't call
185 CacheRetrieveFunc; instead it just returns zero, which makes
186 the code below think that the file *was* successfully
187 retrieved from the cache, therefore it doesn't do any
188 subsequent building. However, the CacheRetrieveString didn't
189 print anything because it didn't actually exist in the cache,
190 and no more build actions will be performed, so the user just
191 sees nothing. The fix is to tell Action.__call__ to always
192 execute the CacheRetrieveFunc and then have the latter
193 explicitly check SCons.Action.execute_actions itself.
194 """
195 if not self.is_enabled():
196 return False
197
198 env = node.get_build_env()
199 if cache_show:
200 if CacheRetrieveSilent(node, [], env, execute=1) == 0:
201 node.build(presub=0, execute=0)
202 return True
203 else:
204 if CacheRetrieve(node, [], env, execute=1) == 0:
205 return True
206
207 return False
208
209 - def push(self, node):
213
217
218
219
220
221
222
223