【问题标题】:Generating a reasonable ctags database for Boost为 Boost 生成合理的 ctags 数据库
【发布时间】:2010-05-13 08:57:06
【问题描述】:

我正在运行 Ubuntu 8.04,我运行了命令:

$ ctags -R --c++-kinds=+p --fields=+iaS --extra=+q -f ~/.vim/tags/stdlibcpp /usr/include/c++/4.2.4/

为我的系统上的标准 C++ 库和 STL ( libstdc++ ) 生成一个 ctags 数据库,以便与OmniCppComplete vim 脚本一起使用。这给了我一个非常合理的 4MB 标签文件,它似乎工作得很好。

但是,当我对已安装的 Boost 标头运行相同的命令时:

$ ctags -R --c++-kinds=+p --fields=+iaS --extra=+q -f ~/.vim/tags/boost /usr/include/boost/

我最终得到了一个 1.4 GB 的标签文件!我还没有尝试过,但这似乎太大而无法使用。有没有办法为我安装的 Boost 标头获取更苗条、更有用的标签文件?

编辑

请注意,libstdc++ 包括 TR1,其中有分配的 Boost 库。因此,libstdc++ 产生 4 MB 的标签文件,而 Boost 最终产生 1.4 GB 的标签文件,一定是发生了一些奇怪的事情。

刚刚在 Boost 邮件列表中遇到了这个:

Boost-users Boost and autocompletion

答案

感谢 Neg_EV 找出问题所在,但解决问题的方法比他建议的要好得多:

确保安装了apt-file,然后运行以下命令

(我将库标签保存在 ~/.vim/tags/ 中):

$ sudo apt-file update
$ apt-file list boost | grep -E -o '/usr/include/.*\.(h|hpp)' | grep -v '/usr/include/boost/typeof/' > ~/.vim/tags/boost-filelist
$ ctags --sort=foldcase --c++-kinds=+p --fields=+iaS --extra=+q -f ~/.vim/tags/boost -L ~/.vim/tags/boost-filelist

我已升级到 Ubuntu 10.04 和 Boost 1.40,这就是我测试此解决方案的原因,但据我所知,它应该适用于任何 Boost 版本。

【问题讨论】:

  • 可以在不使用 apt-file 的情况下完成类似的操作(以使其更广泛地有用吗?)例如只是在 ctags 命令行上使用 --exclude ?
  • 就像你一样,我开始时超过 1.4 G。删除了 typeof 但我仍然在 391 M。我想将它缩小到可能的十分之一。在提升 1.52... 有什么建议吗?
  • @drfrogsplat 不确定这是否仍然与您相关,但我在不使用 zsh 的包管理器实用程序的情况下实现了相同的效果:ctags -R /usr/include/boost/*~*typeof(/)(省略了其他 cmdargs 到 ctags)。您需要启用扩展 globbing 才能使其正常工作。
  • @zanegray 可以通过/usr/include/boost/<libname> 下的目录路径计数找到其他违规者。像这样的东西对我有用:grep -o '/usr/include/boost/[^/]*/' /path/to/boost-tags-file | sort | uniq --count(这需要一段时间)。 phoenixspirit 除了 typeof 之外也相当大,但您可以排除更多,具体取决于您不关心的库(或不需要 ctags)。
  • 使用 Boost 1.55,fusion 也很重(typeof 为 1.4GB,phoenix 为 193MB,fusion 为 122MB)。其余的小于 6MB。

标签: c++ linux vim boost ctags


【解决方案1】:

我知道这篇文章有点老了,但我遇到了同样的问题。我进一步调查了一下,似乎是 boost 中的一个文件夹导致了问题:typeof。我使用的是 boost 1.37,我的标签文件是 1.5G,typeof 是 1.4G。所以我刚刚创建了一个不包含该目录的标签文件,结果大小为 70M。我什至能够在没有空间不足的情况下对其进行排序:) 我想在较新版本的 boost 中它们可能是其他太大的项目,但是我发现的一般解决方案是这样的......

  1. 为每个 boost 文件夹分别生成一个标签文件,一个简单的 bash for 循环应该可以做到这一点。
  2. 看看哪些太大了。
  3. 要么创建一个新的单个标签文件,排除那些大目录,要么保持标签文件分开,简单地删除那些太大的标签文件。

这是我使用的脚本(取自 cmets):

for i in $(find -maxdepth 1 -type d | grep -v '^\.$' | sed 's/\.\///' ); do
    echo $i;
    ctags -f ~/tmp_tags/$i.tags -R --c++-kinds=+p --fields=+iaS --extra=+q --languages=c++ --sort=foldcase $i;
done

希望这会有所帮助。

【讨论】:

  • 我不认为你可以发布脚本?
  • 这应该生成单独的标签文件来找到罪魁祸首: for i in $(find -maxdepth 1 -type d | grep -v '^\.$' | sed 's/\.\/ //' );回声 $i; ctags -f ~/tmp_tags/$i.tags -R --c++-kinds=+p --fields=+iaS --extra=+q --languages=c++ --sort=foldcase $i;完成 然后要生成单个标签文件,您可以简单地执行以下操作: ctags -f ~/tmp_tags/all.tags -R --c++-kinds=+p --fields=+iaS --extra=+q --语言=c++ --sort=foldcase $(ls -d * | grep -v typeof ); grep -v 部分是我排除诸如 typeof 之类的东西的地方。这两个命令都假设你在 boost include 目录中。
  • 终于有时间尝试你的答案。你的想法非常有效,但我有一个更简单的方法来实现它。有关详细信息,请参阅对我的 OP 的编辑。
【解决方案2】:

使用选项

--sort=foldcase

这样,标签的搜索变得更快了。

引用 man page of ctags : “ foldcase 值指定不区分大小写(或大小写折叠)的排序。使用大小写折叠排序的标记文件的快速二进制搜索将需要使用标记文件的工具的特殊支持,例如在 ctags readtags 库或 Vim 6.2 版中找到的工具或更高版本(使用“set ignorecase”)。此选项必须出现在第一个文件名之前”

【讨论】:

  • 这会将标签文件的大小减小到合理的尺寸吗?我的意思是,stdlibc++ 包括 STL 和 TR1,其中实际上有 Boost 的分配 - 它只有 4MB!
  • 我不确定大小,但我在 VIM 中的标签搜索速度至少提高了 5 倍..
  • 没有。包括排序选项在 Ubuntu 10.04 中没有任何好处。仍然获得 1.4G 文件大小
  • @ancechu:有一个经过测试的解决方案,如果您有兴趣,请参阅 OP。
  • 即使是相同大小的 ctags 使用此选项,但 E341 错误消失了。谢谢!
【解决方案3】:

您应该将此选项添加到您的 ctags 调用中:

    -I "BOOST_SYMBOL_VISIBLE BOOST_SYMBOL_IMPORT BOOST_SYMBOL_EXPORT BOOST_FORCEINLINE BOOST_CONSTEXPR=constexpr BOOST_CONSTEXPR_OR_CONST=constexpr BOOST_STATIC_CONSTEXPR=static\ constexpr BOOST_STD_EXTENSION_NAMESPACE=std BOOST_MOVABLE_BUT_NOT_COPYABLE+ BOOST_COPYABLE_AND_MOVABLE+ BOOST_COPYABLE_AND_MOVABLE_ALT+ BOOST_NOEXCEPT=noexcept BOOST_NOEXCEPT_OR_NOTHROW=noexcept BOOST_NOEXCEPT_IF+ BOOST_NOEXCEPT_EXPR+ BOOST_STATIC_CONSTANT BOOST_DELETED_FUNCTION BOOST_DEFAULTED_FUNCTION BOOST_NESTED_TEMPLATE BOOST_UNREACHABLE_RETURN+ BOOST_DEDUCED_TYPENAME=typename BOOST_CTOR_TYPENAME=typename BOOST_LIKELY+ BOOST_UNLIKELY+ BOOST_ALIGNMENT+ BOOST_FALLTHROUGH"

这是我用于 Boost 1.55 的整个 /usr/include/boost 子目录的内容。我得到一个大约 128MB 的标签文件。 -I 似乎是这里的关键,有助于过滤掉虚假标签的生成。

注意:我在 Ubuntu 14.04 上使用 ctags 5.9。我有一个特殊的 -I 用于为 C++ 标准头文件生成 ctags。我花了一段时间才弄明白为什么有些头文件几乎不生成标签,而另一些则生成大量标签。

【讨论】:

    【解决方案4】:

    因为生成的方法(例如vector50.hpp vector100.hpp ...)太多,以至于ctags生成一个大标签文件

    1. 找到 /usr/include (-name ".h" -o -name ".hpp" ) boost/typeof > boost_files.txt
    2. 编辑 boost_files.txt 并删除 vector50.hpp vector100.hpp vector150.hpp vector200.hpp
    3. ctags --c++-kinds=+px --fields=+iaS --extra=+q -f test.tags -L boost_files.txt

    【讨论】: