Beispiel #1
0
def compile(main_py, metadata):
    """Compiles a main.py file into a main.mpy file.

    Parameters
    ----------
    main_py : str
        The main.py file
    metadata : dict
        firmware metadata

    Returns
    -------
    bytes
        compiled main.mpy binary blob
    """
    out, _ = mpy_cross.run('--version', stdout=subprocess.PIPE).communicate()
    mpy_version = int(out.decode().strip()[-1])
    if mpy_version != metadata['mpy-abi-version']:
        print('Firmware package expects mpy-cross ABI ' +
              f'v{metadata["mpy-abi-version"]:} but we have v{mpy_version}',
              file=sys.stderr)
        exit(1)

    with tempfile.TemporaryDirectory('lpf2-flasher') as tmp_dir:
        with open(os.path.join(tmp_dir, 'main.py'), 'w') as f:
            f.write(main_py)
        code = mpy_cross.run(
            *metadata['mpy-cross-options'],
            'main.py',
            cwd=tmp_dir,
        ).wait()
        if code:
            exit(code)
        with open(os.path.join(tmp_dir, 'main.mpy'), 'rb') as f:
            return f.read()
Beispiel #2
0
 def convert_to_mpy():
     for root, dirs, files in os.walk("MPY"):
         root = root.replace("\\", "/")
         for file in files:
             if ".py" == file[-3:] and file != "main.py":
                 py_path = root + "/" + file
                 mpy_cross.run(py_path).wait()
                 os.remove(py_path)
Beispiel #3
0
def compile_tree_inline(directory):
    import mpy_cross
    files_touched = []
    for py_file in walk_pyfiles(directory):
        log.info('Compiling "{}" using mpy-cross'.format(py_file))
        mpy_cross.run(py_file)
        mpy_file = py_file.replace('.py', '.mpy')
        files_touched.append(mpy_file)
    return files_touched
Beispiel #4
0
def mpy_cross_process(*args):
    with mpy_cross.run(*args, stdout=PIPE) as proc:
        while True:
            line = proc.stdout.readline().decode("utf-8")
            if not line:
                break
            print(line.rstrip())
Beispiel #5
0
def cross_compile():
    files = []
    for build_file in glob.iglob(os.path.join(build_dir, "**", "*.py"),
                                 recursive=True):
        if os.path.isfile(build_file):
            target_file = build_file.replace(build_dir, x_build_dir).replace(
                '.py', '.mpy')
            target_dir = os.path.split(target_file)[0]
            os.makedirs(target_dir, exist_ok=True)
            print(target_file)
            mpy_cross.run("-o", target_file, build_file)
            files.append((build_file, target_file))
    sleep(0.1)
    for build_file, target_file in files:
        copystat(build_file, target_file)
    copyfile(os.path.join(lib_dir, 'boot.py'),
             os.path.join(x_build_dir, 'boot.py'))
Beispiel #6
0
def cross_compile(input_path: Path) -> Path:
    output_path = COMPILE_DIR / (".".join(input_path.name.split(".")[:-1]) + ".mpy")
    mpy_cross_process = mpy_cross.run(input_path, "-o", output_path)

    if mpy_cross_process.wait() == 0:
        return output_path
    else:
        exit("Something bad happened!")
Beispiel #7
0
def cross_compile(file):
    print('cross_compile {}'.format(file))
    name, ext = os.path.splitext(file)
    out = os.path.join(OUT_DIR, name + '.mpy')

    try:
        os.makedirs(os.path.dirname(out))
    except FileExistsError:
        pass

    p = mpy_cross.run(file, '-o', out)
    p.wait()
    return out
Beispiel #8
0
def compile_py_to_mpy(py_file_path: str, mpy_file_path: str) -> Error:
    """ Cross-compiles the given .py file into a .mpy file. Assumes destination directory already exists. """

    # Remarks:
    # - Use "stdout=subprocess.PIPE" to capture the standard output.
    #   - https://docs.python.org/3/library/subprocess.html#subprocess.PIPE
    # - Use "stderr=subprocess.STDOUT" to redirect stderr to stdout.
    #   - https://stackoverflow.com/questions/11495783/redirect-subprocess-stderr-to-stdout
    # - Best practice dictates to call proc.kill() and invoke proc.communicate() again after a timeout occurs.
    #   - https://docs.python.org/3/library/subprocess.html#subprocess.Popen.communicate
    # - Popen.communicate() waits (blocks) until the process terminates or the timeout occurs.

    timeout_sec = 5.0
    timed_out = False

    args = [
        "-mno-unicode", "-msmall-int-bits=31", py_file_path, "-o",
        mpy_file_path
    ]

    log("mpy_cross %s" % " ".join(args))

    proc: subprocess.Popen = mpy_cross.run(*args,
                                           stdout=subprocess.PIPE,
                                           stderr=subprocess.STDOUT)
    try:
        stdout_data, _ = proc.communicate(timeout=timeout_sec)
    except subprocess.TimeoutExpired:
        proc.kill()
        stdout_data, _ = proc.communicate()
        timed_out = True

    log(stdout_data.decode("utf-8"))

    if timed_out:
        return Error("%s: mpy_cross failed! It took too long! timeout_sec=%s" %
                     (func(), timeout_sec))

    if proc.returncode != 0:
        return Error("%s: mpy_cross failed! Exit status: %s" %
                     (func(), proc.returncode))

    return Success
Beispiel #9
0
    pass
else:
    os.mkdir('../compiled/MicroWebSrv2')
if os.path.exists('../compiled/MicroWebSrv2/libs'):
    pass
else:
    os.mkdir('../compiled/MicroWebSrv2/libs')
if os.path.exists('../compiled/MicroWebSrv2/mods'):
    pass
else:
    os.mkdir('../compiled/MicroWebSrv2/mods')

for i in os.listdir(workPath):
    if i.endswith('.py') and i not in ['gzipper.py', 'main.py', 'test_pid.py']:
        print("Compiling: " + i)
        mpy_cross.run(workPath + '/' + i)


for i in os.listdir(workPath):
    print("cleaning workSpace...")
    if i.endswith('.mpy'):
        shutil.move(workPath + '/' + i, '../compiled/' + i)
    else:
        pass
#pack MicroWebSrv2 into bytecode
MWS = workPath+'/'+'MicroWebSrv2'
for i in os.listdir(MWS):
    if i.endswith('.py'):
        print("Compiling: " + i)
        mpy_cross.run(MWS + '/' + i)
Beispiel #10
0
def exec_cmd(cmd):
    print('*** Exec: {}'.format(cmd))
    os.system(cmd)


print_with_header('Erase Flash (Press "Boot" button to connect)')
exec_cmd('esptool.py --chip esp32 --port {} erase_flash'.format(port))

print_with_header('Write Firmware')
exec_cmd(
    'esptool.py --chip esp32 --port {} --baud 460800 write_flash -z 0x1000 {}'.
    format(port, fw))

print_with_header('Write Application Files')
for f in files:
    if f != 'boot.py' and f.endswith('.py'):
        print('*** Precompiling: {}'.format(f))
        mpy_return_code = mpy_cross.run(f).wait(2000)
        if mpy_return_code != 0:
            print('!!! Unexpected return code: {}'.format(mpy_return_code))
        f = f.replace('.py', '.mpy')
    if not os.path.exists(f):
        print('!!! path does not exist: {}'.format(f))
    else:
        exec_cmd('ampy --port {} put "{}"'.format(port, f))
    if f.endswith('.mpy'):
        os.remove(f)

print_with_header('Done')
Beispiel #11
0
def uminify(arguments):
    """

    Args:
        arguments:

    Returns:
        None

    Raises:
        ValueError: When filename does not exists.
    """
    def log_it(*args, **kwargs):
        """Wrapper function in order to print verbose output.

        Args:
            *args: Arguments to be passed to the print function.
            **kwargs: Keyword Arguments to be passed to the print function.

        Returns:
            None
        """
        if arguments.verbose:
            print(*args, flush=True, **kwargs)

    input_file = os.path.abspath(arguments.filename)
    intermediate_filename = os.path.join(
        os.path.dirname(os.path.abspath(arguments.filename)),
        f"i{os.path.basename(os.path.abspath(arguments.filename))}")
    output_file = os.path.abspath(arguments.output)
    output_dir = os.path.dirname(os.path.abspath(output_file))

    if not os.path.exists(input_file):
        raise ValueError(f"Seems like the path {input_file} do not exists.")

    # Get input_file size.
    input_size = get_file_size(input_file)
    log_it(f"{input_file}: {input_size} B")

    # Minify the code.
    result = minify_code(input_file)
    # Check whether the output directory exists if not create it.
    if not os.path.exists(output_dir):
        log_it(f"Creating {output_dir} directory.")
        os.makedirs(output_dir, exist_ok=True)

    # Write minified content to a intermediate file.
    with open(intermediate_filename, 'w') as inter_file:
        inter_file.write(result)

    # Get the file size of the generated intermediate file.
    intermediate_size = get_file_size(intermediate_filename)
    log_it(f"{intermediate_filename}: {intermediate_size} B")

    # Convert Python code into mpy byte code.
    compilation_execution = mpy_cross.run("-o", output_file,
                                          intermediate_filename)
    # Wait for the process to be finished.
    compilation_execution.wait()

    # Get the output_file size.
    output_size = get_file_size(output_file)
    log_it(f"{output_file}: {output_size} B")

    # Remove intermediate file created if everything when Ok.
    if not compilation_execution.returncode and os.path.exists(
            intermediate_filename):

        if not arguments.keep:
            log_it(f"Deleting {intermediate_filename}")
            os.remove(intermediate_filename)

    log_it(
        f"\n{TColors.bold + TColors.okgreen}{input_size - output_size} Bytes reduced.{TColors.endc}"
    )
Beispiel #12
0
import hashlib
import os
from functools import partial

LIB = '../mpy_robot_tools/'
MPY_LIB = 'mpy/'
INSTALLER = 'install_mpy_robot_tools.py'
BASE_SCRIPT = 'base_script.py'

files = [f for f in os.listdir(LIB) if f not in ['__pycache__']]
encoded = []

for f in files:
    out_file = f.split(".")[0] + ".mpy"
    out_file_loc = MPY_LIB + out_file
    mpy_cross.run('-march=armv6', LIB + f, '-o', out_file_loc)
    time.sleep(0.5)
    with open(out_file_loc, 'rb') as mpy_file:
        file_hash = hashlib.sha256(mpy_file.read()).hexdigest()
    chunks = []
    with open(out_file_loc, 'rb') as mpy_file:
        for chunk in iter(partial(mpy_file.read, 2**10), b''):
            chunks += [binascii.b2a_base64(chunk).decode('utf-8')]
    print(out_file, ": ", len(chunks), " chunks of ", 2**10)
    encoded += [(out_file, tuple(chunks), file_hash)]

spike_code = open(BASE_SCRIPT, 'r').read()

with open(INSTALLER, 'w') as f:
    f.write(spike_code.format(repr(tuple(encoded))))