-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmake_packages.py
158 lines (133 loc) · 5.18 KB
/
make_packages.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# this script (and the associated github workflows) are taken from
# https://github.com/labscript-suite/vendored-conda-builds
# under the BSD-2-Clause license, copyright Chris Billington
import sys
import os
import toml
import platform
from subprocess import check_call
from pathlib import Path
import shutil
# This script is designed to run from GitHub actions, Github actions will run jobs for
# all of the platforms and Python versions we want to build packages for, and run this
# script in each of them. Our job is to build a conda package if the current platform
# and Python version is requested for a pacakge. Or, if it is a noarch package we only
# want to build it on one of the jobs, and it doesn't matter which one. So the GitHub
# workflow will set the environment variable BUILD_NOARCH=true for one of the jobs and
# there we will build noarch packages.
# This script must be run from within a conda environment with pip and setuptools-conda
# installed.
# Have had massive headaches with the filepaths being too long on GitHub Actions,
# causing conda-build to choke inexplicably. Allow a directory to be passed in as a
# command line arg. The workflow will pass in the value of runner.temp, which is a short
# filepath for a temporary directory we can use.
if len(sys.argv) > 1:
BUILD_DIR = sys.argv[1]
else:
BUILD_DIR = 'build'
if platform.system() == 'Windows' and sys.maxsize > 2 ** 32:
PLATFORM = 'win-64'
elif platform.system() == 'Windows':
PLATFORM = 'win-32'
elif platform.system() == 'Linux':
PLATFORM = 'linux'
elif platform.system() == 'Darwin':
if platform.machine() == 'arm64':
PLATFORM = 'osx-arm64'
else:
PLATFORM = 'osx-64'
else:
raise ValueError(platform.system())
def download(name, source, version):
"""Download an uncompress an sdist from given source and return the resulting
directory"""
# Download the sdist
if source == 'pypi':
name_with_version = name
if version != 'latest':
name_with_version += f'=={version}'
download_cmd = [
'pip',
'download',
'--no-binary=:all:',
'--no-build-isolation',
'--no-deps',
'--dest',
BUILD_DIR,
name_with_version,
]
else:
download_cmd = ['pip', 'download', '--dest', BUILD_DIR, source]
check_call(download_cmd)
# Find it:
for path in Path(BUILD_DIR).iterdir():
if path.stem.rsplit('-', 1)[0] == name:
if path.name.endswith('.zip'):
extension = '.zip'
break
if path.name.endswith('.tar.gz'):
extension = '.tar.gz'
break
else:
raise RuntimeError("Can't find sdist")
# Decompress it:
base = Path(BUILD_DIR, path.name.rsplit(extension, 1)[0])
if extension == '.tar.gz':
check_call(['tar', 'xvf', str(path), '-C', BUILD_DIR])
elif extension == '.zip':
check_call(['unzip', str(path), '-d', BUILD_DIR])
if source.startswith('git+'):
return Path(BUILD_DIR, source.strip('/').split('/')[-1])
else:
return base
def build_conda_package(name, spec):
version = spec.get('version', defaults['version'])
source = spec.get('source', defaults['source'])
noarch = spec.get('noarch', defaults['noarch'])
build_args = spec.get('build_args', defaults['build_args'])[:]
pythons = spec.get('pythons', defaults['pythons'])
platforms = spec.get('platforms', defaults['platforms'])
if noarch and not os.getenv('BUILD_NOARCH'):
print(f"Skipping {name} as it is noarch but BUILD_NOARCH env var is not set")
return
elif not noarch:
if PLATFORM not in platforms:
print(f"Skipping {name} as {PLATFORM} is not in its list of platforms")
return
PY = f'{sys.version_info.major}.{sys.version_info.minor}'
if PY not in pythons:
print(f"Skipping {name} as {PY} is not in its list of Python versions")
return
# Download it:
project_dir = download(name, source, version)
# Build it
if noarch:
build_args += ['--noarch']
# Put the conda_build directory outside the project directory, otherwise it can be
# detected as a top-level Python package in a flat layout not otherwise specifying
# its modules in setup.py or setup.cfg, resulting in an error. Have observed this
# with PyVISA.
build_dir = Path(BUILD_DIR).absolute() / 'conda_build' / name
check_call(
[
'setuptools-conda',
'build',
*build_args,
'--build-dir',
str(build_dir),
str(project_dir),
]
)
for arch in Path(project_dir, 'conda_packages').iterdir():
for package in arch.iterdir():
dest = Path('conda_packages', arch.name, package.name)
dest.parent.mkdir(parents=True, exist_ok=True)
shutil.move(package, dest)
if __name__ == '__main__':
Path(BUILD_DIR).mkdir(exist_ok=True)
packages = toml.load('pkgs.toml')
defaults = packages['defaults']
for name, spec in packages.items():
if name == 'defaults':
continue
build_conda_package(name, spec)