Monday, November 7, 2011

perl development on OSX - installing cpan modules

I learned my lesson on my last MacBook when three years into ownership I decided I wanted to do some development locally, but I had lost the developer's DVD that came with the laptop, and downloading 10 gigs cleanly over DSL was pretty much impossible. So when I got my new MacBookPro, I immediately installed the developer's DVD.

Fast forward a few months, and I try to download and install Selenium's perl bindings from github. Make for this package was failing because of dependency issues,  and cpan was failing in all sorts of noisy ways...it's a pretty sad state of affairs when "cpan> install CPAN::Bundle" doesn't work.

Someone pointed me at macports.org, which got me a little bit further, but some of the packages needed by Selenium weren't available as macports.

It took some more poking around before I was able to isolate a couple of simple use cases (as opposed to hopelessly interconnected dependencies). My use cases were "cpan> install Cwd" and "cpan> install Data::Dumper". Cwd is a utility to determine the current working directory that is used over and over again by cpan while installing things. Data::Dumper is a common utility for dumping objects and structures in printable format.

installing Cwd was failing with the following messages:
/usr/bin/perl /Library/Perl/Updates/5.10.0/ExtUtils/xs
ubpp -typemap /System/Library/Perl/5.10.0/ExtUtils/typemap Cwd.xs > Cwd.xsc && mv Cwd.xsc Cwd.c
gcc-4.2 -c -arch x86_64 -arch i386 -arch ppc -g -pipe -fno-common -DPERL_DARWIN -fno-strict-aliasing -I/usr/local/include -Os -DVERSION=\"3.33\" -DXS_VERSION=\"3.33\" "-I/System/Library/Perl/5.10.0/darwin-thread-multi-2level/CORE" Cwd.c
/usr/libexec/gcc/powerpc-apple-darwin10/4.2.1/as: assembler (/usr/bin/../libexec/gcc/darwin/ppc/as or /usr/bin/../local/libexec/gcc/darwin/ppc/as) for architecture ppc not installed
Installed assemblers are:
/usr/bin/../libexec/gcc/darwin/x86_64/as for architecture x86_64
/usr/bin/../libexec/gcc/darwin/i386/as for architecture i386
lipo: can't open input file: /var/tmp//ccjnJSPb.out (No such file or directory)
make: *** [Cwd.o] Error 2
SMUELLER/PathTools-3.33.tar.gz
/usr/bin/make -- NOT OK

So it's looking for an assembler for the ppc architecture. Why do I need to support the ppc architecture? Current versions of OSX don't support that hardware anymore. Well, the answer appears to be because Apple compiled the version of perl it distributes on the developer DVD to work on all possible platforms, including ppc. CPAN modules (that are dependent on c) are set up in such a way that they expect to be built using the same flags as the perl distribution was built with. In theory, CPAN has an  option where you can specify what flags should be used for compilation. Unfortunately, it does not allow you to set the flags for assembly.

My choices became:
  1. re-build perl without the ppc architecture
  2. hand-build the packages I need
  3. hack the system
I chose option 2, although I expect I will need to go with option 1 in the long term.  Here is what I did:
  1. Try to install the thing you need the usual way. Take note of which packages fail (there should be a list at the end of the cpan output).
  2. Go to the cpan website and manually download the packages that failed. More likely than not, your browser will suggest you open them with the archive utility. It will unpack them and put them in ~/Downloads/<package-name>.
  3. At a shell prompt, go to a package's download directory
  4. Run "perl Makefile.PL" (Generates the Makefile specific to your machine)
  5. Edit "Makefile", remove all occurrences of "-arch ppc". (If you're using vi, :%/-arch ppc// )
  6. Run "make" (this is the stage that was failing inside of cpan)
  7. Run "make test" (make sure it actually works before deploying)
  8. Run "sudo make install" (if you do not sudo, it won't have the permissions to actually install the files)
  9. Run "make clean" (optional, cleans up after make process)
  10. Repeat for each package
  11. After you've installed each of the packages, go back to step one and try it again. It should either run through without errors or tell you that the thing you are trying to install is already up-to-date.
 The friends who helped me troubleshoot this issue are debating the merits of option 3, if/when I decide option 1 is the way to go, you can expect an action report here.

On Sabbatical

I started my career in high tech in Israel, where there is a strong tradition of sabbaticals that stems from the Jewish religion. A common perk of white collar jobs is an education fund that one can tap after 7 years, or 3 or 4 years if being used for official education expenses. I did not live in Israel long enough to take advantage of this fund, but I think there is something there I should learn from.

I am taking a sabbatical with the intention of improving my technical skills, doing some career networking, and establishing an exercise routine.

During my sabbatical I hope to:
  • set up my Macbook as a development environment
  • learn Selenium's new WebDriver interface
  • contribute to an open source project
  • learn python
  • learn ruby
I am not sure how long my sabbatical will run, but I hope that by the time I decide it's time to go back to work, I will have at least one new accomplishment to add to my resume.

Monday, July 18, 2011

there is more than one way to make sure a variable has a value

if (!$variable1) {
    $variable1 = 'default';
}

unless (defined($variable2)) {
    $variable2 = 'default';
}
can be done much more quickly as
$variable1 ||= 'default'; # true or
$variable2 //= 'default'; # defined or
i prefer the second

Friday, July 15, 2011

there is more than one way to access the parameters of the method you just called

sub my_function {
    my $val1 = shift();
    my $val2 = shift();
    my $val3 = shift();

    ...

}
does the same thing as
sub my_function {
    my $val1 = @_->[0];
    my $val2 = @_->[1];
    my $val3 = @_->[2];

    ...

}
but my favorite is
sub my_function {
    my ( $val1, $val2, $val3 ) = @_;

    ...
}