summaryrefslogtreecommitdiffstats
path: root/config/create_rc.py
diff options
context:
space:
mode:
Diffstat (limited to 'config/create_rc.py')
-rw-r--r--config/create_rc.py203
1 files changed, 203 insertions, 0 deletions
diff --git a/config/create_rc.py b/config/create_rc.py
new file mode 100644
index 0000000000..973bb5b44e
--- /dev/null
+++ b/config/create_rc.py
@@ -0,0 +1,203 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+from datetime import datetime
+import io
+import os
+import sys
+
+from mozbuild.preprocessor import Preprocessor
+import buildconfig
+
+
+TEMPLATE = """
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include<winuser.h>
+#include<winver.h>
+
+// Note: if you contain versioning information in an included
+// RC script, it will be discarded
+// Use module.ver to explicitly set these values
+
+// Do not edit this file. Changes won't affect the build.
+
+{include}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+1 VERSIONINFO
+ FILEVERSION {fileversion}
+ PRODUCTVERSION {productversion}
+ FILEFLAGSMASK 0x3fL
+ FILEFLAGS {fileflags}
+ FILEOS VOS__WINDOWS32
+ FILETYPE VFT_DLL
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "000004b0"
+ BEGIN
+ VALUE "Comments", "{comment}"
+ VALUE "LegalCopyright", "{copyright}"
+ VALUE "CompanyName", "{company}"
+ VALUE "FileDescription", "{description}"
+ VALUE "FileVersion", "{mfversion}"
+ VALUE "ProductVersion", "{mpversion}"
+ VALUE "InternalName", "{module}"
+ VALUE "LegalTrademarks", "{trademarks}"
+ VALUE "OriginalFilename", "{binary}"
+ VALUE "ProductName", "{productname}"
+ VALUE "BuildID", "{buildid}"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0, 1200
+ END
+END
+
+"""
+
+
+def preprocess(path, defines):
+ pp = Preprocessor(defines=defines, marker="%")
+ pp.context.update(defines)
+ pp.out = io.StringIO()
+ pp.do_filter("substitution")
+ pp.do_include(io.open(path, "r", encoding="latin1"))
+ pp.out.seek(0)
+ return pp.out
+
+
+def parse_module_ver(path, defines):
+ result = {}
+ for line in preprocess(path, defines):
+ content, *comment = line.split("#", 1)
+ if not content.strip():
+ continue
+ entry, value = content.split("=", 1)
+ result[entry.strip()] = value.strip()
+ return result
+
+
+def get_buildid():
+ path = os.path.join(buildconfig.topobjdir, "buildid.h")
+ define, MOZ_BUILDID, buildid = io.open(path, "r", encoding="utf-8").read().split()
+ return buildid
+
+
+def days_from_2000_to_buildid(buildid):
+ start = datetime(2000, 1, 1, 0, 0, 0)
+ buildid_time = datetime.strptime(buildid, "%Y%m%d%H%M%S")
+ return (buildid_time - start).days
+
+
+def digits_only(s):
+ for l in range(len(s), 0, -1):
+ if s[:l].isdigit():
+ return s[:l]
+ return "0"
+
+
+def split_and_normalize_version(version, len):
+ return ([digits_only(x) for x in version.split(".")] + ["0"] * len)[:len]
+
+
+def has_manifest(module_rc, manifest_id):
+ for line in module_rc.splitlines():
+ line = line.split(None, 2)
+ if len(line) < 2:
+ continue
+ id, what, *rest = line
+ if id == manifest_id and what in ("24", "RT_MANIFEST"):
+ return True
+ return False
+
+
+def generate_module_rc(binary="", rcinclude=None):
+ deps = set()
+ buildid = get_buildid()
+ milestone = buildconfig.substs["GRE_MILESTONE"]
+ app_version = buildconfig.substs.get("MOZ_APP_VERSION") or milestone
+ app_winversion = ",".join(split_and_normalize_version(app_version, 4))
+ milestone_winversion = ",".join(
+ split_and_normalize_version(milestone, 3)
+ + [str(days_from_2000_to_buildid(buildid))]
+ )
+ display_name = buildconfig.substs.get("MOZ_APP_DISPLAYNAME", "Mozilla")
+
+ milestone_string = milestone
+
+ flags = ["0"]
+ if buildconfig.substs.get("MOZ_DEBUG"):
+ flags.append("VS_FF_DEBUG")
+ milestone_string += " Debug"
+ if not buildconfig.substs.get("MOZILLA_OFFICIAL"):
+ flags.append("VS_FF_PRIVATEBUILD")
+ if buildconfig.substs.get("NIGHTLY_BUILD"):
+ flags.append("VS_FF_PRERELEASE")
+
+ defines = {
+ "MOZ_APP_DISPLAYNAME": display_name,
+ "MOZ_APP_VERSION": app_version,
+ "MOZ_APP_WINVERSION": app_winversion,
+ }
+
+ relobjdir = os.path.relpath(".", buildconfig.topobjdir)
+ srcdir = os.path.join(buildconfig.topsrcdir, relobjdir)
+ module_ver = os.path.join(srcdir, "module.ver")
+ if os.path.exists(module_ver):
+ deps.add(module_ver)
+ overrides = parse_module_ver(module_ver, defines)
+ else:
+ overrides = {}
+
+ if rcinclude:
+ include = "// From included resource {}\n{}".format(
+ rcinclude, preprocess(rcinclude, defines).read()
+ )
+ else:
+ include = ""
+
+ data = TEMPLATE.format(
+ include=include,
+ fileversion=overrides.get("WIN32_MODULE_FILEVERSION", milestone_winversion),
+ productversion=overrides.get(
+ "WIN32_MODULE_PRODUCTVERSION", milestone_winversion
+ ),
+ fileflags=" | ".join(flags),
+ comment=overrides.get("WIN32_MODULE_COMMENT", ""),
+ copyright=overrides.get("WIN32_MODULE_COPYRIGHT", "License: MPL 2"),
+ company=overrides.get("WIN32_MODULE_COMPANYNAME", "Mozilla Foundation"),
+ description=overrides.get("WIN32_MODULE_DESCRIPTION", ""),
+ mfversion=overrides.get("WIN32_MODULE_FILEVERSION_STRING", milestone_string),
+ mpversion=overrides.get("WIN32_MODULE_PRODUCTVERSION_STRING", milestone_string),
+ module=overrides.get("WIN32_MODULE_NAME", ""),
+ trademarks=overrides.get("WIN32_MODULE_TRADEMARKS", "Mozilla"),
+ binary=overrides.get("WIN32_MODULE_ORIGINAL_FILENAME", binary),
+ productname=overrides.get("WIN32_MODULE_PRODUCTNAME", display_name),
+ buildid=buildid,
+ )
+
+ manifest_id = "2" if binary.lower().endswith(".dll") else "1"
+ if binary and not has_manifest(data, manifest_id):
+ manifest_path = os.path.join(srcdir, binary + ".manifest")
+ if os.path.exists(manifest_path):
+ manifest_path = manifest_path.replace("\\", "\\\\")
+ data += '\n{} RT_MANIFEST "{}"\n'.format(manifest_id, manifest_path)
+
+ with io.open("{}.rc".format(binary or "module"), "w", encoding="latin1") as fh:
+ fh.write(data)
+
+
+if __name__ == "__main__":
+ generate_module_rc(*sys.argv[1:])