Pulling in available ccmake functionality to devtool.  Running devtool
ccmake ${PN} will call bitbake -c ccmake which will pull up an ncurses
menu where the user can modify config options. After the menu is exited
it will use the same logic available in ccmake.bbclass to generate
configuration.inc and site-file.cmake file and place into
oe-local-files.

The changes can be tested, then committed using:

    devtool finish ${PN} /pathtolayer -f

The '-f' is needed as ${B}/CMakeCache.txt is soft linked to
${S}/CMakeCache.txt.new as devtool is not able to access ${B} because
it ignores the bbappends in build/workspace and this is the only way to
reflect the changes from bitbake -c ccmake.

Multiple devtool ccmake calls will create the diff between the
original CMakeCache.txt file (when calling devtool modify) and final
configuration.

Signed-off-by: Jaewon Lee <jaewon....@xilinx.com>
---
 scripts/lib/devtool/ccmake.py   | 73 +++++++++++++++++++++++++++++++++++++++++
 scripts/lib/devtool/standard.py | 68 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 141 insertions(+)
 create mode 100644 scripts/lib/devtool/ccmake.py

diff --git a/scripts/lib/devtool/ccmake.py b/scripts/lib/devtool/ccmake.py
new file mode 100644
index 0000000..c9597c3
--- /dev/null
+++ b/scripts/lib/devtool/ccmake.py
@@ -0,0 +1,73 @@
+# OpenEmbedded Development tool - ccmake command plugin
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+"""Devtool ccmake plugin"""
+
+import os
+import bb
+import logging
+import argparse
+import re
+import glob
+from devtool import setup_tinfoil, parse_recipe, DevtoolError, standard, 
exec_build_env_command
+
+logger = logging.getLogger('devtool')
+
+def ccmake(args, config, basepath, workspace):
+    """Entry point for the devtool 'ccmake' subcommand"""
+
+    rd = ""
+    localfilesdir = ""
+
+    tinfoil = setup_tinfoil(basepath=basepath)
+    try:
+      rd = parse_recipe(config, tinfoil, args.component, appends=True, 
filter_workspace=False)
+      if not rd:
+         return 1
+
+      pn =  rd.getVar('PN', True)
+      if pn not in workspace:
+         raise DevtoolError("Run devtool modify before calling ccmake for %s" 
%pn)
+
+      if not rd.getVarFlag('do_ccmake','task'):
+         raise DevtoolError("This package does not support ccmake option")
+
+      srctree=rd.getVar('S',True)
+
+      #add check to see if oe_local_files exists or not
+      localfilesdir = os.path.join(srctree,'oe-local-files')
+      if not os.path.exists(localfilesdir):
+          bb.utils.mkdirhier(localfilesdir)
+          #Add gitignore to ensure source tree is clean
+          gitignorefile = os.path.join(localfilesdir,'.gitignore')
+          with open(gitignorefile, 'w') as f:
+                  f.write('# Ignore local files, by default. Remove this file 
if you want to commit the directory to Git\n')
+                  f.write('*\n')
+
+    finally:
+      tinfoil.shutdown()
+
+    logger.info('Launching ccmake')
+    exec_build_env_command(config.init_path, basepath, 'bitbake -c ccmake %s' 
% pn, watch=True)
+
+    standard._create_cmake_diff(srctree,rd)
+
+    return 0
+
+def register_commands(subparsers, context):
+    """register devtool subcommands from this plugin"""
+    parser_ccmake = subparsers.add_parser('ccmake',help='HELP', 
description='Launches the make ccmake command(for recipes where do_ccmake is 
available), allowing users to make changes to the build-time configuration. 
Creates a config fragment corresponding to changes made.', group='advanced')
+    parser_ccmake.add_argument('component', help='component to alter config')
+    parser_ccmake.set_defaults(func=ccmake,fixed_setup=context.fixed_setup)
diff --git a/scripts/lib/devtool/standard.py b/scripts/lib/devtool/standard.py
index 60c9a04..c942798 100644
--- a/scripts/lib/devtool/standard.py
+++ b/scripts/lib/devtool/standard.py
@@ -943,6 +943,11 @@ def modify(args, config, basepath, workspace):
                 '    cp ${B}/.config ${S}/.config.baseline\n'
                 '    ln -sfT ${B}/.config ${S}/.config.new\n'
                 '}\n')
+            if rd.getVarFlag('do_ccmake','task'):
+                    f.write('\ndo_configure_append() {\n'
+                    '    cp ${B}/CMakeCache.txt ${S}/CMakeCache.txt.orig\n'
+                    '    ln -sfT ${B}/CMakeCache.txt ${S}/CMakeCache.txt.new\n'
+                    '}\n')
             if initial_rev:
                 f.write('\n# initial_rev: %s\n' % initial_rev)
                 for commit in commits:
@@ -1332,6 +1337,69 @@ def _export_patches(srctree, rd, start_rev, destdir, 
changed_revs=None):
             added[new_patch] = None
     return (updated, added, existing_patches)
 
+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
+
+def _create_cmake_diff(srctree, rd):
+    import shutil
+    orig_config = os.path.join(srctree, 'CMakeCache.txt.orig')
+    new_config = os.path.join(srctree, 'CMakeCache.txt.new')
+    if os.path.exists(orig_config) and os.path.exists(new_config):
+        if bb.utils.md5_file(orig_config) != bb.utils.md5_file(new_config):
+            # scan the changed options
+            old = list(cmake_parse_config_cache(orig_config))
+            new = list(cmake_parse_config_cache(new_config))
+            _, added = cmake_diff_config_vars(old, new)
+
+            if len(added) != 0:
+                with open(os.path.join(srctree, "oe-local-files", 
"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(os.path.join(srctree, "oe-local-files", "configuration.inc")))
+
+                with open(os.path.join(srctree, "oe-local-files", 
"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(os.path.join(srctree, "oe-local-files", "site-file.cmake")))
+        else:
+            bb.plain("No configuration differences, skipping configuration 
fragment generation.")
+        return True
+    return False
 
 def _create_kconfig_diff(srctree, rd, outfile):
     """Create a kconfig fragment"""
-- 
2.7.4

-- 
_______________________________________________
Openembedded-core mailing list
Openembedded-core@lists.openembedded.org
http://lists.openembedded.org/mailman/listinfo/openembedded-core

Reply via email to