Skip to content

Commit

Permalink
Allow develop/install commands accept CLI options
Browse files Browse the repository at this point in the history
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
  • Loading branch information
oleksandr-pavlyk committed May 20, 2021
1 parent c47e1f9 commit f04a81b
Show file tree
Hide file tree
Showing 2 changed files with 229 additions and 58 deletions.
137 changes: 88 additions & 49 deletions scripts/build_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
"""


def build_backend(l0_support=False):
def build_backend(
l0_support=False, code_coverage=False, sycl_compiler_prefix=None
):
import glob
import os
import shutil
Expand All @@ -35,13 +37,19 @@ def build_backend(l0_support=False):
else:
assert False, sys.platform + " not supported"

CODE_COVERAGE = os.environ.get("CODE_COVERAGE")
ONEAPI_ROOT = os.environ.get("ONEAPI_ROOT")
if sycl_compiler_prefix is None:
oneapi_root = os.getenv("ONEAPI_ROOT")
if IS_LIN:
DPCPP_ROOT = os.path.join(oneapi_root, r"compiler/latest/linux")
elif IS_WIN:
DPCPP_ROOT = os.path.join(oneapi_root, r"compiler\latest\windows")
else:
DPCPP_ROOT = os.path.join(sycl_compiler_prefix)

if IS_LIN:
DPCPP_ROOT = os.path.join(ONEAPI_ROOT, r"compiler/latest/linux")
elif IS_WIN:
DPCPP_ROOT = os.path.join(ONEAPI_ROOT, r"compiler\latest\windows")
if not os.path.isdir(DPCPP_ROOT):
raise ValueError(
"SYCL compile prefix {} is not a directry".format(DPCPP_ROOT)
)

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

if IS_LIN:
if CODE_COVERAGE:
cmake_args = [
"cmake",
"-DCMAKE_BUILD_TYPE=Debug",
"-DCMAKE_INSTALL_PREFIX=" + INSTALL_PREFIX,
"-DCMAKE_PREFIX_PATH=" + INSTALL_PREFIX,
"-DDPCPP_INSTALL_DIR=" + DPCPP_ROOT,
if os.path.exists(os.path.join(DPCPP_ROOT, "bin", "dpcpp")):
cmake_compiler_args = [
"-DCMAKE_C_COMPILER:PATH="
+ os.path.join(DPCPP_ROOT, "bin", "clang"),
"-DCMAKE_CXX_COMPILER:PATH="
+ os.path.join(DPCPP_ROOT, "bin", "dpcpp"),
"-DDPCTL_ENABLE_LO_PROGRAM_CREATION="
+ ENABLE_LO_PROGRAM_CREATION,
"-DDPCTL_BUILD_CAPI_TESTS=ON",
"-DDPCTL_GENERATE_COVERAGE=ON",
"-DDPCTL_COVERAGE_REPORT_OUTPUT_DIR=" + dpctl_dir,
backends,
]
else:
cmake_compiler_args = [
"-DDPCTL_CUSTOM_DPCPP_INSTALL_DIR=" + DPCPP_ROOT,
"-DCMAKE_C_COMPILER:PATH="
+ os.path.join(DPCPP_ROOT, "bin", "clang"),
"-DCMAKE_CXX_COMPILER:PATH="
+ os.path.join(DPCPP_ROOT, "bin", "clang++"),
]
if code_coverage:
cmake_args = (
[
"cmake",
"-DCMAKE_BUILD_TYPE=Debug",
"-DCMAKE_INSTALL_PREFIX=" + INSTALL_PREFIX,
"-DCMAKE_PREFIX_PATH=" + INSTALL_PREFIX,
]
+ cmake_compiler_args
+ [
"-DDPCTL_ENABLE_LO_PROGRAM_CREATION="
+ ENABLE_LO_PROGRAM_CREATION,
"-DDPCTL_BUILD_CAPI_TESTS=ON",
"-DDPCTL_GENERATE_COVERAGE=ON",
"-DDPCTL_COVERAGE_REPORT_OUTPUT_DIR=" + dpctl_dir,
backends,
]
)
subprocess.check_call(
cmake_args, stderr=subprocess.STDOUT, shell=False
)
subprocess.check_call(["make", "V=1", "-j", "4"])
subprocess.check_call(["make", "install"])
subprocess.check_call(["make", "lcov-genhtml"])
else:
cmake_args = [
"cmake",
"-DCMAKE_BUILD_TYPE=Release",
"-DCMAKE_INSTALL_PREFIX=" + INSTALL_PREFIX,
"-DCMAKE_PREFIX_PATH=" + INSTALL_PREFIX,
"-DDPCPP_INSTALL_DIR=" + DPCPP_ROOT,
"-DCMAKE_C_COMPILER:PATH="
+ os.path.join(DPCPP_ROOT, "bin", "clang"),
"-DCMAKE_CXX_COMPILER:PATH="
+ os.path.join(DPCPP_ROOT, "bin", "dpcpp"),
"-DDPCTL_ENABLE_LO_PROGRAM_CREATION="
+ ENABLE_LO_PROGRAM_CREATION,
backends,
]
cmake_args = (
[
"cmake",
"-DCMAKE_BUILD_TYPE=Release",
"-DCMAKE_INSTALL_PREFIX=" + INSTALL_PREFIX,
"-DCMAKE_PREFIX_PATH=" + INSTALL_PREFIX,
]
+ cmake_compiler_args
+ [
"-DDPCTL_ENABLE_LO_PROGRAM_CREATION="
+ ENABLE_LO_PROGRAM_CREATION,
backends,
]
)
subprocess.check_call(
cmake_args, stderr=subprocess.STDOUT, shell=False
)
Expand All @@ -122,21 +145,37 @@ def build_backend(l0_support=False):
):
shutil.copy(file, os.path.join(dpctl_dir, "dpctl"))
elif IS_WIN:
cmake_args = [
"cmake",
"-G",
"Ninja",
"-DCMAKE_BUILD_TYPE=Release",
"-DCMAKE_INSTALL_PREFIX=" + INSTALL_PREFIX,
"-DCMAKE_PREFIX_PATH=" + INSTALL_PREFIX,
"-DDPCPP_INSTALL_DIR=" + DPCPP_ROOT,
"-DCMAKE_C_COMPILER:PATH="
+ os.path.join(DPCPP_ROOT, "bin", "clang-cl.exe"),
"-DCMAKE_CXX_COMPILER:PATH="
+ os.path.join(DPCPP_ROOT, "bin", "dpcpp.exe"),
"-DDPCTL_ENABLE_LO_PROGRAM_CREATION=" + ENABLE_LO_PROGRAM_CREATION,
backends,
]
if os.path.exists(os.path.join(DPCPP_ROOT, "bin", "dpcpp.exe")):
cmake_compiler_args = [
"-DCMAKE_C_COMPILER:PATH="
+ os.path.join(DPCPP_ROOT, "bin", "clang-cl.exe"),
"-DCMAKE_CXX_COMPILER:PATH="
+ os.path.join(DPCPP_ROOT, "bin", "dpcpp.exe"),
]
else:
cmake_compiler_args = [
"-DDPCTL_CUSTOM_DPCPP_INSTALL_DIR=" + DPCPP_ROOT,
"-DCMAKE_C_COMPILER:PATH="
+ os.path.join(DPCPP_ROOT, "bin", "clang-cl.exe"),
"-DCMAKE_CXX_COMPILER:PATH="
+ os.path.join(DPCPP_ROOT, "bin", "clang++.exe"),
]
cmake_args = (
[
"cmake",
"-G",
"Ninja",
"-DCMAKE_BUILD_TYPE=Release",
"-DCMAKE_INSTALL_PREFIX=" + INSTALL_PREFIX,
"-DCMAKE_PREFIX_PATH=" + INSTALL_PREFIX,
]
+ cmake_compiler_args
+ [
"-DDPCTL_ENABLE_LO_PROGRAM_CREATION="
+ ENABLE_LO_PROGRAM_CREATION,
backends,
]
)
subprocess.check_call(cmake_args, stderr=subprocess.STDOUT, shell=False)
subprocess.check_call(["ninja", "-n"])
subprocess.check_call(["ninja", "install"])
Expand Down
150 changes: 141 additions & 9 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def get_suppressed_warning_flags():
return []


def build_backend():
def build_backend(l0_support, coverage, sycl_compiler_prefix):
import os.path
from importlib.util import module_from_spec, spec_from_file_location

Expand All @@ -110,15 +110,19 @@ def build_backend():
)
builder_module = module_from_spec(spec)
spec.loader.exec_module(builder_module)
builder_module.build_backend(l0_support=True)
builder_module.build_backend(
l0_support=l0_support,
code_coverage=coverage,
sycl_compiler_prefix=sycl_compiler_prefix,
)


def extensions():
# Security flags
eca = get_sdl_cflags()
ela = get_sdl_ldflags()
libs = []
librarys = []
libraries = []
CODE_COVERAGE = os.environ.get("CODE_COVERAGE")

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

if IS_LIN:
librarys = [dpctl_sycl_interface_lib]
libraries = [dpctl_sycl_interface_lib]
elif IS_WIN:
librarys = [dpctl_sycl_interface_lib]
libraries = [dpctl_sycl_interface_lib]
elif IS_MAC:
librarys = [dpctl_sycl_interface_lib]
libraries = [dpctl_sycl_interface_lib]

if IS_LIN or IS_MAC:
runtime_library_dirs = ["$ORIGIN"]
Expand All @@ -150,7 +154,7 @@ def extensions():
),
"extra_link_args": ela,
"libraries": libs,
"library_dirs": librarys,
"library_dirs": libraries,
"runtime_library_dirs": runtime_library_dirs,
"language": "c++",
"define_macros": [],
Expand Down Expand Up @@ -261,14 +265,142 @@ def extensions():


class install(orig_install.install):
description = "Installs dpctl into Python prefix"
user_options = orig_install.install.user_options + [
(
"level-zero-support=",
None,
"Whether to enable support for program creation "
"for Level-zero backend",
),
(
"sycl-compiler-prefix=",
None,
"Path to SYCL compiler installation. None means "
"read it off ONEAPI_ROOT environment variable or fail.",
),
(
"coverage=",
None,
"Whether to generate coverage report "
"when building the backend library",
),
]

def initialize_options(self):
super().initialize_options()
self.level_zero_support = "True"
self.coverage = os.getenv("CODE_COVERAGE", "False")
self.sycl_compiler_prefix = None

def finalize_options(self):
if isinstance(self.level_zero_support, str):
self.level_zero_support = self.level_zero_support.capitalize()
if self.level_zero_support in ["True", "False", "0", "1"]:
self.level_zero_support = bool(eval(self.level_zero_support))
else:
raise ValueError(
"--level-zero-support value is invalid, use True/False"
)
if isinstance(self.coverage, str):
self.coverage = self.coverage.capitalize()
if self.coverage in ["True", "False", "0", "1"]:
self.coverage = bool(eval(self.coverage))
else:
print(type(self.coverage))
print(self.coverage)
raise ValueError("--coverage value is invalid, use True/False")
if isinstance(self.sycl_compiler_prefix, str):
if not os.path.exists(os.path.join(self.sycl_compiler_prefix)):
raise ValueError(
"--sycl-compiler-prefix expects a path "
"to an existing directory"
)
elif self.sycl_compiler_prefix is None:
pass
else:
raise ValueError(
"--sycl-compiler-prefix value is invalid, use a "
"path to compiler intallation. To use oneAPI, use the "
"default value, but remember to activate the compiler "
"environment"
)
super().finalize_options()

def run(self):
build_backend()
build_backend(
self.level_zero_support, self.coverage, self.sycl_compiler_prefix
)
return super().run()


class develop(orig_develop.develop):
description = "Installs dpctl in place"
user_options = orig_develop.develop.user_options + [
(
"level-zero-support=",
None,
"Whether to enable support for program creation "
"for Level-zero backend",
),
(
"sycl-compiler-prefix=",
None,
"Path to SYCL compiler installation. None means "
"read it off ONEAPI_ROOT environment variable or fail.",
),
(
"coverage=",
None,
"Whether to generate coverage report "
"when building the backend library",
),
]

def initialize_options(self):
super().initialize_options()
self.level_zero_support = "True"
self.coverage = os.getenv("CODE_COVERAGE", "False")
self.sycl_compiler_prefix = None

def finalize_options(self):
if isinstance(self.level_zero_support, str):
self.level_zero_support = self.level_zero_support.capitalize()
if self.level_zero_support in ["True", "False", "0", "1"]:
self.level_zero_support = bool(eval(self.level_zero_support))
else:
raise ValueError(
"--level-zero-support value is invalid, use True/False"
)
if isinstance(self.coverage, str):
self.coverage = self.coverage.capitalize()
if self.coverage in ["True", "False", "0", "1"]:
self.coverage = bool(eval(self.coverage))
else:
print(type(self.coverage))
print(self.coverage)
raise ValueError("--coverage value is invalid, use True/False")
if isinstance(self.sycl_compiler_prefix, str):
if not os.path.exists(os.path.join(self.sycl_compiler_prefix)):
raise ValueError(
"--sycl-compiler-prefix expects a path "
"to an existing directory"
)
elif self.sycl_compiler_prefix is None:
pass
else:
raise ValueError(
"--sycl-compiler-prefix value is invalid, use a "
"path to compiler intallation. To use oneAPI, use the "
"default value, but remember to activate the compiler "
"environment"
)
super().finalize_options()

def run(self):
build_backend()
build_backend(
self.level_zero_support, self.coverage, self.sycl_compiler_prefix
)
return super().run()


Expand Down

0 comments on commit f04a81b

Please sign in to comment.