Building C/C++ libraries with Perl

    Alberto Manuel Brand˜o Sim˜es
                        a     o
            ambs@perl.pt



           YAPC::EU::2012




        Alberto Sim˜es
                   o     Building C/C++ libraries with Perl
Disclaimer



                              This is my point of view;

                              This is not the best approach. . .
                                    . . . surely . . .
                                    . . . just not sure what it is!

                              This is the way I decided to go. . .

                              And it is working (so far!)




             Alberto Sim˜es
                        o      Building C/C++ libraries with Perl
Standard Source Packaging




                             Perl modules are not a problem.

                             C/C++ libraries or apps are usually:
                                   bundled with a autoconf script;
                                   bundled with a cmake;




                  Alberto Sim˜es
                             o     Building C/C++ libraries with Perl
AutoTools


                       The autotools are the most used, but:
                             not portable (check Windows);
                             a mess:
                             Perl script that processes a DSL that
                             includes references to M4 macros,
                             and Shell snippets, and generate a
                             shell script. It also interpolates
                             makefiles, and other crazy stuff.

                       Most macros are copy & paste from
                       other projects

                       Few people really understand them



            Alberto Sim˜es
                       o     Building C/C++ libraries with Perl
AutoTools Dependencies

     To use AutoTools we need:
         AutoConf;
         AutoMake;
         LibTool;
         Perl;
         shell;
     I know end-users should only require sh. Is that really true?




                       Alberto Sim˜es
                                  o     Building C/C++ libraries with Perl
Hey, u said Perl?
Use Perl as a Build System


                              Use Perl as a Build System.
                              What are the (my) options?
                                         ExtUtils::MakeMaker;
                                         Module::Build;

      ExtUtils::MakeMaker is not suitable:
          Constructing a Makefile string is error prone;
          Most system detection needs to be defined at configure time;
      Module::Build is easy to subclass:
          Gives all the power of Perl (that can be bad);
          Easier to develop and debug.




                        Alberto Sim˜es
                                   o        Building C/C++ libraries with Perl
Use Perl as a Build System


                              Use Perl as a Build System.
                              What are the (my) options?
                                         ExtUtils::MakeMaker;
                                         Module::Build;

      ExtUtils::MakeMaker is not suitable:
          Constructing a Makefile string is error prone;
          Most system detection needs to be defined at configure time;
      Module::Build is easy to subclass:
          Gives all the power of Perl (that can be bad);
          Easier to develop and debug.




                        Alberto Sim˜es
                                   o        Building C/C++ libraries with Perl
What more do I need?

                   ExtUtils::CBuilder
                   Something that helps compiling C/C++ code
                   ExtUtils::ParseXS
                   Something that helps me parse XS files
                   ExtUtils::Mkbootstrap
                   Something to create DynaLoader bootstrap
                   files
                   ExtUtils::PkgConfig or PkgConfig
                   Something to detect libs that ship a .pc file
                   Config::AutoConf
                   Something that helps me detecting other
                   libraries. . .
                   ExtUtils::LibBuilder
                   Something that knows how to link a standard
                   library
                  Alberto Sim˜es
                             o     Building C/C++ libraries with Perl
The Nuts and Bolts




                     Alberto Sim˜es
                                o     Building C/C++ libraries with Perl
Case Study 1

  Lingua::Jspell
      A Morphological Analyzer for NLP;
      It is a standard C app based on ispell code;
      It includes Perl bindings (through Open3 atm);
      There is no real reason to bundle the app with the Perl
      module.
  The build chain uses:
      Module::Build;
      ExtUtils::CBuilder;
      ExtUtils::LibBuilder;
      Config::AutoConf;


                          Alberto Sim˜es
                                     o     Building C/C++ libraries with Perl
Case Study 1

  Lingua::Jspell
      A Morphological Analyzer for NLP;
      It is a standard C app based on ispell code;
      It includes Perl bindings (through Open3 atm);
      There is no real reason to bundle the app with the Perl
      module.
  The build chain uses:
      Module::Build;
      ExtUtils::CBuilder;
      ExtUtils::LibBuilder;
      Config::AutoConf;


                          Alberto Sim˜es
                                     o     Building C/C++ libraries with Perl
Case Study 1


  Config::AutoConf is used to:


       Detect libraries and headers (in Build.PL):
      §                                                                             ¤
          Config : : AutoConf−>check_header ( ” n c u r s e s . h ” ) ;
          Config : : AutoConf−>check_lib ( ” n c u r s e s ” , ”t g o t o ” ) ;
      ¦                                                                             ¥




  More details on the Build.PL script in the article.



                              Alberto Sim˜es
                                         o     Building C/C++ libraries with Perl
Case Study 1
  I subclass Builder redefining methods:
 §                                                                                     ¤
  sub ACTION_code {
    my $self = s h i f t ;

      # c r e a t e t h e L i b B u i l d e r o b j e c t and c a c h e i t
      $self−>notes ( libbuilder => ExtUtils : : LibBuilder−>new ) ;

      # d i s p a t c h e v e r y needed a c t i o n
      $self−>dispatch ( ” c r e a t e b l i b f o l d e r s ” ) ;
      $self−>dispatch ( ”c r e a t e m a n p a g e s ” ) ;
      $self−>dispatch ( ” c r e a t e y a c c ” ) ;
      $self−>dispatch ( ” c r e a t e o b j e c t s ” ) ;
      $self−>dispatch ( ” c r e a t e l i b r a r y ” ) ;
      $self−>dispatch ( ” c r e a t e b i n a r i e s ” ) ;

      # and now , c a l l s u p e r c l a s s .
      $self−>SUPER : : ACTION_code ;
  }
 ¦                                                                                     ¥

                               Alberto Sim˜es
                                          o       Building C/C++ libraries with Perl
Case Study 1

  The create yacc action also uses Config::AutoConf
 §                                                                                    ¤
  sub ACTION_create_yacc {
    my $self = s h i f t ;

      my $ytabc = ’ s r c / y . t a b . c ’ ;
      my $parsey = ’ s r c / p a r s e . y ’ ;

      r e t u r n i f $self−>up_to_date ( $parsey , $ytabc ) ;

      my $yacc = Config : : AutoConf−>check_prog ( ”y a c c ” ,
                                                   ”b i s o n ” ) ;
      i f ( $yacc ) {
         ‘ $yacc −o $ytabc $parsey ‘ ;
      }
  }
 ¦                                                                                    ¥



                               Alberto Sim˜es
                                          o      Building C/C++ libraries with Perl
Case Study 1
  Build object files (plain ExtUtils::CBuilder usage):
 §                                                                               ¤
  sub ACTION_create_objects {
    my $self = s h i f t ;

      my $cbuilder = $self−>cbuilder ;
      my $c_files = $self−>rscan_dir ( ’ s r c ’ , qr /  . c$ / ) ;
      my $xtr_comp_flags = ”−g ” . $self−>notes ( ’ c c u r s e s ’ ) ;

      f o r my $file ( @$c_files ) {
           my $object = $file =˜ s /  . c / . o/r ;
           n e x t i f $self−>up_to_date ( $file , $object ) ;

          $cbuilder−>compile ( object_file => $object ,
                               source       => $file ,
                               include_dirs => [ ” s r c ” ] ,
                               extra_compiler_flags =>
                                        $xtr_comp_flags ) ;
      }
  }
 ¦                                                                               ¥
                           Alberto Sim˜es
                                      o     Building C/C++ libraries with Perl
Case Study 1
  And the main stuff, build a standard library
 §                                                                                 ¤
  sub ACTION_create_library {
    my $self = s h i f t ;
    my $libbuilder = $self−>notes ( ’ l i b b u i l d e r ’ ) ;
    ...
    # d e f i n e the l i n k e r f l a g s
    my $xlinkerflags = $self−>notes ( ’ l c u r s e s ’ )
                              . $self−>notes ( ’ c c u r s e s ’ ) ;
    i f ( $ˆO =˜ / darwin / ) {
       $xlinkerflags .= ” − i n s t a l l n a m e $ l i b p a t h ” }

     # l i n k i f t h e l i b r a r y i s n o t up t o d a t e
     i f ( ! $self−>up_to_date (  @objs , $libfile ) ) {
        $libbuilder−>l i n k ( module_name => ’ l i b j s p e l l ’ ,
                       extra_linker_flags => $xlinkerflags ,
                       objects =>  @objects ,
                       lib_file => $libfile ) ;
     }
     ...
 ¦                                                                                 ¥
                             Alberto Sim˜es
                                        o     Building C/C++ libraries with Perl
Case Study 1
  And build the C binaries.
 §                                                                                         ¤
     sub ACTION_create_binaries {
       my $self = s h i f t ;
       my $libbuilder = $self−>notes ( ’ l i b b u i l d e r ’ ) ;
       ...
       # define flags
       my $extralinkerflags = $self−>notes ( ’ l c u r s e s ’ )
                                   . $self−>notes ( ’ c c u r s e s ’ ) ;
       ...
       # i f needed , l i n k t h e e x e c u t a b l e
       i f ( ! $self−>up_to_date ( $object , $exe_file ) ) {
             $libbuilder−>link_executable (
                  exe_file => $exe_file ,
                  objects => [ $object ] ,
                  extra_linker_flags =>
                       ”−L s r c − l j s p e l l $ e x t r a l i n k e r f l a g s ” ) ;
       }
       ...
 ¦                                                                                         ¥

                                Alberto Sim˜es
                                           o     Building C/C++ libraries with Perl
Case Study 1
  Work out a testing environment.
 §                                                                                      ¤
  sub ACTION_test {
    my $self = s h i f t ;

      i f ( $ˆO =˜ / mswin32 /i ) {
          $ENV { PATH } = $self−>blib . ”/ u s r l i b ; $ENV{PATH} ” ;
      }
      e l s i f ( $ˆO =˜ / darwin /i ) {
          $ENV { DYLD_LIBRARY_PATH } = $self−>blib . ”/ u s r l i b ” ;
      }
      e l s i f ( $ˆO =˜/linux | bsd | sun | sol | dragon | hpux | irix /i ) {
          $ENV { LD_LIBRARY_PATH } = $self−>blib . ”/ u s r l i b ” ;
      }
      e l s i f ( $ˆO =˜ / aix /i ) {
         my $oldlibpath = $ENV { LIBPATH } | | ’ / l i b : / u s r / l i b ’ ;
          $ENV { LIBPATH } = $self−>blib . ”/ u s r l i b : $ o l d l i b p a t h ” ;
      }
      $self−>SUPER : : ACTION_test
  }
 ¦                                                                                      ¥
                               Alberto Sim˜es
                                          o     Building C/C++ libraries with Perl
Case Study 2

  Lingua::Identify::CLD
      Interface to Google’s Compact Language Detector;
      It bundles a standard C++ library;
      It includes Perl bindings (through XS);
  The build chain uses:
      Module::Build;
      ExtUtils::CBuilder;
      ExtUtils::LibBuilder;
      Config::AutoConf;
      ExtUtils::ParseXS;
      ExtUtils::Mkbootstrap;


                          Alberto Sim˜es
                                     o     Building C/C++ libraries with Perl
Case Study 2

  Lingua::Identify::CLD
      Interface to Google’s Compact Language Detector;
      It bundles a standard C++ library;
      It includes Perl bindings (through XS);
  The build chain uses:
      Module::Build;
      ExtUtils::CBuilder;
      ExtUtils::LibBuilder;
      Config::AutoConf;
      ExtUtils::ParseXS;
      ExtUtils::Mkbootstrap;


                          Alberto Sim˜es
                                     o     Building C/C++ libraries with Perl
Case Study 2
  Compiling XS code as... standard XS code (mostly)
 §                                                                                          ¤
  sub ACTION_compile_xscode {
    ...
    # c r e a t e CLD . c c from CLD . x s
    ExtUtils : : ParseXS : : process_file ( . . . ) ;

     # c r e a t e CLD . o from CLD . c c
     $cbuilder−>compile ( . . . ) ;

     # C r e a t e . b s b o o t s t r a p f i l e , n e e d e d by D y n a l o a d e r .
     ExtUtils : : Mkbootstrap : : Mkbootstrap ( . . . ) ;

     # set linker flags
     my $xlinkerflags = ”−L c l d −s r c − l c l d − l s t d c++” ;
     $xlinkerflags .= ” − l g c c s ” i f $ˆO eq ’ n e t b s d ’ ;

     # link
     $cbuilder−>l i n k ( . . . ) ;
 ¦                                                                                          ¥

                                 Alberto Sim˜es
                                            o      Building C/C++ libraries with Perl
Concluding




     It works!
     The process is similar for all modules;
     Then, this can be generalized in a module;
     Works on UNIX systems;
     Works on Strawberry Win32;




                       Alberto Sim˜es
                                  o     Building C/C++ libraries with Perl
Thank you!




             Alberto Sim˜es
                        o     Building C/C++ libraries with Perl

Building C and C++ libraries with Perl

  • 1.
    Building C/C++ librarieswith Perl Alberto Manuel Brand˜o Sim˜es a o ambs@perl.pt YAPC::EU::2012 Alberto Sim˜es o Building C/C++ libraries with Perl
  • 2.
    Disclaimer This is my point of view; This is not the best approach. . . . . . surely . . . . . . just not sure what it is! This is the way I decided to go. . . And it is working (so far!) Alberto Sim˜es o Building C/C++ libraries with Perl
  • 3.
    Standard Source Packaging Perl modules are not a problem. C/C++ libraries or apps are usually: bundled with a autoconf script; bundled with a cmake; Alberto Sim˜es o Building C/C++ libraries with Perl
  • 4.
    AutoTools The autotools are the most used, but: not portable (check Windows); a mess: Perl script that processes a DSL that includes references to M4 macros, and Shell snippets, and generate a shell script. It also interpolates makefiles, and other crazy stuff. Most macros are copy & paste from other projects Few people really understand them Alberto Sim˜es o Building C/C++ libraries with Perl
  • 5.
    AutoTools Dependencies To use AutoTools we need: AutoConf; AutoMake; LibTool; Perl; shell; I know end-users should only require sh. Is that really true? Alberto Sim˜es o Building C/C++ libraries with Perl
  • 6.
  • 7.
    Use Perl asa Build System Use Perl as a Build System. What are the (my) options? ExtUtils::MakeMaker; Module::Build; ExtUtils::MakeMaker is not suitable: Constructing a Makefile string is error prone; Most system detection needs to be defined at configure time; Module::Build is easy to subclass: Gives all the power of Perl (that can be bad); Easier to develop and debug. Alberto Sim˜es o Building C/C++ libraries with Perl
  • 8.
    Use Perl asa Build System Use Perl as a Build System. What are the (my) options? ExtUtils::MakeMaker; Module::Build; ExtUtils::MakeMaker is not suitable: Constructing a Makefile string is error prone; Most system detection needs to be defined at configure time; Module::Build is easy to subclass: Gives all the power of Perl (that can be bad); Easier to develop and debug. Alberto Sim˜es o Building C/C++ libraries with Perl
  • 9.
    What more doI need? ExtUtils::CBuilder Something that helps compiling C/C++ code ExtUtils::ParseXS Something that helps me parse XS files ExtUtils::Mkbootstrap Something to create DynaLoader bootstrap files ExtUtils::PkgConfig or PkgConfig Something to detect libs that ship a .pc file Config::AutoConf Something that helps me detecting other libraries. . . ExtUtils::LibBuilder Something that knows how to link a standard library Alberto Sim˜es o Building C/C++ libraries with Perl
  • 10.
    The Nuts andBolts Alberto Sim˜es o Building C/C++ libraries with Perl
  • 11.
    Case Study 1 Lingua::Jspell A Morphological Analyzer for NLP; It is a standard C app based on ispell code; It includes Perl bindings (through Open3 atm); There is no real reason to bundle the app with the Perl module. The build chain uses: Module::Build; ExtUtils::CBuilder; ExtUtils::LibBuilder; Config::AutoConf; Alberto Sim˜es o Building C/C++ libraries with Perl
  • 12.
    Case Study 1 Lingua::Jspell A Morphological Analyzer for NLP; It is a standard C app based on ispell code; It includes Perl bindings (through Open3 atm); There is no real reason to bundle the app with the Perl module. The build chain uses: Module::Build; ExtUtils::CBuilder; ExtUtils::LibBuilder; Config::AutoConf; Alberto Sim˜es o Building C/C++ libraries with Perl
  • 13.
    Case Study 1 Config::AutoConf is used to: Detect libraries and headers (in Build.PL): § ¤ Config : : AutoConf−>check_header ( ” n c u r s e s . h ” ) ; Config : : AutoConf−>check_lib ( ” n c u r s e s ” , ”t g o t o ” ) ; ¦ ¥ More details on the Build.PL script in the article. Alberto Sim˜es o Building C/C++ libraries with Perl
  • 14.
    Case Study 1 I subclass Builder redefining methods: § ¤ sub ACTION_code { my $self = s h i f t ; # c r e a t e t h e L i b B u i l d e r o b j e c t and c a c h e i t $self−>notes ( libbuilder => ExtUtils : : LibBuilder−>new ) ; # d i s p a t c h e v e r y needed a c t i o n $self−>dispatch ( ” c r e a t e b l i b f o l d e r s ” ) ; $self−>dispatch ( ”c r e a t e m a n p a g e s ” ) ; $self−>dispatch ( ” c r e a t e y a c c ” ) ; $self−>dispatch ( ” c r e a t e o b j e c t s ” ) ; $self−>dispatch ( ” c r e a t e l i b r a r y ” ) ; $self−>dispatch ( ” c r e a t e b i n a r i e s ” ) ; # and now , c a l l s u p e r c l a s s . $self−>SUPER : : ACTION_code ; } ¦ ¥ Alberto Sim˜es o Building C/C++ libraries with Perl
  • 15.
    Case Study 1 The create yacc action also uses Config::AutoConf § ¤ sub ACTION_create_yacc { my $self = s h i f t ; my $ytabc = ’ s r c / y . t a b . c ’ ; my $parsey = ’ s r c / p a r s e . y ’ ; r e t u r n i f $self−>up_to_date ( $parsey , $ytabc ) ; my $yacc = Config : : AutoConf−>check_prog ( ”y a c c ” , ”b i s o n ” ) ; i f ( $yacc ) { ‘ $yacc −o $ytabc $parsey ‘ ; } } ¦ ¥ Alberto Sim˜es o Building C/C++ libraries with Perl
  • 16.
    Case Study 1 Build object files (plain ExtUtils::CBuilder usage): § ¤ sub ACTION_create_objects { my $self = s h i f t ; my $cbuilder = $self−>cbuilder ; my $c_files = $self−>rscan_dir ( ’ s r c ’ , qr / . c$ / ) ; my $xtr_comp_flags = ”−g ” . $self−>notes ( ’ c c u r s e s ’ ) ; f o r my $file ( @$c_files ) { my $object = $file =˜ s / . c / . o/r ; n e x t i f $self−>up_to_date ( $file , $object ) ; $cbuilder−>compile ( object_file => $object , source => $file , include_dirs => [ ” s r c ” ] , extra_compiler_flags => $xtr_comp_flags ) ; } } ¦ ¥ Alberto Sim˜es o Building C/C++ libraries with Perl
  • 17.
    Case Study 1 And the main stuff, build a standard library § ¤ sub ACTION_create_library { my $self = s h i f t ; my $libbuilder = $self−>notes ( ’ l i b b u i l d e r ’ ) ; ... # d e f i n e the l i n k e r f l a g s my $xlinkerflags = $self−>notes ( ’ l c u r s e s ’ ) . $self−>notes ( ’ c c u r s e s ’ ) ; i f ( $ˆO =˜ / darwin / ) { $xlinkerflags .= ” − i n s t a l l n a m e $ l i b p a t h ” } # l i n k i f t h e l i b r a r y i s n o t up t o d a t e i f ( ! $self−>up_to_date ( @objs , $libfile ) ) { $libbuilder−>l i n k ( module_name => ’ l i b j s p e l l ’ , extra_linker_flags => $xlinkerflags , objects => @objects , lib_file => $libfile ) ; } ... ¦ ¥ Alberto Sim˜es o Building C/C++ libraries with Perl
  • 18.
    Case Study 1 And build the C binaries. § ¤ sub ACTION_create_binaries { my $self = s h i f t ; my $libbuilder = $self−>notes ( ’ l i b b u i l d e r ’ ) ; ... # define flags my $extralinkerflags = $self−>notes ( ’ l c u r s e s ’ ) . $self−>notes ( ’ c c u r s e s ’ ) ; ... # i f needed , l i n k t h e e x e c u t a b l e i f ( ! $self−>up_to_date ( $object , $exe_file ) ) { $libbuilder−>link_executable ( exe_file => $exe_file , objects => [ $object ] , extra_linker_flags => ”−L s r c − l j s p e l l $ e x t r a l i n k e r f l a g s ” ) ; } ... ¦ ¥ Alberto Sim˜es o Building C/C++ libraries with Perl
  • 19.
    Case Study 1 Work out a testing environment. § ¤ sub ACTION_test { my $self = s h i f t ; i f ( $ˆO =˜ / mswin32 /i ) { $ENV { PATH } = $self−>blib . ”/ u s r l i b ; $ENV{PATH} ” ; } e l s i f ( $ˆO =˜ / darwin /i ) { $ENV { DYLD_LIBRARY_PATH } = $self−>blib . ”/ u s r l i b ” ; } e l s i f ( $ˆO =˜/linux | bsd | sun | sol | dragon | hpux | irix /i ) { $ENV { LD_LIBRARY_PATH } = $self−>blib . ”/ u s r l i b ” ; } e l s i f ( $ˆO =˜ / aix /i ) { my $oldlibpath = $ENV { LIBPATH } | | ’ / l i b : / u s r / l i b ’ ; $ENV { LIBPATH } = $self−>blib . ”/ u s r l i b : $ o l d l i b p a t h ” ; } $self−>SUPER : : ACTION_test } ¦ ¥ Alberto Sim˜es o Building C/C++ libraries with Perl
  • 20.
    Case Study 2 Lingua::Identify::CLD Interface to Google’s Compact Language Detector; It bundles a standard C++ library; It includes Perl bindings (through XS); The build chain uses: Module::Build; ExtUtils::CBuilder; ExtUtils::LibBuilder; Config::AutoConf; ExtUtils::ParseXS; ExtUtils::Mkbootstrap; Alberto Sim˜es o Building C/C++ libraries with Perl
  • 21.
    Case Study 2 Lingua::Identify::CLD Interface to Google’s Compact Language Detector; It bundles a standard C++ library; It includes Perl bindings (through XS); The build chain uses: Module::Build; ExtUtils::CBuilder; ExtUtils::LibBuilder; Config::AutoConf; ExtUtils::ParseXS; ExtUtils::Mkbootstrap; Alberto Sim˜es o Building C/C++ libraries with Perl
  • 22.
    Case Study 2 Compiling XS code as... standard XS code (mostly) § ¤ sub ACTION_compile_xscode { ... # c r e a t e CLD . c c from CLD . x s ExtUtils : : ParseXS : : process_file ( . . . ) ; # c r e a t e CLD . o from CLD . c c $cbuilder−>compile ( . . . ) ; # C r e a t e . b s b o o t s t r a p f i l e , n e e d e d by D y n a l o a d e r . ExtUtils : : Mkbootstrap : : Mkbootstrap ( . . . ) ; # set linker flags my $xlinkerflags = ”−L c l d −s r c − l c l d − l s t d c++” ; $xlinkerflags .= ” − l g c c s ” i f $ˆO eq ’ n e t b s d ’ ; # link $cbuilder−>l i n k ( . . . ) ; ¦ ¥ Alberto Sim˜es o Building C/C++ libraries with Perl
  • 23.
    Concluding It works! The process is similar for all modules; Then, this can be generalized in a module; Works on UNIX systems; Works on Strawberry Win32; Alberto Sim˜es o Building C/C++ libraries with Perl
  • 24.
    Thank you! Alberto Sim˜es o Building C/C++ libraries with Perl