1 # This Source Code Form is subject to the terms of the Mozilla Public
2 # License, v. 2.0. If a copy of the MPL was not distributed with this
3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 from mozbuild
.makeutil
import Makefile
11 CL_INCLUDES_PREFIX
= os
.environ
.get("CL_INCLUDES_PREFIX", "Note: including file:")
13 GetShortPathName
= ctypes
.windll
.kernel32
.GetShortPathNameW
14 GetLongPathName
= ctypes
.windll
.kernel32
.GetLongPathNameW
17 # cl.exe likes to print inconsistent paths in the showIncludes output
18 # (some lowercased, some not, with different directions of slashes),
19 # and we need the original file case for make/pymake to be happy.
20 # As this is slow and needs to be called a lot of times, use a cache
25 # Get*PathName want paths with backslashes
26 path
= path
.replace('/', os
.sep
)
27 dir = os
.path
.dirname(path
)
28 # name is fortunately always going to have the right case,
29 # so we can use a cache for the directory part only.
30 name
= os
.path
.basename(path
)
31 if dir in _normcase_cache
:
32 result
= _normcase_cache
[dir]
34 path
= ctypes
.create_unicode_buffer(dir)
35 length
= GetShortPathName(path
, None, 0)
36 shortpath
= ctypes
.create_unicode_buffer(length
)
37 GetShortPathName(path
, shortpath
, length
)
38 length
= GetLongPathName(shortpath
, None, 0)
39 if length
> len(path
):
40 path
= ctypes
.create_unicode_buffer(length
)
41 GetLongPathName(shortpath
, path
, length
)
42 result
= _normcase_cache
[dir] = path
.value
43 return os
.path
.join(result
, name
)
46 def InvokeClWithDependencyGeneration(cmdline
):
48 # Figure out what the target is
50 if arg
.startswith("-Fo"):
55 print >>sys
.stderr
, "No target set" and sys
.exit(1)
57 # Assume the source file is the last argument
59 assert not source
.startswith('-')
61 # The deps target lives here
62 depstarget
= os
.path
.basename(target
) + ".pp"
64 cmdline
+= ['-showIncludes']
65 cl
= subprocess
.Popen(cmdline
, stdout
=subprocess
.PIPE
)
68 rule
= mk
.create_rule([target
])
69 rule
.add_dependencies([normcase(source
)])
70 for line
in cl
.stdout
:
71 # cl -showIncludes prefixes every header with "Note: including file:"
72 # and an indentation corresponding to the depth (which we don't need)
73 if line
.startswith(CL_INCLUDES_PREFIX
):
74 dep
= line
[len(CL_INCLUDES_PREFIX
):].strip()
75 # We can't handle pathes with spaces properly in mddepend.pl, but
76 # we can assume that anything in a path with spaces is a system
77 # header and throw it away.
79 rule
.add_dependencies([normcase(dep
)])
81 sys
.stdout
.write(line
) # Make sure we preserve the relevant output
85 if ret
!= 0 or target
== "":
88 depsdir
= os
.path
.normpath(os
.path
.join(os
.curdir
, ".deps"))
89 depstarget
= os
.path
.join(depsdir
, depstarget
)
90 if not os
.path
.isdir(depsdir
):
94 pass # This suppresses the error we get when the dir exists, at the
95 # cost of masking failure to create the directory. We'll just
96 # die on the next line though, so it's not that much of a loss.
98 with
open(depstarget
, "w") as f
:
101 if __name__
== "__main__":
102 InvokeClWithDependencyGeneration(sys
.argv
[1:])