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/.
11 def relativize(path
, base
=None):
12 # For absolute path in Unix builds, we need relative paths because
13 # Windows programs run via Wine don't like these Unix absolute paths
14 # (they look like command line arguments).
15 if path
.startswith("/"):
16 return os
.path
.relpath(path
, base
)
17 # For Windows absolute paths, we can just use the unmodified path.
18 # And if the path starts with '-', it's a command line argument.
19 if os
.path
.isabs(path
) or path
.startswith("-"):
21 # Remaining case is relative paths, which may be relative to a different
22 # directory (os.getcwd()) than the needed `base`, so we "rebase" it.
23 return os
.path
.relpath(path
, base
)
26 def midl(out
, input, *flags
):
27 out
.avoid_writing_to_file()
28 midl
= buildconfig
.substs
["MIDL"]
29 wine
= buildconfig
.substs
.get("WINE")
30 base
= os
.path
.dirname(out
.name
) or "."
31 if midl
.lower().endswith(".exe") and wine
:
32 command
= [wine
, midl
]
35 command
.extend(buildconfig
.substs
["MIDL_FLAGS"])
36 command
.extend([relativize(f
, base
) for f
in flags
])
37 command
.append("-Oicf")
38 command
.append(relativize(input, base
))
39 print("Executing:", " ".join(command
))
40 result
= subprocess
.run(command
, cwd
=base
)
41 return result
.returncode
44 # midl outputs dlldata to a single dlldata.c file by default. This prevents running
45 # midl in parallel in the same directory for idl files that would generate dlldata.c
46 # because of race conditions updating the file. Instead, we ask midl to create
47 # separate files, and we merge them manually.
48 def merge_dlldata(out
, *inputs
):
49 inputs
= [open(i
) for i
in inputs
]
50 read_a_line
= [True] * len(inputs
)
53 f
.readline() if read_a_line
[n
] else lines
[n
] for n
, f
in enumerate(inputs
)
55 unique_lines
= set(lines
)
56 if len(unique_lines
) == 1:
57 # All the lines are identical
61 read_a_line
= [True] * len(inputs
)
63 len(unique_lines
) == 2
64 and len([l
for l
in unique_lines
if "#define" in l
]) == 1
66 # Most lines are identical. When they aren't, it's typically because some
67 # files have an extra #define that others don't. When that happens, we
68 # print out the #define, and get a new input line from the files that had
69 # a #define on the next iteration. We expect that next line to match what
70 # the other files had on this iteration.
71 # Note: we explicitly don't support the case where there are different
72 # defines across different files, except when there's a different one
73 # for each file, in which case it's handled further below.
74 a
= unique_lines
.pop()
78 out
.write(unique_lines
.pop())
79 read_a_line
= ["#define" in l
for l
in lines
]
80 elif len(unique_lines
) != len(lines
):
81 # If for some reason, we don't get lines that are entirely different
82 # from each other, we have some unexpected input.
84 "Error while merging dlldata. Last lines read: {}".format(lines
),
91 read_a_line
= [True] * len(inputs
)