Skip to content

Commit aacfab4

Browse files
committed
Add CIBW_DELOCATE_COMMAND env variable
to allow different options to auditwheel/delocate, alternative commands and a future Windows-equivalent. Fix pypa#191 .
1 parent 96a2505 commit aacfab4

File tree

7 files changed

+103
-60
lines changed

7 files changed

+103
-60
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,9 @@ Options
9595
| | [`CIBW_BUILD`](https://cibuildwheel.readthedocs.io/en/stable/options/#build-skip) [`CIBW_SKIP`](https://cibuildwheel.readthedocs.io/en/stable/options/#build-skip) | Choose the Python versions to build |
9696
| **Build environment** | [`CIBW_ENVIRONMENT`](https://cibuildwheel.readthedocs.io/en/stable/options/#environment) | Set environment variables needed during the build |
9797
| | [`CIBW_BEFORE_BUILD`](https://cibuildwheel.readthedocs.io/en/stable/options/#before-build) | Execute a shell command preparing each wheel's build |
98+
| | [`CIBW_DELOCATE_COMMAND`](https://cibuildwheel.readthedocs.io/en/stable/options/#delocate-command) | Execute a shell command to delocate each (non-pure Python) built wheel |
9899
| | [`CIBW_MANYLINUX_X86_64_IMAGE`](https://cibuildwheel.readthedocs.io/en/stable/options/#manylinux-image) [`CIBW_MANYLINUX_I686_IMAGE`](https://cibuildwheel.readthedocs.io/en/stable/options/#manylinux-image) | Specify alternative manylinux docker images |
99-
| **Testing** | [`CIBW_TEST_COMMAND`](https://cibuildwheel.readthedocs.io/en/stable/options/#test-command) | Execute a shell command to test all built wheels |
100+
| **Testing** | [`CIBW_TEST_COMMAND`](https://cibuildwheel.readthedocs.io/en/stable/options/#test-command) | Execute a shell command to test each built wheel |
100101
| | [`CIBW_TEST_REQUIRES`](https://cibuildwheel.readthedocs.io/en/stable/options/#test-requires) | Install Python dependencies before running the tests |
101102
| | [`CIBW_TEST_EXTRAS`](https://cibuildwheel.readthedocs.io/en/stable/options/#test-extras) | Install your wheel for testing using extras_require |
102103
| **Other** | [`CIBW_BUILD_VERBOSITY`](https://cibuildwheel.readthedocs.io/en/stable/options/#test-extras) | Increase/decrease the output of pip wheel |

cibuildwheel/__main__.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,13 @@ def main():
8989
before_build = get_option_from_environment('CIBW_BEFORE_BUILD', platform=platform)
9090
build_verbosity = get_option_from_environment('CIBW_BUILD_VERBOSITY', platform=platform, default='')
9191
build_config, skip_config = os.environ.get('CIBW_BUILD', '*'), os.environ.get('CIBW_SKIP', '')
92+
if platform == 'linux':
93+
delocate_command_default = 'auditwheel repair -w {dest_dir} {wheel}'
94+
elif platform == 'macos':
95+
delocate_command_default = 'delocate-listdeps {wheel} && delocate-wheel -w {dest_dir} {wheel}'
96+
else:
97+
delocate_command_default = ''
98+
delocate_command = get_option_from_environment('CIBW_DELOCATE_COMMAND', platform=platform, default=delocate_command_default)
9299
environment_config = get_option_from_environment('CIBW_ENVIRONMENT', platform=platform, default='')
93100

94101
if test_extras:
@@ -130,6 +137,7 @@ def main():
130137
before_build=before_build,
131138
build_verbosity=build_verbosity,
132139
build_selector=build_selector,
140+
delocate_command=delocate_command,
133141
environment=environment,
134142
)
135143

cibuildwheel/linux.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def get_python_configurations(build_selector):
3030
return [c for c in python_configurations if build_selector(c.identifier)]
3131

3232

33-
def build(project_dir, output_dir, test_command, test_requires, test_extras, before_build, build_verbosity, build_selector, environment, manylinux_images):
33+
def build(project_dir, output_dir, test_command, test_requires, test_extras, before_build, build_verbosity, build_selector, delocate_command, environment, manylinux_images):
3434
try:
3535
subprocess.check_call(['docker', '--version'])
3636
except:
@@ -77,11 +77,11 @@ def build(project_dir, output_dir, test_command, test_requires, test_extras, bef
7777
# Delocate the wheel
7878
# NOTE: 'built_wheel' here is a bash array of glob matches; "$built_wheel" returns
7979
# the first element
80-
if [[ "$built_wheel" == *none-any.whl ]]; then
81-
# pure python wheel - just copy
80+
if [[ "$built_wheel" == *none-any.whl ]] || [ -z {delocate_command} ]; then
81+
# pure Python wheel or empty delocate command
8282
mv "$built_wheel" /tmp/delocated_wheels
8383
else
84-
auditwheel repair "$built_wheel" -w /tmp/delocated_wheels
84+
built_wheel=$built_wheel sh -c {delocate_command}
8585
fi
8686
delocated_wheels=(/tmp/delocated_wheels/*.whl)
8787
@@ -135,12 +135,15 @@ def build(project_dir, output_dir, test_command, test_requires, test_extras, bef
135135
test_requires=' '.join(test_requires),
136136
test_extras=test_extras,
137137
test_command=shlex_quote(
138-
prepare_command(test_command, project='/project') if test_command else ''
138+
prepare_command(test_command, {'project': '/project'}) if test_command else ''
139139
),
140140
before_build=shlex_quote(
141-
prepare_command(before_build, project='/project') if before_build else ''
141+
prepare_command(before_build, {'project': '/project'}) if before_build else ''
142142
),
143143
build_verbosity_flag=' '.join(get_build_verbosity_extra_flags(build_verbosity)),
144+
delocate_command=shlex_quote(
145+
prepare_command(delocate_command, {'wheel': '"$built_wheel"', 'dest_dir': '/tmp/delocated_wheels'}) if delocate_command else ''
146+
),
144147
environment_exports='\n'.join(environment.as_shell_commands()),
145148
uid=os.getuid(),
146149
gid=os.getgid(),

cibuildwheel/macos.py

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,12 @@ def get_python_configurations(build_selector):
2525
return [c for c in python_configurations if build_selector(c.identifier)]
2626

2727

28-
def build(project_dir, output_dir, test_command, test_requires, test_extras, before_build, build_verbosity, build_selector, environment):
28+
def build(project_dir, output_dir, test_command, test_requires, test_extras, before_build, build_verbosity, build_selector, delocate_command, environment):
29+
abs_project_dir = os.path.abspath(project_dir)
30+
temp_dir = tempfile.mkdtemp(prefix='cibuildwheel')
31+
built_wheel_dir = os.path.join(temp_dir, 'built_wheel')
32+
delocated_wheel_dir = os.path.join(temp_dir, 'delocated_wheel')
33+
2934
python_configurations = get_python_configurations(build_selector)
3035
get_pip_url = 'https://bootstrap.pypa.io/get-pip.py'
3136
get_pip_script = '/tmp/get-pip.py'
@@ -44,8 +49,6 @@ def call(args, env=None, cwd=None, shell=False):
4449

4550
return subprocess.check_call(args, env=env, cwd=cwd, shell=shell)
4651

47-
abs_project_dir = os.path.abspath(project_dir)
48-
4952
# get latest pip once and for all
5053
call(['curl', '-L', '-o', get_pip_script, get_pip_url])
5154

@@ -94,32 +97,29 @@ def call(args, env=None, cwd=None, shell=False):
9497
call(['pip', 'install', 'wheel'], env=env)
9598
call(['pip', 'install', 'delocate'], env=env)
9699

97-
# setup dirs
98-
if os.path.exists('/tmp/built_wheel'):
99-
shutil.rmtree('/tmp/built_wheel')
100-
os.makedirs('/tmp/built_wheel')
101-
if os.path.exists('/tmp/delocated_wheel'):
102-
shutil.rmtree('/tmp/delocated_wheel')
103-
os.makedirs('/tmp/delocated_wheel')
104-
105100
# run the before_build command
106101
if before_build:
107-
before_build_prepared = prepare_command(before_build, project=abs_project_dir)
102+
before_build_prepared = prepare_command(before_build, {'project': abs_project_dir})
108103
call(before_build_prepared, env=env, shell=True)
109104

110105
# build the wheel
111-
call(['pip', 'wheel', abs_project_dir, '-w', '/tmp/built_wheel', '--no-deps'] + get_build_verbosity_extra_flags(build_verbosity), env=env)
112-
built_wheel = glob('/tmp/built_wheel/*.whl')[0]
113-
114-
if built_wheel.endswith('none-any.whl'):
115-
# pure python wheel - just move
116-
shutil.move(built_wheel, '/tmp/delocated_wheel')
106+
if os.path.exists(built_wheel_dir):
107+
shutil.rmtree(built_wheel_dir)
108+
os.makedirs(built_wheel_dir)
109+
call(['pip', 'wheel', abs_project_dir, '-w', built_wheel_dir, '--no-deps'] + get_build_verbosity_extra_flags(build_verbosity), env=env)
110+
built_wheel = glob(os.path.join(built_wheel_dir, '*.whl'))[0]
111+
112+
# delocate the wheel
113+
if os.path.exists(delocated_wheel_dir):
114+
shutil.rmtree(delocated_wheel_dir)
115+
os.makedirs(delocated_wheel_dir)
116+
if built_wheel.endswith('none-any.whl') or not delocate_command:
117+
# pure Python wheel or empty delocate command
118+
shutil.move(built_wheel, delocated_wheel_dir)
117119
else:
118-
# list the dependencies
119-
call(['delocate-listdeps', built_wheel], env=env)
120-
# rebuild the wheel with shared libraries included and place in output dir
121-
call(['delocate-wheel', '-w', '/tmp/delocated_wheel', built_wheel], env=env)
122-
delocated_wheel = glob('/tmp/delocated_wheel/*.whl')[0]
120+
delocate_command_prepared = prepare_command(delocate_command, {'wheel': built_wheel, 'dest_dir': delocated_wheel_dir})
121+
call(delocate_command_prepared, env=env, shell=True)
122+
delocated_wheel = glob(os.path.join(delocated_wheel_dir, '*.whl'))[0]
123123

124124
if test_command:
125125
# set up a virtual environment to install and test from, to make sure
@@ -150,7 +150,7 @@ def call(args, env=None, cwd=None, shell=False):
150150
# run the tests from $HOME, with an absolute path in the command
151151
# (this ensures that Python runs the tests against the installed wheel
152152
# and not the repo code)
153-
test_command_prepared = prepare_command(test_command, project=abs_project_dir)
153+
test_command_prepared = prepare_command(test_command, {'project': abs_project_dir})
154154
call(test_command_prepared, cwd=os.environ['HOME'], env=virtualenv_env, shell=True)
155155

156156
# clean up

cibuildwheel/util.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22
import warnings
33

44

5-
def prepare_command(command, project):
5+
def prepare_command(command, replace_dict):
66
'''
7-
Preprocesses a command by expanding variables like {project}.
7+
Preprocesses a command by expanding variables like {python}.
88
9-
For example, used in the test_command option, to specify the path to the
10-
tests directory.
9+
For example, used in the test_command option to specify the path to the
10+
project's root.
1111
'''
12-
return command.format(python='python', pip='pip', project=project)
12+
return command.format(python='python', pip='pip', **replace_dict)
1313

1414

1515
def get_build_verbosity_extra_flags(level):

cibuildwheel/windows.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,7 @@ def get_python_configurations(build_selector):
5757
return python_configurations
5858

5959

60-
61-
def build(project_dir, output_dir, test_command, test_requires, test_extras, before_build, build_verbosity, build_selector, environment):
60+
def build(project_dir, output_dir, test_command, test_requires, test_extras, before_build, build_verbosity, build_selector, delocate_command, environment):
6261
def simple_shell(args, env=None, cwd=None):
6362
print('+ ' + ' '.join(args))
6463
args = ['cmd', '/E:ON', '/V:ON', '/C'] + args
@@ -90,6 +89,7 @@ def shell(args, env=None, cwd=None):
9089
abs_project_dir = os.path.abspath(project_dir)
9190
temp_dir = tempfile.mkdtemp(prefix='cibuildwheel')
9291
built_wheel_dir = os.path.join(temp_dir, 'built_wheel')
92+
delocated_wheel_dir = os.path.join(temp_dir, 'delocated_wheel')
9393

9494
# install nuget as best way to provide python
9595
nuget = 'C:\\cibw\\nuget.exe'
@@ -136,12 +136,20 @@ def shell(args, env=None, cwd=None):
136136

137137
# run the before_build command
138138
if before_build:
139-
before_build_prepared = prepare_command(before_build, project=abs_project_dir)
139+
before_build_prepared = prepare_command(before_build, {'project': abs_project_dir})
140140
shell([before_build_prepared], env=env)
141141

142142
# build the wheel
143143
shell(['pip', 'wheel', abs_project_dir, '-w', built_wheel_dir, '--no-deps'] + get_build_verbosity_extra_flags(build_verbosity), env=env)
144-
built_wheel = glob(built_wheel_dir+'/*.whl')[0]
144+
built_wheel = glob(os.path.join(built_wheel_dir, '*.whl'))[0]
145+
146+
if built_wheel.endswith('none-any.whl') or not delocate_command:
147+
# pure Python wheel or empty delocate command
148+
shutil.move(built_wheel, delocated_wheel_dir)
149+
else:
150+
delocate_command_prepared = prepare_command(delocate_command, {'wheel': built_wheel, 'dest_dir': delocated_wheel_dir})
151+
shell([delocate_command_prepared], env=env)
152+
delocated_wheel = glob(os.path.join(delocated_wheel_dir, '*.whl'))[0]
145153

146154
if test_command:
147155
# set up a virtual environment to install and test from, to make sure
@@ -160,7 +168,7 @@ def shell(args, env=None, cwd=None):
160168
shell(['which', 'python'], env=virtualenv_env)
161169

162170
# install the wheel
163-
shell(['pip', 'install', built_wheel + test_extras], env=virtualenv_env)
171+
shell(['pip', 'install', delocated_wheel + test_extras], env=virtualenv_env)
164172

165173
# test the wheel
166174
if test_requires:
@@ -169,14 +177,14 @@ def shell(args, env=None, cwd=None):
169177
# run the tests from c:\, with an absolute path in the command
170178
# (this ensures that Python runs the tests against the installed wheel
171179
# and not the repo code)
172-
test_command_prepared = prepare_command(test_command, project=abs_project_dir)
180+
test_command_prepared = prepare_command(test_command, {'project': abs_project_dir})
173181
shell([test_command_prepared], cwd='c:\\', env=virtualenv_env)
174182

175183
# clean up
176184
shutil.rmtree(venv_dir)
177185

178186
# we're all done here; move it to output (remove if already exists)
179-
dst = os.path.join(output_dir, os.path.basename(built_wheel))
187+
dst = os.path.join(output_dir, os.path.basename(delocated_wheel))
180188
if os.path.isfile(dst):
181189
os.remove(dst)
182-
shutil.move(built_wheel, dst)
190+
shutil.move(delocated_wheel, dst)

0 commit comments

Comments
 (0)