|
| 1 | +#!/usr/bin/env python3 |
| 2 | + |
| 3 | +# The MIT License (MIT) |
| 4 | +# |
| 5 | +# Copyright (c) 2016 Scott Shawcroft for Adafruit Industries |
| 6 | +# |
| 7 | +# Permission is hereby granted, free of charge, to any person obtaining a copy |
| 8 | +# of this software and associated documentation files (the "Software"), to deal |
| 9 | +# in the Software without restriction, including without limitation the rights |
| 10 | +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 11 | +# copies of the Software, and to permit persons to whom the Software is |
| 12 | +# furnished to do so, subject to the following conditions: |
| 13 | +# |
| 14 | +# The above copyright notice and this permission notice shall be included in |
| 15 | +# all copies or substantial portions of the Software. |
| 16 | +# |
| 17 | +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 18 | +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 19 | +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 20 | +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 21 | +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 22 | +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| 23 | +# THE SOFTWARE. |
| 24 | + |
| 25 | +import os |
| 26 | +import shlex |
| 27 | +import shutil |
| 28 | +import sys |
| 29 | +import subprocess |
| 30 | +import zipfile |
| 31 | + |
| 32 | +os.chdir("circuitpython/mpy-cross") |
| 33 | +make = subprocess.run(["make"]) |
| 34 | +os.chdir("../../") |
| 35 | + |
| 36 | +if make.returncode != 0: |
| 37 | + print("Unable to make mpy-cross.") |
| 38 | + sys.exit(1) |
| 39 | + |
| 40 | +mpy_cross = "circuitpython/mpy-cross/mpy-cross" |
| 41 | + |
| 42 | +if "build" in os.listdir("."): |
| 43 | + print("Deleting existing build.") |
| 44 | + shutil.rmtree("build") |
| 45 | +os.mkdir("build") |
| 46 | +os.mkdir("build/lib") |
| 47 | + |
| 48 | +success = True |
| 49 | +total_size = 512 |
| 50 | +for subdirectory in os.listdir("libraries"): |
| 51 | + for library in os.listdir(os.path.join("libraries", subdirectory)): |
| 52 | + library_path = os.path.join("libraries", subdirectory, library) |
| 53 | + |
| 54 | + py_files = [] |
| 55 | + package_files = [] |
| 56 | + for filename in os.listdir(library_path): |
| 57 | + full_path = os.path.join(library_path, filename) |
| 58 | + if os.path.isdir(full_path) and os.path.isfile(os.path.join(full_path, "__init__.py")): |
| 59 | + files = os.listdir(full_path) |
| 60 | + files = filter(lambda x: x.endswith(".py"), files) |
| 61 | + files = map(lambda x: os.path.join(filename, x), files) |
| 62 | + package_files.extend(files) |
| 63 | + if filename.endswith(".py") and filename != "setup.py" and filename != "conf.py": |
| 64 | + py_files.append(filename) |
| 65 | + |
| 66 | + output_directory = os.path.join("build", "lib") |
| 67 | + if len(py_files) > 1: |
| 68 | + output_directory = os.path.join(output_directory, library) |
| 69 | + os.makedirs(output_directory) |
| 70 | + package_init = os.path.join(output_directory, "__init__.py") |
| 71 | + with open(package_init, 'a'): |
| 72 | + pass |
| 73 | + print(output_directory, 512) |
| 74 | + total_size += 512 |
| 75 | + |
| 76 | + if len(package_files) > 1: |
| 77 | + for fn in package_files: |
| 78 | + base_dir = os.path.join(output_directory, os.path.dirname(fn)) |
| 79 | + if not os.path.isdir(base_dir): |
| 80 | + os.makedirs(base_dir) |
| 81 | + print(base_dir, 512) |
| 82 | + total_size += 512 |
| 83 | + |
| 84 | + for filename in py_files: |
| 85 | + full_path = os.path.join(library_path, filename) |
| 86 | + output_file = os.path.join(output_directory, filename.replace(".py", ".mpy")) |
| 87 | + mpy_success = subprocess.call([mpy_cross, "-o", output_file, full_path]) |
| 88 | + if mpy_success != 0: |
| 89 | + print("mpy-cross failed on", full_path) |
| 90 | + success = False |
| 91 | + continue |
| 92 | + |
| 93 | + for filename in package_files: |
| 94 | + full_path = os.path.join(library_path, filename) |
| 95 | + if os.stat(full_path).st_size == 0 or filename.endswith("__init__.py"): |
| 96 | + output_file = os.path.join(output_directory, filename) |
| 97 | + shutil.copyfile(full_path, output_file) |
| 98 | + else: |
| 99 | + output_file = os.path.join(output_directory, filename.replace(".py", ".mpy")) |
| 100 | + mpy_success = subprocess.call([mpy_cross, "-o", output_file, full_path]) |
| 101 | + if mpy_success != 0: |
| 102 | + print("mpy-cross failed on", full_path) |
| 103 | + success = False |
| 104 | + continue |
| 105 | + |
| 106 | +version = None |
| 107 | +tag = subprocess.run(shlex.split("git describe --tags --exact-match"), stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
| 108 | +if tag.returncode == 0: |
| 109 | + version = tag.stdout.strip() |
| 110 | +else: |
| 111 | + commitish = subprocess.run(shlex.split("git log --pretty=format:'%h' -n 1"), stdout=subprocess.PIPE) |
| 112 | + version = commitish.stdout.strip() |
| 113 | + |
| 114 | +with open("build/lib/VERSIONS.txt", "w") as f: |
| 115 | + f.write(version.decode("utf-8", "strict") + "\r\n") |
| 116 | + versions = subprocess.run(shlex.split("git submodule foreach \"git remote get-url origin && git describe --tags\""), stdout=subprocess.PIPE) |
| 117 | + repo = None |
| 118 | + for line in versions.stdout.split(b"\n"): |
| 119 | + if line.startswith(b"Entering") or not line: |
| 120 | + continue |
| 121 | + if line.startswith(b"git@"): |
| 122 | + repo = b"https://github.com/" + line.split(b":")[1][:-len(".git")] |
| 123 | + elif line.startswith(b"https:"): |
| 124 | + repo = line.strip() |
| 125 | + else: |
| 126 | + f.write(repo.decode("utf-8", "strict") + "/releases/tag/" + line.strip().decode("utf-8", "strict") + "\r\n") |
| 127 | + |
| 128 | +zip_filename = 'build/circuitpython-community-bundle-' + version.decode("utf-8", "strict") + '.zip' |
| 129 | + |
| 130 | +def add_file(bundle, src_file, zip_name): |
| 131 | + global total_size |
| 132 | + bundle.write(src_file, zip_name) |
| 133 | + file_size = os.stat(src_file).st_size |
| 134 | + file_sector_size = file_size |
| 135 | + if file_size % 512 != 0: |
| 136 | + file_sector_size = (file_size // 512 + 1) * 512 |
| 137 | + total_size += file_sector_size |
| 138 | + print(zip_name, file_size, file_sector_size) |
| 139 | + |
| 140 | +with zipfile.ZipFile(zip_filename, 'w') as bundle: |
| 141 | + add_file(bundle, "README.txt", "lib/README.txt") |
| 142 | + for filename in os.listdir("update_scripts"): |
| 143 | + src_file = os.path.join("update_scripts", filename) |
| 144 | + add_file(bundle, src_file, os.path.join("lib", filename)) |
| 145 | + for root, dirs, files in os.walk("build/lib"): |
| 146 | + ziproot = root[len("build/"):].replace("-", "_") |
| 147 | + for filename in files: |
| 148 | + add_file(bundle, os.path.join(root, filename), |
| 149 | + os.path.join(ziproot, filename.replace("-", "_"))) |
| 150 | + |
| 151 | +print() |
| 152 | +print(total_size, "B", total_size / 1024, "kiB", total_size / 1024 / 1024, "MiB") |
| 153 | +print("Bundled in", zip_filename) |
| 154 | +if not success: |
| 155 | + sys.exit(2) |
0 commit comments