Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add prebuild script to use additional build options #8095

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 40 additions & 2 deletions doc/faq/readme.rst
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,15 @@ version). WPS is always available, and not using it will give an extra
~4.5KB compared to releases until 2.4.1 included.

This Arduino library doesn't work on ESP. How do I make it work?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

You would like to use this Arduino library with ESP8266 and it does not
perform. It is not listed among libraries verified to work with ESP8266.

`Read more <a03-library-does-not-work.rst>`__.

In the IDE, for ESP-12E that has 4M flash, I can choose 4M (1M FS) or 4M (3M FS). No matter what I select, the IDE tells me the maximum code space is about 1M. Where does my flash go?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The reason we cannot have more than 1MB of code in flash has to do with
a hardware limitation. Flash cache hardware on the ESP8266 only allows
Expand Down Expand Up @@ -152,6 +152,44 @@ Artificially clearing them is a workaround to help saving precious heap.

Ref. `#1923 <https://github.com/esp8266/Arduino/issues/1923>`__

Use custom defines from build options file
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

A file named ``build_opt.h`` next to the ``sketch.ino`` file enables the user
to specify custom definitons in a central and organized location.

The following code is a slightly modified Blink example sketch. It opens the
possibility to define the ``WAIT_TIME`` between the LED state changes. If no
``build_opt.h`` file is placed next to the sketch file, the default value will
be set as 1000ms in this example.

.. code:: cpp

#ifndef WAIT_TIME
#define WAIT_TIME 1000 // use 1000ms if not defined different
#endif

void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
digitalWrite(LED_BUILTIN, HIGH);
delay(WAIT_TIME);
digitalWrite(LED_BUILTIN, LOW);
delay(WAIT_TIME);
}

Place the following content in a file named ``build_opt.h`` at the same
location as the ``sketch.ino`` file to define the ``WAIT_TIME`` to 500ms.

.. code:: cpp

-DWAIT_TIME=500
earlephilhower marked this conversation as resolved.
Show resolved Hide resolved

``core.s`` files are not automatically rebuilt when changes are made to the
``build_opt.h`` file.

Why is there a board generator and what about it ?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down
14 changes: 11 additions & 3 deletions platform.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ version=3.0.1-dev
runtime.tools.xtensa-lx106-elf-gcc.path={runtime.platform.path}/tools/xtensa-lx106-elf
runtime.tools.python3.path={runtime.platform.path}/tools/python3

runtime.tools.prebuild={runtime.platform.path}/tools/prebuild.py
runtime.tools.esptool.path={runtime.platform.path}/tools/esptool
runtime.tools.signing={runtime.platform.path}/tools/signing.py
runtime.tools.elf2bin={runtime.platform.path}/tools/elf2bin.py
Expand Down Expand Up @@ -85,6 +86,13 @@ compiler.size.cmd=xtensa-lx106-elf-size
# This can be overridden in boards.txt
build.extra_flags=-DESP8266

# Pre and post build hooks
build.opt.name=build_opt.h
earlephilhower marked this conversation as resolved.
Show resolved Hide resolved
build.opt.path={build.path}/sketch/{build.opt.name}

# Create empty {build.opt} if it does not exist in the output sketch dir
recipe.hooks.prebuild.1.pattern="{runtime.tools.python3.path}/python3" "{runtime.tools.prebuild}" "{build.path}" "{build.source.path}"

# These can be overridden in platform.local.txt
compiler.c.extra_flags=
compiler.c.elf.extra_flags=
Expand All @@ -107,13 +115,13 @@ recipe.hooks.linking.prelink.3.pattern="{compiler.path}{compiler.c.cmd}" -CC -E
recipe.hooks.linking.prelink.4.pattern="{compiler.path}{compiler.c.cmd}" -CC -E -P {build.vtable_flags} {build.mmuflags} "{runtime.platform.path}/tools/sdk/ld/eagle.app.v6.common.ld.h" -o "{build.path}/local.eagle.app.v6.common.ld"

## Compile c files
recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.c.flags} -D{build.sdk}=1 -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.c.flags} -D{build.sdk}=1 -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.c.extra_flags} {build.extra_flags} "@{build.opt.path}" {includes} "{source_file}" -o "{object_file}"

## Compile c++ files
recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpreprocessor.flags} {compiler.cpp.flags} -D{build.sdk}=1 -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpreprocessor.flags} {compiler.cpp.flags} -D{build.sdk}=1 -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.cpp.extra_flags} {build.extra_flags} "@{build.opt.path}" {includes} "{source_file}" -o "{object_file}"

## Compile S files
recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.S.flags} -D{build.sdk}=1 -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.S.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.S.flags} -D{build.sdk}=1 -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.S.extra_flags} {build.extra_flags} "@{build.opt.path}" {includes} "{source_file}" -o "{object_file}"
earlephilhower marked this conversation as resolved.
Show resolved Hide resolved

## Create archives
recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}"
Expand Down
130 changes: 130 additions & 0 deletions tools/prebuild.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# prebuild.py — create build_opt.h file in build directory if it does not exist
#
# This script will create a folder called "sketch" in the build path if it does
# not yet exist and create an empty build options file inside if this does also
# not exist yet
#
# Written by brainelectronics, 2021.
#

import os
import sys


def create_sketch_dir(build_path):
"""
Create the sketch directory
:param build_path: The path to the build directory
:type build_path: str
"""
sketch_build_path = os.path.join(build_path, "sketch")

if not os.path.exists(sketch_build_path):
os.makedirs(sketch_build_path)


def create_build_options_file(source_path, build_path, build_opt_name="build_opt.h"):
"""
Create the build options file in the build directory.
The modification time of the build options file is set to the sketch
modification time in case the file did not exist or the users build options
modification time to reflect changes which require a recompilation
:param source_path: The path to the source directory
:type source_path: str
:param build_path: The path to the build directory
:type build_path: str
:param build_opt_name: The build option file name
:type build_opt_name: str, optional
"""
build_opt_source_path = os.path.join(source_path, build_opt_name)
build_opt_build_path = os.path.join(build_path, "sketch", build_opt_name)

# check for an existing build options file in the source directory
if os.path.exists(build_opt_source_path):
# user does have/use an build options file in it's sketch directory

if os.path.exists(build_opt_build_path):
# set build options file modification time to the same time as the
# sketch modification time to avoid rebuilding libraries
set_file_time_to_sketch_time(source_path, build_opt_build_path)
else:
# the build options file does not yet exist in the build directory
# just continue as it will be copied by the IDE automatically on
# time. This section is only entered on the very first run
pass
else:
# user does not have a build options file, create empty one to avoid
# compilation error due to missing file for compilation
open(build_opt_build_path, 'a').close()

# set build options file modification time to the same time as the
# sketch modification time to avoid rebuilding libraries
set_file_time_to_sketch_time(source_path, build_opt_build_path)


def set_file_time_to_sketch_time(source_path, destination_path):
"""
Set the file ctime and mtime to the ctime and mtime of the sketch.
:param source_path: The source path to the sketch
:type source_path: str
:param destination_path: The destination path to the file to modify
:type destination_path: str
"""
sketch_path = get_full_sketch_path(source_path)
sketch_mtime = get_modification_time(sketch_path)
destination_ctime = get_creation_time(destination_path)

os.utime(destination_path, (destination_ctime, sketch_mtime))


def get_full_sketch_path(source_path):
"""
Get the full sketch path.
:param source_path: The source path
:type source_path: str
:returns: The full sketch path including the '.ino' extension.
:rtype: str
"""
base_name = os.path.basename(source_path)

sketch_path = os.path.join(source_path, base_name + '.ino')

return sketch_path


def get_modification_time(file_path):
"""
Get the modification time of a file.
:param file_path: The file path
:type file_path: str
:returns: The modification time.
:rtype: float
"""
return os.path.getmtime(file_path)


def get_creation_time(file_path):
"""
Gets the creation time if a file.
:param file_path: The file path
:type file_path: str
:returns: The creation time.
:rtype: float
"""
return os.path.getctime(file_path)


def main():
if len(sys.argv) == 3:
build_path = sys.argv[1]
source_path = sys.argv[2]

create_sketch_dir(build_path)
create_build_options_file(source_path, build_path)


if __name__ == '__main__':
sys.exit(main())