| """Build the single-file MQL5 Market versions and compile them on a testing install.
|
|
|
| usage: build_market.py
|
| market/Tick_Forge.mq5 Expert (the utility product), TF_Gui / TF_Engine / TF_Expr inlined
|
| market/Tick_Forge_Indicator.mq5 indicator build of the same window (alternate)
|
| Each is compiled; errors / warnings are printed. The Market compiles the uploaded source server-side, so it
|
| must be ONE file with no custom includes (standard library includes are fine).
|
| Set TF_DATA / TF_EDITOR for your own install.
|
| """
|
| import os, re, shutil, subprocess, sys
|
| from pathlib import Path
|
|
|
| HERE = Path(__file__).resolve().parent.parent
|
| D = Path(os.environ.get("TF_DATA", r"C:\Users\gebruiker\AppData\Roaming\MetaQuotes\Terminal\D0E8209F77C8CF37AD8BF550E51FF075"))
|
| EDIT = os.environ.get("TF_EDITOR", r"C:\Program Files\MetaTrader 5\metaeditor64.exe")
|
|
|
| # (source in repo, output name in market/, MQL5 sub-folder it compiles in, file name there)
|
| BUILDS = (("Tick_Forge.mq5", "Tick_Forge.mq5", "Experts", "Tick_Forge_Market"),
|
| ("variants/Tick_Forge_Indicator.mq5", "Tick_Forge_Indicator.mq5", "Indicators", "Tick_Forge_Market"))
|
|
|
|
|
| def body(name):
|
| return (HERE / name).read_text(encoding="utf-8")
|
|
|
|
|
| def inline(text):
|
| def sub(m):
|
| inc = m.group(1)
|
| return "// ---- inlined from %s ----\n%s\n// ---- end %s ----" % (inc, inline(body(inc)), inc)
|
| return re.sub(r'^#include "([^"]+)"[ \t]*$', sub, text, flags=re.M)
|
|
|
|
|
| out = HERE / "market"
|
| out.mkdir(exist_ok=True)
|
| (HERE / "release").mkdir(exist_ok=True)
|
| status = 0
|
| for src_rel, out_name, kind, folder in BUILDS:
|
| src = inline(body(src_rel))
|
| first = src.find("#property strict")
|
| if first >= 0: # inlined headers may repeat it; keep the first
|
| src = src[:first + 17] + src[first + 17:].replace("#property strict\n", "")
|
| (out / out_name).write_text(src, encoding="utf-8", newline="\n")
|
| left = re.findall(r'^#include "[^"]+"', src, flags=re.M)
|
| if left:
|
| sys.exit("custom includes left in %s: %s" % (out_name, left))
|
| dst = D / "MQL5" / kind / folder
|
| dst.mkdir(parents=True, exist_ok=True)
|
| shutil.copy2(out / out_name, dst / out_name)
|
| ex = dst / out_name.replace(".mq5", ".ex5")
|
| if ex.exists():
|
| ex.unlink()
|
| log = dst / (out_name + ".log")
|
| subprocess.run([EDIT, "/compile:%s" % (dst / out_name), "/log:%s" % log], capture_output=True)
|
| txt = log.read_bytes().decode("utf-16", "ignore") if log.exists() else ""
|
| res = [l.strip() for l in txt.splitlines() if re.search(r"error|warning|Result", l, re.I)]
|
| print("%s (%d lines): %s | ex5 %s" % (out_name, len(src.splitlines()), res[-1] if res else "?", ex.exists()))
|
| if ex.exists():
|
| shutil.copy2(ex, HERE / "release" / ex.name)
|
| else:
|
| status = 1
|
| sys.exit(status)
|