环境搭建:

安装vscode

安装clangd插件,C/C++插件

https://blog.csdn.net/weixin_43862847/article/details/119274382

安装python3

生成compile_commands.json

这里做了一个python脚本工具,用来自动根据编译日志,生成clangd所需的compile_commands.json文件

mkdir .vscode
cd .vscode
vi generate_compdb_kernel.py
# 填入文件内容,保存并退出
vi gen_compdb_kernel.sh
# 填入文件内容,将TATGET, ANDROID_ROOT字段按自己的路径修改一下,保存并退出
chmod a+x gen_compdb_kernel.sh
 
./gen_compdb_kernel.sh

参考的generate_compdb_kernel.py文件

#!/usr/bin/env python3

from __future__ import print_function, division

import argparse
import fnmatch
import functools
import json
import math
import multiprocessing
import os
import re
import sys
import logging

__version__ = "0.1.1"

logger = logging.getLogger()
logger.setLevel(logging.INFO)
console_handler = logging.StreamHandler(sys.stdout)
console_formatter = logging.Formatter(
    fmt='%(asctime)s [%(levelname)s] [%(name)s:%(lineno)d] %(message)s')
console_handler.setFormatter(console_formatter)
logger.addHandler(console_handler)

CMD_VAR_RE = re.compile(r'^\s*cmd_(\S+)\s*:=\s*(.+)\s*$', re.MULTILINE)
SOURCE_VAR_RE = re.compile(r'^\s*source_(\S+)\s*:=\s*(.+)\s*$', re.MULTILINE)


def print_progress_bar(progress):
    progress_bar = '[' + '|' * \
        int(50 * progress) + '-' * int(50 * (1.0 - progress)) + ']'
    print('\r', progress_bar, "{0:.1%}".format(progress), end='\r')


def parse_cmd_file(android_root, docker_android_root, output_dir, cmdfile_path):
    if docker_android_root:
        docker_dir_replace = os.path.abspath(docker_android_root) + "/"
    else:
        docker_dir_replace = os.path.abspath(android_root) + "/"
    with open(cmdfile_path, 'r') as cmdfile:
        cmdfile_content = cmdfile.read()

    commands = {match.group(1): match.group(2)
                for match in CMD_VAR_RE.finditer(cmdfile_content)}
    sources = {match.group(1): match.group(2)
               for match in SOURCE_VAR_RE.finditer(cmdfile_content)}

    return [{
            'directory': android_root,
            'command': commands[o_file_name].replace(docker_dir_replace, "")\
                .replace("./", output_dir)\
                .replace(o_file_name, os.path.join(output_dir, o_file_name))\
                .replace("-Wp,-MD,", "-Wp,-MD," + output_dir)\
                .replace('\\\"', '\"'),
            'file': source.replace(docker_dir_replace, ""),
            'output': os.path.join(output_dir, o_file_name)
            } for o_file_name, source in sources.items()]


def gen_compile_commands(target, android_root, docker_android_root):
    logging.info("Building *.o.cmd file list...")
    logging.info(
        "The out dir where contains the obj of target is '%s'" % (android_root))
    android_root = os.path.abspath(android_root)

    output_dir = format("out/target/product/%s/obj/KERNEL_OBJ/" % (target))
    cmd_file_search_path = [os.path.join(android_root, output_dir)]
    logging.info("Searching *.o.cmd from path %s..." % (cmd_file_search_path))
    cmd_files = []
    for search_path in cmd_file_search_path:
        if (os.path.isdir(search_path)):
            for cur_dir, subdir, files in os.walk(search_path):
                cmd_files.extend(os.path.join(cur_dir, cmdfile_name)
                                 for cmdfile_name in fnmatch.filter(files, '*.o.cmd'))
        else:
            cmd_files.extend(search_path)

    if not cmd_files:
        logging.info("No *.o.cmd files found in",
                     ", ".join(cmd_file_search_path))
        return

    logging.info("Parsing *.o.cmd files...")

    n_processed = 0
    print_progress_bar(0)

    compdb = []
    pool = multiprocessing.Pool()
    try:
        for compdb_chunk in pool.imap_unordered(functools.partial(parse_cmd_file, android_root, docker_android_root, output_dir), cmd_files, chunksize=int(math.sqrt(len(cmd_files)))):
            compdb.extend(compdb_chunk)
            n_processed += 1
            print_progress_bar(n_processed / len(cmd_files))

    finally:
        pool.terminate()
        pool.join()

    # logging.info(compdb)
    logging.info("Writing compile_commands.json...")

    with open('../compile_commands.json', 'w') as compdb_file:
        json.dump(compdb, compdb_file, indent=1)


def main():
    parser = argparse.ArgumentParser(
        description='Generate compile_commands.json for kernel')
    parser.add_argument('--version', action='version',
                        version='%(prog)s '+__version__)
    parser.add_argument('--target', help='build target')
    parser.add_argument('--android_root', help='android root dir in host PC')
    parser.add_argument('--docker_android_root',
                        help='the android root dir in docker build env')
    args = parser.parse_args()

    if not args.target:
        logging.error("no target")
        exit(-2)
    if not args.android_root:
        logging.error("no android root dir")
        exit(-3)

    gen_compile_commands(args.target, args.android_root,
                         args.docker_android_root)


if __name__ == '__main__':
    ret = 0
    try:
        ret = main()
    except Exception as e:
        logging.error('Unexpected error:' + str(sys.exc_info()[0]))
        logging.exception(e)
    sys.exit(ret)

参数说明

--target TARGET 编译目标,编译时lunch的目标名称
--android_root ANDROID_ROOT android代码根目录所在的实际存储路径
--docker_android_root DOCKER_ANDROID_ROOT 可选参数,如果使用docker编译,这个参数填docker环境下的 android代码根目录

参考的gen_compdb_kernel.sh文件内容

#!/bin/bash

product='Test'
python3 generate_compdb_kernel.py --target $product \
     --android_root code/android \
     --docker_android_root workspace/android

参考的vscode settings.json配置

{
    "git.ignoreLimitWarning": true,
    "C_Cpp.errorSquiggles": "disabled",
    "C_Cpp.intelliSenseEngineFallback": "disabled",
    "C_Cpp.intelliSenseEngine": "disabled",
    "C_Cpp.autocomplete": "disabled",
 
    "clangd.arguments": [
        // "--completion-style=detailed",
        // "--header-insertion=never",
        // "--clang-tidy",
        // Let Clangd generate more detailed logs
        "--log=verbose",
        // The output JSON file is more beautiful
        "--pretty",
        // Global completion (the pop-up suggestions during input will provide possible symbols in all files configured in CMakeLists.txt, and the header file will be automatically supplemented)
        "--all-scopes-completion",
        // More detailed completion
        "--completion-style=detailed",
        // Allow supplementary header files
        "--header-insertion=iwyu",
        // In input suggestions, items that contain header files are distinguished by dots from items that do not yet contain header files
        "--header-insertion-decorators",
        // Automatically analyze files in the background (based on complie)_ Commands, which we generate with CMake)
        "--background-index",
        // Enable clang tidy to provide static checking
        "--clang-tidy",
        // The parameter of clang tidy static check indicates which rules are followed for static check. For details, see "advantages over VSCode configured according to official documents"
        // The * after the parameter indicates a wildcard
        // Adding - such as - modernize use trailing return type before the parameter will disable a rule
        "--clang-tidy-checks=cppcoreguidelines-*,performance-*,bugprone-*,portability-*,modernize-*,google-*",
        // Default formatting style: Google open source project code Guide
        "--fallback-style=Google",
        // Number of tasks opened at the same time
        "-j=12",
        // pch optimized location (memory or disk, selecting memory will increase memory overhead, but will improve performance)
        "--pch-storage=memory",
        // After adding this item, placeholders will be provided for the parameters when completing the function. After typing, press Tab to switch to the next placeholder or even the end of the function
        "--function-arg-placeholders",
        // compelie_ Directory location of the commands.json file (relative to the workspace, the file generated by CMake is in the build folder by default, so it is set to build)
        "--compile-commands-dir=build"
    ],
    // Cland's snippets have many jump points. Without this, Intellisense must be triggered manually
    "editor.suggest.snippetsPreventQuickSuggestions": false,
    "search.useIgnoreFiles": false,
}

重启vscode或者restart clangd language server

需要重启vscode或者重启clangd server,触发代码index


版权声明:本文为kongming2liya原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/kongming2liya/article/details/128969842