Merge pull request #2 from madebr/pr74

Use CMake toolchain + download ninja
This commit is contained in:
Mark Langen 2023-07-02 18:15:54 -07:00 committed by GitHub
commit a32c041ab5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 114 additions and 62 deletions

3
.gitignore vendored
View File

@ -5,4 +5,5 @@ ISLE.EXE
LEGO1.DLL
build/
original/
compiler/
tools/msvc42/
tools/ninja/

View File

@ -2,9 +2,6 @@ cmake_minimum_required(VERSION 2.8...3.5 FATAL_ERROR)
project(isle CXX)
link_directories("$ENV{LIB}")
include_directories("$ENV{INCLUDE}")
option(ISLE_BUILD_APP "Build ISLE.EXE application" ON)
add_library(lego1 SHARED

16
build.py Normal file → Executable file
View File

@ -1,10 +1,12 @@
#! /usr/bin/env python3
#!/usr/bin/env python3
import pathlib
import subprocess
import argparse
import pathlib
import re
import requests
import subprocess
ISLE_PATH = pathlib.Path(__file__).parents[0]
parser = argparse.ArgumentParser()
parser.add_argument("-i", "--inspect", metavar='<offset>',
@ -16,6 +18,7 @@
parser.add_argument("--inspect-shim", nargs=2, metavar=('<file>', '<line>'),
help="Inspect the assembly diff of the function spanning <line> in <file>. "
"Intended to be invoked by IDE commands.")
parser.add_argument("-B", dest="builddir", default=ISLE_PATH / "build", type=pathlib.Path, help="build directory")
args = parser.parse_args()
# Figure out what offset to pass to the reccmp tool if any
@ -44,17 +47,18 @@ def get_inspect_offset():
return None
# If the build directory doesn't exist yet, run configure.py
if not pathlib.Path("build").exists():
if not args.builddir.exists():
print("Not configured yet, please run configure.py first.")
exit(1)
# Run cmake, with no parallel build because that does not play nice the
# MSVC420 compiler the original game was built with thanks to the different
# threads contending over the pdb file.
result = subprocess.run(["cmake", "--build", ".", "-j", "1"], cwd="build")
result = subprocess.run(["cmake", "--build", ".", "-j", "1"], cwd=str(args.builddir))
def require_original():
if not pathlib.Path("original/LEGO1.DLL").exists():
if not (ISLE_PATH / "original/LEGO1.DLL").exists():
(ISLE_PATH / "original").mkdir(parents=True, exist_ok=True)
print("Couldn't find original/LEGO1.DLL. Downloading a copy...")
url1 = "https://legoisland.org/download/ISLE.EXE"
r1 = requests.get(url1, stream=True)

154
configure.py Normal file → Executable file
View File

@ -1,72 +1,122 @@
#! /usr/bin/env python3
#!/usr/bin/env python3
import pathlib
import subprocess
import argparse
import shutil
import platform
import requests
import zipfile
import io
import os
import pathlib
import platform
import requests
import shutil
import subprocess
import textwrap
import zipfile
parser = argparse.ArgumentParser()
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()
# Do we have a builtin ninja?
specific_ninja = None
if shutil.which("ninja") is None:
sys = platform.system()
# Use the bundled ninja
if sys == "Windows":
specific_ninja = "./tools/ninja/ninja-win.exe"
elif sys == "Linux":
specific_ninja = "./tools/ninja/ninja-linux"
elif sys == "Darwin":
specific_ninja = "./tools/ninja/ninja-mac"
else:
print("No bundled ninja for this platform, please install ninja and add it to your path.")
exit(1)
specific_ninja = str(pathlib.Path(specific_ninja).absolute())
builddir = args.builddir.resolve()
compilerdir = ISLE_PATH / "tools/msvc42"
# Create a build folder in the current directory if it does not exist
pathlib.Path("build").mkdir(parents=True, exist_ok=True)
# Create a folder for the compiler
pathlib.Path("compiler").mkdir(parents=True, exist_ok=True)
builddir.mkdir(parents=True, exist_ok=True)
# Check if MSVC420 is in the INCLUDE environment variable
set_compiler_paths = False
if not args.modern_compiler:
if not pathlib.Path("compiler/MSVC420-master").exists():
print("MSVC420 not found in compiler/...")
url = "https://github.com/itsmattkc/MSVC420/archive/refs/heads/master.zip"
print("Downloading MSVC420...")
r = requests.get(url, stream=True)
print("Unzipping to compiler/...")
z = zipfile.ZipFile(io.BytesIO(r.content))
z.extractall(path="compiler")
set_compiler_paths = True
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_args = []
cmake_args += ["-G", "Ninja"]
cmake_args += ["-DCMAKE_BUILD_TYPE=RelWithDebInfo"]
if specific_ninja:
cmake_args += ["-DCMAKE_MAKE_PROGRAM="+specific_ninja]
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 = pathlib.Path.cwd() / "compiler" / "MSVC420-master/"
cmake_args += ["-DCMAKE_CXX_COMPILER=" + (full_compiler_path / "bin" / "CL.EXE").as_posix()]
cmake_args += ["-DCMAKE_C_COMPILER=" + (full_compiler_path / "bin" / "CL.EXE").as_posix()]
cmake_args += ["-DCMAKE_LINKER=" + (full_compiler_path / "bin" / "LINK.EXE").as_posix()]
cmake_args += ["-DCMAKE_RC_COMPILER=" + (full_compiler_path / "bin" / "RC.EXE").as_posix()]
os.environ["INCLUDE"] = (full_compiler_path / "include").as_posix()
os.environ["LIB"] = (full_compiler_path / "lib").as_posix()
cmake_args += [".."]
subprocess.run(["cmake"] + cmake_args, cwd="build")
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():

Binary file not shown.

Binary file not shown.

Binary file not shown.