Skip to content

Commit 67932dc

Browse files
committed
Allow to build executable and pack with python package
1 parent 703254f commit 67932dc

File tree

7 files changed

+92
-39
lines changed

7 files changed

+92
-39
lines changed

CHANGES.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
CHANGES
22
=======
33

4+
5+
0.7.0 (2017-08-11)
6+
------------------
7+
8+
- Allow to build executable and pack with python package.
9+
410
- Use PyO3 0.1 for example.
511

612

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from setuptools import setup
22

3-
version = '0.6.4'
3+
version = '0.7.0'
44

55

66
setup(

setuptools_rust/build.py

Lines changed: 70 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
DistutilsPlatformError, DistutilsSetupError)
1111

1212
from .extension import RustExtension
13-
from .utils import cpython_feature, get_rust_version
13+
from .utils import Binding, cpython_feature, get_rust_version
1414

1515

1616
class build_rust(Command):
@@ -43,6 +43,8 @@ def finalize_options(self):
4343
if isinstance(ext, RustExtension)]
4444

4545
def build_extension(self, ext):
46+
executable = ext.binding == Binding.Exec
47+
4648
# Make sure that if pythonXX-sys is used, it builds against the current
4749
# executing python interpreter.
4850
bindir = os.path.dirname(sys.executable)
@@ -75,20 +77,30 @@ def build_extension(self, ext):
7577

7678
# build cargo command
7779
feature_args = ["--features", " ".join(features)] if features else []
78-
args = (["cargo", "rustc", "--lib", "--manifest-path", ext.path]
79-
+ feature_args
80-
+ list(ext.args or []))
81-
if not debug_build:
82-
args.append("--release")
83-
if quiet:
84-
args.append("-q")
8580

86-
args.extend(["--", '--crate-type', 'cdylib'])
81+
if executable:
82+
args = (["cargo", "build", "--manifest-path", ext.path]
83+
+ feature_args
84+
+ list(ext.args or []))
85+
if not debug_build:
86+
args.append("--release")
87+
if quiet:
88+
args.append("-q")
89+
else:
90+
args = (["cargo", "rustc", "--lib", "--manifest-path", ext.path]
91+
+ feature_args
92+
+ list(ext.args or []))
93+
if not debug_build:
94+
args.append("--release")
95+
if quiet:
96+
args.append("-q")
97+
98+
args.extend(["--", '--crate-type', 'cdylib'])
8799

88-
# OSX requires special linker argument
89-
if sys.platform == "darwin":
90-
args.extend(["-C", "link-arg=-undefined",
91-
"-C", "link-arg=dynamic_lookup"])
100+
# OSX requires special linker argument
101+
if sys.platform == "darwin":
102+
args.extend(["-C", "link-arg=-undefined",
103+
"-C", "link-arg=dynamic_lookup"])
92104

93105
if not quiet:
94106
print(" ".join(args), file=sys.stderr)
@@ -129,19 +141,37 @@ def build_extension(self, ext):
129141
target_dir = os.path.join(
130142
os.path.dirname(ext.path), "target/", suffix)
131143

132-
if sys.platform == "win32":
133-
wildcard_so = "*.dll"
134-
elif sys.platform == "darwin":
135-
wildcard_so = "*.dylib"
144+
if executable:
145+
# search executable
146+
dylib_path = None
147+
for name in os.listdir(target_dir):
148+
path = os.path.join(target_dir, name)
149+
if name.startswith(".") or not os.path.isfile(path):
150+
continue
151+
152+
if os.access(path, os.X_OK):
153+
dylib_path = path
154+
break
155+
156+
if dylib_path is None:
157+
raise DistutilsExecError(
158+
"rust build failed; unable to find executable in %s" %
159+
target_dir)
136160
else:
137-
wildcard_so = "*.so"
161+
if sys.platform == "win32":
162+
wildcard_so = "*.dll"
163+
elif sys.platform == "darwin":
164+
wildcard_so = "*.dylib"
165+
else:
166+
wildcard_so = "*.so"
138167

139-
try:
140-
dylib_path = glob.glob(os.path.join(target_dir, wildcard_so))[0]
141-
except IndexError:
142-
raise DistutilsExecError(
143-
"rust build failed; unable to find any %s in %s" %
144-
(wildcard_so, target_dir))
168+
try:
169+
dylib_path = glob.glob(
170+
os.path.join(target_dir, wildcard_so))[0]
171+
except IndexError:
172+
raise DistutilsExecError(
173+
"rust build failed; unable to find any %s in %s" %
174+
(wildcard_so, target_dir))
145175

146176
# Ask build_ext where the shared library would go if it had built it,
147177
# then copy it there.
@@ -152,13 +182,23 @@ def build_extension(self, ext):
152182
target_fname = os.path.basename(os.path.splitext(
153183
os.path.basename(dylib_path)[3:])[0])
154184

155-
ext_path = build_ext.get_ext_fullpath(target_fname)
185+
if executable:
186+
ext_path = build_ext.get_ext_fullpath(target_fname)
187+
ext_path, _ = os.path.splitext(ext_path)
188+
else:
189+
ext_path = build_ext.get_ext_fullpath(target_fname)
190+
156191
try:
157192
os.makedirs(os.path.dirname(ext_path))
158193
except OSError:
159194
pass
160195
shutil.copyfile(dylib_path, ext_path)
161196

197+
if executable:
198+
mode = os.stat(ext_path).st_mode
199+
mode |= (mode & 0o444) >> 2 # copy R bits to X
200+
os.chmod(ext_path, mode)
201+
162202
def run(self):
163203
if not self.extensions:
164204
return
@@ -182,10 +222,12 @@ def run(self):
182222
version, ext.rust_version))
183223

184224
self.build_extension(ext)
185-
except (DistutilsSetupError, DistutilsFileError, DistutilsExecError,
186-
DistutilsPlatformError, CompileError) as e:
225+
except (DistutilsSetupError, DistutilsFileError,
226+
DistutilsExecError, DistutilsPlatformError,
227+
CompileError) as e:
187228
if not ext.optional:
188229
raise
189230
else:
190-
print('Build optional Rust extension %s failed.' % ext.name)
231+
print('Build optional Rust extension %s failed.' %
232+
ext.name)
191233
print(str(e))

setuptools_rust/check.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,16 @@ def run(self):
6262
try:
6363
if not os.path.exists(ext.path):
6464
raise DistutilsFileError(
65-
"Can not file rust extension project file: %s" % ext.path)
65+
"Can not file rust extension project file: %s" %
66+
ext.path)
6667

6768
features = set(ext.features)
6869
features.update(cpython_feature(binding=ext.binding))
6970

7071
# check cargo command
7172
feature_args = [
7273
"--features", " ".join(features)] if features else []
73-
args = (["cargo", "check", "--lib", "--manifest-path", ext.path]
74+
args = (["cargo", "check", "--manifest-path", ext.path]
7475
+ feature_args
7576
+ list(ext.args or []))
7677

@@ -92,5 +93,6 @@ def run(self):
9293
if not ext.optional:
9394
raise
9495
else:
95-
print('Check optional Rust extension %s failed.' % ext.name)
96+
print('Check optional Rust extension %s failed.' %
97+
ext.name)
9698
print(str(e))

setuptools_rust/extension.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,10 @@ class RustExtension:
3535
Binding.PyO3 uses PyO3
3636
Binding.RustCPython uses Rust CPython.
3737
Binding.NoBinding uses no binding.
38+
Binding.Exec build executable.
3839
optional : bool
39-
if it is true, a build failure in the extension will not abort the build process,
40-
but instead simply not install the failing extension.
40+
if it is true, a build failure in the extension will not abort the
41+
build process, but instead simply not install the failing extension.
4142
"""
4243

4344
def __init__(self, name, path,

setuptools_rust/test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ def run(self):
6262
# test cargo command
6363
feature_args = [
6464
"--features", " ".join(features)] if features else []
65-
args = (["cargo", "test", "--lib", "--manifest-path", ext.path]
65+
args = (["cargo", "test", "--manifest-path", ext.path]
6666
+ feature_args
6767
+ list(ext.args or []))
6868

setuptools_rust/utils.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,20 @@ class Binding:
1010
"""
1111
Binding Options
1212
"""
13-
# https://github.com/PyO3/PyO3
13+
# https://github.com/PyO3/PyO3
1414
PyO3 = 0
15-
# https://github.com/dgrunwald/rust-cpython
15+
# https://github.com/dgrunwald/rust-cpython
1616
RustCPython = 1
17-
# Bring your own binding
17+
# Bring your own binding
1818
NoBinding = 2
19+
# Build executable
20+
Exec = 3
1921

2022

2123
def cpython_feature(ext=True, binding=Binding.PyO3):
2224
version = sys.version_info
2325

24-
if binding is Binding.NoBinding:
26+
if binding in (Binding.NoBinding, Binding.Exec):
2527
return ()
2628
elif binding is Binding.PyO3:
2729
if (2, 7) < version < (2, 8):

0 commit comments

Comments
 (0)