-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtasks.py
More file actions
123 lines (101 loc) · 4 KB
/
tasks.py
File metadata and controls
123 lines (101 loc) · 4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import os
import shutil
from invoke.tasks import task
import platform
from enum import StrEnum
class Mode(StrEnum):
RELEASE="Release"
DEBUG="Debug"
RELWITHDEBINFO="RelWithDebInfo"
MINSIZEREL="MinSizeRel"
# Define paths
BUILD_DIR = os.path.abspath("build")
SOURCE_DIR = os.path.abspath(".")
@task(help = {"mode": "Sets the compile mode (CMake flags as compiler flags): Release, Debug, RelWithDebInfo, MinSizeRel (also specifies output folder)."})
def config(c, mode=Mode.RELEASE, forceninja=False):
"""
Configures the project using CMake and vcpkg.
"""
print(f"--- Configure build in {mode} Mode.")
mode_dir = create_mode_dir(BUILD_DIR, mode, forceninja)
# 1. Create Build Directory
if not os.path.exists(mode_dir):
os.makedirs(mode_dir)
# 2. Run CMake Configure
# -S = Source Dir, -B = Build Dir, -G = Generator (Ninja)
cmd = [
"cmake",
f"-S {SOURCE_DIR}",
f"-B {mode_dir}",
f"-DCMAKE_BUILD_TYPE={mode}",
"-DCMAKE_EXPORT_COMPILE_COMMANDS=1" # Generates compile_commands.json
]
if platform.system() == "Linux" or forceninja:
cmd.append("-GNinja")
c.run(" ".join(cmd))
# 3. Symlink compile_commands.json (for IDEs/LSPs)
# This makes clangd or VS Code C++ tools work immediately at root level
source_cc = os.path.join(mode_dir, "compile_commands.json")
target_cc = os.path.join(".", "compile_commands.json")
if platform.system() == "Windows" and not forceninja:
return
if os.path.lexists(target_cc):
try:
os.remove(target_cc)
except OSError as ose:
print("Warning: Could not remove compile_commands.json. LSP might not work as expected. \n", ose)
# Symlinks on Windows often require admin privs, so we fallback to copy if link fails
try:
os.symlink(source_cc, target_cc)
print(f"Symlinked {target_cc}")
except OSError:
shutil.copy(source_cc, target_cc)
print(f"Copied {target_cc} (Symlink failed or not supported)")
@task(help = {"mode": "Compile the preconfigured build for given mode (also specifies output folder)."})
def build(c, mode=Mode.RELEASE, forceninja=False, silent=False):
"""
Builds the project.
"""
if not silent:
print(f"--- Compiling build in {mode} Mode.")
mode_dir = create_mode_dir(BUILD_DIR, mode, forceninja)
if not os.path.exists(mode_dir):
print(f"build directory for mode: \"{mode}\" does not exist, configure the project first (invoke config --mode [Release|Debug]).")
return 1
# declare which build dir for Windows multi configuration
flags = ""
if platform.system() == "Windows":
flags = f"--config {mode}"
if silent:
flags += " > /dev/null"
c.run(f"cmake --build {mode_dir} {flags}")
print(executable_path(mode))
@task(help = {"mode": "Run the compiled build for given mode (also specifies output folder)."})
def run(c, mode=Mode.RELEASE):
"""
Runs the executable.
"""
app_path = executable_path(mode)
if not os.path.exists(app_path):
build(c, mode)
print(f"\n--- Running build in {mode} Mode: {app_path}\n\n")
c.run(app_path)
@task
def clean(c, mode=Mode.RELEASE):
"""
Deletes the contents of the build directory
"""
mode_dir = create_mode_dir(BUILD_DIR, mode)
print(f"--- Deleting build folder {mode_dir}")
c.run(f"cmake -E rm -rf {mode_dir}")
# TODO: "app" string is static but set in CMakeLists.txt
def executable_path(mode=Mode.RELEASE):
ext = ".exe" if platform.system() == "Windows" else ""
app_path = f"{BUILD_DIR}{os.path.sep}{mode}{os.path.sep}nEngine{ext}"
return app_path
def copy_assets(dist_path, folder):
shutil.copytree(f"{SOURCE_DIR}{os.path.sep}{folder}", f"{dist_path}{os.path.sep}{folder}", dirs_exist_ok=True)
def create_mode_dir(build_dir, mode, forceninja=False):
if platform.system() != "Windows" or forceninja:
return os.path.join(build_dir, mode)
return build_dir