Skip to content

Commit a558c49

Browse files
author
Bogdan Marinescu
committed
Rebuild sources if configuration is changed
This commit adds a check for configuration data changes. If a change in configuration data is detected, all the sources in the tree are rebuilt. This is a fix for #2073. #2162 was originally proposed as a fix, but it was agreed that `--preinclude` is a more convenient way to include configuration data, since it can be used to change the behaviour of source files that don't include "mbed_config.h" directly, which is a big advantage when importing 3rd party source trees. Compared to #2162, this commit has the disadvantage of rebuilding all the source files if a configuration change is detected, but it was agreed that the advantage of using `--preinclude` outweighs the disadvantage of the increased compilation time.
1 parent ee2f917 commit a558c49

File tree

1 file changed

+56
-13
lines changed

1 file changed

+56
-13
lines changed

tools/toolchains/__init__.py

+56-13
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
import re
1919
import sys
20-
from os import stat, walk, getcwd, sep
20+
from os import stat, walk, getcwd, sep, remove
2121
from copy import copy
2222
from time import time, sleep
2323
from types import ListType
@@ -252,6 +252,12 @@ def __init__(self, target, options=None, notify=None, macros=None, silent=False,
252252
# This will hold the configuration data (as returned by Config.get_config_data())
253253
self.config_data = None
254254

255+
# This will hold the location of the configuration file or None if there's no configuration available
256+
self.config_file = None
257+
258+
# Call guard for "get_config_data" (see the comments of get_config_data for details)
259+
self.config_processed = False
260+
255261
# Non-incremental compile
256262
self.build_all = False
257263

@@ -663,6 +669,9 @@ def compile_sources(self, resources, build_path, inc_dirs=None):
663669
queue = []
664670
prev_dir = None
665671

672+
# Generate configuration header (this will update self.build_all if needed)
673+
self.get_config_header()
674+
666675
# Sort compile queue for consistency
667676
files_to_compile.sort()
668677
work_dir = getcwd()
@@ -944,19 +953,53 @@ def mem_stats(self, map):
944953
def set_config_data(self, config_data):
945954
self.config_data = config_data
946955

947-
# Return the location of the config header. This function will create the config
948-
# header first if needed. The header will be written in a file called "mbed_conf.h"
949-
# located in the project's build directory.
950-
# If config headers are not used (self.config_header_content is None), the function
951-
# returns None
956+
# Creates the configuration header if needed:
957+
# - if there is no configuration data, "mbed_config.h" is not create (or deleted if it exists).
958+
# - if there is configuration data and "mbed_config.h" does not exist, it is created.
959+
# - if there is configuration data similar to the previous configuration data,
960+
# "mbed_config.h" is left untouched.
961+
# - if there is new configuration data, "mbed_config.h" is overriden.
962+
# The function needs to be called exactly once for the lifetime of this toolchain instance.
963+
# The "config_processed" variable (below) ensures this behaviour.
964+
# The function returns the location of the configuration file, or None if there is no
965+
# configuration data available (and thus no configuration file)
952966
def get_config_header(self):
953-
if self.config_data is None:
954-
return None
955-
config_file = join(self.build_dir, self.MBED_CONFIG_FILE_NAME)
956-
if not exists(config_file):
957-
with open(config_file, "wt") as f:
958-
f.write(Config.config_to_header(self.config_data))
959-
return config_file
967+
if self.config_processed: # this function was already called, return its result
968+
return self.config_file
969+
# The config file is located in the build directory
970+
self.config_file = join(self.build_dir, self.MBED_CONFIG_FILE_NAME)
971+
# If the file exists, read its current content in prev_data
972+
if exists(self.config_file):
973+
with open(self.config_file, "rt") as f:
974+
prev_data = f.read()
975+
else:
976+
prev_data = None
977+
# Get the current configuration data
978+
crt_data = Config.config_to_header(self.config_data) if self.config_data else None
979+
# "changed" indicates if a configuration change was detected
980+
changed = False
981+
if prev_data is not None: # a previous mbed_config.h exists
982+
if crt_data is None: # no configuration data, so "mbed_config.h" needs to be removed
983+
remove(self.config_file)
984+
self.config_file = None # this means "config file not present"
985+
changed = True
986+
elif crt_data != prev_data: # different content of config file
987+
with open(self.config_file, "wt") as f:
988+
f.write(crt_data)
989+
changed = True
990+
else: # a previous mbed_config.h does not exist
991+
if crt_data is not None: # there's configuration data available
992+
with open(self.config_file, "wt") as f:
993+
f.write(crt_data)
994+
changed = True
995+
else:
996+
self.config_file = None # this means "config file not present"
997+
# If there was a change in configuration, rebuild everything
998+
self.build_all = changed
999+
# Make sure that this function will only return the location of the configuration
1000+
# file for subsequent calls, without trying to manipulate its content in any way.
1001+
self.config_processed = True
1002+
return self.config_file
9601003

9611004
# Return the list of macros geenrated by the build system
9621005
def get_config_macros(self):

0 commit comments

Comments
 (0)