Skip to content

Commit f7acaea

Browse files
Closes #777 (#778)
When scikit-build assembles dpctl, it runs cmake with "_skbuild/*/cmake-build" being its build directory, "_skbuild/*/cmake-install" being its install directory. It then runs setuptools.setup to execute build_py steps using "_skbuild/*/setuptools" as its build_base. Since sycl interface library is registered in package-data, it is copied from cmake-install (where is has symbolic links) to setuptools (where unpatched setuptools.command.build_py command follows them turning them into hard files). Then, when running install_lib step, files from _"skbuild/*/setuptools/lib/dpctl" are copied into site-packages/dpctl using copy_tree, which also follows symbolic links, hence turning them into hard links). This PR transfers logic from pre-scikit-build setup.py to fix hard links as post setuptools.command.install.run() step). A test is added to tests/test_service.py to verify that on Linux some of library files are symbolic links.
1 parent 902fa01 commit f7acaea

File tree

2 files changed

+64
-6
lines changed

2 files changed

+64
-6
lines changed

dpctl/tests/test_service.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import os
2424
import os.path
2525
import re
26+
import sys
2627

2728
import pytest
2829

@@ -129,3 +130,25 @@ def test_dev_utils():
129130
with pytest.raises(ValueError):
130131
with ctx_mngr(log_dir="/not_a_dir"):
131132
dpctl.SyclDevice().parent_device
133+
134+
135+
def test_syclinterface():
136+
install_dir = os.path.dirname(os.path.abspath(dpctl.__file__))
137+
paths = glob.glob(os.path.join(install_dir, "*DPCTLSyclInterface*"))
138+
if "linux" in sys.platform:
139+
assert len(paths) > 1 and any(
140+
[os.path.islink(fn) for fn in paths]
141+
), "All library instances are hard links"
142+
elif sys.platform in ["win32", "cygwin"]:
143+
exts = []
144+
for fn in paths:
145+
_, file_ext = os.path.splitext(fn)
146+
exts.append(file_ext.lower())
147+
assert (
148+
".lib" in exts
149+
), "Installation does not have DPCTLSyclInterface.lib"
150+
assert (
151+
".dll" in exts
152+
), "Installation does not have DPCTLSyclInterface.dll"
153+
else:
154+
raise RuntimeError("Unsupported system")

setup.py

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,18 @@
1414
# See the License for the specific language governing permissions and
1515
# limitations under the License.
1616

17+
import glob
1718
import os.path
1819
import pathlib
1920
import shutil
21+
import sys
2022

2123
import skbuild
2224
import skbuild.setuptools_wrap
2325
import skbuild.utils
2426
from setuptools import find_packages
27+
from skbuild.command.build_py import build_py as _skbuild_build_py
28+
from skbuild.command.install import install as _skbuild_install
2529

2630
import versioneer
2731

@@ -30,11 +34,6 @@
3034
long_description = file.read()
3135

3236

33-
def _get_cmdclass():
34-
cmdclass = versioneer.get_cmdclass()
35-
return cmdclass
36-
37-
3837
def cleanup_destination(cmake_manifest):
3938
"""Delete library files from dpctl/ folder before
4039
letting skbuild copy them over to avoid errors.
@@ -52,7 +51,9 @@ def cleanup_destination(cmake_manifest):
5251
return cmake_manifest
5352

5453

55-
def _patched_copy_file(src_file, dest_file, hide_listing=True):
54+
def _patched_copy_file(
55+
src_file, dest_file, hide_listing=True, preserve_mode=True
56+
):
5657
"""Copy ``src_file`` to ``dest_file`` ensuring parent directory exists.
5758
5859
By default, message like `creating directory /path/to/package` and
@@ -79,6 +80,40 @@ def _patched_copy_file(src_file, dest_file, hide_listing=True):
7980
skbuild.setuptools_wrap._copy_file = _patched_copy_file
8081

8182

83+
class BuildPyCmd(_skbuild_build_py):
84+
def copy_file(self, src, dst, preserve_mode=True):
85+
_patched_copy_file(src, dst, preserve_mode=preserve_mode)
86+
return (dst, 1)
87+
88+
89+
class InstallCmd(_skbuild_install):
90+
def run(self):
91+
ret = super().run()
92+
if "linux" in sys.platform:
93+
this_dir = os.path.dirname(os.path.abspath(__file__))
94+
dpctl_build_dir = os.path.join(this_dir, self.build_lib, "dpctl")
95+
dpctl_install_dir = os.path.join(self.install_libbase, "dpctl")
96+
for fn in glob.glob(
97+
os.path.join(dpctl_install_dir, "*DPCTLSyclInterface.so*")
98+
):
99+
os.remove(fn)
100+
base_fn = os.path.basename(fn)
101+
src_file = os.path.join(dpctl_build_dir, base_fn)
102+
dst_file = os.path.join(dpctl_install_dir, base_fn)
103+
_patched_copy_file(src_file, dst_file)
104+
return ret
105+
106+
107+
def _get_cmdclass():
108+
cmdclass = versioneer.get_cmdclass(
109+
cmdclass={
110+
"build_py": BuildPyCmd,
111+
"install": InstallCmd,
112+
}
113+
)
114+
return cmdclass
115+
116+
82117
skbuild.setup(
83118
name="dpctl",
84119
version=versioneer.get_version(),

0 commit comments

Comments
 (0)