Generate CTAGS for libstdc++ (from current GCC)
Asked Answered
M

3

8

I know YoucompleteMe on base of LLVM, but I want to use OmniCppComplete. This works nice, if I use the modified headers for C++. This modified headers are outdated and doesn't contain anything from C++11.

If noticed that I can modifiy my headers myself e.g.:

$ find . -name '*.h' | xargs sed -i 's/__STL_BEGIN_NAMESPACE/namespace std {/'
$ find . -name '*.h' | xargs sed -i 's/__STL_END_NAMESPACE/}/'

Or use this setting:

let OmniCpp_DefaultNamespaces = ["std", "_GLIBCXX_STD"]

Both doesn't work and of course most headers doesn't have and any file extensions. I've already tried to workaround this by using a list of files. How can I create working CTAGS on base of my current GCC (e.g. /usr/include/c++/...)? What is the common way?

Thank you

This is what I got, if I try to complete something from LIBSTD++:

std::fs
Omni completion (^O^N^P) Back at original
Ctrl+x, Ctrl+o
Omni completion (^O^N^P) Pattern not found
Mezzosoprano answered 30/6, 2014 at 12:10 Comment(0)
M
6

Finally I've written despairingly an email to the author of the modified headers for the LIBSTDC++ (GCC). He answered me promptly (thanks!):

Requirements:
Install vim and vim-omnicppcomplete and ctags (dependency of vim-omnicppcomplete).

Solution:

$ cp -R /usr/include/c++/$GCC_VERSION ~/.vim/cpp_src
# it is not necessary to rename headers without an extension
# replace the "namespace std _GLIBCXX_VISIBILITY(default)" with "namespace std"
$ find . -type f | xargs sed -i 's/namespace std _GLIBCXX_VISIBILITY(default)/namespace std/'
$ ctags -f cpp_tags -R --c++-kinds=+p --fields=+iaS --extra=+q --language-force=C++ -I _GLIBCXX_NOEXCEPT cpp_src

Edit your ~/.vimrc:

" configure tags - add additional tags here or comment out not-used ones
set tags+=~/.vim/cpp_tags
" build tags of your own project with Ctrl-F12
map <C-F12> :!ctags -R --sort=yes --c++-kinds=+p --fields=+iaS --extra=+q -I _GLIBCXX_NOEXCEPT .<CR>

" OmniCppComplete
let OmniCpp_NamespaceSearch = 1
let OmniCpp_GlobalScopeSearch = 1
let OmniCpp_ShowAccess = 1
let OmniCpp_ShowPrototypeInAbbr = 1 " show function parameters
let OmniCpp_MayCompleteDot = 1 " autocomplete after .
let OmniCpp_MayCompleteArrow = 1 " autocomplete after ->
let OmniCpp_MayCompleteScope = 1 " autocomplete after ::
" also necessary for fixing LIBSTDC++ releated stuff
let OmniCpp_DefaultNamespaces = ["std", "_GLIBCXX_STD"]
" automatically open and close the popup menu / preview window
au CursorMovedI,InsertLeave * if pumvisible() == 0|silent! pclose|endif
set completeopt=menuone,menu,longest,preview

Autocompletion for LIBSTDC++ should now work within vim!
Manuall autocomplete with Ctrl+x -> Ctrl+o.

If you still have trouble with autocomplete, you maybe find a solution in the documentation (see FAQ 7).

Bye

Mezzosoprano answered 3/7, 2014 at 11:56 Comment(2)
In meanwhile I also got YouCompleteMe (based on CLANG/LLVM) working, which is doing it's job well. I liked to get CTAGS also working, because it is lightweight and doesn't require a full-blown VIM with Python-Support. Furthermore YouCompleteMe must be compiled manullay on Archlinux and requires a lot of stuff I don't use (LLVM, CLANG, MONO...) and a lot of extra configuration.Mezzosoprano
Tested this October 2021, and just completing the first part under "Solution" will give excellent STL completion with a base vim install on Ubuntu 21.04, vim 8.2.3428. This along with robust ctag of all included headers makes vim quite a robust IDE with minimal overhead and setupRudolfrudolfo
C
3

After try hard to search how to create c++-specific tags file using ctags, finally I made desirable progress. Need to say, ctags indeed is a little hard to use, powerful though.

First to emphasize, DONOT ignore -I option (see here for more option info) provided by ctags. It's pretty important for you to see more symbols in the tags file. Simply speaking, ctags cannot process some irregular syntactic statements, for example, prefixed or suffixed with C/C++ macros. If many functions are prefixed or suffixed with some kind of macros, ctags may be very likely to drop it. In the end, you cannot see them when coding.

Here's a way I use to find such macros as more as possible from C++ standard header path, /usr/include/c++/4.9.3 for example, and add them to -I option.

find /usr/include/c++/ -type f -exec grep '_GLIBCXX_' {} \; | grep -v -E '^[#if|#end]' | sort -u > glibcxx.log

After the command, you'll find several macros used in C++ 4.9.3 source files, then choose some of them to be ignored by ctags.

My final command to generate c++ tags file is this:

ctags -R --languages=c++ --langmap=c++:+.tcc. --c++-kinds=+p --fields=+iaS --extra=+qf -I "_GLIBCXX_NOEXCEPT _GLIBCXX_USE_NOEXCEPT _GLIBCXX_NOTHROW _GLIBCXX_USE_CONSTEXPR _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _GLIBCXX_END_NAMESPACE_CONTAINER _GLIBCXX_CONSTEXPR _GLIBCXX_NAMESPACE_LDBL _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_END_NAMESPACE_VERSION _GLIBCXX_VISIBILITY+" -f gcc-4.9.3.tags /usr/include/c++/4.9.3/

Caveat

  1. DONOT forget to write . sign following word tcc, it means match those files without explicit extension name such as vector,set
  2. DONOT forget to write + sign following word VISIBILITY, it means match std _GLIBCXX_VISIBILITY(**)
  3. DONOT forget to write + sign followed by .tcc, it means append the denoted extension to current map of the langugae, otherwise replace the map
Catatonia answered 19/10, 2017 at 11:39 Comment(1)
Thanks this was really helpful, especially your command line to generate the tags file!Marigolda
E
2

I actually use OmniCppComplete too, and have been happily using a C++ only tags file (amongst others. I break my tags files up into smaller pieces, like C++, boost, X11, etc.) for quite a while. Here's the solution I use for generating that tags file on Ubuntu 14.04:

ctags -f cpp_tags --c-kinds=cdefgmstuv --c++-kinds=cdefgmstuv --fields=+iaSmKz --extra=+q --langmap=c++:+.tcc. --languages=c,c++ -I "_GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_END_NAMESPACE_VERSION _GLIBCXX_VISIBILITY+" -n $INC_DIR/* /usr/include/$CPP_TARGET/c++/$CPP_VERSION/bits/* /usr/include/$CPP_TARGET/c++/$CPP_VERSION/ext/* $INC_DIR/bits/* $INC_DIR/ext $SYSTEM/* $SYSTEM2/*

Where:

CPP_VERSION=4.8
INC_DIR=/usr/include/c++/$CPP_VERSION
CPP_TARGET=x86_64-linux-gnu
SYSTEM=/usr/lib/gcc/x86_64-linux-gnu/4.8/include
SYSTEM2=/usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed

Please note that the real trick to getting most of the tags generated is the -I option! It may need to be tweaked. Of course, the --c-kinds/c++-kinds and fields options can be adjusted as well.

The final piece is adding:

tags+=cpp_tags

to your .vimrc file to allow the tags to be seen.

All of this requires NO MODIFICATIONS to the headers. If you use a different C++ library, chances are you'll need to fiddle with the -I option to get the tags to show up properly (or even at all).

Now that I think about it, I should probably post this information in the Vim Wiki also.

Your second part about let OmniCpp_DefaultNamespaces can stand some improvement. Try let OmniCpp_DefaultNamespaces = ["std", "_GLIBCXX_STD", "_GLIBCXX_STD_A", "_GLIBCXX_STD_C"]. That's what I use and should allow for more items to be found.

Finally, don't forget about using Vim's CTRL-p to complete the std::fs. It's quite powerful... and no tags file required!

Elbertelberta answered 19/12, 2014 at 19:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.