Centos7 VBoxGuestAdditions cannot find kernel-devel

I saw the silliest reason ever for the VBoxGuestAdditions being unable to find the correct kernel headers.

The story normally goes that you try to compile these things inside your virtual machine, the VBoxLinuxAdditions.run file will tell you to install kernel-devel, you do so and everything’s fine. Not today, though! Today the header files were undiscoverable.

I poked around for a while with no success and eventually just asked myself what the simplest possible problem could be. On a hunch I did:

ls /usr/src/kernels



uname -r


So the output of uname -r doesn’t contain one of the patchlevels that’s recorded in /usr/src/kernel.

This is because the following command installs the latest kernel-devel available in the rpm repos

sudo dnf install kernel-devel

But an older kernel is installed on the running system. I had to upgrade my running kernel

sudo dnf upgrade

HomeBrew Always Uses The System Ruby

I got back to looking at HomeBrew today. Something I noticed last week, though, was that HomeBrew was always using the system ruby, even when I’m using rbenv to set a global ruby. I decided to take an hour or two out to figure out why that was happening.

Last week, I spent some time figuring out how HomeBrew does command loading. It’s pretty simple: there’s the brew command, which is a shell script, and mostly it sets some variables and dispatches to Library/brew.sh.

brew.sh sets up a whole bunch of the HomeBrew environment stuff, then it attempts to find a shell version of the command you’ve asked for. If a shell implementation can’t be found, it dispatches to this:

{ update-preinstall; exec "$HOMEBREW_RUBY_PATH" -W0 "$HOMEBREW_LIBRARY/brew.rb" "$@"; }

brew.rb attempt to find a ruby implementation of the command you’re looking for.

So, it looked like $HOMEBREW_RUBY_PATH is probably the thing that I need to research. How does it get set? In brew.sh, we can see the following code:

if [[ -z "$HOMEBREW_RUBY_PATH" ]]
 if [[ -n "$HOMEBREW_OSX" ]]
 HOMEBREW_RUBY_PATH="$(which ruby)"
 if [[ -z "$HOMEBREW_RUBY_PATH" ]]
 odie "No Ruby found, cannot proceed."

What’s super cool here is that we can see that on Max OS X, there’s an explicit requirement to use the system ruby. Rbenv and the like aren’t even _asked_ about what ruby they’re providing. As an aside, any budding hackers who’re interested may want to inject support for rbenv here.

What problem is this addressing? I suspect that the homebrew devs don’t want to have to support multiple versions of ruby on OS X. In fact, the commit that implements this reads:

Replace /usr/bin/ruby with full Framework path

Rationale: some users insist on replacing the /usr/bin/ruby symlink
 to point to another ruby on their system, which may break homebrew.
 Use the full Framework path instead, which is less likely to be tampered with.

This also reorganizes the brew --config checks to reflect the different path.

Fixes Homebrew/homebrew#12009.

Closes Homebrew/homebrew#12333.

To see why this was implemented, I checked the issues noted in the git log message.


That all seems reasonable enough. I had wondered if this was an issue of trying to reduce maintenance overhead, and it appears that it was.

Hacking on gist-logs. How do we get there?

Just through exploring the codebase a little, I can see that homebrew behaves a little differently if you have the environment variable HOMEBREW_DEVELOPER set. So that’s a neat little win.

I wanted to understand how brew dispatches all the way to gist-logs, so I could be sure I’m implementing a feature in the right place. I started out by just calling gist-logs with no arguments and received a handy error message:

usage: brew gist-logs [--new-issue|-n] <formula>

I searched for the string “–new-issue” in the brew codebase and found it’s only in the gist-logs.rb file. So that’s useful! I then got sidetracked trying to figure out why these two behaved differently:

[james@greentreeredsky brew (issue44706)]$ brew gist-logs
usage: brew gist-logs [--new-issue|-n] <formula>
b[james@greentreeredsky brew (issue44706)]$ brew gist-logs --help
Warning: No help text in: /usr/local/Library/Homebrew/cmd/gist-logs.rb
Example usage:
  brew search [TEXT|/REGEX/]
  brew (info|home|options) [FORMULA...]
  brew install FORMULA...
  brew update
  brew upgrade [FORMULA...]
  brew uninstall FORMULA...
  brew list [FORMULA...]

  brew config
  brew doctor
  brew install -vd FORMULA

  brew create [URL [--no-fetch]]
  brew edit [FORMULA...]

Further help:
  man brew
  brew help [COMMAND]
  brew home

It turns out homebrew has an internal help generation system! If you are writing a new tool, and you use a magic comment beginning with #:, then homebrew will automatically find the help.

Which means that the failure of the –help command is a defect! I’m an hour in and finding something to fix! Yay! I’m going to let myself get sidetracked by this, as it seems like an easy fix.

First, I added the following magic comment to the top of the file:

#: usage: brew gist-logs [--new-issue|-n] <formula>

Now both –help and no arguments behave the same, but at the cost of introducing duplication. I don’t want to introduce duplication, so I want to figure out how a different command handles both the case that someone enters the –help argument and that ARGV is empty.

Fortunately, I’m half way there. –help is handled by the magic comment and a little support in brew.rb. But the way that the empty ARGV is handled internally to gist-logs is with this little piece of logic:

 if ARGV.resolved_formulae.length != 1
  puts "usage: brew gist-logs [--new-issue|-n] <formula>"
  Homebrew.failed = true

So, I need to figure out how to remove that logic, and invoke the help system when there’s no arguments.

I checked the install.rb command to see how it handles this situation. It raises a FormulaUnspecifiedError exception, which is caught in brew.rb (FormulaUnspecifiedError inherits from UsageError). This dispatches to Homebrew#help, which displays the error message and the text from the FormulaUnspecifiedError exception and exits with 1. So changing the code to this seems reasonable:

raise FormulaUnspecifiedError if ARGV.resolved_formulae.length != 1

The problem here’s simple enough, though. The old implementation set Homebrew.failed = 1, but the new code does not set that. The question is, does that change matter?

From what I can tell, Homebrew.failed is used in brew.rb to simply do an “exit 1”. The help implementation also does an “exit 1”, so the command line contract is maintained, and because Homebrew.failed isn’t actually used anywhere in the new call chain, and it wasn’t _doing_ anything in the old call chain, I think the refactor is a win.

I’ll create a branch for this change and submit it to the dev team and see what they think.

And there’s the pull request: https://github.com/Homebrew/brew/pull/217

Hacking On Homebrew

I decided to work a little more independently on my ruby programming chops, and I wanted to be giving a little more back to the free software world, so I signed up for CodeTriage and picked Homebrew as the project I’ll look at. So far:

  • Code’s hosted on github, so that’s easy enough.
  • There’s a feature request against gist-logs that sounds simple enough to start with (https://github.com/Homebrew/legacy-homebrew/issues/44706), and it’s what codetriage recommended anyway.
  • It looks like cloning the remote repo and then just using the brew command in $HOMEBREW_DIR/bin/brew is enough that you can start hacking away on a local copy of the codebase.
  • I haven’t reached out to the devs on the google groups channel yet, but I’ll probably try that later today.
  • The dispatch chain when looking for a script is $HOMEBREW_DIR/bin/brew –> $HOMEBREW_DIR/Library/brew.sh –> $HOMEBREW_DIR/Library/brew.rb
  • rubocop fails the project on its own style guidelines (I think inappropriately, because most of the violations are in formulae not in core, but I’ll ask the dev team)

So, this is kind of fun!