Last active
December 13, 2021 01:50
-
-
Save scue/e1a84e9677d788fbbe2d to your computer and use it in GitHub Desktop.
A script generate cscope index and .ycm_extra_conf.py, find parse all Android.mk files under current directory to get all include paths.-- 根据当前目录下所有的Android.mk文件,来生成cscope索引和.ycm_extra_conf.py文件。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash - | |
#=============================================================================== | |
# | |
# FILE: cscope-android.sh | |
# | |
# USAGE: | |
# . build/envsetup.sh | |
# lunch | |
# cd /path/to/workdir | |
# # first setup, find c include path by mmm command: | |
# source ~/bin/cscope-ycm-android.sh 1 # must run by source! | |
# # second setup, generate cscope index and .ycm_extra_conf.py | |
# ~/bin/cscope-ycm-android.sh 2 | |
# | |
# DESCRIPTION: A script generate cscope index and .ycm_extra_conf.py, find | |
# parse all Android.mk files under current directory to get all | |
# include paths. | |
# 根据当前目录下所有的Android.mk文件,来生成cscope索引和 | |
# .ycm_extra_conf.py文件。 | |
# | |
# OPTIONS: --- | |
# REQUIREMENTS: | |
# cp cscope-ycm-android.sh ~/bin/ | |
# chmod +x ~/bin/cscope-ycm-android.sh | |
# BUGS: --- | |
# NOTES: --- | |
# AUTHOR: linkscue(scue) | |
# ORGANIZATION: | |
# CREATED: 2015年09月10日 15:39 | |
# REVISION: --- | |
#=============================================================================== | |
#------------------------------------------------------------------------------- | |
# 背景故事: | |
# 现在正式做Android的底层开发,第一个任务就是视频流的硬解码工作; | |
# 但是在过程中发现,VIM编辑Android这些底层的源码,跳转得不是很灵活,尝试过 | |
# 1)使用Eclipse和Android Studio,把整个Android工程导入进行代码浏览 -- 太大 | |
# 2)使用Source Insight进入源码索引,这个方法按理说是最好的 -- 需要Windows | |
# 3)使用OpenGrok进入源码浏览,这个也是非常好的 -- 但它基于搜索的不是很精确 | |
# | |
# 所以最后还是选择了VIM + cscope来操作 -- 因为我现在只在一个不起眼的目录下工作 | |
# 我只要把这个目录下,所依赖的头文件都整理出来,交给cscope来建立一个完善的索引 | |
# 或者,让 youcomleteme 正确的找到头文件,ycm最强大的功能莫过于可以帮助检查错误 | |
# | |
# 于是乎,最后写了一这个这样子的简单脚本,实现我以上的需求 | |
# | |
#------------------------------------------------------------------------------- | |
MYSRCTOP=/source/VDI4.5-Android-OS4C | |
# 用于存储C/C++头文件索引路径 | |
include_path_file=LOCAL_C_INCLUDES.txt | |
#------------------------------------------------------------------------------- | |
# 运行方法: | |
# . build/envsetup.sh | |
# lunch | |
# cd /path/to/workdir | |
# source ~/bin/cscope-ycm-android.sh 1 | |
# 因为调用mmm命令解析 LOCAL_C_INCLUDE 变量,所以必须使用 source 来执行 | |
# | |
# 输出结果: | |
# 文件: LOCAL_C_INCLUDES.txt | |
# 包含从Android.mk中解决出来的 LOCAL_C_INCLUDE 变量,保存形式 $MYSRCTOP/具体路径 | |
# | |
# 之所以定义一个 $MYSRCTOP,是因为某些童鞋,Android编译环境可能是Docker容器里边的 | |
# 路径,与外边的Ubuntu真实路径有所不一致,若你没有这个问题,大可以设定MYSRCTOP为$T | |
#------------------------------------------------------------------------------- | |
find_c_include(){ | |
( | |
# 错误检查 | |
if [[ ! -f Android.mk ]]; then | |
echo "Error: can't find an Android.mk file in currect path" | |
return 1 | |
fi | |
# 备份旧的Android.mk文件 | |
find . -name Android.mk -exec cp -f {} {}_ \; | |
# 直接修改Android.mk文件,添加输出信息 | |
find . -name Android.mk -exec \ | |
sed -i '/include \$(BUILD_/ i\$(info LOCAL_C_INCLUDES=$(LOCAL_PATH))' {} \; | |
# 逐个Android.mk文件进行分析 | |
echo -e "\nFind all Android.mk under currect directory ..\n" | |
while read line; do | |
include_path=$(echo $line | awk -F'=' '{print $2}') | |
for path in $include_path ; do | |
echo -e "$MYSRCTOP/$path" | tee -a $include_path_file | |
done | |
done < <(mmm . -n | grep '^LOCAL_C_INCLUDES') | |
# 恢复原始的Android.mk文件 | |
echo -e "\nRestore the origin Android.mk files .." | |
find . -name Android.mk_ | while read mkfile; do | |
mv -f $mkfile ${mkfile%_} | |
done | |
) | |
} | |
#------------------------------------------------------------------------------- | |
# 运行方法: | |
# cd /path/to/workdir | |
# ~/bin/cscope-ycm-android.sh 2 | |
# 输出结果: | |
# cscope.files -- cscope 索引时自动读取这个文件 | |
# cscope.out -- cscope 索引输出文件,我们主要目的是要这个文件 | |
# .ycm_extra_conf.py -- YouCompleteMe 额外配置文件,有了它可以检查Android编程 | |
# 错误,以及实际跳转(cscope也可以跳转,两者不冲突) | |
#------------------------------------------------------------------------------- | |
generate_cscope_ycmconf(){ | |
( | |
# 获取 cscope 搜索路径 | |
cscsope_paths="." | |
while read line; do | |
cscsope_paths="$cscsope_paths $line" | |
done < <(cat $include_path_file) | |
# 保存至 cscope.files | |
find $cscsope_paths \ | |
-iname '*.java' -print -o \ | |
-iname '*.aidl' -print -o \ | |
-iname '*.hpp' -print -o \ | |
-iname '*.cpp' -print -o \ | |
-iname '*.xml' -print -o \ | |
-iname '*.mk' -print -o \ | |
-iname '*.[chxsS]' -print > cscope.files | |
# 生成索引 | |
cscope -Rbqk && echo -e "\nGenerate cscope index done!" | |
# Youcompleteme | |
ycm_extra_conf_temp=/tmp/.ycm_extra_conf.py_android.tmp | |
for path in $cscsope_paths ; do | |
echo -e "'-isystem',\n'$path'," | |
done > $ycm_extra_conf_temp | |
test -s $ycm_extra_conf_temp && \ | |
test -f .ycm_extra_conf.py && \ | |
mv .ycm_extra_conf.py .ycm_extra_conf.py.bak | |
cat <<-EOF > .ycm_extra_conf.py | |
#!/usr/bin/env python | |
# | |
# Copyright (C) 2014 Google Inc. | |
# | |
# This file is part of YouCompleteMe. | |
# | |
# YouCompleteMe is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, either version 3 of the License, or | |
# (at your option) any later version. | |
# | |
# YouCompleteMe 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 YouCompleteMe. If not, see <http://www.gnu.org/licenses/>. | |
import os | |
import ycm_core | |
# These are the compilation flags that will be used in case there's no | |
# compilation database set (by default, one is not set). | |
# CHANGE THIS LIST OF FLAGS. YES, THIS IS THE DROID YOU HAVE BEEN LOOKING FOR. | |
flags = [ | |
'-Wall', | |
'-Wextra', | |
'-Werror', | |
'-fexceptions', | |
'-DNDEBUG', | |
# THIS IS IMPORTANT! Without a "-std=<something>" flag, clang won't know which | |
# language to use when compiling headers. So it will guess. Badly. So C++ | |
# headers will be compiled as C headers. You don't want that so ALWAYS specify | |
# a "-std=<something>". | |
# For a C project, you would set this to something like 'c99' instead of | |
# 'c++11'. | |
'-std=c++11', | |
# ...and the same thing goes for the magic -x option which specifies the | |
# language that the files to be compiled are written in. This is mostly | |
# relevant for c++ headers. | |
# For a C project, you would set this to 'c' instead of 'c++'. | |
'-x', | |
'c++', | |
$(cat $ycm_extra_conf_temp) | |
'' | |
] | |
# Set this to the absolute path to the folder (NOT the file!) containing the | |
# compile_commands.json file to use that instead of 'flags'. See here for | |
# more details: http://clang.llvm.org/docs/JSONCompilationDatabase.html | |
# | |
# Most projects will NOT need to set this to anything; you can just change the | |
# 'flags' list of compilation flags. | |
compilation_database_folder = '' | |
if os.path.exists( compilation_database_folder ): | |
database = ycm_core.CompilationDatabase( compilation_database_folder ) | |
else: | |
database = None | |
SOURCE_EXTENSIONS = [ '.cpp', '.cxx', '.cc', '.c', '.m', '.mm' ] | |
def DirectoryOfThisScript(): | |
return os.path.dirname( os.path.abspath( __file__ ) ) | |
def MakeRelativePathsInFlagsAbsolute( flags, working_directory ): | |
if not working_directory: | |
return list( flags ) | |
new_flags = [] | |
make_next_absolute = False | |
path_flags = [ '-isystem', '-I', '-iquote', '--sysroot=' ] | |
for flag in flags: | |
new_flag = flag | |
if make_next_absolute: | |
make_next_absolute = False | |
if not flag.startswith( '/' ): | |
new_flag = os.path.join( working_directory, flag ) | |
for path_flag in path_flags: | |
if flag == path_flag: | |
make_next_absolute = True | |
break | |
if flag.startswith( path_flag ): | |
path = flag[ len( path_flag ): ] | |
new_flag = path_flag + os.path.join( working_directory, path ) | |
break | |
if new_flag: | |
new_flags.append( new_flag ) | |
return new_flags | |
def IsHeaderFile( filename ): | |
extension = os.path.splitext( filename )[ 1 ] | |
return extension in [ '.h', '.hxx', '.hpp', '.hh' ] | |
def GetCompilationInfoForFile( filename ): | |
# The compilation_commands.json file generated by CMake does not have entries | |
# for header files. So we do our best by asking the db for flags for a | |
# corresponding source file, if any. If one exists, the flags for that file | |
# should be good enough. | |
if IsHeaderFile( filename ): | |
basename = os.path.splitext( filename )[ 0 ] | |
for extension in SOURCE_EXTENSIONS: | |
replacement_file = basename + extension | |
if os.path.exists( replacement_file ): | |
compilation_info = database.GetCompilationInfoForFile( | |
replacement_file ) | |
if compilation_info.compiler_flags_: | |
return compilation_info | |
return None | |
return database.GetCompilationInfoForFile( filename ) | |
# This is the entry point; this function is called by ycmd to produce flags for | |
# a file. | |
def FlagsForFile( filename, **kwargs ): | |
if database: | |
# Bear in mind that compilation_info.compiler_flags_ does NOT return a | |
# python list, but a "list-like" StringVec object | |
compilation_info = GetCompilationInfoForFile( filename ) | |
if not compilation_info: | |
return None | |
final_flags = MakeRelativePathsInFlagsAbsolute( | |
compilation_info.compiler_flags_, | |
compilation_info.compiler_working_dir_ ) | |
else: | |
relative_to = DirectoryOfThisScript() | |
final_flags = MakeRelativePathsInFlagsAbsolute( flags, relative_to ) | |
return { | |
'flags': final_flags, | |
'do_cache': True | |
} | |
EOF | |
echo -e "\nGenerate .ycm_extra_conf.py done!" | |
) | |
} | |
case $1 in | |
1|f|find ) | |
find_c_include | |
;; | |
2|g|gen ) | |
generate_cscope_ycmconf | |
;; | |
esac |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment