mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-07-11 10:59:17 +08:00
328 lines
9.9 KiB
Python
328 lines
9.9 KiB
Python
#!/usr/bin/env python
|
|
|
|
import sys
|
|
import os
|
|
sys.path.append('../../../../build_tools/scripts')
|
|
import base
|
|
|
|
# suppresses status output when set via --quiet/-q; errors are still shown
|
|
QUIET = False
|
|
|
|
def log(msg):
|
|
if not QUIET:
|
|
print(msg)
|
|
return
|
|
|
|
def log_info(msg):
|
|
if not QUIET:
|
|
base.print_info(msg)
|
|
return
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Per-target defaults (mirror LIBXML2_WITH_* options from CMakeLists.txt
|
|
# and the platform branches inside configure.ac)
|
|
# ---------------------------------------------------------------------------
|
|
COMMON_FEATURES = {
|
|
"WITH_C14N": 0,
|
|
"WITH_CATALOG": 0,
|
|
"WITH_DEBUG": 0,
|
|
"WITH_HTML": 1,
|
|
"WITH_HTTP": 0,
|
|
"WITH_ICONV": 0,
|
|
"WITH_ICU": 0,
|
|
"WITH_ISO8859X": 0,
|
|
"WITH_MODULES": 0,
|
|
"WITH_OUTPUT": 1,
|
|
"WITH_PATTERN": 0,
|
|
"WITH_PUSH": 1,
|
|
"WITH_READER": 1,
|
|
"WITH_REGEXPS": 0,
|
|
"WITH_RELAXNG": 0,
|
|
"WITH_SAX1": 1,
|
|
"WITH_SCHEMAS": 0,
|
|
"WITH_SCHEMATRON": 0,
|
|
"WITH_THREADS": 0,
|
|
"WITH_THREAD_ALLOC": 0,
|
|
"WITH_VALID": 0,
|
|
"WITH_WRITER": 0,
|
|
"WITH_XINCLUDE": 0,
|
|
"WITH_XPATH": 0,
|
|
"WITH_XPTR": 1,
|
|
"WITH_ZLIB": 0
|
|
}
|
|
|
|
TARGETS = {
|
|
"windows": {
|
|
"WITH_WINPATH": 1,
|
|
"HAVE_DECL_GETENTROPY": 0,
|
|
"HAVE_DECL_GLOB": 0,
|
|
"HAVE_DECL_MMAP": 0,
|
|
"HAVE_FUNC_ATTRIBUTE_DESTRUCTOR": 0,
|
|
"HAVE_DLOPEN": 0,
|
|
"HAVE_SHLLOAD": 0,
|
|
"HAVE_LIBHISTORY": 0,
|
|
"HAVE_LIBREADLINE": 0,
|
|
"HAVE_STDINT_H": 1,
|
|
"XML_SYSCONFDIR": "/etc",
|
|
"MODULE_EXTENSION": ".dll",
|
|
"XML_THREAD_LOCAL": "__declspec(thread)"
|
|
},
|
|
"linux": {
|
|
"WITH_WINPATH": 0,
|
|
"HAVE_DECL_GETENTROPY": 0,
|
|
"HAVE_DECL_GLOB": 1,
|
|
"HAVE_DECL_MMAP": 1,
|
|
"HAVE_FUNC_ATTRIBUTE_DESTRUCTOR": 1,
|
|
"HAVE_DLOPEN": 1,
|
|
"HAVE_SHLLOAD": 0,
|
|
"HAVE_LIBHISTORY": 0,
|
|
"HAVE_LIBREADLINE": 0,
|
|
"HAVE_STDINT_H": 1,
|
|
"XML_SYSCONFDIR": "/etc",
|
|
"MODULE_EXTENSION": ".so",
|
|
"XML_THREAD_LOCAL": "__thread"
|
|
},
|
|
"mac": {
|
|
"WITH_WINPATH": 0,
|
|
"HAVE_DECL_GETENTROPY": 0,
|
|
"HAVE_DECL_GLOB": 1,
|
|
"HAVE_DECL_MMAP": 1,
|
|
"HAVE_FUNC_ATTRIBUTE_DESTRUCTOR": 1,
|
|
"HAVE_DLOPEN": 1,
|
|
"HAVE_SHLLOAD": 0,
|
|
"HAVE_LIBHISTORY": 0,
|
|
"HAVE_LIBREADLINE": 0,
|
|
"HAVE_STDINT_H": 1,
|
|
"XML_SYSCONFDIR": "/etc",
|
|
"MODULE_EXTENSION": ".dylib",
|
|
"XML_THREAD_LOCAL": "__thread"
|
|
}
|
|
}
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Helpers
|
|
# ---------------------------------------------------------------------------
|
|
def build_defaults(target):
|
|
if target not in TARGETS:
|
|
base.print_error("unknown target: " + target)
|
|
sys.exit(1)
|
|
cfg = {}
|
|
for k in COMMON_FEATURES:
|
|
cfg[k] = COMMON_FEATURES[k]
|
|
for k in TARGETS[target]:
|
|
cfg[k] = TARGETS[target][k]
|
|
return cfg
|
|
|
|
def derive(cfg):
|
|
parts = cfg["VERSION"].split(".")
|
|
major = int(parts[0])
|
|
minor = int(parts[1])
|
|
micro = int(parts[2])
|
|
cfg["LIBXML_MAJOR_VERSION"] = major
|
|
cfg["LIBXML_MINOR_VERSION"] = minor
|
|
cfg["LIBXML_MICRO_VERSION"] = micro
|
|
cfg["LIBXML_VERSION_NUMBER"] = major * 10000 + minor * 100 + micro
|
|
if "LIBXML_VERSION_EXTRA" not in cfg:
|
|
cfg["LIBXML_VERSION_EXTRA"] = ""
|
|
return
|
|
|
|
def subst_atvars(text, cfg):
|
|
for key in cfg:
|
|
text = text.replace("@" + key + "@", str(cfg[key]))
|
|
# warn about leftover placeholders (helps catch typos in xmlversion.h.in)
|
|
i = text.find("@")
|
|
while i != -1:
|
|
j = text.find("@", i + 1)
|
|
if j == -1:
|
|
break
|
|
token = text[i + 1:j]
|
|
is_name = (len(token) > 0)
|
|
for ch in token:
|
|
if not (ch.isalnum() or ch == "_"):
|
|
is_name = False
|
|
break
|
|
if is_name:
|
|
base.print_error("undefined template variable: @" + token + "@")
|
|
i = text.find("@", j + 1)
|
|
return text
|
|
|
|
def process_cmakedefine_line(line, cfg):
|
|
stripped = line.lstrip()
|
|
if not stripped.startswith("#"):
|
|
return None
|
|
indent = line[:len(line) - len(stripped)]
|
|
body = stripped[1:].lstrip() # skip '#' and any whitespace after it
|
|
|
|
if body.startswith("cmakedefine01"):
|
|
rest = body[len("cmakedefine01"):].strip()
|
|
if rest == "":
|
|
return None
|
|
name = rest.split()[0]
|
|
value = 1 if int(cfg.get(name, 0)) else 0
|
|
return indent + "#define " + name + " " + str(value)
|
|
|
|
if body.startswith("cmakedefine"):
|
|
rest = body[len("cmakedefine"):]
|
|
if rest == "" or not rest[0].isspace():
|
|
return None
|
|
rest = rest.lstrip()
|
|
sp = -1
|
|
for k in range(len(rest)):
|
|
if rest[k].isspace():
|
|
sp = k
|
|
break
|
|
if sp == -1:
|
|
name = rest
|
|
tail = ""
|
|
else:
|
|
name = rest[:sp]
|
|
tail = rest[sp:]
|
|
if cfg.get(name):
|
|
return indent + "#define " + name + subst_atvars(tail, cfg)
|
|
return indent + "/* #undef " + name + " */"
|
|
|
|
return None
|
|
|
|
def process_template(text, cfg, cmake_style):
|
|
out_lines = []
|
|
for line in text.splitlines():
|
|
if cmake_style:
|
|
replaced = process_cmakedefine_line(line, cfg)
|
|
if replaced is not None:
|
|
out_lines.append(replaced)
|
|
continue
|
|
out_lines.append(subst_atvars(line, cfg))
|
|
return "\n".join(out_lines) + "\n"
|
|
|
|
def configure_file(src, dst, cfg, cmake_style):
|
|
if not base.is_file(src):
|
|
base.print_error("template not found: " + src)
|
|
sys.exit(1)
|
|
text = base.readFile(src)
|
|
dst_dir = os.path.dirname(base.get_path(dst))
|
|
if dst_dir != "":
|
|
base.create_dir(dst_dir)
|
|
base.writeFile(dst, process_template(text, cfg, cmake_style))
|
|
log(" wrote " + dst)
|
|
return
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# CLI
|
|
# ---------------------------------------------------------------------------
|
|
def print_help():
|
|
print("Usage: python configure_libxml2.py [options]")
|
|
print("")
|
|
print("Generates config.h and include/libxml/xmlversion.h from the")
|
|
print("libxml2 *.in templates, mirroring the logic of configure.ac /")
|
|
print("CMakeLists.txt without invoking autoconf or cmake.")
|
|
print("")
|
|
print("Paths:")
|
|
print(" --source DIR libxml2 source root (default: cwd)")
|
|
print(" --config-h PATH explicit path for config.h")
|
|
print(" (default: <script-dir>/config.h)")
|
|
print(" --xmlversion-h PATH explicit path for xmlversion.h")
|
|
print(" (default: <script-dir>/xmlversion.h)")
|
|
print("")
|
|
print("Build options:")
|
|
print(" --target NAME windows | linux | mac (default: host)")
|
|
print(" --with-FEATURE 0|1 toggle any LIBXML2_WITH_* feature")
|
|
print(" e.g. --with-zlib 1 --with-iconv 1")
|
|
print(" --have-NAME 0|1 set any HAVE_* probe value")
|
|
print(" e.g. --have-dlopen 1")
|
|
print(" --xml-sysconfdir DIR override XML_SYSCONFDIR")
|
|
print(" --xml-thread-local S override TLS specifier")
|
|
print(" --module-extension S override dynamic-module suffix")
|
|
print(" --version-extra S set LIBXML_VERSION_EXTRA")
|
|
print("")
|
|
print(" -q, --quiet suppress status output (errors still shown)")
|
|
print(" -h, --help show this message")
|
|
return
|
|
|
|
def parse_args(argv):
|
|
args = {}
|
|
i = 1
|
|
while i < len(argv):
|
|
arg = argv[i]
|
|
if arg == "-h" or arg == "--help":
|
|
args["help"] = "1"
|
|
i += 1
|
|
continue
|
|
if arg == "-q" or arg == "--quiet":
|
|
args["quiet"] = "1"
|
|
i += 1
|
|
continue
|
|
if not arg.startswith("--"):
|
|
base.print_error("unexpected positional argument: " + arg)
|
|
sys.exit(1)
|
|
key = arg[2:]
|
|
if i + 1 >= len(argv):
|
|
base.print_error("missing value for --" + key)
|
|
sys.exit(1)
|
|
args[key] = argv[i + 1]
|
|
i += 2
|
|
return args
|
|
|
|
def apply_overrides(cfg, args):
|
|
reserved = ("source", "target", "config-h", "xmlversion-h",
|
|
"version-extra", "help", "quiet")
|
|
for key in args:
|
|
if key in reserved:
|
|
continue
|
|
cfg_key = key.upper().replace("-", "_")
|
|
value = args[key]
|
|
if cfg_key not in cfg:
|
|
base.print_error("unknown option: --" + key + " "
|
|
"(maps to " + cfg_key + ")")
|
|
sys.exit(1)
|
|
# keep type stable: numeric keys stay numeric
|
|
if isinstance(cfg[cfg_key], int):
|
|
try:
|
|
cfg[cfg_key] = int(value)
|
|
except ValueError:
|
|
base.print_error("--" + key + " expects 0 or 1, got: " + value)
|
|
sys.exit(1)
|
|
else:
|
|
cfg[cfg_key] = value
|
|
return
|
|
|
|
def main(argv):
|
|
global QUIET
|
|
args = parse_args(argv)
|
|
if "help" in args:
|
|
print_help()
|
|
return 0
|
|
QUIET = ("quiet" in args)
|
|
|
|
source = args.get("source", os.getcwd())
|
|
script_dir = os.path.dirname(os.path.realpath(__file__))
|
|
target = args.get("target", base.host_platform())
|
|
|
|
cfg = build_defaults(target)
|
|
|
|
version_file = source + "/VERSION"
|
|
if not base.is_file(version_file):
|
|
base.print_error("VERSION file not found in: " + source)
|
|
return 1
|
|
cfg["VERSION"] = base.readFile(version_file).strip()
|
|
|
|
apply_overrides(cfg, args)
|
|
if "version-extra" in args:
|
|
cfg["LIBXML_VERSION_EXTRA"] = args["version-extra"]
|
|
|
|
derive(cfg)
|
|
|
|
config_h_out = args.get("config-h", script_dir + "/config.h")
|
|
xmlversion_h_out = args.get("xmlversion-h", script_dir + "/xmlversion.h")
|
|
|
|
log_info("libxml2 " + cfg["VERSION"] + " target=" + target)
|
|
log(" source = " + source)
|
|
|
|
configure_file(source + "/config.h.cmake.in",
|
|
config_h_out, cfg, True)
|
|
configure_file(source + "/include/libxml/xmlversion.h.in",
|
|
xmlversion_h_out, cfg, False)
|
|
return 0
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main(sys.argv))
|