blob: c5b4bf6260117931c17c8d4eba91b70cc5ac9f95 [file] [log] [blame]
Patrick Williams92b42cb2022-09-03 06:53:57 -05001#
2# Copyright OpenEmbedded Contributors
3#
4# SPDX-License-Identifier: MIT
5#
6
Brad Bishopd89cb5f2019-04-10 09:02:41 -04007inherit terminal
8
9python do_ccmake() {
10 import shutil
11
12 # copy current config for diffing
13 config = os.path.join(d.getVar("B"), "CMakeCache.txt")
14 if os.path.exists(config):
15 shutil.copy(config, config + ".orig")
16
17 oe_terminal(d.expand("ccmake ${OECMAKE_GENERATOR_ARGS} ${OECMAKE_SOURCEPATH} -Wno-dev"),
18 d.getVar("PN") + " - ccmake", d)
19
20 if os.path.exists(config) and os.path.exists(config + ".orig"):
21 if bb.utils.md5_file(config) != bb.utils.md5_file(config + ".orig"):
22 # the cmake class uses cmake --build, which will by default
23 # regenerate configuration, simply mark the compile step as tainted
24 # to ensure it is re-run
25 bb.note("Configuration changed, recompile will be forced")
26 bb.build.write_taint('do_compile', d)
27
28}
29do_ccmake[depends] += "cmake-native:do_populate_sysroot"
30do_ccmake[nostamp] = "1"
31do_ccmake[dirs] = "${B}"
32addtask ccmake after do_configure
33
34def cmake_parse_config_cache(path):
35 with open(path, "r") as f:
36 for i in f:
37 i = i.rstrip("\n")
38 if len(i) == 0 or i.startswith("//") or i.startswith("#"):
39 continue # empty or comment
40 key, value = i.split("=", 1)
41 key, keytype = key.split(":")
42 if keytype in ["INTERNAL", "STATIC"]:
43 continue # skip internal and static config options
44 yield key, keytype, value
45
46def cmake_diff_config_vars(a, b):
47 removed, added = [], []
48
49 for ak, akt, av in a:
50 found = False
51 for bk, bkt, bv in b:
52 if bk == ak:
53 found = True
54 if bkt != akt or bv != av: # changed
55 removed.append((ak, akt, av))
56 added.append((bk, bkt, bv))
57 break
58 # remove any missing from b
59 if not found:
60 removed.append((ak, akt, av))
61
62 # add any missing from a
63 for bk, bkt, bv in b:
64 if not any(bk == ak for ak, akt, av in a):
65 added.append((bk, bkt, bv))
66
67 return removed, added
68
69python do_ccmake_diffconfig() {
70 import shutil
71 config = os.path.join(d.getVar("B"), "CMakeCache.txt")
72 if os.path.exists(config) and os.path.exists(config + ".orig"):
73 if bb.utils.md5_file(config) != bb.utils.md5_file(config + ".orig"):
74 # scan the changed options
75 old = list(cmake_parse_config_cache(config + ".orig"))
76 new = list(cmake_parse_config_cache(config))
77 _, added = cmake_diff_config_vars(old, new)
78
79 if len(added) != 0:
80 with open(d.expand("${WORKDIR}/configuration.inc"), "w") as f:
81 f.write("EXTRA_OECMAKE += \" \\\n")
82 for k, kt, v in added:
83 escaped = v if " " not in v else "\"{0}\"".format(v)
84 f.write(" -D{0}:{1}={2} \\\n".format(k, kt, escaped))
85 f.write(" \"\n")
86 bb.plain("Configuration recipe fragment written to: {0}".format(d.expand("${WORKDIR}/configuration.inc")))
87
88 with open(d.expand("${WORKDIR}/site-file.cmake"), "w") as f:
89 for k, kt, v in added:
Brad Bishopc342db32019-05-15 21:57:59 -040090 f.write("SET({0} \"{1}\" CACHE {2} \"\")\n".format(k, v, kt))
Brad Bishopd89cb5f2019-04-10 09:02:41 -040091 bb.plain("Configuration cmake fragment written to: {0}".format(d.expand("${WORKDIR}/site-file.cmake")))
92
93 # restore the original config
94 shutil.copy(config + ".orig", config)
95 else:
96 bb.plain("No configuration differences, skipping configuration fragment generation.")
97 else:
98 bb.fatal("No config files found. Did you run ccmake?")
99}
100do_ccmake_diffconfig[nostamp] = "1"
101do_ccmake_diffconfig[dirs] = "${B}"
102addtask ccmake_diffconfig
103