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 5023 2010/06/14 22:05:46 scons"
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
58
60 t = target[0]
61 fs = t.fs
62 cd = env.get_CacheDir()
63 cachedir, cachefile = cd.cachepath(t)
64 if t.fs.exists(cachefile):
65 return "Retrieved `%s' from cache" % t.path
66 return None
67
68 CacheRetrieve = SCons.Action.Action(CacheRetrieveFunc, CacheRetrieveString)
69
70 CacheRetrieveSilent = SCons.Action.Action(CacheRetrieveFunc, None)
71
73 t = target[0]
74 if t.nocache:
75 return
76 fs = t.fs
77 cd = env.get_CacheDir()
78 cachedir, cachefile = cd.cachepath(t)
79 if fs.exists(cachefile):
80
81
82
83
84
85
86
87 cd.CacheDebug('CachePush(%s): %s already exists in cache\n', t, cachefile)
88 return
89
90 cd.CacheDebug('CachePush(%s): pushing to %s\n', t, cachefile)
91
92 tempfile = cachefile+'.tmp'+str(os.getpid())
93 errfmt = "Unable to copy %s to cache. Cache file is %s"
94
95 if not fs.isdir(cachedir):
96 try:
97 fs.makedirs(cachedir)
98 except EnvironmentError:
99
100
101 if not fs.isdir(cachedir):
102 msg = errfmt % (str(target), cachefile)
103 raise SCons.Errors.EnvironmentError(msg)
104
105 try:
106 if fs.islink(t.path):
107 fs.symlink(fs.readlink(t.path), tempfile)
108 else:
109 fs.copy2(t.path, tempfile)
110 fs.rename(tempfile, cachefile)
111 st = fs.stat(t.path)
112 fs.chmod(cachefile, stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE)
113 except EnvironmentError:
114
115
116
117
118
119 msg = errfmt % (str(target), cachefile)
120 SCons.Warnings.warn(SCons.Warnings.CacheWriteErrorWarning, msg)
121
122 CachePush = SCons.Action.Action(CachePushFunc, None)
123
125
137
149
152
154 """
155 """
156 if not self.is_enabled():
157 return None, None
158
159 sig = node.get_cachedir_bsig()
160 subdir = sig[0].upper()
161 dir = os.path.join(self.path, subdir)
162 return dir, os.path.join(dir, sig)
163
165 """
166 This method is called from multiple threads in a parallel build,
167 so only do thread safe stuff here. Do thread unsafe stuff in
168 built().
169
170 Note that there's a special trick here with the execute flag
171 (one that's not normally done for other actions). Basically
172 if the user requested a no_exec (-n) build, then
173 SCons.Action.execute_actions is set to 0 and when any action
174 is called, it does its showing but then just returns zero
175 instead of actually calling the action execution operation.
176 The problem for caching is that if the file does NOT exist in
177 cache then the CacheRetrieveString won't return anything to
178 show for the task, but the Action.__call__ won't call
179 CacheRetrieveFunc; instead it just returns zero, which makes
180 the code below think that the file *was* successfully
181 retrieved from the cache, therefore it doesn't do any
182 subsequent building. However, the CacheRetrieveString didn't
183 print anything because it didn't actually exist in the cache,
184 and no more build actions will be performed, so the user just
185 sees nothing. The fix is to tell Action.__call__ to always
186 execute the CacheRetrieveFunc and then have the latter
187 explicitly check SCons.Action.execute_actions itself.
188 """
189 if not self.is_enabled():
190 return False
191
192 env = node.get_build_env()
193 if cache_show:
194 if CacheRetrieveSilent(node, [], env, execute=1) == 0:
195 node.build(presub=0, execute=0)
196 return True
197 else:
198 if CacheRetrieve(node, [], env, execute=1) == 0:
199 return True
200
201 return False
202
203 - def push(self, node):
207
211
212
213
214
215
216
217