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/.
5 from datetime
import datetime
10 from mozbuild
.preprocessor
import Preprocessor
15 // This Source Code Form is subject to the terms of the Mozilla Public
16 // License, v. 2.0. If a copy of the MPL was not distributed with this
17 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
22 // Note: if you contain versioning information in an included
23 // RC script, it will be discarded
24 // Use module.ver to explicitly set these values
26 // Do not edit this file. Changes won't affect the build.
31 /////////////////////////////////////////////////////////////////////////////
37 FILEVERSION {fileversion}
38 PRODUCTVERSION {productversion}
45 BLOCK "StringFileInfo"
49 VALUE "Comments", "{comment}"
50 VALUE "LegalCopyright", "{copyright}"
51 VALUE "CompanyName", "{company}"
52 VALUE "FileDescription", "{description}"
53 VALUE "FileVersion", "{mfversion}"
54 VALUE "ProductVersion", "{mpversion}"
55 VALUE "InternalName", "{module}"
56 VALUE "LegalTrademarks", "{trademarks}"
57 VALUE "OriginalFilename", "{binary}"
58 VALUE "ProductName", "{productname}"
59 VALUE "BuildID", "{buildid}"
64 VALUE "Translation", 0x0, 1200
71 def preprocess(path
, defines
):
72 pp
= Preprocessor(defines
=defines
, marker
="%")
73 pp
.context
.update(defines
)
74 pp
.out
= io
.StringIO()
75 pp
.do_filter("substitution")
76 pp
.do_include(io
.open(path
, "r", encoding
="latin1"))
81 def parse_module_ver(path
, defines
):
83 for line
in preprocess(path
, defines
):
84 content
, *comment
= line
.split("#", 1)
85 if not content
.strip():
87 entry
, value
= content
.split("=", 1)
88 result
[entry
.strip()] = value
.strip()
93 path
= os
.path
.join(buildconfig
.topobjdir
, "buildid.h")
94 define
, MOZ_BUILDID
, buildid
= io
.open(path
, "r", encoding
="utf-8").read().split()
98 def days_from_2000_to_buildid(buildid
):
99 start
= datetime(2000, 1, 1, 0, 0, 0)
100 buildid_time
= datetime
.strptime(buildid
, "%Y%m%d%H%M%S")
101 return (buildid_time
- start
).days
105 for l
in range(len(s
), 0, -1):
111 def split_and_normalize_version(version
, len):
112 return ([digits_only(x
) for x
in version
.split(".")] + ["0"] * len)[:len]
115 def has_manifest(module_rc
, manifest_id
):
116 for line
in module_rc
.splitlines():
117 line
= line
.split(None, 2)
120 id, what
, *rest
= line
121 if id == manifest_id
and what
in ("24", "RT_MANIFEST"):
126 def generate_module_rc(binary
="", rcinclude
=None):
128 buildid
= get_buildid()
129 milestone
= buildconfig
.substs
["GRE_MILESTONE"]
130 app_version
= buildconfig
.substs
.get("MOZ_APP_VERSION") or milestone
131 app_winversion
= ",".join(split_and_normalize_version(app_version
, 4))
132 milestone_winversion
= ",".join(
133 split_and_normalize_version(milestone
, 3)
134 + [str(days_from_2000_to_buildid(buildid
))]
136 display_name
= buildconfig
.substs
.get("MOZ_APP_DISPLAYNAME", "Mozilla")
138 milestone_string
= milestone
141 if buildconfig
.substs
.get("MOZ_DEBUG"):
142 flags
.append("VS_FF_DEBUG")
143 milestone_string
+= " Debug"
144 if not buildconfig
.substs
.get("MOZILLA_OFFICIAL"):
145 flags
.append("VS_FF_PRIVATEBUILD")
146 if buildconfig
.substs
.get("NIGHTLY_BUILD"):
147 flags
.append("VS_FF_PRERELEASE")
150 "MOZ_APP_DISPLAYNAME": display_name
,
151 "MOZ_APP_VERSION": app_version
,
152 "MOZ_APP_WINVERSION": app_winversion
,
155 relobjdir
= os
.path
.relpath(".", buildconfig
.topobjdir
)
156 srcdir
= os
.path
.join(buildconfig
.topsrcdir
, relobjdir
)
157 module_ver
= os
.path
.join(srcdir
, "module.ver")
158 if os
.path
.exists(module_ver
):
160 overrides
= parse_module_ver(module_ver
, defines
)
165 include
= "// From included resource {}\n{}".format(
166 rcinclude
, preprocess(rcinclude
, defines
).read()
171 data
= TEMPLATE
.format(
173 fileversion
=overrides
.get("WIN32_MODULE_FILEVERSION", milestone_winversion
),
174 productversion
=overrides
.get(
175 "WIN32_MODULE_PRODUCTVERSION", milestone_winversion
177 fileflags
=" | ".join(flags
),
178 comment
=overrides
.get("WIN32_MODULE_COMMENT", ""),
179 copyright
=overrides
.get("WIN32_MODULE_COPYRIGHT", "License: MPL 2"),
180 company
=overrides
.get("WIN32_MODULE_COMPANYNAME", "Mozilla Foundation"),
181 description
=overrides
.get("WIN32_MODULE_DESCRIPTION", ""),
182 mfversion
=overrides
.get("WIN32_MODULE_FILEVERSION_STRING", milestone_string
),
183 mpversion
=overrides
.get("WIN32_MODULE_PRODUCTVERSION_STRING", milestone_string
),
184 module
=overrides
.get("WIN32_MODULE_NAME", ""),
185 trademarks
=overrides
.get("WIN32_MODULE_TRADEMARKS", "Mozilla"),
186 binary
=overrides
.get("WIN32_MODULE_ORIGINAL_FILENAME", binary
),
187 productname
=overrides
.get("WIN32_MODULE_PRODUCTNAME", display_name
),
191 manifest_id
= "2" if binary
.lower().endswith(".dll") else "1"
192 if binary
and not has_manifest(data
, manifest_id
):
193 manifest_path
= os
.path
.join(srcdir
, binary
+ ".manifest")
194 if os
.path
.exists(manifest_path
):
195 manifest_path
= manifest_path
.replace("\\", "\\\\")
196 data
+= '\n{} RT_MANIFEST "{}"\n'.format(manifest_id
, manifest_path
)
198 with io
.open("{}.rc".format(binary
or "module"), "w", encoding
="latin1") as fh
:
202 if __name__
== "__main__":
203 generate_module_rc(*sys
.argv
[1:])