derwiki

Apr 21 2009

What I Wish I Had Known About Developing C/C++ From Linux Before I Started

After doing Java/PHP development from Eclipse in Windows or an X11 environment for almost my entire programming career, I found myself in a job where I basically had to switch to the command line for C/C++ development on a large project. One year and some off months later, I’ve taken for granted what I’ve picked up and feel like I should pass on my knowledge to people who might just be starting out. What follows is a list of things I wish I had known over a year ago, or how I learned to stop worrying and love the shell.


screen

Cheat Sheet: Screen VT100/ANSI Terminal Emulator br Peteris Krumins
.screenrc link: from dotfiles.org
GNU screen is a full-screen window manager for the shell, and is the single most useful command line utility I’ve come across. You create multiple windows within screen and you can “alt-tab” between them with [ Ctrl-a X ] commands (X is: (n)ext, (p)revious, (a) last, etc). I found that screen was initially a little daunting because by default it didn’t have a status bar, but you can fix that by creating a .screenrc in your home directory (check the link above for some example .screenrcs). By exclusively using the keyboard, I’ve found it a lot quicker to switch between different programs. I often have Vim open in one screen, cgdb in another, a free shell in another, and a log file in another. Screen also get you regions where you can split your console in half horizontally and have the top and bottom halves holding different windows (you switch between them with [ Ctrl-a <tab> ]). Screen lets you keep a persistent work space. If you’re ssh’ed in somewhere and your connection drops, screen keeps your session active; just reconnect over ssh and run [ screen -xRR ] to pull up your session exactly where you left it. The -x lets you connect to a screen session from more than one location, which means that screen is also extremely useful for collaboration. If you’re ssh’ed into a machine and you want to work with someone else, give them your credentials/rlogin access and have them run [ screen -xRR ] to connect to your active session. I’ve used this for help with a remote colleague and to teaching colleagues/leading education sessions that involve the shell.


Vim (for development)

Cheat Sheet: Vim Quick Reference Card by Laurent Grégoire
.vimrc link: from dotfiles.org
I fought this for a while. I really did. You could pry Eclipse from my cold dead hands. I “grew up” as a coder using Eclipse for Java and PHP projects, so nothing else seemed to make sense. The way our development environment is set up though, there was really no good way to use Eclipse because everything is done on a remote development box, and they won’t let us run Eclipse and forward over X (which is reasonable; Eclipse has a lot of overhead). I tried mounting the filesystem locally with sshfs so my local Eclipse could access the remote files, but I changed connections enough that sshfs wasn’t a viable option. Faced with that fact and that the development machines really only had (g)vim and (x)emacs, coupled with the fact that many of our source code management utilites used Vim, I decided to take the plunge. I went with Vim over Gvim so that I could run it from within screen, but that’s a small detail.

After developing in Vim for about half a year, I can’t look back. I even started programming Python/Django in Vim. More than just an editor, it’s kind of changed my entire development mindset, on the same level as switching from any other email client to Gmail. Vim has changed:

  • how I navigate code. If I can remember a keyword for where I want to be, I just search-navigate there with [ <ESC> /Keyword<ENTER> (‘n’ as needed)]. It’s a lot quicker than it ever was for me in Eclipse using Find or the mouse.
  • the amount of code I have to keep in my head at any point in time. Last night I tried installing Netbeans at a friend’s recommendation. What immediately struck me was, “I can’t see the code anymore!” By keeping the code fullscreened all the time, keeping multiple tabs open for different files, and being able to quickly navigate between sections, I remember where stuff is instead of what the stuff is. Keeping this lookup table in my mind allows me to hold larger chunks of functionality in my head, and quickly jump to implementation when I need details.

Quick tips:

  • tabs (Vim 7.x): open vim with several tabs by calling [ vim -p file1 file2 ]. From within vim, [ :tabnew file1 ] will do the same. [ <ESC> gt ] lets you cycle through tabs
  • regions: these let you divide the screen into sections. [ Ctrl-w s ] splits horizontally and [ Ctrl-w v ] splits vertically. I prefer a vertical split so that I can keep reference source code in one region and where I’m coding in the region next to it.

Another nice thing about Vim is that a lot of standard Linux utilities use the same syntax. Search and replace, for example, is [ s/search/replace/g ], which happens to be the same syntax for doing a search and replace in sed (see below). One bug I’ve found is that using vim with screen is that vim doesn’t always redraw the screen correctly; [ ctrl-l ] is sometimes useful (although that doesn’t always seem to redraw completely either).
Note: if you prefer emacs, that’s fine. I don’t care. It’s the same thing as Vim as far as I’m concerned.


gdb/cgdb

Cheat Sheet: GDB Quick Reference from SmashTheStack
If you have to use gdb for debugging C/C++ applications, I strongly recommend cgdb, the curses GNU debugger. You get a horizontal split screen with Vim at the top and gdb at the bottom. Vim follows along in the source code as you step through. I know X11 gdb interfaces exist, but X11 apps don’t play well with screen, so I avoid them. Here are some general purpose gdb commands that I’ve found useful:

  • set scheduler-locking [on/off] — very important for multithreaded apps! Turn this on and it prevents other threads from running when you’re stepping through a section of code. It’s important to only turn this on after you’ve hit your breakpoint and turn it back off when you want to continue execution.
  • set print pretty on — formats objects more prettier for your viewing pleasure.
  • set logging [on/off] — turn it on, print a variable, turn it off. This will dump the object to gdb.txt in your current directory.



Various command line utilities

  • xargs: great for piping output of one command sequentially to another. I’m trying to cut down on [ for i in `cmd` ] usage in favor of this; it feels cleaner.
  • grep: one of the most versatile and useful commands I’ve used. Useful options are [ grep -{C,B,A} n ] for n lines of context around, before, or after; -i for insensitive; -n for line number. Very useful input for piping to other commands (like xargs).
  • sed: stream editor, great for search/replace on the fly (as well as other simple text commands).
  • awk: great for extracting parts of a line of input, i.e. grabbing a column from a text file or command [ awk ‘{print $2}’ ].
  • tee: like a plumbers tee; it takes input from STDIN and passes back to STDOUT while also copying to a file you specify. Useful in conjunction with sudo when you need to echo something to a file: if file.txt is root owned, [ sudo echo “hello” > file.txt ] runs echo as sudo and doesn’t give sudo access to the ». [ echo “hello” | sudo tee file.txt ] will do what you want.
  • nohup: run a process detached in the background; persists between logouts (be sure to put & at the end of the command).
  • diff: pretty standard utility, but this is what I use it for: I loop through all the files I’ve modified and diff to the previous version, then pipe to a grep where I can search for something I think I’ve changed — but can’t remember where.
  • find: a lot more convenient for recursively listing all files contained within a directory than ls. [ find . ] gets you a list of everything, and [ find /path -name <name>  ] lets you filter. You can use wildcards, just make sure that you escape them so that BASH doesn’t expand them before find sees them. It’s useful to pipe filenames from find to xargs, use the [ -print0 ] switch if you filenames with spaces give you problems.

Update: HN started a good discussion on this post.

Comments (View)
blog comments powered by Disqus