Skip to content

Commit f04a81b

Browse files
Allow develop/install commands accept CLI options
python setup.py develop ---help displays them, with use messaes Options are --level-zerop-support=(true|false) --coverage=(true|false) --sycl-compiler-path=(path to prefix, optional) If path is not provided backend builder looks up ONEAPI_ROOT variable. In the path, builder looks for bin/dpcpp (Linux), or bin/dpcpp.exe (Windows). If found, cmake does see -DDPCTL_DPCPP_ROOT variable set. Otherwise the variable is set, and clang++ is used instead of dpcpp
1 parent c47e1f9 commit f04a81b

File tree

2 files changed

+229
-58
lines changed

2 files changed

+229
-58
lines changed

scripts/build_backend.py

Lines changed: 88 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@
1818
"""
1919

2020

21-
def build_backend(l0_support=False):
21+
def build_backend(
22+
l0_support=False, code_coverage=False, sycl_compiler_prefix=None
23+
):
2224
import glob
2325
import os
2426
import shutil
@@ -35,13 +37,19 @@ def build_backend(l0_support=False):
3537
else:
3638
assert False, sys.platform + " not supported"
3739

38-
CODE_COVERAGE = os.environ.get("CODE_COVERAGE")
39-
ONEAPI_ROOT = os.environ.get("ONEAPI_ROOT")
40+
if sycl_compiler_prefix is None:
41+
oneapi_root = os.getenv("ONEAPI_ROOT")
42+
if IS_LIN:
43+
DPCPP_ROOT = os.path.join(oneapi_root, r"compiler/latest/linux")
44+
elif IS_WIN:
45+
DPCPP_ROOT = os.path.join(oneapi_root, r"compiler\latest\windows")
46+
else:
47+
DPCPP_ROOT = os.path.join(sycl_compiler_prefix)
4048

41-
if IS_LIN:
42-
DPCPP_ROOT = os.path.join(ONEAPI_ROOT, r"compiler/latest/linux")
43-
elif IS_WIN:
44-
DPCPP_ROOT = os.path.join(ONEAPI_ROOT, r"compiler\latest\windows")
49+
if not os.path.isdir(DPCPP_ROOT):
50+
raise ValueError(
51+
"SYCL compile prefix {} is not a directry".format(DPCPP_ROOT)
52+
)
4553

4654
dpctl_dir = os.getcwd()
4755
build_cmake_dir = os.path.join(dpctl_dir, "build_cmake")
@@ -71,45 +79,60 @@ def build_backend(l0_support=False):
7179
ENABLE_LO_PROGRAM_CREATION = "ON" if l0_support else "OFF"
7280

7381
if IS_LIN:
74-
if CODE_COVERAGE:
75-
cmake_args = [
76-
"cmake",
77-
"-DCMAKE_BUILD_TYPE=Debug",
78-
"-DCMAKE_INSTALL_PREFIX=" + INSTALL_PREFIX,
79-
"-DCMAKE_PREFIX_PATH=" + INSTALL_PREFIX,
80-
"-DDPCPP_INSTALL_DIR=" + DPCPP_ROOT,
82+
if os.path.exists(os.path.join(DPCPP_ROOT, "bin", "dpcpp")):
83+
cmake_compiler_args = [
8184
"-DCMAKE_C_COMPILER:PATH="
8285
+ os.path.join(DPCPP_ROOT, "bin", "clang"),
8386
"-DCMAKE_CXX_COMPILER:PATH="
8487
+ os.path.join(DPCPP_ROOT, "bin", "dpcpp"),
85-
"-DDPCTL_ENABLE_LO_PROGRAM_CREATION="
86-
+ ENABLE_LO_PROGRAM_CREATION,
87-
"-DDPCTL_BUILD_CAPI_TESTS=ON",
88-
"-DDPCTL_GENERATE_COVERAGE=ON",
89-
"-DDPCTL_COVERAGE_REPORT_OUTPUT_DIR=" + dpctl_dir,
90-
backends,
9188
]
89+
else:
90+
cmake_compiler_args = [
91+
"-DDPCTL_CUSTOM_DPCPP_INSTALL_DIR=" + DPCPP_ROOT,
92+
"-DCMAKE_C_COMPILER:PATH="
93+
+ os.path.join(DPCPP_ROOT, "bin", "clang"),
94+
"-DCMAKE_CXX_COMPILER:PATH="
95+
+ os.path.join(DPCPP_ROOT, "bin", "clang++"),
96+
]
97+
if code_coverage:
98+
cmake_args = (
99+
[
100+
"cmake",
101+
"-DCMAKE_BUILD_TYPE=Debug",
102+
"-DCMAKE_INSTALL_PREFIX=" + INSTALL_PREFIX,
103+
"-DCMAKE_PREFIX_PATH=" + INSTALL_PREFIX,
104+
]
105+
+ cmake_compiler_args
106+
+ [
107+
"-DDPCTL_ENABLE_LO_PROGRAM_CREATION="
108+
+ ENABLE_LO_PROGRAM_CREATION,
109+
"-DDPCTL_BUILD_CAPI_TESTS=ON",
110+
"-DDPCTL_GENERATE_COVERAGE=ON",
111+
"-DDPCTL_COVERAGE_REPORT_OUTPUT_DIR=" + dpctl_dir,
112+
backends,
113+
]
114+
)
92115
subprocess.check_call(
93116
cmake_args, stderr=subprocess.STDOUT, shell=False
94117
)
95118
subprocess.check_call(["make", "V=1", "-j", "4"])
96119
subprocess.check_call(["make", "install"])
97120
subprocess.check_call(["make", "lcov-genhtml"])
98121
else:
99-
cmake_args = [
100-
"cmake",
101-
"-DCMAKE_BUILD_TYPE=Release",
102-
"-DCMAKE_INSTALL_PREFIX=" + INSTALL_PREFIX,
103-
"-DCMAKE_PREFIX_PATH=" + INSTALL_PREFIX,
104-
"-DDPCPP_INSTALL_DIR=" + DPCPP_ROOT,
105-
"-DCMAKE_C_COMPILER:PATH="
106-
+ os.path.join(DPCPP_ROOT, "bin", "clang"),
107-
"-DCMAKE_CXX_COMPILER:PATH="
108-
+ os.path.join(DPCPP_ROOT, "bin", "dpcpp"),
109-
"-DDPCTL_ENABLE_LO_PROGRAM_CREATION="
110-
+ ENABLE_LO_PROGRAM_CREATION,
111-
backends,
112-
]
122+
cmake_args = (
123+
[
124+
"cmake",
125+
"-DCMAKE_BUILD_TYPE=Release",
126+
"-DCMAKE_INSTALL_PREFIX=" + INSTALL_PREFIX,
127+
"-DCMAKE_PREFIX_PATH=" + INSTALL_PREFIX,
128+
]
129+
+ cmake_compiler_args
130+
+ [
131+
"-DDPCTL_ENABLE_LO_PROGRAM_CREATION="
132+
+ ENABLE_LO_PROGRAM_CREATION,
133+
backends,
134+
]
135+
)
113136
subprocess.check_call(
114137
cmake_args, stderr=subprocess.STDOUT, shell=False
115138
)
@@ -122,21 +145,37 @@ def build_backend(l0_support=False):
122145
):
123146
shutil.copy(file, os.path.join(dpctl_dir, "dpctl"))
124147
elif IS_WIN:
125-
cmake_args = [
126-
"cmake",
127-
"-G",
128-
"Ninja",
129-
"-DCMAKE_BUILD_TYPE=Release",
130-
"-DCMAKE_INSTALL_PREFIX=" + INSTALL_PREFIX,
131-
"-DCMAKE_PREFIX_PATH=" + INSTALL_PREFIX,
132-
"-DDPCPP_INSTALL_DIR=" + DPCPP_ROOT,
133-
"-DCMAKE_C_COMPILER:PATH="
134-
+ os.path.join(DPCPP_ROOT, "bin", "clang-cl.exe"),
135-
"-DCMAKE_CXX_COMPILER:PATH="
136-
+ os.path.join(DPCPP_ROOT, "bin", "dpcpp.exe"),
137-
"-DDPCTL_ENABLE_LO_PROGRAM_CREATION=" + ENABLE_LO_PROGRAM_CREATION,
138-
backends,
139-
]
148+
if os.path.exists(os.path.join(DPCPP_ROOT, "bin", "dpcpp.exe")):
149+
cmake_compiler_args = [
150+
"-DCMAKE_C_COMPILER:PATH="
151+
+ os.path.join(DPCPP_ROOT, "bin", "clang-cl.exe"),
152+
"-DCMAKE_CXX_COMPILER:PATH="
153+
+ os.path.join(DPCPP_ROOT, "bin", "dpcpp.exe"),
154+
]
155+
else:
156+
cmake_compiler_args = [
157+
"-DDPCTL_CUSTOM_DPCPP_INSTALL_DIR=" + DPCPP_ROOT,
158+
"-DCMAKE_C_COMPILER:PATH="
159+
+ os.path.join(DPCPP_ROOT, "bin", "clang-cl.exe"),
160+
"-DCMAKE_CXX_COMPILER:PATH="
161+
+ os.path.join(DPCPP_ROOT, "bin", "clang++.exe"),
162+
]
163+
cmake_args = (
164+
[
165+
"cmake",
166+
"-G",
167+
"Ninja",
168+
"-DCMAKE_BUILD_TYPE=Release",
169+
"-DCMAKE_INSTALL_PREFIX=" + INSTALL_PREFIX,
170+
"-DCMAKE_PREFIX_PATH=" + INSTALL_PREFIX,
171+
]
172+
+ cmake_compiler_args
173+
+ [
174+
"-DDPCTL_ENABLE_LO_PROGRAM_CREATION="
175+
+ ENABLE_LO_PROGRAM_CREATION,
176+
backends,
177+
]
178+
)
140179
subprocess.check_call(cmake_args, stderr=subprocess.STDOUT, shell=False)
141180
subprocess.check_call(["ninja", "-n"])
142181
subprocess.check_call(["ninja", "install"])

setup.py

Lines changed: 141 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ def get_suppressed_warning_flags():
101101
return []
102102

103103

104-
def build_backend():
104+
def build_backend(l0_support, coverage, sycl_compiler_prefix):
105105
import os.path
106106
from importlib.util import module_from_spec, spec_from_file_location
107107

@@ -110,15 +110,19 @@ def build_backend():
110110
)
111111
builder_module = module_from_spec(spec)
112112
spec.loader.exec_module(builder_module)
113-
builder_module.build_backend(l0_support=True)
113+
builder_module.build_backend(
114+
l0_support=l0_support,
115+
code_coverage=coverage,
116+
sycl_compiler_prefix=sycl_compiler_prefix,
117+
)
114118

115119

116120
def extensions():
117121
# Security flags
118122
eca = get_sdl_cflags()
119123
ela = get_sdl_ldflags()
120124
libs = []
121-
librarys = []
125+
libraries = []
122126
CODE_COVERAGE = os.environ.get("CODE_COVERAGE")
123127

124128
if IS_LIN:
@@ -129,11 +133,11 @@ def extensions():
129133
libs += ["DPCTLSyclInterface"]
130134

131135
if IS_LIN:
132-
librarys = [dpctl_sycl_interface_lib]
136+
libraries = [dpctl_sycl_interface_lib]
133137
elif IS_WIN:
134-
librarys = [dpctl_sycl_interface_lib]
138+
libraries = [dpctl_sycl_interface_lib]
135139
elif IS_MAC:
136-
librarys = [dpctl_sycl_interface_lib]
140+
libraries = [dpctl_sycl_interface_lib]
137141

138142
if IS_LIN or IS_MAC:
139143
runtime_library_dirs = ["$ORIGIN"]
@@ -150,7 +154,7 @@ def extensions():
150154
),
151155
"extra_link_args": ela,
152156
"libraries": libs,
153-
"library_dirs": librarys,
157+
"library_dirs": libraries,
154158
"runtime_library_dirs": runtime_library_dirs,
155159
"language": "c++",
156160
"define_macros": [],
@@ -261,14 +265,142 @@ def extensions():
261265

262266

263267
class install(orig_install.install):
268+
description = "Installs dpctl into Python prefix"
269+
user_options = orig_install.install.user_options + [
270+
(
271+
"level-zero-support=",
272+
None,
273+
"Whether to enable support for program creation "
274+
"for Level-zero backend",
275+
),
276+
(
277+
"sycl-compiler-prefix=",
278+
None,
279+
"Path to SYCL compiler installation. None means "
280+
"read it off ONEAPI_ROOT environment variable or fail.",
281+
),
282+
(
283+
"coverage=",
284+
None,
285+
"Whether to generate coverage report "
286+
"when building the backend library",
287+
),
288+
]
289+
290+
def initialize_options(self):
291+
super().initialize_options()
292+
self.level_zero_support = "True"
293+
self.coverage = os.getenv("CODE_COVERAGE", "False")
294+
self.sycl_compiler_prefix = None
295+
296+
def finalize_options(self):
297+
if isinstance(self.level_zero_support, str):
298+
self.level_zero_support = self.level_zero_support.capitalize()
299+
if self.level_zero_support in ["True", "False", "0", "1"]:
300+
self.level_zero_support = bool(eval(self.level_zero_support))
301+
else:
302+
raise ValueError(
303+
"--level-zero-support value is invalid, use True/False"
304+
)
305+
if isinstance(self.coverage, str):
306+
self.coverage = self.coverage.capitalize()
307+
if self.coverage in ["True", "False", "0", "1"]:
308+
self.coverage = bool(eval(self.coverage))
309+
else:
310+
print(type(self.coverage))
311+
print(self.coverage)
312+
raise ValueError("--coverage value is invalid, use True/False")
313+
if isinstance(self.sycl_compiler_prefix, str):
314+
if not os.path.exists(os.path.join(self.sycl_compiler_prefix)):
315+
raise ValueError(
316+
"--sycl-compiler-prefix expects a path "
317+
"to an existing directory"
318+
)
319+
elif self.sycl_compiler_prefix is None:
320+
pass
321+
else:
322+
raise ValueError(
323+
"--sycl-compiler-prefix value is invalid, use a "
324+
"path to compiler intallation. To use oneAPI, use the "
325+
"default value, but remember to activate the compiler "
326+
"environment"
327+
)
328+
super().finalize_options()
329+
264330
def run(self):
265-
build_backend()
331+
build_backend(
332+
self.level_zero_support, self.coverage, self.sycl_compiler_prefix
333+
)
266334
return super().run()
267335

268336

269337
class develop(orig_develop.develop):
338+
description = "Installs dpctl in place"
339+
user_options = orig_develop.develop.user_options + [
340+
(
341+
"level-zero-support=",
342+
None,
343+
"Whether to enable support for program creation "
344+
"for Level-zero backend",
345+
),
346+
(
347+
"sycl-compiler-prefix=",
348+
None,
349+
"Path to SYCL compiler installation. None means "
350+
"read it off ONEAPI_ROOT environment variable or fail.",
351+
),
352+
(
353+
"coverage=",
354+
None,
355+
"Whether to generate coverage report "
356+
"when building the backend library",
357+
),
358+
]
359+
360+
def initialize_options(self):
361+
super().initialize_options()
362+
self.level_zero_support = "True"
363+
self.coverage = os.getenv("CODE_COVERAGE", "False")
364+
self.sycl_compiler_prefix = None
365+
366+
def finalize_options(self):
367+
if isinstance(self.level_zero_support, str):
368+
self.level_zero_support = self.level_zero_support.capitalize()
369+
if self.level_zero_support in ["True", "False", "0", "1"]:
370+
self.level_zero_support = bool(eval(self.level_zero_support))
371+
else:
372+
raise ValueError(
373+
"--level-zero-support value is invalid, use True/False"
374+
)
375+
if isinstance(self.coverage, str):
376+
self.coverage = self.coverage.capitalize()
377+
if self.coverage in ["True", "False", "0", "1"]:
378+
self.coverage = bool(eval(self.coverage))
379+
else:
380+
print(type(self.coverage))
381+
print(self.coverage)
382+
raise ValueError("--coverage value is invalid, use True/False")
383+
if isinstance(self.sycl_compiler_prefix, str):
384+
if not os.path.exists(os.path.join(self.sycl_compiler_prefix)):
385+
raise ValueError(
386+
"--sycl-compiler-prefix expects a path "
387+
"to an existing directory"
388+
)
389+
elif self.sycl_compiler_prefix is None:
390+
pass
391+
else:
392+
raise ValueError(
393+
"--sycl-compiler-prefix value is invalid, use a "
394+
"path to compiler intallation. To use oneAPI, use the "
395+
"default value, but remember to activate the compiler "
396+
"environment"
397+
)
398+
super().finalize_options()
399+
270400
def run(self):
271-
build_backend()
401+
build_backend(
402+
self.level_zero_support, self.coverage, self.sycl_compiler_prefix
403+
)
272404
return super().run()
273405

274406

0 commit comments

Comments
 (0)