From c2784a8eada38e597297015c6250baad8c53f8a8 Mon Sep 17 00:00:00 2001 From: Jonas Scharpf Date: Wed, 2 Jun 2021 15:34:30 +0200 Subject: [PATCH 1/9] Add prebuild script to use additional build options Additional compile arguments can be given by a file named "build_opt.h". This enables users to easily extend their arguments on a central place. The script has been taken from stm32duino's Arduino_Core_STM32 package --- platform.txt | 16 +++++++++++++--- tools/extras/prebuild.sh | 14 ++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) create mode 100755 tools/extras/prebuild.sh diff --git a/platform.txt b/platform.txt index 7541466196..e5a65d983b 100644 --- a/platform.txt +++ b/platform.txt @@ -85,6 +85,16 @@ 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 +build.opt.path={build.path}/sketch/{build.opt.name} + +# extras.path={build.core.path}/extras +extras.path={runtime.platform.path}/tools/extras + +# Create empty {build.opt} if not exists in the output sketch dir and force include of SrcWrapper library +recipe.hooks.prebuild.1.pattern="{extras.path}/prebuild.sh" "{build.path}" "{build.source.path}" + # These can be overridden in platform.local.txt compiler.c.extra_flags= compiler.c.elf.extra_flags= @@ -107,13 +117,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}" ## Create archives recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}" diff --git a/tools/extras/prebuild.sh b/tools/extras/prebuild.sh new file mode 100755 index 0000000000..50bbed8a93 --- /dev/null +++ b/tools/extras/prebuild.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +BUILD_PATH="$1" +BUILD_SOURCE_PATH="$2" + +# Create sketch dir if not exists +if [ ! -f "$BUILD_PATH/sketch" ]; then + mkdir -p "$BUILD_PATH/sketch" +fi + +# Create empty build.opt.h if not exists in the original sketch dir +if [ ! -f "$BUILD_SOURCE_PATH/build_opt.h" ]; then + touch "$BUILD_PATH/sketch/build_opt.h" +fi From 5c0f07fe5fee6e0737eaa033fd1a4c7115bef375 Mon Sep 17 00:00:00 2001 From: Jonas Scharpf Date: Wed, 2 Jun 2021 19:29:46 +0200 Subject: [PATCH 2/9] replace bash with python script --- platform.txt | 8 +++----- tools/extras/prebuild.sh | 14 -------------- tools/prebuild.py | 42 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 19 deletions(-) delete mode 100755 tools/extras/prebuild.sh create mode 100644 tools/prebuild.py diff --git a/platform.txt b/platform.txt index e5a65d983b..555171d473 100644 --- a/platform.txt +++ b/platform.txt @@ -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 @@ -89,11 +90,8 @@ build.extra_flags=-DESP8266 build.opt.name=build_opt.h build.opt.path={build.path}/sketch/{build.opt.name} -# extras.path={build.core.path}/extras -extras.path={runtime.platform.path}/tools/extras - -# Create empty {build.opt} if not exists in the output sketch dir and force include of SrcWrapper library -recipe.hooks.prebuild.1.pattern="{extras.path}/prebuild.sh" "{build.path}" "{build.source.path}" +# 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= diff --git a/tools/extras/prebuild.sh b/tools/extras/prebuild.sh deleted file mode 100755 index 50bbed8a93..0000000000 --- a/tools/extras/prebuild.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -BUILD_PATH="$1" -BUILD_SOURCE_PATH="$2" - -# Create sketch dir if not exists -if [ ! -f "$BUILD_PATH/sketch" ]; then - mkdir -p "$BUILD_PATH/sketch" -fi - -# Create empty build.opt.h if not exists in the original sketch dir -if [ ! -f "$BUILD_SOURCE_PATH/build_opt.h" ]; then - touch "$BUILD_PATH/sketch/build_opt.h" -fi diff --git a/tools/prebuild.py b/tools/prebuild.py new file mode 100644 index 0000000000..7590e18b89 --- /dev/null +++ b/tools/prebuild.py @@ -0,0 +1,42 @@ +#!/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): + 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): + file_source_path = os.path.join(source_path, "build_opt.h") + file_build_path = os.path.join(build_path, "sketch", "build_opt.h") + + if not os.path.exists(file_source_path): + open(file_build_path, 'a').close() + + +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()) From 286cc4c3d7197296b665202c190e35979c52e012 Mon Sep 17 00:00:00 2001 From: Jonas Scharpf Date: Thu, 3 Jun 2021 11:44:38 +0200 Subject: [PATCH 3/9] add documentation for build_opt.h file to the faq readme --- doc/faq/readme.rst | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/doc/faq/readme.rst b/doc/faq/readme.rst index 4fb065a38f..5f51505ff0 100644 --- a/doc/faq/readme.rst +++ b/doc/faq/readme.rst @@ -152,6 +152,41 @@ Artificially clearing them is a workaround to help saving precious heap. Ref. `#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 Why is there a board generator and what about it ? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From b49484de2e2af642aa26176f58685320e9b76079 Mon Sep 17 00:00:00 2001 From: Jonas Scharpf Date: Fri, 4 Jun 2021 09:14:54 +0200 Subject: [PATCH 4/9] set build option file modification time as sketch modification time or users build options file --- tools/prebuild.py | 89 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 84 insertions(+), 5 deletions(-) diff --git a/tools/prebuild.py b/tools/prebuild.py index 7590e18b89..1618a342ff 100644 --- a/tools/prebuild.py +++ b/tools/prebuild.py @@ -15,18 +15,97 @@ 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): - file_source_path = os.path.join(source_path, "build_opt.h") - file_build_path = os.path.join(build_path, "sketch", "build_opt.h") +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) + build_opt_ctime = get_creation_time(build_opt_build_path) + + if not os.path.exists(build_opt_source_path): + # create empty file + open(build_opt_build_path, 'a').close() + + # set build_opt.h file modification time to the same time as the sketch + # modification time to avoid rebuilding libraries + sketch_path = get_full_sketch_path(source_path) + sketch_mtime = get_modification_time(sketch_path) + os.utime(build_opt_build_path, (build_opt_ctime, sketch_mtime)) + else: + # set build option file modification time to the same time as the users + # build option file modification time to reflect changes which require + # a recompilation + build_opt_mtime = get_modification_time(build_opt_source_path) + os.utime(build_opt_build_path, (build_opt_ctime, build_opt_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 + """ + dir_name = os.path.dirname(source_path) + base_name = os.path.basename(dir_name) + + sketch_path = os.path.join(dir_name, 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 - if not os.path.exists(file_source_path): - open(file_build_path, 'a').close() + :returns: The creation time. + :rtype: float + """ + return os.path.getctime(file_path) def main(): From 34f85e76cbb13ea9c5b1c1a6ffb255e8dfd3f565 Mon Sep 17 00:00:00 2001 From: Jonas Scharpf Date: Fri, 4 Jun 2021 09:15:45 +0200 Subject: [PATCH 5/9] mentioning no automatic rebuild of core.s files on changes of build options file in faq docs --- doc/faq/readme.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/faq/readme.rst b/doc/faq/readme.rst index 5f51505ff0..1887033760 100644 --- a/doc/faq/readme.rst +++ b/doc/faq/readme.rst @@ -188,6 +188,9 @@ location as the ``sketch.ino`` file to define the ``WAIT_TIME`` to 500ms. -DWAIT_TIME=500 +``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 ? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 4aa76d3f5bf90e9e0aef2bcb30078095eb819637 Mon Sep 17 00:00:00 2001 From: Jonas Scharpf Date: Fri, 4 Jun 2021 15:39:10 +0200 Subject: [PATCH 6/9] fix collection of creation time only after creating build options file --- tools/prebuild.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/prebuild.py b/tools/prebuild.py index 1618a342ff..869acc0a2b 100644 --- a/tools/prebuild.py +++ b/tools/prebuild.py @@ -44,7 +44,6 @@ def create_build_options_file(source_path, build_path, build_opt_name="build_opt """ 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) - build_opt_ctime = get_creation_time(build_opt_build_path) if not os.path.exists(build_opt_source_path): # create empty file @@ -54,11 +53,13 @@ def create_build_options_file(source_path, build_path, build_opt_name="build_opt # modification time to avoid rebuilding libraries sketch_path = get_full_sketch_path(source_path) sketch_mtime = get_modification_time(sketch_path) + build_opt_ctime = get_creation_time(build_opt_build_path) os.utime(build_opt_build_path, (build_opt_ctime, sketch_mtime)) else: # set build option file modification time to the same time as the users # build option file modification time to reflect changes which require # a recompilation + build_opt_ctime = get_creation_time(build_opt_build_path) build_opt_mtime = get_modification_time(build_opt_source_path) os.utime(build_opt_build_path, (build_opt_ctime, build_opt_mtime)) From 97c3d8dfadb9d5a1e47890c83a1f81c02a4813fe Mon Sep 17 00:00:00 2001 From: Jonas Scharpf Date: Mon, 7 Jun 2021 17:26:31 +0200 Subject: [PATCH 7/9] fix correct creation of full sketch path --- tools/prebuild.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tools/prebuild.py b/tools/prebuild.py index 869acc0a2b..a879746ae2 100644 --- a/tools/prebuild.py +++ b/tools/prebuild.py @@ -74,10 +74,9 @@ def get_full_sketch_path(source_path): :returns: The full sketch path including the '.ino' extension. :rtype: str """ - dir_name = os.path.dirname(source_path) - base_name = os.path.basename(dir_name) + base_name = os.path.basename(source_path) - sketch_path = os.path.join(dir_name, base_name + '.ino') + sketch_path = os.path.join(source_path, base_name + '.ino') return sketch_path From dec7ab8820ceb89b9857d025e8105e3085395780 Mon Sep 17 00:00:00 2001 From: "Earle F. Philhower, III" Date: Thu, 17 Jun 2021 15:56:05 -0700 Subject: [PATCH 8/9] Minor cleanup FAQ section under-tildes --- doc/faq/readme.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/faq/readme.rst b/doc/faq/readme.rst index 1887033760..5bea6ce0da 100644 --- a/doc/faq/readme.rst +++ b/doc/faq/readme.rst @@ -72,7 +72,7 @@ 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. @@ -80,7 +80,7 @@ perform. It is not listed among libraries verified to work with ESP8266. `Read more `__. 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 @@ -153,7 +153,7 @@ Artificially clearing them is a workaround to help saving precious heap. Ref. `#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. From d03a2ecde0e1c0e439d2c785f3ef9d5c5bb83496 Mon Sep 17 00:00:00 2001 From: Jonas Scharpf Date: Mon, 21 Jun 2021 10:30:46 +0200 Subject: [PATCH 9/9] modify build opt time only if required and file available --- tools/prebuild.py | 59 +++++++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/tools/prebuild.py b/tools/prebuild.py index a879746ae2..3b074ca65e 100644 --- a/tools/prebuild.py +++ b/tools/prebuild.py @@ -17,7 +17,6 @@ def create_sketch_dir(build_path): """ Create the sketch directory - :param build_path: The path to the build directory :type build_path: str """ @@ -30,11 +29,9 @@ def create_sketch_dir(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 @@ -45,32 +42,49 @@ def create_build_options_file(source_path, build_path, build_opt_name="build_opt 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) - if not os.path.exists(build_opt_source_path): - # create empty file + # 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_opt.h file modification time to the same time as the sketch - # modification time to avoid rebuilding libraries - sketch_path = get_full_sketch_path(source_path) - sketch_mtime = get_modification_time(sketch_path) - build_opt_ctime = get_creation_time(build_opt_build_path) - os.utime(build_opt_build_path, (build_opt_ctime, sketch_mtime)) - else: - # set build option file modification time to the same time as the users - # build option file modification time to reflect changes which require - # a recompilation - build_opt_ctime = get_creation_time(build_opt_build_path) - build_opt_mtime = get_modification_time(build_opt_source_path) - os.utime(build_opt_build_path, (build_opt_ctime, build_opt_mtime)) + # 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 """ @@ -84,24 +98,19 @@ def get_full_sketch_path(source_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 """