Files
2026-06-26 20:50:07 +08:00

67 lines
2.4 KiB
Python

"""Compile an EA from .mq5 to .ex5 with MetaEditor (doc 07 §1).
The tester runs a compiled ``.ex5``. Compile from the command line so the
bridge can do it programmatically. Custom indicators the EA calls must be
compiled too and placed in ``MQL5\\Indicators\\``. If the EA's ``#include``
files live in a non-standard folder, compile the terminal in portable mode
(``/portable``) so MetaEditor resolves includes from that terminal's
``MQL5\\Include\\``.
"""
from __future__ import annotations
import subprocess
from pathlib import Path
DEFAULT_MT5_INSTALL = r"C:\Program Files\MetaTrader 5 IC Markets Global"
def default_metaeditor_path(mt5_install: str = DEFAULT_MT5_INSTALL) -> str:
"""Return the metaeditor64.exe path for the given MT5 install."""
return str(Path(mt5_install) / "metaeditor64.exe")
def compile_ea(
mq5_path: str | Path,
*,
metaeditor_path: str | None = None,
mt5_install: str = DEFAULT_MT5_INSTALL,
timeout: int = 120,
) -> tuple[bool, str]:
"""Compile an ``.mq5`` EA to ``.ex5`` via MetaEditor's command line.
Returns ``(success, log_text)``. MetaEditor writes a ``.log`` next to the
source; on a clean compile the ``.ex5`` appears beside the ``.mq5``.
Command line (doc 07 §1)::
metaeditor64.exe /compile:"C:\\path\\to\\Expert.mq5" /log
"""
mq5 = Path(mq5_path)
if not mq5.exists():
return False, f"source not found: {mq5}"
editor = metaeditor_path or default_metaeditor_path(mt5_install)
if not Path(editor).exists():
return False, f"metaeditor not found: {editor}"
cmd = [editor, f"/compile:{mq5}", "/log"]
try:
proc = subprocess.run(
cmd, capture_output=True, text=True, timeout=timeout, check=False,
)
log_path = mq5.with_suffix(".log")
log_text = proc.stdout + "\n" + proc.stderr
if log_path.exists():
try:
log_text += "\n--- metaeditor log ---\n" + log_path.read_text(
encoding="utf-16-le", errors="replace"
)
except Exception:
pass
ex5 = mq5.with_suffix(".ex5")
success = ex5.exists() and ex5.stat().st_size > 0
return success, log_text
except subprocess.TimeoutExpired:
return False, f"compile timed out after {timeout}s"
except FileNotFoundError as e:
return False, f"failed to launch metaeditor: {e}"