Open Up Your Open Source Module – Part 3: CODE_OF_CONDUCT File

This is Part 3 of a 5 part series.  Links to other parts (as they become available) are below.

We’ve previously talked about adding the CONTRIBUTING and TODO files, so now we’ll get to the post I’ve been dreading: the CODE_OF_CONDUCT file. I believe strongly in the value of codes of conduct, and think every project should have one.

So, why would I dread it?

Continue reading

Open Up Your Open Source Module – Part 2: TODO File

This is Part 2 of a 5 part series.  Links to other parts (as they become available) are below.

So, you’ve added a CONTRIBUTING file to your module (in part 1).  That’s great! Now people know the ground rules for contributing to your module.  But there is another thing you can do to encourage the contributions you want: Simply tell the potential developer what changes you might appreciate.

Continue reading

Open Up Your Open Source Module – Part 1: CONTRIBUTING File

You’ve written something awesome! You want to release it as open source software into the world.  And, you hope other people will want to polish the rough edges, oil the squeaking hinge, and translate the help text into Klingon. Assuming that your module is interesting to people, how do you help them help you? I’ll give examples of how to do this in the context of Perl 5 modules, but they’ll work in other languages, too.

I talked about this in a lightning talk @ The Perl Conference 2018

But I also thought I could expand and organize my thoughts a bit better, so for the textually inclined, read on!

This is part one of a five part series.  I’ll link them all here when they are up.

Continue reading

Making PAR::Packer Work with RPM

I needed to distribute some RPMs with a PAR::Packer created (using pp) executable.

If you don’t know what PAR::Packer is, it is the incredibly awesome Perl 5 utility that allows you to create an executable that contains your Perl interpreter, your code, and any libraries you need.  It’s basically one of the ways you have to escape dependency hell with Perl – you can use all the wonderful CPAN modules without fear. You can use the new features of recent versions of Perl (such as subroutine signatures and enhanced performance), without worrying about what version of Perl is installed on someone else’s machine. You don’t need to worry about missing core modules in Fedora and other platforms (Fedora is missing autodie – an essential module for lazy programmers).  So building an archived executable is a great way to distribute Perl apps to people not comfortable with the Perl toolchain.

You can think of it like a Perl compiler (it’s not, but the distinction isn’t terribly important for this context).

It’s a somewhat finicky beast, and can take some effort to get it to package things the way you need them, but it’s a standard trick of the trade when I can’t just use perlbrew to build what I want on a machine. It certainly is a lot quicker to install a single executable than to compile and test hundreds of CPAN modules!

So, it seems natural to combine this with RPM. This way, users can install my stuff just by doing a simple rpm --install <file>.rpm – that’s awesome.  Well, it would be, but building an RPM with a PAR::Packer built executable doesn’t actually work, at least not on Red Hat Enterprise Linux 5 (RHEL5) or RHEL6.

Let me explain….

Take this script, hello.pl:

#!/usr/bin/env perl

use v5.22; # Use perl 5.22's features
use strict;
use warnings;

use autodie; # This causes issues on Fedora out of the box

MAIN: {
    say reverse (split //, "!dlroW olleH");
}

If I run it on most distributions, line 3 will give me an error (the OS Perl isn’t new enough). On Red Hat/Fedora installs, if I changed line 3 to support older perl interpreters, the inclusion of autodie in line 7 will error out, unless that module has already been installed.

For instance:

perldemo:demo$ ./hello.pl
Perl v5.22.0 required--this is only v5.18.2, stopped at hello.pl line 3.
BEGIN failed--compilation aborted at hello.pl line 3.

Of course it works fine when I use my local perl interpreter (a perlbrew-built 5.22.1):

perldemo:demo$ perl hello.pl
Hello World!

So, I can create a packed executable, which runs great (at least on other systems with the same system libraries – the same limitations a an executable you dynamically link and build using C):

perldemo:demo$ pp -o hello hello.pl
perldemo:demo$ ./hello
Hello World!

Perfect! Note that I ran the executable hello, not hello.pl. The hello file is a self-contained executable that doesn’t depend on the system perl.

So what happens when I put this in an RPM package?  I won’t go through the steps of building an RPM, but will let you see what error you will get when you try running the executable:

perldemo:demo$ ./hello
Usage: ./hello [ -Alib.par ] [ -Idir ] [ -Mmodule ] [ src.par ] [ program.pl ]
./hello [ -B|-b ] [-Ooutfile] src.par

What the heck? It’s expecting a PAR file to be passed to it – the PAR, or Perl ARchive, of course contains the perl interpreter, your code, and your modules – for some reason the file can’t find it.

You can duplicate this without RPM by using strip on the output of pp on Linux:

perldemo:demo$ pp -o hello hello.pl
perldemo:demo$ ./hello
Hello World!
perldemo:demo$ strip ./hello
perldemo:demo$ ./hello
Usage: ./hello [ -Alib.par ] [ -Idir ] [ -Mmodule ] [ src.par ] [ program.pl ]
./hello [ -B|-b ] [-Ooutfile] src.par

What is going on? The strip removes debugging information and the like, but generally isn’t expected to change how your program runs – but in this case it seems to be removing a lot more. Running this same strip on OSX (Apple) is enlightening:

perldemo:demo$ strip hello
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/strip: the __LINKEDIT segment does not cover the end of the file (can't be processed) in: /Users/jmaslak/pp/hello
perldemo:demo$ ./hello
Hello World!

So it appears Macs won’t strip the archive out of the extraction executable produced by pp – but Linux has no problem happily stripping it.

It turns out that standard configurations of rpmbuild on at least RHEL5 and RHEL6 automatically strip all binaries in the binary package (that’s the “standard” package you would install).

So how do you disable this evil? It turns out it’s not easy. On RHEL6, you add this near the top of your SPEC file (the SPEC file rpmbuild uses to create the RPM):

%global __os_install_post %{nil}

Now, rpmbuild won’t strip the file. But this doesn’t help RHEL5. So I added another line, that did what I want (assuming I don’t need a debug package, which I don’t in this case):

%define debug_package %{nil}
%global __os_install_post %{nil}

Sure enough, now my code does exactly what I want, even when I install the PAR executable via RPM:

perldemo:demo$ ./hello
Hello World!

Whew!

A Fix for Perl SSL on MacOS X 10.11

UPDATE (August 12, 2017) – Check out Tom Vander Aa’s comment in the comments. His solution is better than my solution in the original post – it has much less chance of breaking other stuff that uses OpenSSL.

ORIGINAL:

When trying to install some Perl Programming Language modules on MacOS X, using a perlbrew-built perl, I was getting some weird linking errors with various OpenSSL headers.  Here’s an example from Net::SSLeay:

laptop$ cpan install Net::SSLeay
...
Configuring M/MI/MIKEM/Net-SSLeay-1.72.tar.gz with Makefile.PL
CPAN::Reporter not installed.  No reports will be sent.
*** Found OpenSSL-0.9.8z installed in /usr
*** Be sure to use the same compiler and options to compile your OpenSSL, perl,
    and Net::SSLeay. Mixing and matching compilers is not supported.
...
cc -c   -fno-common -DPERL_DARWIN -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -O3   -DVERSION=\"1.72\" -DXS_VERSION=\"1.72\"  "-I/Users/jmaslak/perl5/perlbrew/perls/perl-5.22.1/lib/5.22.1/darwin-2level/CORE"   SSLeay.c
SSLeay.xs:163:10: fatal error: 'openssl/err.h' file not found
#include <openssl/err.h>
         ^
1 error generated.
make: *** [SSLeay.o] Error 1
  MIKEM/Net-SSLeay-1.72.tar.gz
  /usr/bin/make -- NOT OK

I highlighted the interesting parts – I run homebrew on my Mac to manage development tools and the like. Sure enough, it had installed openssl already:

laptop$ brew install openssl
Warning: openssl-1.0.2e already installed

Hmmm, version 1.0.2e, which doesn’t look like the 0.9.8z that Net::SSLeay found.

A bit of Googling and scratching my head and I found the magic incantation:

laptop$ brew link openssl --force

Once that was done, I could successfully install Net::SSLeay and other SSL Perl modules.  I’m guessing that the links broke sometime during an OS upgrade. Hopefully this post will save you a bit of time!

Perl is Good for Nothing

I love Perl – and the perl interpreter always impresses me.  Today, I decided to try a few languages to see how they compare.

How well does the language do nothing?  I decided to test this out on my fairly speedy Macbook Pro.  All tests were executed multiple times and the best result was used for this post, to account for various caching speedups.

First, C:

do-nothing$ touch nothing.c
do-nothing$ time clang nothing.c
Undefined symbols for architecture x86_64:
  "_main", referenced from:
     implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

real	0m0.041s
user	0m0.017s
sys	0m0.017s

So, C can spit out an error that will probably not make sense to people new to the language (it’s missing a main function, although usually you’ll define main without a leading underscore – for reasons I won’t get into here).  But it was fairly quick – about 40ms (I repeated this several times to account for caching).

Next I tried Java (using the SunOracle implementation):

do-nothing$ touch nothing.java
do-nothing$ time javac nothing.java

real 0m0.759s
user 0m1.323s
sys 0m0.105s

Java doesn’t throw any errors, but it takes over 750ms to compile nothing (in a somewhat satisfyingly mathematically pure way, it literally produces nothing – no output files are created). When I ran javac with the -verbose option (how a Unix workstation company would think long options with a single hypen are okay is beyond me, but I digress), it spits out some timing information. It takes 23ms to parse nothing and roughly 290ms to do the compilation. I can only assume the other 450ms or so are going to compiler startup overhead.

How about Ruby?

do-nothing$ touch nothing.rb
do-nothing$ time ruby nothing.rb

real 0m0.073s
user 0m0.053s
sys 0m0.010s
do-nothing$

It takes 73ms to do nothing, but it does properly do nothing.

How about Python (v2)?

do-nothing:t$ touch nothing.py
do-nothing:t$ time python nothing.py

real 0m0.018s
user 0m0.009s
sys 0m0.007s

Python does nothing pretty darn well – 18ms!

Now, my language of choice, Perl 5:

do-nothing$ touch nothing.pl
do-nothing$ time perl nothing.pl

real 0m0.006s
user 0m0.002s
sys 0m0.003s
do-nothing$

Brilliant – it does nothing very quickly compared to other languages – 6ms.

That said, my old version (Christmas) of the Rokudo-based Perl 6 takes roughly 250ms – not all that good. I’m not sure how the newer versions do. It’s certainly a powerful new language (you should think of Perl 5 and Perl 6 as distinct language – both are being actively developed with new features, optimizations, bug fixes, etc, added to both continually, with no plans to discontinue development on either).

So, It think, in conclusion:

  • C isn’t good for nothing
  • Java can’t do nothing quickly
  • Perl 6 can do nothing, but not too quickly
  • Ruby seems okay for nothing, while Python 2 is pretty darn good at nothing
  • Perl 5 is good for nothing!

(Yes, this post is 90% jest – startup time of the tools is important, but is almost always a dumb reason to pick a language)