2424# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2525# THE SOFTWARE.
2626
27+ import functools
28+ import multiprocessing
2729import os
2830import os .path
2931import platform
3032import pathlib
33+ import re
3134import requests
3235import semver
3336import shutil
3437import stat
3538import sys
3639import subprocess
3740import tempfile
41+ import platformdirs
42+
43+ @functools .cache
44+ def _git_version ():
45+ version_str = subprocess .check_output (["git" , "--version" ], encoding = "ascii" , errors = "replace" )
46+ version_str = re .search ("([0-9]\.*)*[0-9]" , version_str ).group (0 )
47+ return tuple (int (part ) for part in version_str .split ("." ))
48+
49+ def git_filter_arg ():
50+ clone_supports_filter = (
51+ False if "NO_USE_CLONE_FILTER" in os .environ else _git_version () >= (2 , 36 , 0 )
52+ )
53+
54+ if clone_supports_filter :
55+ return ["--filter=blob:none" ]
56+ else :
57+ return []
3858
3959# pyproject.toml `py_modules` values that are incorrect. These should all have PRs filed!
4060# and should be removed when the fixed version is incorporated in its respective bundle.
6080else :
6181 from tomli import loads as load_toml
6282
83+ mpy_cross_path = platformdirs .user_cache_path ("circuitpython-build-tools" , ensure_exists = True )
84+
6385def load_pyproject_toml (lib_path : pathlib .Path ):
6486 try :
6587 return load_toml ((lib_path / "pyproject.toml" ) .read_text (encoding = "utf-8" ))
@@ -106,9 +128,14 @@ def version_string(path=None, *, valid_semver=False):
106128 version = commitish
107129 return version
108130
109- def mpy_cross (mpy_cross_filename , circuitpython_tag , quiet = False ):
131+ def mpy_cross (version , quiet = False ):
132+ circuitpython_tag = version ["tag" ]
133+ name = version ["name" ]
134+ ext = ".exe" * (os .name == "nt" )
135+ mpy_cross_filename = mpy_cross_path / f"mpy-cross-{ name } { ext } "
136+
110137 if os .path .isfile (mpy_cross_filename ):
111- return
138+ return mpy_cross_filename
112139
113140 # Try to pull from S3
114141 uname = platform .uname ()
@@ -136,7 +163,7 @@ def mpy_cross(mpy_cross_filename, circuitpython_tag, quiet=False):
136163 os .chmod (mpy_cross_filename , os .stat (mpy_cross_filename )[0 ] | stat .S_IXUSR )
137164 if not quiet :
138165 print (" FOUND" )
139- return
166+ return mpy_cross_filename
140167 except Exception as e :
141168 if not quiet :
142169 print (f" exception fetching from S3: { e } " )
@@ -149,26 +176,21 @@ def mpy_cross(mpy_cross_filename, circuitpython_tag, quiet=False):
149176 print (title )
150177 print ("=" * len (title ))
151178
152- os .makedirs ("build_deps/" , exist_ok = True )
153- if not os .path .isdir ("build_deps/circuitpython" ):
154- clone = subprocess .run ("git clone https://github.com/adafruit/circuitpython.git build_deps/circuitpython" , shell = True )
155- if clone .returncode != 0 :
156- sys .exit (clone .returncode )
157-
158- current_dir = os .getcwd ()
159- os .chdir ("build_deps/circuitpython" )
160- make = subprocess .run ("git fetch && git checkout {TAG} && git submodule update" .format (TAG = circuitpython_tag ), shell = True )
161- os .chdir ("tools" )
162- make = subprocess .run ("git submodule update --init ." , shell = True )
163- os .chdir ("../mpy-cross" )
164- make = subprocess .run ("make clean && make" , shell = True )
165- os .chdir (current_dir )
166-
167- if make .returncode != 0 :
168- print ("Failed to build mpy-cross from source... bailing out" )
169- sys .exit (make .returncode )
170-
171- shutil .copy ("build_deps/circuitpython/mpy-cross/mpy-cross" , mpy_cross_filename )
179+ build_dir = mpy_cross_path / f"build-circuitpython-{ circuitpython_tag } "
180+ if not os .path .isdir (build_dir ):
181+ subprocess .check_call (["git" , "clone" , * git_filter_arg (), "-b" , circuitpython_tag , "https://github.com/adafruit/circuitpython.git" , build_dir ])
182+
183+ subprocess .check_call (["git" , "submodule" , "update" , "--recursive" ], cwd = build_dir )
184+ subprocess .check_call ([sys .executable , "tools/ci_fetch_deps.py" , "mpy-cross" ], cwd = build_dir )
185+ subprocess .check_call (["make" , "clean" ], cwd = build_dir / "mpy-cross" )
186+ subprocess .check_call (["make" , f"-j{ multiprocessing .cpu_count ()} " ], cwd = build_dir / "mpy-cross" )
187+
188+ mpy_built = build_dir / f"mpy-cross/build/mpy-cross{ ext } "
189+ if not os .path .exists (mpy_built ):
190+ mpy_built = build_dir / f"mpy-cross/mpy-cross{ ext } "
191+
192+ shutil .copy (mpy_built , mpy_cross_filename )
193+ return mpy_cross_filename
172194
173195def _munge_to_temp (original_path , temp_file , library_version ):
174196 with open (original_path , "r" , encoding = "utf-8" ) as original_file :
0 commit comments