@@ -63,6 +63,7 @@ def main():
6363 parser .add_argument (
6464 "--python" ,
6565 choices = {
66+ "all" ,
6667 "cpython-3.9" ,
6768 "cpython-3.10" ,
6869 "cpython-3.11" ,
@@ -117,13 +118,23 @@ def main():
117118
118119 supported_pythons = {"cpython-%s" % p for p in settings ["pythons_supported" ]}
119120
120- if args .python not in supported_pythons :
121+ if args .python != "all" and args . python not in supported_pythons :
121122 print (
122123 "%s only supports following Pythons: %s"
123124 % (target_triple , ", " .join (supported_pythons ))
124125 )
125126 return 1
126127
128+ if args .python == "all" :
129+ if args .python_source :
130+ print ("--python-source is not compatible with --python all" )
131+ return 1
132+
133+ # This can be removed once 3.13 is the minimum version.
134+ if "freethreaded" in args .options :
135+ print ("freedthreaded builds not compatible with --python all" )
136+ return 1
137+
127138 python_source = (
128139 (str (pathlib .Path (args .python_source ).resolve ()))
129140 if args .python_source
@@ -145,41 +156,40 @@ def main():
145156 if args .no_docker :
146157 env ["PYBUILD_NO_DOCKER" ] = "1"
147158
148- if not args .python_source :
149- entry = DOWNLOADS [args .python ]
150- env ["PYBUILD_PYTHON_VERSION" ] = cpython_version = entry ["version" ]
159+ if args .python == "all" :
160+ cpython_versions = [
161+ DOWNLOADS ["cpython-%s" % p ]["version" ]
162+ for p in settings ["pythons_supported" ]
163+ ]
164+
165+ elif not args .python_source :
166+ cpython_versions = [DOWNLOADS [args .python ]["version" ]]
151167 else :
152168 # TODO consider parsing version from source checkout. Or defining version
153169 # from CLI argument.
154170 if "PYBUILD_PYTHON_VERSION" not in env :
155171 print ("PYBUILD_PYTHON_VERSION must be set when using `--python-source`" )
156172 return 1
157- cpython_version = env ["PYBUILD_PYTHON_VERSION" ]
173+ cpython_versions = [env ["PYBUILD_PYTHON_VERSION" ]]
174+
175+ env ["PYBUILD_PYTHON_VERSIONS" ] = " " .join (cpython_versions )
158176
159- python_majmin = "." .join (cpython_version .split ("." )[0 :2 ])
177+ python_majmins = [ "." .join (v .split ("." )[0 :2 ]) for v in cpython_versions ]
160178
161179 if "PYBUILD_RELEASE_TAG" in os .environ :
162180 release_tag = os .environ ["PYBUILD_RELEASE_TAG" ]
163181 else :
164182 release_tag = release_tag_from_git ()
165183
166- # Guard against accidental misuse of the free-threaded flag with older versions
167- if "freethreaded" in args .options and python_majmin not in ("3.13" ,):
184+ # Guard against accidental misuse of the free-threaded flag with older versions.
185+ if "freethreaded" in args .options and any (
186+ v not in ("3.13" ,) for v in python_majmins
187+ ):
168188 print (
169- "Invalid build option: 'freethreaded' is only compatible with CPython 3.13+ (got %s)"
170- % cpython_version
189+ "Invalid build option: 'freethreaded' is only compatible with CPython 3.13+"
171190 )
172191 return 1
173192
174- archive_components = [
175- "cpython-%s" % cpython_version ,
176- target_triple ,
177- args .options ,
178- ]
179-
180- build_basename = "-" .join (archive_components ) + ".tar"
181- dist_basename = "-" .join (archive_components + [release_tag ])
182-
183193 # We run make with static parallelism no greater than the machine's CPU count
184194 # because we can get some speedup from parallel operations. But we also don't
185195 # share a make job server with each build. So if we didn't limit the
@@ -195,7 +205,18 @@ def main():
195205 DIST .mkdir (exist_ok = True )
196206
197207 if args .make_target == "default" :
198- compress_python_archive (BUILD / build_basename , DIST , dist_basename )
208+ # TODO this could be made parallel.
209+ for version in cpython_versions :
210+ archive_components = [
211+ "cpython-%s" % version ,
212+ target_triple ,
213+ args .options ,
214+ ]
215+
216+ build_basename = "-" .join (archive_components ) + ".tar"
217+ dist_basename = "-" .join (archive_components + [release_tag ])
218+
219+ compress_python_archive (BUILD / build_basename , DIST , dist_basename )
199220
200221
201222if __name__ == "__main__" :
0 commit comments