mirror of
https://github.com/0O0o0oOoO00/Alas.git
synced 2026-05-14 10:59:24 +08:00
243 lines
8.0 KiB
Python
243 lines
8.0 KiB
Python
|
|
import os
|
||
|
|
import pipes
|
||
|
|
import re
|
||
|
|
import shutil
|
||
|
|
import subprocess
|
||
|
|
import sys
|
||
|
|
import logging
|
||
|
|
|
||
|
|
import argparse
|
||
|
|
|
||
|
|
platforms = {
|
||
|
|
"macos": ["x86_64", "arm64", "arm64e"],
|
||
|
|
"iphoneos": ["arm64", "arm64e"],
|
||
|
|
"linux": ["x86", "x86_64", "arm", "arm64"],
|
||
|
|
"android": ["x86", "x86_64", "armeabi-v7a", "arm64-v8a"]
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
class PlatformBuilder(object):
|
||
|
|
cmake_args = list()
|
||
|
|
cmake_build_type = "Release"
|
||
|
|
cmake_build_verbose = False
|
||
|
|
cmake_build_dir = ""
|
||
|
|
|
||
|
|
library_build_type = "static"
|
||
|
|
|
||
|
|
project_dir = ""
|
||
|
|
output_dir = ""
|
||
|
|
|
||
|
|
shared_output_name = ""
|
||
|
|
static_output_name = ""
|
||
|
|
|
||
|
|
platform = ""
|
||
|
|
arch = ""
|
||
|
|
|
||
|
|
def __init__(self, project_dir, library_build_type, platform, arch):
|
||
|
|
self.project_dir = project_dir
|
||
|
|
self.library_build_type = library_build_type
|
||
|
|
self.platform = platform
|
||
|
|
self.arch = arch
|
||
|
|
|
||
|
|
self.cmake_build_dir = f"{self.project_dir}/build/cmake-build-{platform}-{arch}"
|
||
|
|
self.output_dir = f"{self.project_dir}/build/{platform}/{arch}"
|
||
|
|
|
||
|
|
self.cmake = "cmake" if PlatformBuilder.cmake_dir is None else f"{PlatformBuilder.cmake_dir}/bin/cmake"
|
||
|
|
self.clang = "clang" if PlatformBuilder.llvm_dir is None else f"{PlatformBuilder.llvm_dir}/bin/clang"
|
||
|
|
self.clangxx = "clang++" if PlatformBuilder.llvm_dir is None else f"{PlatformBuilder.llvm_dir}/bin/clang++"
|
||
|
|
|
||
|
|
self.setup_common_args()
|
||
|
|
|
||
|
|
def cmake_generate_build_system(self):
|
||
|
|
cmake_cmd_options = ["-S {}".format(self.project_dir), "-B {}".format(self.cmake_build_dir)]
|
||
|
|
cmd = [f"{self.cmake}"] + cmake_cmd_options + self.cmake_args
|
||
|
|
# subprocess.run(cmd, check=True)
|
||
|
|
cmd_line = " ".join(cmd)
|
||
|
|
print(cmd_line)
|
||
|
|
os.system(cmd_line)
|
||
|
|
|
||
|
|
def setup_common_args(self):
|
||
|
|
self.cmake_args += [f"-DCMAKE_C_COMPILER={self.clang}", f"-DCMAKE_CXX_COMPILER={self.clangxx}"]
|
||
|
|
|
||
|
|
self.cmake_args += ["-DCMAKE_BUILD_TYPE={}".format(self.cmake_build_type)]
|
||
|
|
|
||
|
|
if self.library_build_type == "shared":
|
||
|
|
pass
|
||
|
|
# self.cmake_args += ["-DDOBBY_GENERATE_SHARED=ON"]
|
||
|
|
elif self.library_build_type == "static":
|
||
|
|
pass
|
||
|
|
# self.cmake_args += ["-DDOBBY_GENERATE_SHARED=OFF"]
|
||
|
|
|
||
|
|
def build(self):
|
||
|
|
subprocess.run(["mkdir", "-p", "{}".format(self.output_dir)], check=True)
|
||
|
|
self.cmake_generate_build_system()
|
||
|
|
|
||
|
|
subprocess.run("cmake --build . --clean-first --target dobby --target dobby_static -- -j8", cwd=self.cmake_build_dir, shell=True, check=True)
|
||
|
|
|
||
|
|
os.system(f"mkdir -p {self.output_dir}")
|
||
|
|
os.system(f"cp {self.cmake_build_dir}/{self.shared_output_name} {self.output_dir}")
|
||
|
|
os.system(f"cp {self.cmake_build_dir}/{self.static_output_name} {self.output_dir}")
|
||
|
|
|
||
|
|
|
||
|
|
class WindowsPlatformBuilder(PlatformBuilder):
|
||
|
|
|
||
|
|
def __init__(self, project_dir, library_build_type, platform, arch):
|
||
|
|
super().__init__(project_dir, library_build_type, platform, arch)
|
||
|
|
|
||
|
|
if self.library_build_type == "shared":
|
||
|
|
self.output_name = "libdobby.dll"
|
||
|
|
else:
|
||
|
|
self.output_name = "libdobby.lib"
|
||
|
|
|
||
|
|
triples = {
|
||
|
|
"x86": "i686-pc-windows-msvc",
|
||
|
|
"x64": "x86_64-pc-windows-msvc",
|
||
|
|
# "arm": "arm-pc-windows-msvc",
|
||
|
|
"arm64": "arm64-pc-windows-msvc",
|
||
|
|
}
|
||
|
|
|
||
|
|
# self.cmake_args += ["--target {}".format(triples[arch])]
|
||
|
|
self.cmake_args += [
|
||
|
|
"-DCMAKE_SYSTEM_PROCESSOR={}".format(arch),
|
||
|
|
]
|
||
|
|
|
||
|
|
|
||
|
|
class LinuxPlatformBuilder(PlatformBuilder):
|
||
|
|
|
||
|
|
def __init__(self, project_dir, library_build_type, arch):
|
||
|
|
super().__init__(project_dir, library_build_type, "linux", arch)
|
||
|
|
|
||
|
|
self.shared_output_name = "libdobby.so"
|
||
|
|
self.static_output_name = "libdobby.a"
|
||
|
|
|
||
|
|
targets = {
|
||
|
|
"x86": "i686-linux-gnu",
|
||
|
|
"x86_64": "x86_64-linux-gnu",
|
||
|
|
"arm": "arm-linux-gnueabi",
|
||
|
|
"aarch64": "aarch64-linux-gnu",
|
||
|
|
}
|
||
|
|
|
||
|
|
# self.cmake_args += ["--target={}".format(targets[arch])]
|
||
|
|
self.cmake_args += [
|
||
|
|
"-DCMAKE_SYSTEM_NAME=Linux",
|
||
|
|
"-DCMAKE_SYSTEM_PROCESSOR={}".format(arch),
|
||
|
|
]
|
||
|
|
|
||
|
|
|
||
|
|
class AndroidPlatformBuilder(PlatformBuilder):
|
||
|
|
|
||
|
|
def __init__(self, android_nkd_dir, project_dir, library_build_type, arch):
|
||
|
|
super().__init__(project_dir, library_build_type, "android", arch)
|
||
|
|
|
||
|
|
self.shared_output_name = "libdobby.so"
|
||
|
|
self.static_output_name = "libdobby.a"
|
||
|
|
|
||
|
|
android_api_level = 21
|
||
|
|
if arch == "armeabi-v7a" or arch == "x86":
|
||
|
|
android_api_level = 19
|
||
|
|
|
||
|
|
self.cmake_args += [
|
||
|
|
"-DCMAKE_SYSTEM_NAME=Android", f"-DCMAKE_ANDROID_NDK={android_nkd_dir}", f"-DCMAKE_ANDROID_ARCH_ABI={arch}",
|
||
|
|
f"-DCMAKE_SYSTEM_VERSION={android_api_level}"
|
||
|
|
]
|
||
|
|
|
||
|
|
|
||
|
|
class DarwinPlatformBuilder(PlatformBuilder):
|
||
|
|
|
||
|
|
def __init__(self, project_dir, library_build_type, platform, arch):
|
||
|
|
super().__init__(project_dir, library_build_type, platform, arch)
|
||
|
|
|
||
|
|
self.cmake_args += [
|
||
|
|
"-DCMAKE_OSX_ARCHITECTURES={}".format(arch),
|
||
|
|
"-DCMAKE_SYSTEM_PROCESSOR={}".format(arch),
|
||
|
|
]
|
||
|
|
|
||
|
|
if platform == "macos":
|
||
|
|
self.cmake_args += ["-DCMAKE_SYSTEM_NAME=Darwin"]
|
||
|
|
elif platform == "iphoneos":
|
||
|
|
self.cmake_args += ["-DCMAKE_SYSTEM_NAME=iOS", "-DCMAKE_OSX_DEPLOYMENT_TARGET=9.3"]
|
||
|
|
|
||
|
|
self.shared_output_name = "libdobby.dylib"
|
||
|
|
self.static_output_name = "libdobby.a"
|
||
|
|
|
||
|
|
@classmethod
|
||
|
|
def lipo_create_fat(cls, project_dir, platform, output_name):
|
||
|
|
files = list()
|
||
|
|
archs = platforms[platform]
|
||
|
|
for arch in archs:
|
||
|
|
file = f"{project_dir}/build/{platform}/{arch}/{output_name}"
|
||
|
|
files.append(file)
|
||
|
|
|
||
|
|
fat_output_dir = f"{project_dir}/build/{platform}/universal"
|
||
|
|
subprocess.run(["mkdir", "-p", "{}".format(fat_output_dir)], check=True)
|
||
|
|
cmd = ["lipo", "-create"] + files + ["-output", f"{fat_output_dir}/{output_name}"]
|
||
|
|
subprocess.run(cmd, check=True)
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
parser = argparse.ArgumentParser()
|
||
|
|
parser.add_argument("--platform", type=str, required=True)
|
||
|
|
parser.add_argument("--arch", type=str, required=True)
|
||
|
|
parser.add_argument("--library_build_type", type=str, default="static")
|
||
|
|
parser.add_argument("--android_ndk_dir", type=str)
|
||
|
|
parser.add_argument("--cmake_dir", type=str)
|
||
|
|
parser.add_argument("--llvm_dir", type=str)
|
||
|
|
args = parser.parse_args()
|
||
|
|
|
||
|
|
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
|
||
|
|
|
||
|
|
platform = args.platform
|
||
|
|
arch = args.arch
|
||
|
|
library_build_type = args.library_build_type
|
||
|
|
|
||
|
|
PlatformBuilder.cmake_dir = args.cmake_dir
|
||
|
|
PlatformBuilder.llvm_dir = args.llvm_dir
|
||
|
|
|
||
|
|
project_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
|
||
|
|
logging.info("project dir: {}".format(project_dir))
|
||
|
|
if not os.path.exists(f"{project_dir}/CMakeLists.txt"):
|
||
|
|
logging.error("Please run this script in Dobby project root directory")
|
||
|
|
sys.exit(1)
|
||
|
|
|
||
|
|
if platform not in platforms:
|
||
|
|
logging.error("invalid platform {}".format(platform))
|
||
|
|
sys.exit(-1)
|
||
|
|
|
||
|
|
if arch != "all" and arch not in platforms[platform]:
|
||
|
|
logging.error("invalid arch {} for platform {}".format(arch, platform))
|
||
|
|
sys.exit(-1)
|
||
|
|
|
||
|
|
if platform == "android":
|
||
|
|
if args.android_ndk_dir is None:
|
||
|
|
logging.error("ndk dir is required for android platform")
|
||
|
|
sys.exit(-1)
|
||
|
|
|
||
|
|
archs = list()
|
||
|
|
if arch == "all":
|
||
|
|
archs = platforms[platform]
|
||
|
|
else:
|
||
|
|
archs.append(arch)
|
||
|
|
logging.info("build platform: {}, archs: {}".format(platform, archs))
|
||
|
|
|
||
|
|
builder: PlatformBuilder = None
|
||
|
|
for arch_ in archs:
|
||
|
|
if platform == "macos":
|
||
|
|
builder = DarwinPlatformBuilder(project_dir, library_build_type, platform, arch_)
|
||
|
|
elif platform == "iphoneos":
|
||
|
|
builder = DarwinPlatformBuilder(project_dir, library_build_type, platform, arch_)
|
||
|
|
elif platform == "android":
|
||
|
|
builder = AndroidPlatformBuilder(args.android_ndk_dir, project_dir, library_build_type, arch_)
|
||
|
|
elif platform == "linux":
|
||
|
|
builder = LinuxPlatformBuilder(project_dir, library_build_type, arch_)
|
||
|
|
else:
|
||
|
|
logging.error("invalid platform {}".format(platform))
|
||
|
|
sys.exit(-1)
|
||
|
|
logging.info(
|
||
|
|
f"build platform: {platform}, arch: {arch_}, cmake_build_dir: {builder.cmake_build_dir}, output_dir: {builder.output_dir}"
|
||
|
|
)
|
||
|
|
builder.build()
|
||
|
|
|
||
|
|
if platform in ["iphoneos", "macos"] and arch == "all":
|
||
|
|
DarwinPlatformBuilder.lipo_create_fat(project_dir, platform, builder.shared_output_name)
|
||
|
|
DarwinPlatformBuilder.lipo_create_fat(project_dir, platform, builder.static_output_name)
|