Mirror of espurna firmware for wireless switches and more
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

158 lines
4.8 KiB

  1. #!/usr/bin/env python
  2. #
  3. # Copyright (C) 2020 by Maxim Prokhorov <prokhorov dot max at outlook dot com>
  4. #
  5. # This program is free software: you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation, either version 3 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. import os
  18. import argparse
  19. import re
  20. import shlex
  21. import configparser
  22. import collections
  23. CI = "true" == os.environ.get("CI", "false")
  24. Build = collections.namedtuple("Build", "env extends build_flags src_build_flags")
  25. def expand_variables(cfg, value):
  26. RE_VARS = re.compile("\$\{.*?\}")
  27. for var in RE_VARS.findall(value):
  28. section, option = var.replace("${", "").replace("}", "").split(".", 1)
  29. value = value.replace(var, expand_variables(cfg, cfg.get(section, option)))
  30. return value
  31. def get_builds(cfg):
  32. RE_NEWLINE = re.compile("\r\n|\n")
  33. BASE_BUILD_FLAGS = set(
  34. shlex.split(expand_variables(cfg, cfg.get("env", "build_flags")))
  35. )
  36. for section in cfg.sections():
  37. if (not section.startswith("env:")) or (
  38. section.startswith("env:esp8266-") and section.endswith("-base")
  39. ):
  40. continue
  41. build_flags = None
  42. src_build_flags = None
  43. try:
  44. build_flags = cfg.get(section, "build_flags")
  45. build_flags = RE_NEWLINE.sub(" ", build_flags).strip()
  46. build_flags = " ".join(
  47. BASE_BUILD_FLAGS ^ set(shlex.split(expand_variables(cfg, build_flags)))
  48. )
  49. except configparser.NoOptionError:
  50. pass
  51. try:
  52. src_build_flags = cfg.get(section, "src_build_flags")
  53. src_build_flags = RE_NEWLINE.sub(" ", src_build_flags).strip()
  54. src_build_flags = expand_variables(cfg, src_build_flags)
  55. except configparser.NoOptionError:
  56. pass
  57. yield Build(
  58. section.replace("env:", ""),
  59. cfg.get(section, "extends").replace("env:", ""),
  60. build_flags,
  61. src_build_flags,
  62. )
  63. def find_any(string, values):
  64. for value in values:
  65. if value in string:
  66. return True
  67. return False
  68. def generate_lines(builds, ignore):
  69. cores = []
  70. generic = []
  71. for build in builds:
  72. if find_any(build.env, ignore):
  73. continue
  74. flags = []
  75. if build.build_flags:
  76. flags.append('PLATFORMIO_BUILD_FLAGS="{}"'.format(build.build_flags))
  77. if build.src_build_flags:
  78. flags.append('ESPURNA_FLAGS="{}"'.format(build.src_build_flags))
  79. flags.append('ESPURNA_RELEASE_NAME="{env}"'.format(env=build.env))
  80. flags.append("ESPURNA_BUILD_SINGLE_SOURCE=1")
  81. cmd = ["env"]
  82. cmd.extend(flags)
  83. cmd.extend(["pio", "run", "-e", build.extends, "-s", "-t", "release"])
  84. line = " ".join(cmd)
  85. # push core variants to the front as they definetly include global build_flags
  86. output = generic
  87. if "ESPURNA_CORE" in build.src_build_flags:
  88. output = cores
  89. output.append(line)
  90. return cores + generic
  91. def every(seq, nth, total):
  92. index = 0
  93. for value in seq:
  94. if index == nth:
  95. yield value
  96. index = (index + 1) % total
  97. if __name__ == "__main__":
  98. if not CI:
  99. raise ValueError("* Not in CI *")
  100. parser = argparse.ArgumentParser()
  101. parser.add_argument("--version", required=True)
  102. parser.add_argument("--destination", required=True)
  103. parser.add_argument("--ignore", action="append")
  104. args = parser.parse_args()
  105. Config = configparser.ConfigParser()
  106. with open("platformio.ini", "r") as f:
  107. Config.read_file(f)
  108. builder_total_threads = int(os.environ["BUILDER_TOTAL_THREADS"])
  109. builder_thread = int(os.environ["BUILDER_THREAD"])
  110. if builder_thread >= builder_total_threads:
  111. raise ValueError("* Builder thread index out of range *")
  112. builds = every(get_builds(Config), builder_thread, builder_total_threads)
  113. print("#!/bin/bash")
  114. print("set -e -x")
  115. print('export ESPURNA_RELEASE_VERSION="{}"'.format(args.version))
  116. print('export ESPURNA_RELEASE_DESTINATION="{}"'.format(args.destination))
  117. print('trap "ls -l ${ESPURNA_RELEASE_DESTINATION}" EXIT')
  118. print(
  119. 'echo "Selected thread #{} out of {}"'.format(
  120. builder_thread + 1, builder_total_threads
  121. )
  122. )
  123. for line in generate_lines(builds, args.ignore or ()):
  124. print(line)