3

Hello Ubuntu Community,

so first of all I'd like to say that I am quite new to ubuntu (16.10) and linux. I decided to use Windows as little as possible and also wanted to start learning the Programming language C. However, I thought it would be nice to do so in Emacs so I started learning Emacs and did some Tutorials on emacs. Mostly Basics and than learning by doing. So I found this Tutorial https://tuhdo.github.io/c-ide.html Before that I installed a lot of packages including helm and gtags and helm-gtags. I also installed ncurses libary in order to install gnu global.

So now we get to my problem / question. First of all if i am honest I don't really now what gtags is, but I thought I gonna figure it out when I install it (Something for navigation I guess). But under section 'Source Code Navigation' he talks about:

"Before using ggtags or helm-gtags, remember to create a GTAGS database by running gtags at your project root in terminal: ".. and then some commands

I think i somehow have to connect a libary with emacs. I the GNU_Global FAQ is written to create a link to my project folder reffering to: /usr/src/lib

But in my /usr/src directory is no lib folder. Now I guess , because Ubuntu has slightly different structures than other linux distros this libary is somewhere else ? Or am I completely wrong ? I couldn't find answers with google so maybe you can enlighten me.

Thanks in advance, Andi

2 Answers 2

6

gtags is a Linux tool that generates a symbol database for source code and then allows searching of those symbols for usage and definition. ggtags is the "plugin" for Emacs that provides an automated frontend to the tool. Some alternatives that have similar functionality to gtags are ctags, etags, and cscope, most of which have their own Emacs plugins.
Notably, many of these tools are not very good at handling large codebases (Linux kernel size and larger) because of the way they store their databases. The Linux kernel for example will generate a 2GB text file when using just gtags, and that file has to be loaded and searched whenever you try to do a symbol lookup. Workarounds exist to resolve this problem (below).

Simple solution

1.Install gtags on your system.

sudo apt-get install global

On a command line you should now be able to run this command and see where it's installed:

which gtags

2.Tell the Emacs ggtags plugin where to find the gtags tool.

Using the path returned by the which gtags command, add the following line to your ~/.emacs file:

(setq ggtags-executable-directory "/path/to/gtags/parent/dir")

3.Create a gtags database for a code project.

By default ggtags will search upward through the directory tree from the file in which you performed a symbol lookup trying to find a GTAGS file. That GTAGS file (and possibly some associated ones) is your symbol database. If it doesn't find a match for the symbol in the first database file, it will continue searching up the directory tree for additional databases. Matches are prioritized based on file proximity of symbol usage/definition to the file you're doing the lookup in. Generation of this database is called "tagging", and it's usually located at the root of a source tree you want to tag. The gtags tool itself does not do this continuation search since it's passed a path to a specific database, and the native Emacs provided gtags plugin maintains this single-database behavior.

To create a gtags database for a source folder out of Emacs when you're using the ggtags plugin (recommended over the native Emacs gtags plugin), you need to run the command ggtags-create-tags. The default key-binding for running arbitrary commands in Emacs is M-x, so press that and then type ggtags-create-tags. It will prompt you for a folder everything should be tagged and the database should be placed, so point it to the top directory of the source folder you want to tag. It will run for a while, possibly quite a while if you have a large source tree, blocking the entire Emacs GUI while it generates the tag database. Once it completes it will get used automatically by ggtags when relevant.

Much better solution

One of the problems with gtags, ctags, etags, and cscope is the size of the databases produced. Since they're tagging where symbols are defined as well as where they're used, you can end up with a database larger than your actual source tree. Very large databases then present the problem of searching them in a reasonable time. Using ggtags with the default Ubuntu gnu-global tool installed produces a very inefficient database format that gets exponentially worse the larger it grows. Mostly this is because Ubuntu is still providing the gnu-global tool from 2008 rather than a modern version, and it's not built to use the much more efficient ctags tools as an underlying framework.

To avoid the problems with gtags and get it to use the more efficient ctags, you need global-6.4 or later, and it needs to be built to point to your ctags installations. The only way I've really found to do this is to build it from source and provide the proper options as well as all the necessary dependent package installations. I ended up writing a shell script to do this installation and setup for me, and I keep it in GitHub with the rest of my emacs configuration and installation scripts. You can get it from https://github.com/mtalexan/emacs-settings/blob/master/global_install.sh.

You'll need to set a few things in your ~/.emacs to make full use of this:

(setq ggtags-use-idutils t)
(setq ggtags-use-project-gtagsconf nil)

This enables the use of the very efficient idutils sub-package, and makes sure gtags calls use your global settings for gtags that you've now compiled in.

How to use gtags/ggtags/helm-gtags

I personally use ggtags and not helm-gtags or gtags. Emacs provides a default gtags "plugin", but it has a much worse interface than ggtags and will only search a single database. I use helm regularly for most things, but I like my ggtags interface separated from my helm interface when I'm parsing matches so I don't use helm-gtags. Also helm-gtags is pretty slow if your gtags database is large.

For ggtags you need to set ggtags-mode for it to be useful. This can be done by adding it to automatically trigger on c-mode by adding something like the following to your .emacs file

(add-hook 'c-mode-common-hook
  (lambda ()
    (when (derived-mode-p 'c-mode 'c++-mode 'java-mode)
     (ggtags-mode 1))))

Alternatively you can set it to always be enabled by instead using a line like this:

(setq ggtags-global-mode 1)



Settings I recommend if you're going to be using a large codebase require the following lines in your ~/.emacs file:

; Allow very large database files
(setq ggtags-oversize-limit 104857600)
(setq ggtags-sort-by-nearness t)



When browsing the code, the most common things I do are to follow a symbol underneath my cursor, find all uses of a symbol underneath my cursor, and occasionally to do a symbol lookup unrelated to where my cursor is. These correspond to the commands: ggtags-find-tag-dwim and ggtags-find-reference. These commands operate on a point (your Emacs cursor position) but will open a prompt for you to enter a symbol when there is no symbol under your point or when they're called from M-x.
When you run ggtags-find-tag-dwim it can do a number of things best understood by playing with it, but generally will jump to a match when there's only one match (equivalent that doesn't auto-jump is ggtags-find-tag) or will open a side windows like ggtags-find-reference with a list of possible matches that includes the file, line number, and some context for it where each entry is clickable to jump directly there.
Be careful when that window is open, it puts you in a special minor mode that means the up and down keys will switch between matches until you press Enter to officially select a match.
Conveniently when you select a match your tag-mark is left behind. This means you can use the command pop-tag-mark to jump back to the last place you were at. tag-mark is a stack of tag-marks, so you can repeatedly look up symbols and will always be able to go back to each location prior to following a lookup. If you want to just do a manual lookup rather than one based on the symbol at the point, there are some ggtags functions that operate like ggtags-find-tag-dwim, but prompt you for the symbol in the minibuffer. ggtags-find-tag-dwim will do this as well if there is no symbol under the point.

4
  • Thanks for that writeup. Not sure why your script at github.com/mtalexan/emacs-settings/blob/master/… goes through lengths to avoid the "ctags" that comes with Emacs. Doesn't GNU Global generate its own format, avoiding any conflict with the ctags that is built with Emacs? Is "global" internally using the "ctags" that happens to be in the users $PATH? Also there is github.com/universal-ctags/ctags which is claiming to be a maintained version of what was exhuberant-tags, so maybe your script should use universal-tags instead?
    – bgoodr
    Aug 21, 2019 at 0:23
  • Alright answering some of my question since you wrote: "Mostly this is because Ubuntu is still providing the gnu-global tool from 2008 rather than a modern version, and it's not built to use the much more efficient ctags tools as an underlying framework.". But your answer was written in 2017, so wouldn't the ctags that ships with some more recent version of Emacs have rectified this now, or do we have to build universal-ctags?
    – bgoodr
    Aug 21, 2019 at 0:34
  • 1
    ctags shipped with emacs is not exuberant ctags, it's a different tool with a conflicting name that produces similar but less efficient output. When building gtags from scratch, the configure step will find ctags based on your path, and you want to use the efficient exuberant-ctags, so that's why the complicated avoidance of the emacs provided ctags.
    – mtalexan
    Aug 21, 2019 at 4:17
  • 1
    Thanks. Also, I'm concluding that we should be now using github.com/universal-ctags/ctags and not the "exuberant tags" but I take your point. Not sure what the benefit of Universal Ctags is over whatever "native" GNU Global produces. The file sizes look the same, but the contents of the files are different (as compared using shasum).
    – bgoodr
    Aug 21, 2019 at 14:44
-3

sudo apt get global

/*********************** Below is irrelevant *****************/ Welcome to linux and C. and this is my first post. LOL

You are in the right path! congrats! I am a EE student doing CS now.

I hope my advice will help you.

  1. GET rid of windows, dont even use it in a virtual machine. if cant, but a second laptop only for linux and programming C/C++.

Windows is for entertaining, for non-programmer, I might be a little extreme. YEAH, C/C++ and unix are for the bold, for the pro!

  1. My guess is you havent start learn C++ yet. If ture, Dude, start C++ first, use or any book from stack exchange, or quora.

why? C++ is harder, and more job, and if you familiar with C++. I am not sure, I think C can be pick up easily.

why C++ first, a lot of C programming style is not suggested in C++. Some are forbidden if you want to write good and modern C++.

YES, learn C the hard way. there is even a book called that.

HAHA, but if you are EE student, and doing embedded system, learn C! Learn C! Learn C! C is definitely the wonderland here.

To become a god in C programming: (my path)

  1. K&R book, the bible!

  2. APUE, the bible again! there is a online course in APUE, people are serious.

  3. I think you are good to go, no need to read more, BUT!

if you have enough time and energy, read UNIX source code. there is a book called "unix source code commentary". It was a must-have computer science book in MIT. but before that, you need some knowledge about OS.

Enough about C!

Lets talk about IDE, since you are new to Linux.

Use Emacs, Vi, or .. for both C and C++, python, oh, might be other programming languages.

IDE makes you lazy, not thinking about what is really going on.

Think about this, C/C++ are created long before some fancy IDE, windows OS!

how do folks programmed OS those days? use a IDE? haha

Learn C/C++ the hard way. I guarantee you will enjoy it.

LAST, DONT get gnu global.

"It is useful for hacking a large projects which contain many sub-directories" says the web.

Are you maintaining some large projects or just doing some textbook programming exercises?

Again, it makes you lazy!

2
  • sudo apt install global
    – Yan Ge
    Jan 12, 2017 at 19:47
  • Note that the command sudo apt install global will fail to install the global package unless you first enable the universe repository I suggest that you edit your post to include this useful information that relates to the question asked and remove the TL;DR cruft which as you say yourself, "is irrelevant"
    – Elder Geek
    Jan 12, 2017 at 20:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.