summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathan Rossi <nathan@nathanrossi.com>2019-04-03 05:37:02 +0000
committerRichard Purdie <richard.purdie@linuxfoundation.org>2019-04-05 17:33:01 +0100
commit091c46a8ecba6b6b7c44078ae2b567a2ef6e72e9 (patch)
tree2713b41f3351b7fbf1a0d8294bc8fcc5897da1fe
parenta8397def4eebacb8876d021129309a6903b71b2f (diff)
downloadopenembedded-core-091c46a8ecba6b6b7c44078ae2b567a2ef6e72e9.tar.gz
ccmake.bbclass: Create a cml1 style class for the CMake curses UI
The ccmake bbclass implements two tasks. The first task 'ccmake' preserves the configured state of CMakeCache.txt (generated from the configure task) and invokes the 'ccmake' program within a oe_terminal execution. The user can then review, select and modify configuration options and once satisfied with the configuration exit ccmake. Once ccmake has exited the build can be run and the updated configuration should be reflected in the output build. The ccmake bbclass has a second task 'ccmake_diffconfig' to compute the differences in configuration which was modified by ccmake. Since there are many ways to persist the configuration changes within recipes and layer configuration, the differences are emitted as a bitbake recipe fragment (configuration.inc) using EXTRA_OECMAKE as well as a CMake script file which can be used as a input to cmake via the '-C' argument. Both files are generated in the WORKDIR of the build and the paths to the files are written as output from the build. It is then up to the user to take this configuration and apply it to the desired location. Signed-off-by: Nathan Rossi <nathan@nathanrossi.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--meta/classes/ccmake.bbclass97
1 files changed, 97 insertions, 0 deletions
diff --git a/meta/classes/ccmake.bbclass b/meta/classes/ccmake.bbclass
new file mode 100644
index 0000000000..4114daa61b
--- /dev/null
+++ b/meta/classes/ccmake.bbclass
@@ -0,0 +1,97 @@
+inherit terminal
+
+python do_ccmake() {
+ import shutil
+
+ # copy current config for diffing
+ config = os.path.join(d.getVar("B"), "CMakeCache.txt")
+ if os.path.exists(config):
+ shutil.copy(config, config + ".orig")
+
+ oe_terminal(d.expand("ccmake ${OECMAKE_GENERATOR_ARGS} ${OECMAKE_SOURCEPATH} -Wno-dev"),
+ d.getVar("PN") + " - ccmake", d)
+
+ if os.path.exists(config) and os.path.exists(config + ".orig"):
+ if bb.utils.md5_file(config) != bb.utils.md5_file(config + ".orig"):
+ # the cmake class uses cmake --build, which will by default
+ # regenerate configuration, simply mark the compile step as tainted
+ # to ensure it is re-run
+ bb.note("Configuration changed, recompile will be forced")
+ bb.build.write_taint('do_compile', d)
+
+}
+do_ccmake[depends] += "cmake-native:do_populate_sysroot"
+do_ccmake[nostamp] = "1"
+do_ccmake[dirs] = "${B}"
+addtask ccmake after do_configure
+
+def cmake_parse_config_cache(path):
+ with open(path, "r") as f:
+ for i in f:
+ i = i.rstrip("\n")
+ if len(i) == 0 or i.startswith("//") or i.startswith("#"):
+ continue # empty or comment
+ key, value = i.split("=", 1)
+ key, keytype = key.split(":")
+ if keytype in ["INTERNAL", "STATIC"]:
+ continue # skip internal and static config options
+ yield key, keytype, value
+
+def cmake_diff_config_vars(a, b):
+ removed, added = [], []
+
+ for ak, akt, av in a:
+ found = False
+ for bk, bkt, bv in b:
+ if bk == ak:
+ found = True
+ if bkt != akt or bv != av: # changed
+ removed.append((ak, akt, av))
+ added.append((bk, bkt, bv))
+ break
+ # remove any missing from b
+ if not found:
+ removed.append((ak, akt, av))
+
+ # add any missing from a
+ for bk, bkt, bv in b:
+ if not any(bk == ak for ak, akt, av in a):
+ added.append((bk, bkt, bv))
+
+ return removed, added
+
+python do_ccmake_diffconfig() {
+ import shutil
+ config = os.path.join(d.getVar("B"), "CMakeCache.txt")
+ if os.path.exists(config) and os.path.exists(config + ".orig"):
+ if bb.utils.md5_file(config) != bb.utils.md5_file(config + ".orig"):
+ # scan the changed options
+ old = list(cmake_parse_config_cache(config + ".orig"))
+ new = list(cmake_parse_config_cache(config))
+ _, added = cmake_diff_config_vars(old, new)
+
+ if len(added) != 0:
+ with open(d.expand("${WORKDIR}/configuration.inc"), "w") as f:
+ f.write("EXTRA_OECMAKE += \" \\\n")
+ for k, kt, v in added:
+ escaped = v if " " not in v else "\"{0}\"".format(v)
+ f.write(" -D{0}:{1}={2} \\\n".format(k, kt, escaped))
+ f.write(" \"\n")
+ bb.plain("Configuration recipe fragment written to: {0}".format(d.expand("${WORKDIR}/configuration.inc")))
+
+ with open(d.expand("${WORKDIR}/site-file.cmake"), "w") as f:
+ for k, kt, v in added:
+ f.write("SET({0} \"{1}\" CACHE {2} "")\n".format(k, v, kt))
+ bb.plain("Configuration cmake fragment written to: {0}".format(d.expand("${WORKDIR}/site-file.cmake")))
+
+ # restore the original config
+ shutil.copy(config + ".orig", config)
+ else:
+ bb.plain("No configuration differences, skipping configuration fragment generation.")
+ else:
+ bb.fatal("No config files found. Did you run ccmake?")
+}
+do_ccmake_diffconfig[nostamp] = "1"
+do_ccmake_diffconfig[dirs] = "${B}"
+addtask ccmake_diffconfig
+