forked from reaktoro/reaktoro
-
Notifications
You must be signed in to change notification settings - Fork 0
/
tasks.py
171 lines (148 loc) · 5.5 KB
/
tasks.py
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
from invoke import task
from invoke.exceptions import Exit
from pathlib import Path
from typing import Optional
import os
import shutil
import sys
def _get_vcvars_paths():
template = r"%PROGRAMFILES(X86)%\Microsoft Visual Studio\2019\{edition}\VC\Auxiliary\Build\vcvarsall.bat"
template = os.path.expandvars(template)
editions = ('BuildTools', 'Professional', 'WDExpress', 'Community', 'Enterprise')
return tuple(Path(template.format(edition=edition)) for edition in editions)
def strip_and_join(s: str):
return ' '.join(line.strip() for line in s.splitlines() if line.strip() != '')
def echo(c, msg: str):
from colorama.ansi import Fore, Style
if c.config.run.echo:
print(f"{Fore.WHITE}{Style.BRIGHT}{msg}{Style.RESET_ALL}")
def remove_directory(c, path: Path):
if path.is_dir():
echo(c, f"Removing {path}")
shutil.rmtree(path)
else:
echo(c, f"Not removing {path} (not a directory)")
def _get_and_prepare_build_and_artifacts_dir(
c,
clean: bool=False,
build_subdirectory: str="build",
) -> Path:
'''
Returns build directory where `cmake` shall be called from. Creates it and
possibly removes its contents (and artifacts_dir contents) if `clean=True`
is passed.
'''
root_dir = Path(__file__).parent
build_dir = root_dir / build_subdirectory
artifacts_dir = root_dir / "artifacts"
if clean:
remove_directory(c, build_dir)
remove_directory(c, artifacts_dir)
build_dir.mkdir(parents=True, exist_ok=not clean)
artifacts_dir.mkdir(parents=True, exist_ok=not clean)
return build_dir, artifacts_dir
def _get_cmake_command(
c,
build_dir: Path,
artifacts_dir: Path,
cmake_generator: str,
cmake_arch: Optional[str]=None,
config: str='Release',
verbose=False,
):
'''
:param build_dir: Directory from where cmake will be called.
:param artifacts_dir: Directory where binaries and python modules will be installed.
'''
root_dir = Path(__file__).parent
relative_root_dir = Path(os.path.relpath(root_dir, build_dir))
relative_artifacts_dir = Path(os.path.relpath(artifacts_dir, build_dir))
if sys.platform.startswith('win'):
cmake_include_path = f"{os.environ['CONDA_PREFIX']}\\Library\\include"
else:
cmake_include_path = f"{os.environ['CONDA_PREFIX']}\\include"
# `PYTHON_INSTALL_PREFIX` is configured to `artifacts_dir / 'python'`
# so that it won't "pollute" the Python environment when in develop
# mode.
return strip_and_join(f"""
cmake
{f'-G "{cmake_generator}"' if cmake_generator is not None else ""}
{f'-A "{cmake_arch}"' if cmake_arch is not None else ""}
-DPYBIND11_PYTHON_VERSION={os.environ.get("PY_VER", "3.7")}
-DREAKTORO_BUILD_ALL=ON
-DREAKTORO_PYTHON_INSTALL_PREFIX="{(artifacts_dir / 'python').as_posix()}"
-DCMAKE_BUILD_TYPE={config}
-DCMAKE_INCLUDE_PATH="{cmake_include_path}"
-DCMAKE_INSTALL_PREFIX="{relative_artifacts_dir.as_posix()}"
{f'-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON' if verbose else ''}
{f'-DREAKTORO_USE_OPENLIBM:BOOL=ON' if os.environ.get('REAKTORO_USE_OPENLIBM', '0').strip() != '0' else ''}
{f'"-DREAKTORO_THIRDPARTY_EXTRA_BUILD_ARGS=-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON"' if verbose else ''}
"{str(relative_root_dir)}"
""")
if sys.platform.startswith('win'):
@task
def msvc(c, clean=False, config='Release'):
"""
Generates a Visual Studio project at the "build/msvc" directory.
Assumes that the environment is already configured using:
conda devenv
activate reaktoro
"""
build_dir, artifacts_dir = _get_and_prepare_build_and_artifacts_dir(
c,
clean=clean,
build_subdirectory="build/msvc",
)
cmake_command = _get_cmake_command(
c,
build_dir=build_dir,
artifacts_dir=artifacts_dir,
cmake_generator="Visual Studio 16 2019",
cmake_arch="x64",
config=config,
)
os.chdir(build_dir)
c.run(cmake_command)
@task
def compile(c, clean=False, config='Release', number_of_jobs=-1, verbose=False):
"""
Compiles Reaktoro by running CMake and building with `ninja`.
Assumes that the environment is already configured using:
conda devenv
[source] activate reaktoro
"""
build_dir, artifacts_dir = _get_and_prepare_build_and_artifacts_dir(
c,
clean=clean,
build_subdirectory="build",
)
cmake_command = _get_cmake_command(
c,
build_dir=build_dir,
artifacts_dir=artifacts_dir,
cmake_generator="Ninja",
config=config,
verbose=verbose,
)
build_command = strip_and_join(f"""
cmake
--build .
--target install
--config {config}
--
{f"-j {number_of_jobs}" if number_of_jobs > 0 else ""}
""")
commands = [cmake_command, build_command]
if sys.platform.startswith('win'):
for vcvars_path in _get_vcvars_paths():
if not vcvars_path.is_file():
continue
commands.insert(0, f'"{vcvars_path}" amd64')
break
else:
raise Exit(
'Error: Commands to configure MSVC environment variables not found.',
code=1,
)
os.chdir(build_dir)
c.run("&&".join(commands))