isle/configure.py
2023-07-03 01:39:29 +02:00

128 lines
4.3 KiB
Python
Executable File

#!/usr/bin/env python3
import argparse
import io
import os
import pathlib
import platform
import requests
import shutil
import subprocess
import textwrap
import zipfile
ISLE_PATH = pathlib.Path(__file__).parents[0]
parser = argparse.ArgumentParser(allow_abbrev=False)
parser.add_argument("-m", "--modern-compiler", action="store_true",
help="Use a contemporary compiler instead of Microsoft Visual C++ 4.2 even though this will result in non-matching code")
parser.add_argument("-B", dest="builddir", default=ISLE_PATH / "build", type=pathlib.Path, help="build directory")
args = parser.parse_args()
builddir = args.builddir.resolve()
compilerdir = ISLE_PATH / "tools/msvc42"
# Create a build folder in the current directory if it does not exist
builddir.mkdir(parents=True, exist_ok=True)
# Check if MSVC420 is in the INCLUDE environment variable
set_compiler_paths = not args.modern_compiler
if not args.modern_compiler and not compilerdir.exists():
# Create a folder for the compiler
compilerdir.mkdir(parents=True, exist_ok=True)
print(f"MSVC420 not found in {compilerdir}/...")
url = "https://github.com/itsmattkc/MSVC420/archive/refs/heads/master.zip"
print("Downloading MSVC420...")
r = requests.get(url, stream=True)
z = zipfile.ZipFile(io.BytesIO(r.content))
print(f"Unzipping MSVC420 to {compilerdir}/...")
for name in z.namelist():
info = z.getinfo(name)
# Remove the MSVC420-master prefix
extract_name = name.split("/", 1)[1]
if not extract_name:
continue
fullpath = compilerdir / extract_name
if info.is_dir():
fullpath.mkdir(parents=True, exist_ok=True)
else:
with fullpath.open("wb") as f:
f.write(z.read(name))
# Run cmake in the build folder
cmake_cmd = [
"cmake",
str(ISLE_PATH),
"-G", "Ninja",
"-DCMAKE_BUILD_TYPE=RelWithDebInfo"
]
# Do we have a builtin ninja?
if shutil.which("ninja") is None:
sys = platform.system()
ninjadir = ISLE_PATH / "tools/ninja" / sys
ninja_urls = {
"Windows": "https://github.com/ninja-build/ninja/releases/download/v1.11.1/ninja-win.zip",
"Linux": "https://github.com/ninja-build/ninja/releases/download/v1.11.1/ninja-linux.zip",
"Darwin": "https://github.com/ninja-build/ninja/releases/download/v1.11.1/ninja-mac.zip",
}
if sys not in ninja_urls:
print("Ninja is not available for this platform, please install ninja and add it to your PATH.")
exit(1)
if not ninjadir.exists():
print("Downloading Ninja...")
r = requests.get(ninja_urls[sys], stream=True)
z = zipfile.ZipFile(io.BytesIO(r.content))
print(f"Unzipping Ninja to {ninjadir}/...")
z.extractall(path=str(ninjadir))
specific_ninja = ninjadir / ("ninja" + ".exe" if sys == "Windows" else "")
print("Using specific ninja:", specific_ninja)
cmake_cmd += [f"-DCMAKE_MAKE_PROGRAM={specific_ninja.as_posix()}"]
extra_include_dirs = []
extra_library_dirs = []
if set_compiler_paths:
full_compiler_path = compilerdir
cl_path = (full_compiler_path / "bin" / "CL.EXE").as_posix()
link_path = (full_compiler_path / "bin" / "LINK.EXE").as_posix()
rc_path = (full_compiler_path / "bin" / "RC.EXE").as_posix()
extra_include_dirs += [
(full_compiler_path / "include").as_posix(),
]
extra_library_dirs += [
(full_compiler_path / "lib").as_posix(),
]
cmake_toolchain_file = builddir / "msvc42.cmake"
cmake_cmd += [f"-DCMAKE_TOOLCHAIN_FILE={cmake_toolchain_file}"]
with cmake_toolchain_file.open("w") as f:
print(textwrap.dedent(f"""\
set(CMAKE_SYSTEM_NAME "Windows")
set(CMAKE_C_COMPILER "{cl_path}")
set(CMAKE_CXX_COMPILER "{cl_path}")
set(CMAKE_RC_COMPILER "{rc_path}")
set(CMAKE_LINKER "{link_path}")
"""), file=f)
for incdir in extra_include_dirs:
print(f"""include_directories("{incdir}")""", file=f)
for libdir in extra_library_dirs:
print(f"""link_directories("{libdir}")""", file=f)
print("cmake command:", " ".join(cmake_cmd))
subprocess.run(cmake_cmd, cwd=builddir)
# Create a folder for the original binaries
if not pathlib.Path("original/LEGO1.DLL").exists():
pathlib.Path("original").mkdir(parents=True, exist_ok=True)
print("\nIf you plan on contributing, place a copy of the original game's "
"ISLE.EXE and LEGO1.DLL into the `original/` folder so that the assembly "
"diff tools can compare against them. If you do not, build.py will download "
"a copy of these files for you.")