Monday 27 June 2011

qrcode generator with perl

There are some good pages for genereating QRcode and a lot of not so good ones. There are probably to many to decide which one to use so I decided to create yet another one:
pmg-qrcode




I have used
HTML::QRCode
Imager::QRCode



[...]
use Imager::QRCode;
use HTML::QRCode;

[...]

sub get_html_qr {
  my $text = shift;
  my $qrcode = HTML::QRCode->new->plot($text);
  return $qrcode;
}

sub print_qrimage {
  my $text = shift;
  my $imga_type = shift || 'png';
  my $qr = Imager::QRCode->new(
      size  =>  5,
      level => 'M',
    );

  $qr->plot($text)->write( fh => \*STDOUT, type => $img_type);
}


This is very simple, but .....
the difficult part is to have them working because the prerequisites not very well explained.

If you read the README for HTML::QRCode it says that it works out of the box with an standard cpan install. Well that is true if you have already Text::QRCode, that usually is not the case. Don't panic, lets install T::QRC and all will be fine. Humm... Marvin still depressed. Despite T::QRC also telling you about doing a standard install and all will go OK, again, that will only be true if you have all prerequisites already installed and in the default place. T::QRC needs libqrencode headers and libs and look for them at the root installed paths. The README does not say anything about this but the description of T::QRC gives a hint
DESCRIPTION ^
This module allows you to generate QR Code using ' ' and '*'. 
This module use libqrencode '2.0.0' and above.  

To make the long story short, I tried to install HTML::QRCode in my local-lib environment and failed because Text::QRCode missing. I tried to install T::QRC and failed because no lib-qrencode. Installed locally lib-qrencode and not able to install T::QRC because not knowing how to pass a 'prefix' option to Makefile.pl for the ld_lib and includes. Solved editing the Makefile.PL manually, adding an env-var for LD_RUN_PATH and install manually T::QRC and then cpan install of HTML::QRCode.

Long story:

HTML::QRCode needs Text::QRCode and Text::QRCode needs lib-qrencode:

HTML::QRCode:
t/00-load.t .. 1/1
        #   Failed test 'use Text::QRCode;'
        #   at t/00-load.t line 6.
        #     Tried to use 'Text::QRCode'.
        #     Error:  Can't load '/homes/pmg/.cpan/build/Text-QRCode-0.01-n4g2CG/blib/arch/auto/Text/QRCode/QRCode.so' for module Text::QRCode: libqrencode.so.3: cannot open shared object \
file: No such file or directory at /homes/pmg/pmg-soft/local-perl/lib/5.12.1/x86_64-linux/DynaLoader.pm line 200

I searched for libqrencode and download it:

# download
wget http://fukuchi.org/works/qrencode/qrencode-3.1.1.tar.gz
# extract
# install
[~/pmg-soft/src/qrencode-3.1.1]
$  ./configure --prefix=$HOME/pmg-soft
$ make
$ make install

And obtained a helpful message that I save for later:

----------------------------------------------------------------------
Libraries have been installed in:
/homes/pmg/pmg-soft/lib

If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the `-LLIBDIR'
flag during linking and do at least one of the following:
- add LIBDIR to the `LD_LIBRARY_PATH' environment variable
during execution
- add LIBDIR to the `LD_RUN_PATH' environment variable
during linking
- use the `-Wl,-rpath -Wl,LIBDIR' linker flag
- have your system administrator add LIBDIR to `/etc/ld.so.conf'

See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.
----------------------------------------------------------------------

Now I have a T::QRC build extracted somewhere (I can see the path in the error message) [ Error: Can't load '/homes/pmg/.cpan/build/Text-QRCode-0.01-n4g2CG/blib/arch/auto/Text/QRCode/QRCode.so'].

I went there and read the Makefile.PL. It has two places (includes and ld-lib) where I need to add the path for my local lib-qrencode files:

a) the directives for the Makefile

sub MY::post_constants {
  [...]
  return <<"POST_CONST";
  CCFLAGS += $define -I/homes/pmg/pmg-soft/include
  LDDLFLAGS += -L/homes/pmg/pmg-soft/lib -lqrencode
  LDFLAGS += -L/homes/pmg/pmg-soft/lib -lqrencode
  POST_CONST
}
b) the comand for testing that the lib-qrencode exist (testing existence by compilation success)
sub test_libqrencode {
  my $compile_cmd
        = 'cc -I/homes/pmg/pmg-soft/include -I/usr/local/include -I/usr/include -L/homes/pmg/pmg-soft/lib -L/usr/lib -L/usr/local/lib -lqrencode';
  [..]
}
Then exported the environmental variable 'LD_RUN_PATH':
export LD_RUN_PATH=/homes/pmg/pmg-soft/lib
$ make clean
$ perl Makefile.PL 
| Cannot determine perl version info from lib/Text/QRCode.pm
| Checking if your kit is complete...
| Looks good 
| Writing Makefile for Text::QRCode
$ make          
$ make test
| PERL_DL_NONLAZY=1 /homes/pmg/pmg-soft//local-perl/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(0, 'inc', 'blib/lib', 'blib/arch')" t/00-load.t t/01-plot.t
| t/00-load.t .. 1/1 # Testing Text::QRCode 0.01, Perl 5.012001, /homes/pmg/pmg-soft//local-perl/bin/perl
| t/00-load.t .. ok
| t/01-plot.t .. ok
| All tests successful.
| Files=2, Tests=3,  0 wallclock secs ( 0.02 usr  0.03 sys +  0.06 cusr  0.04 csys =  0.15 CPU)
| Result: PASS
$ make install
|Files found in blib/arch: installing files in blib/lib into architecture dependent library tree
|Installing /homes/pmg/pmg-soft/local-perl/local-lib/lib/perl5/x86_64-linux/auto/Text/QRCode/QRCode.so
|Installing /homes/pmg/pmg-soft/local-perl/local-lib/lib/perl5/x86_64-linux/auto/Text/QRCode/QRCode.bs  
|Installing /homes/pmg/pmg-soft/local-perl/local-lib/lib/perl5/x86_64-linux/Text/QRCode.pm
|Installing /homes/pmg/pmg-soft/local-perl/local-lib/man/man3/Text::QRCode.3
|Appending installation info to /homes/pmg/pmg-soft/local-perl/local-lib/lib/perl5/x86_64-linux/perllocal.pod

Then go to cpan and intall HTML::QRCode
cpan[2]> install HTML::QRCode 

That's all, happy hacking.


Pablo

1 comment:

Anonymous said...

Another option is HTML::Barcode::QRCode.

First install libqrencode (e.g. `apt-get install libqrencode-dev`), then simply `cpanm HTML::Barcode::QRCode`