Convert .ino -> .cpp (#2228)

- general conversion from .ino modules into a separate .cpp files
- clean-up internal headers, place libraries into .h. guard .cpp with _SUPPORT flags 
- fix some instances of shared variables instead of public methods
- tweak build system to still build a single source file via os environment variable ESPURNA_BUILD_SINGLE_SOURCE
This commit is contained in:
Max Prokhorov
2020-04-30 13:55:07 +03:00
committed by GitHub
parent 732e84c45e
commit edb23dbfc4
125 changed files with 2977 additions and 2352 deletions

View File

@@ -1,5 +1,17 @@
import atexit
import os
import shutil
import tempfile
from .display import print_warning
def try_remove(path):
try:
os.remove(path)
except: # pylint: disable=bare-except
print_warning("Please manually remove the file `{}`".format(path))
def copy_release(target, source, env):
# target filename and subdir for release files
@@ -20,3 +32,18 @@ def copy_release(target, source, env):
shutil.copy(src, dest)
# emulate .ino concatenation to speed up compilation times
def merge_cpp(sources, output):
with tempfile.TemporaryFile() as tmp:
tmp.write(b"// !!! Automatically generated file; DO NOT EDIT !!! \n")
tmp.write(b'#include "espurna.h"\n')
for source in sources:
with open(source, "rb") as fobj:
shutil.copyfileobj(fobj, tmp)
tmp.seek(0)
with open(output, "wb") as fobj:
shutil.copyfileobj(tmp, fobj)
atexit.register(try_remove, output)

View File

@@ -97,6 +97,7 @@ def generate_lines(builds, ignore):
if build.src_build_flags:
flags.append('ESPURNA_FLAGS="{}"'.format(build.src_build_flags))
flags.append('ESPURNA_RELEASE_NAME="{env}"'.format(env=build.env))
flags.append("ESPURNA_BUILD_SINGLE_SOURCE=1")
cmd = ["env"]
cmd.extend(flags)

View File

@@ -20,9 +20,11 @@ from espurna_utils import (
copy_release,
)
Import("env", "projenv")
import os
CI = any([os.environ.get("TRAVIS"), os.environ.get("CI")])
# Always show warnings for project code

View File

@@ -19,6 +19,8 @@ import sys
from SCons.Script import ARGUMENTS
from espurna_utils.release import merge_cpp
CI = any([os.environ.get("TRAVIS"), os.environ.get("CI")])
PIO_PLATFORM = env.PioPlatform()
@@ -99,7 +101,7 @@ def ensure_platform_updated():
env.Append(
ESPURNA_BOARD=os.environ.get("ESPURNA_BOARD", ""),
ESPURNA_AUTH=os.environ.get("ESPURNA_AUTH", ""),
ESPURNA_FLAGS=os.environ.get("ESPURNA_FLAGS", "")
ESPURNA_FLAGS=os.environ.get("ESPURNA_FLAGS", ""),
)
ESPURNA_OTA_PORT = os.environ.get("ESPURNA_IP")
@@ -115,7 +117,7 @@ if CI:
env.Append(
ESPURNA_RELEASE_NAME=os.environ.get("ESPURNA_RELEASE_NAME", ""),
ESPURNA_RELEASE_VERSION=os.environ.get("ESPURNA_RELEASE_VERSION", ""),
ESPURNA_RELEASE_DESTINATION=os.environ.get("ESPURNA_RELEASE_DESTINATION", "")
ESPURNA_RELEASE_DESTINATION=os.environ.get("ESPURNA_RELEASE_DESTINATION", ""),
)
# updates arduino core git to the latest master commit
@@ -136,3 +138,25 @@ if os.environ.get("ESPURNA_PIO_SHARED_LIBRARIES"):
log("using shared library storage: {}".format(storage))
subprocess_libdeps(env.GetProjectOption("lib_deps"), storage)
# tweak build system to ignore espurna.ino, but include user code
# ref: platformio-core/platformio/tools/piomisc.py::ConvertInoToCpp()
def ConvertInoToCpp(env):
pass
ino = env.Glob("$PROJECT_DIR/espurna/*.ino") + env.Glob("$PROJECT_DIR/espurna/*.pde")
if len(ino) == 1 and ino[0].name == "espurna.ino":
env.AddMethod(ConvertInoToCpp)
# merge every .cpp into a single file and **only** build that single file
if os.environ.get("ESPURNA_BUILD_SINGLE_SOURCE"):
cpp_files = []
for root, dirs, filenames in os.walk("espurna"):
for name in filenames:
if not name.endswith(".cpp"):
continue
path = os.path.join(root, name)
env.AddBuildMiddleware(lambda node: None, "*?/{}".format(path))
cpp_files.append(path)
merge_cpp(cpp_files, "espurna/espurna_single_source.cpp")

View File

@@ -25,52 +25,45 @@ import subprocess
import os
import sys
import datetime
from espurna_utils.display import Color, clr, print_warning
CUSTOM_HEADER = "espurna/config/custom.h"
if os.path.exists(CUSTOM_HEADER):
raise SystemExit(
clr(
Color.YELLOW,
"{} already exists, please run this script in a git-worktree(1) or a separate directory".format(
CUSTOM_HEADER
),
)
)
from espurna_utils.display import clr, print_warning, Color
def restore_source_tree(files):
cmd = ["git", "checkout", "-f", "--"]
cmd.extend(files)
subprocess.check_call(cmd)
def try_remove(path):
try:
os.remove(path)
except: # pylint: disable=bare-except
except: # pylint: disable=bare-except
print_warning("Please manually remove the file `{}`".format(path))
atexit.register(try_remove, CUSTOM_HEADER)
total_time = 0
def main(args):
configurations = []
if not args.no_default:
configurations = list(glob.glob(args.default_configurations))
def print_total_time():
print()
print(
clr(
Color.BOLD,
"> Total time: {}".format(datetime.timedelta(seconds=total_time)),
)
)
configurations.extend(x for x in (args.add or []))
if not configurations:
raise SystemExit(clr(Color.YELLOW, "No configurations selected"))
print(clr(Color.BOLD, "> Selected configurations:"))
for cfg in configurations:
print(cfg)
if args.list:
return
if not args.environment:
raise SystemExit(clr(Color.YELLOW, "No environment selected"))
print(clr(Color.BOLD, "> Selected environment: {}".format(args.environment)))
def run_configurations(args, configurations):
cmd = ["platformio", "run"]
if not args.no_silent:
cmd.extend(["-s"])
cmd.extend(["-e", args.environment])
for cfg in configurations:
print(clr(Color.BOLD, "> Building {}".format(cfg)))
with open(CUSTOM_HEADER, "w") as custom_h:
with open(args.custom_h, "w") as custom_h:
def write(line):
sys.stdout.write(line)
@@ -87,11 +80,15 @@ def main(args):
os_env = os.environ.copy()
os_env["PLATFORMIO_SRC_BUILD_FLAGS"] = "-DUSE_CUSTOM_H"
os_env["PLATFORMIO_BUILD_CACHE_DIR"] = "test/pio_cache"
cmd = ["platformio", "run", "-s", "-e", args.environment]
os_env["ESPURNA_BUILD_SINGLE_SOURCE"] = "1"
start = time.time()
subprocess.check_call(cmd, env=os_env)
end = time.time()
diff = time.time() - start
global total_time
total_time += diff
print(
clr(
Color.BOLD,
@@ -100,17 +97,59 @@ def main(args):
os.stat(
os.path.join(".pio", "build", args.environment, "firmware.bin")
).st_size,
datetime.timedelta(seconds=(end - start)),
datetime.timedelta(seconds=diff),
),
)
)
def main(args):
if os.path.exists(args.custom_h):
raise SystemExit(
clr(
Color.YELLOW,
"{} already exists, please run this script in a git-worktree(1) or a separate directory".format(
args.custom_h
),
)
)
configurations = []
if not args.no_default:
configurations = list(glob.glob(args.default_configurations))
configurations.extend(x for x in (args.add or []))
if not configurations:
raise SystemExit(clr(Color.YELLOW, "No configurations selected"))
if len(configurations) > 1:
atexit.register(print_total_time)
print(clr(Color.BOLD, "> Selected configurations:"))
for cfg in configurations:
print(cfg)
if args.list:
return
if not args.environment:
raise SystemExit(clr(Color.YELLOW, "No environment selected"))
print(clr(Color.BOLD, "> Selected environment: {}".format(args.environment)))
atexit.register(try_remove, args.custom_h)
run_configurations(args, configurations)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument(
"-l", "--list", action="store_true", help="List selected configurations"
)
parser.add_argument(
"--custom-h",
default="espurna/config/custom.h",
help="Header that will be included in by the config/all.h",
)
parser.add_argument(
"-n",
"--no-default",
@@ -129,5 +168,8 @@ if __name__ == "__main__":
default="test/build/*.h",
help="(glob) default configuration headers",
)
parser.add_argument(
"--no-silent", action="store_true", help="Do not silence pio-run"
)
main(parser.parse_args())