Adventures in Meta-Debugging

Okay did I mention how I sucked at the command line? This is part of the journey towards stopping. Yes, I’m on a Mac and it’s not very *nix-y in some ways but it’s enough for me for now.

Today’s story starts when I learned about gdb, the pure-command-line GNU Debugger, which is incredibly cool. I have tried and failed to learn how to use the debug function on many of my IDEs; I found shotgunning printf statements as needed faster. This may well be the first time I found a command-line tool so much more intuitive than the GUI-equipped programs. Wow.

Then I learned that for some reason the gdb on this computer was 6.3, which is 1.2~1.5 major versions behind (depending on how you count) and missing a frustrating amount of features. (The one that the current Code::Blocks installer installs is also something like 6.4. Blech.)

Okay, great. Well, I can download gdb… I can change to the right directory and type make, even though I don’t think I’ve ever done so without being destroyed by weird dependencies… I can wait through the resulting explosion of unreadable computer-y text (this would be a lot more authentic background image for the news on “hackers” compared to whatever they’re showing)… I can make install which will, as the readme file says, install by default into /usr/bin/local

Hmm, permission denied? That’s right, I need to sudo make install! I have just blown myself away with my expertise.

Darn, gdb --version still gives me 6.4.

Lesson number two: Mac OS X has this really complicated routine for deciding what your $PATH environment variable is, which is from what I know just where the computer looks for each program name (e.g. gdb) you attempt to run. The list appears to be:

  1. /etc/paths, text file with one directory per line
  2. /etc/manpaths, ditto above
  3. /etc/paths.d/, directory with text files, parsed alphabetically, that work as above
  4. /etc/manpaths.d/, directory … ditto above
  5. ~/.bashrc, shell script with lots of commands if it does something like export PATH
  6. ~/.bash_profile, ditto under some confusing conditions
  7. ~/.bash_login, ditto
  8. ~/.profile, ditto

(This is my source and I’m going to scream if you ask me what feline species that version corresponds to because it’s too much and it probably doesn’t matter)

Now. The fundamental Mac default $PATH (which you can see by viewing /etc/paths) puts /usr/bin before /usr/local/bin, which is why my first make install didn’t change the version. So, question: why?

I figured it out from Unix Mages, which has this ebook full of stuff that was mostly explained by all the *nix tutorials ever except for this part about the directory structure of the whole system around page 40. The book uses a thoroughly-extended but perfectly apt metaphor (we call it a “conceit” in literature class) comparing the command-line to magic. Anyway, the important bit is:

At the top of local, we, once again, see rooms [folders] with the same names [stuff like bin, etc, lib, sbin] as the first and second floors [/ and /usr/]. The local rooms are usually customized for the Tower [computer system] itself – the archmages [people who don’t suck at the command line] can create whatever they want here. It’s an unwritten mage rule that says you should try to keep your Towers [sic] first two floors similar, but you can use the third floor however you want. So don’t be surprised if you ever visit another Tower and see that the third floor looks completely different!

So logically /usr/local/bin should indeed take precedence since the user installs stuff there instead of it being more-or-less built-in, and searching says it does on other *nix systems. The answer to “why?” is “I don’t know, but I think Apple did something dumb.”

Well, you can sudo (favorite editor) /etc/paths to move it if you’re brave, but the safe solution is apparently just throwing

PATH=/usr/local/bin:$PATH
export PATH

or combining it with whatever’s in whichever of items 5 to 8 above you’re using. I’m going to gently suggest .profile because it’s the only file I have that exists and some automated Python thing I did a while ago added something there. There’s a difference related to whether the shell is a login shell that I haven’t figured out yet.

Still clueless, but at least I have the debugging skip command working now.

Why all this now? Tomorrow is the local informatics competition which I got into somehow, and it appears they want us to bring our own programming software on a USB, which is… weird. I half-expect that we don’t actually need to do it, but I brought a copy of Vim, the basic MinGW library, and one of every version of installer of Dev-C++ and Code::Blocks I could find. Serendipitously, it means I get to postpone two of my midterms. Well, we’ll see what happens.

(note: the commenting setup here is experimental and I may not check my comments often; if you want to tell me something instead of the world, email me!)