Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Exploring Inline::C (Generating primes)

by davido (Cardinal)
on Oct 25, 2011 at 10:16 UTC ( [id://933587]=perlmeditation: print w/replies, xml ) Need Help??

I love it when a plan comes together.

I set out to figure out how to use Inline::C today, and thought I'd share the experience from the perspective of someone who was using Inline::C for the first time.

The Inline::CPP experience: Before I get into discussing Inline::C, I should mention that I really set out to explore Inline::CPP, but was disappointed to find that building it on my Windows Vista system with Strawberry Perl v5.12, as well as my Ubuntu Linux 11.10 system with Perl v5.14 proved more difficult than I cared to deal with at this time. The CPAN Testers Matrix shows it pretty much failing across the board for the versions of Perl I'm using on the OS's I have available at my fingertips. The CPAN Testers Reports summary page also shows v0.25 not passing on Win32 Perl 5.12.3 and just about any version of Linux. Given it hasn't been updated in a number of years, it seems that's probably a dead end. But if others have been successful, I'd love to hear about it.

Back to Inline::C. Installation was straightforward. On both Windows with Strawberry Perl, and Linux it was just a matter of invoking cpan Inline::C. The rest went like clockwork. That's nice.

The documentation for Inline::C also refers the reader to Inline::C-Cookbook. Anyone interested in getting some use out of this module should read both documents. The cookbook really helped to illustrate what is discussed in (or left out of) the documents for Inline::C. In particular, I was glad to find that I didn't have to jump through big hoops to pass a list back to Perl. Minor hoops yes, but I was expecting to have to build up a linked list or something by hand. Instead, the macros provided give access to Perl's lists.

Observe the following example from the Inline::C-Cookbook:

perl -e 'use Inline C=>q{void greet(){printf("Hello, world\n");}};gree +t'

Now that looks promising... Next I pulled up an old benchmark test I had in a trivia folder. I had already written two of the benchmark subs I wanted to compare with Inline::C. The first was a pure Perl Perl implementation of a pretty straightforward subroutine that searches for primes in the first 0 .. n integers. The second sub was a Perl wrapper around a system call (via open to a pipe). The system call invokes a compiled C++ implementation of the same algorithm as the one used in the pure Perl subroutine.

I had hoped to employ that same C++ code in an Inline::CPP test, but since I couldn't get that to install I re-implemented the same algorithm in C using the Inline::C hooks for Perl.

Here's the code, followed by a sample run:

use strict; use warnings; use autodie; use v5.12; use Benchmark qw/cmpthese/; use Test::More tests => 3; use Inline 'C'; use constant TOP => 150000; use constant TIME => 5; is( scalar @{ basic_perl( 3571 ) }, 500, "The first 500 primes are found from 2 to 3571." ); is_deeply( external_cpp(), basic_perl(), "external_cpp() function gives same results as basic_perl()." ); is_deeply( inline_c(), basic_perl(), "inline_c() function gives same results as basic_perl()." ); note "\nComparing basic_perl(), external_cpp(), and inline_c() for\n", TIME, " seconds searching ", TOP, " integers.\n\n"; cmpthese( - TIME, { basic_perl => \&basic_perl, external_cpp => \&external_cpp, inline_c => \&inline_c, }, ); note "\nI love it when a plan comes together.\n\n"; # The pure Perl version. sub basic_perl { my $top = $_[0] // TOP; my @primes = ( 2 ); BASIC_OUTER: for( my $i = 3; $i <= $top; $i += 2 ) { my $sqrt_i = sqrt( $i ); for( my $j = 3; $j <= $sqrt_i; $j += 2 ) { next BASIC_OUTER unless $i % $j; } push @primes, $i; } return \@primes; } # A wrapper around the external executable compiled in C++. sub external_cpp { my $top = TOP; open my $fh, '-|', "primes.exe $top"; chomp( my @primes = <$fh> ); close $fh; return \@primes; } # To be consistent: a wrapper around the Inline C version. sub inline_c{ my $top = TOP; my @primes = inline_c_primes( $top ); return \@primes; } __END__ // Reference only (not used by Inline::C ) // The source code, "primes.cpp" for "primes.exe", // used by external_cpp(). #include <iostream> #include <cmath> #include <cstdlib> #include <vector> #include <algorithm> using namespace std; vector<int> get_primes( int search_to ); void print( int value ); // The first 500 primes are found from 2 to 3571. const int TOP = 3571; // http://en.wikipedia.org/wiki/List_of_prime_numbers int main( int argc, char *argv[] ) { int search_to = ( argc > 1 ) ? atoi(argv[1]) : TOP; vector<int> primes = get_primes( search_to ); for_each( primes.begin(), primes.end(), print ); return 0; } vector<int> get_primes( int search_to ) { vector<int> primes; primes.push_back( 2 ); for( int i = 3; i <= search_to; i += 2 ) { int sqrt_i = sqrt( i ); for( int j = 3; j <= sqrt_i; j += 2 ) { if( i % j == 0 ) goto SKIP; } primes.push_back( i ); SKIP: {}; } return primes; } void print ( int value ) { cout << value << endl; } __C__ # Here is the C code that is compiled by Inline::C #include "math.h" void inline_c_primes( int search_to ) { Inline_Stack_Vars; Inline_Stack_Reset; Inline_Stack_Push(sv_2mortal(newSViv(2))); int i; for( i = 3; i <= search_to; i+=2 ) { int sqrt_i = sqrt( i ); int qualifies = 1; int j; for( j = 3; ( j <= sqrt_i ) && ( qualifies==1 ); j += 2 ) { if( i % j == 0 ) { qualifies = 0; } } if( qualifies == 1 ) { Inline_Stack_Push(sv_2mortal(newSViv(i))); } } Inline_Stack_Done; } # Cross your fingers and hope for the best!

...the sample run (Windows)...

1..3 ok 1 - The first 500 primes are found from 2 to 3571. ok 2 - external_cpp() function gives same results as basic_perl(). ok 3 - inline_c() function gives same results as basic_perl(). # # Comparing basic_perl(), external_cpp(), and inline_c() for # 5 seconds searching 150000 integers. # Rate basic_perl external_cpp inline_c basic_perl 1.27/s -- -94% -98% external_cpp 20.0/s 1467% -- -66% inline_c 59.3/s 4555% 197% -- # # I love it when a plan comes together. #

A sample run from my Linux system:

1..3 ok 1 - The first 500 primes are found from 2 to 3571. ok 2 - external_cpp() function gives same results as basic_perl(). ok 3 - inline_c() function gives same results as basic_perl(). # # Comparing basic_perl(), external_cpp(), and inline_c() for # 5 seconds searching 150000 integers. # Rate basic_perl external_cpp inline_c basic_perl 2.37/s -- -91% -97% external_cpp 25.3/s 969% -- -67% inline_c 76.0/s 3106% 200% -- # # I love it when a plan comes together. #

It took a little time getting used to debugging under Inline::C. But the error messages are about as informative as the C compiler would give on its own, if not a little better. For one thing, compile time errors get printed into a log file in the build directory, and the error messages that dump to the screen indicate the path to where the full error message dump resides. That's nice.

However, you do have to take note that line numbers in error messages won't correspond with those in your Perl source code. Instead, they refer to a C source file that gets placed in the build directory, with an .xs suffix. Again, the error log and screen messages point to that same file. Open it up in an editor that shows line numbers and the error messages will make more sense. But don't bother editing the .xs file. Changes need to be made to the C code within the Perl source file. (I know this is common sense, but with several editors opened it's easy to mistakenly start editing the .xs file just because that's where you're crossreferencing the error line numbers.)

Now for the fun: As the benchmark shows, the Inline::C screams by comparison to the other methods. Of course dropping into C or C++ is generally a big pain in the neck, but when performance counts, it doesn't disappoint.

Another thing to notice is that the external system call method is significantly slower than the inline method. Earlier I had a benchmark where I was doing an external call to essentially a "no-op", and it's pretty obvious that the work being done in an external call doesn't come for free. But even with that extra work, the external call method is an order of magnitude faster than the pure Perl subroutine.

Pros and cons of each: The benchmark results speak for themselves; if speed is what matters, the Inline::C method wins. It's not surprising that the Perl sub was the easiest to implement, followed by the external system call (which could be in any language, without worrying about Perl's C macros for passing data around), followed by the Inline::C method, which was the most trouble to work out.

I've always sort of avoided working with XS because I didn't see a lot of need. And in fact, I've gotten by just fine without Inline::C in the past as well. But it turns out that using Inline::C is fairly simple. I don't think I'll be as pleasantly surprised when I get around to tackling full blown XS. This, however, was a pretty positive experience. I hope others will be motivated to give it a try too.

Added several days later: Here's a revised version of the code that now has two Inline::C alternatives. The first alternative passes a list back to Perl, which then returns a reference to the list. The second alternative passes a reference directly back to Perl. The performance difference is minimal. Perl probably doesn't copy the list that C passed back to it in the first example.

use strict; use warnings; use autodie; use v5.12; use Benchmark qw/cmpthese/; use Test::More tests => 4; use Inline 'C' => 'DATA'; use constant TOP => 200000; use constant TIME => 10; note "Operating system: $^O, Perl version: $^V\n\n"; note "Constant TOP is ", TOP; note "Constant TIME is ", TIME, "\n\n"; is( scalar @{ basic_perl( 3571 ) }, 500, "basic_perl(3571): The first 500 primes are found from 2 to 3571." + ); is_deeply( external_cpp(TOP), basic_perl(TOP), "external_cpp(TOP): Same results as basic_perl(TOP)." ); is_deeply( inline_c_list(TOP), basic_perl(TOP), "inline_c_list(TOP): Same results as basic_perl(TOP)." ); is_deeply( inline_c_aref(TOP), basic_perl(TOP), "inline_c_aref(TOP): Same result as basic_perl(TOP)." ); note "\nComparing basic_perl(), external_cpp(), inline_c_list(), inli +ne_c_aref()\n", "for ", TIME, " seconds searching ", TOP, " integers.\n\n"; cmpthese( - TIME, { basic_perl => \&basic_perl, external_cpp => \&external_cpp, inline_c_list => \&inline_c_list, inline_c_aref => \&inline_c_aref, }, ); note "\nI love it when a plan comes together.\n\n"; # The pure Perl version. sub basic_perl { my $top = $_[0] // TOP; my @primes = ( 2 ); BASIC_OUTER: for( my $i = 3; $i <= $top; $i += 2 ) { my $sqrt_i = sqrt( $i ); for( my $j = 3; $j <= $sqrt_i ; $j += 2 ) { next BASIC_OUTER unless $i % $j; } push @primes, $i; } return \@primes; } # A wrapper around the external executable compiled in C++. sub external_cpp { my $top = $_[0] // TOP; open my $fh, '-|', "primes $top"; chomp( my @primes = <$fh> ); close $fh; return \@primes; } # To be consistent: a wrapper around the Inline C version. sub inline_c_list{ my $top = $_[0] // TOP; my @primes = inline_c_list_primes( $top ); return \@primes; } sub inline_c_aref{ my $top = $_[0] // TOP; return inline_c_aref_primes( $top ); } __END__ // Reference only (not used by Inline::C ) // The source code, "primes.cpp" for "primes.exe", // used by external_cpp(). #include <iostream> #include <cmath> #include <cstdlib> #include <vector> #include <algorithm> using namespace std; vector<int> get_primes( int search_to ); void print( int value ); // The first 500 primes are found from 2 to 3571. const int TOP = 3571; // http://en.wikipedia.org/wiki/List_of_prime_numbers int main(int argc, char *argv[] ) { int search_to = ( argc > 1 ) ? atoi(argv[1]) : TOP; vector<int> primes = get_primes( search_to ); for_each( primes.begin(), primes.end(), print ); return 0; } vector<int> get_primes( int search_to ) { vector<int> primes; primes.push_back(2); for( int i = 3; i <= search_to; i += 2 ) { int sqrt_i = sqrt( i ); for( int j = 3; j <= sqrt_i; j += 2 ) { if( i % j == 0 ) goto SKIP; } primes.push_back(i); SKIP: {}; } return primes; } void print ( int value ) { cout << value << endl; } __C__ #include "math.h" void inline_c_list_primes( int search_to ) { Inline_Stack_Vars; Inline_Stack_Reset; Inline_Stack_Push(sv_2mortal(newSViv(2))); int i; for( i = 3; i <= search_to; i+=2 ) { int sqrt_i = sqrt( i ); int qualifies = 1; int j; for( j = 3; (j<=sqrt_i) && (qualifies==1); j += 2 ) { if( i % j == 0 ) { qualifies = 0; } } if( qualifies == 1 ) { Inline_Stack_Push(sv_2mortal(newSViv(i))); } } Inline_Stack_Done; } AV * inline_c_aref_primes ( int search_to ) { AV* av; av = newAV(); av_push( av, newSViv( 2 ) ); int i; for( i = 3; i <= search_to; i+=2 ) { int sqrt_i = sqrt( i ); int qualifies = 1; int j; for( j = 3; (j<=sqrt_i) && (qualifies==1); j += 2 ) { if( i % j == 0 ) { qualifies = 0; } } if( qualifies == 1 ) { av_push( av, newSViv( i ) ); } } return sv_2mortal( av ); }

Tests were also tweaked a little. Here's the sample run.

1..4 # Operating system: linux, Perl version: v5.14.2 # # Constant TOP is 200000 # Constant TIME is 10 # ok 1 - basic_perl(3571): The first 500 primes are found from 2 to 3571 +. ok 2 - external_cpp(TOP): Same results as basic_perl(TOP). ok 3 - inline_c_list(TOP): Same results as basic_perl(TOP). ok 4 - inline_c_aref(TOP): Same result as basic_perl(TOP). # # Comparing basic_perl(), external_cpp(), inline_c_list(), inline_c_a +ref() # for 10 seconds searching 200000 integers. # Rate basic_perl external_cpp inline_c_list inline_ +c_aref basic_perl 1.64/s -- -91% -97% + -97% external_cpp 17.6/s 977% -- -67% + -67% inline_c_list 53.0/s 3138% 201% -- + -2% inline_c_aref 54.1/s 3202% 207% 2% + -- # # I love it when a plan comes together. #

Update: Added readmore tags after the node got FrontPaged, to reduce FP clutter. Tinkered with formatting.


Dave

Replies are listed 'Best First'.
Re: Exploring Inline::C (Generating primes)
by BrowserUk (Patriarch) on Oct 25, 2011 at 10:45 UTC
    It took a little time getting used to debugging under Inline::C.... However, you do have to take note that line numbers in error messages won't correspond with those in your Perl source code. Instead, they refer to a C source file that gets placed in the build directory, with an .xs suffix. Again, the error log and screen messages point to that same file.

    This may or may not suit your preferences, but I always start my Inline::C files with:

    #! perl -slw use strict; use Inline C => Config => BUILD_NOISY => 1; use Inline C => <<'END_C', NAME => 'scriptname', CLEAN_AFTER_BUILD => + 0; // XS code here ... END_C # perl code here ...

    This has several effects I find extremely useful.

    • BUILD_NOISY => 1 ensures that warnings and errors from the .XS/.c compile phase are also output to the terminal.

      Unfortunately it also produces a lot of clutter -- starting xxx/Finishing xxx -- that I'm not interested in, but getting the direct feedback of the C compiler output is more than compensation.

    • NAME => '....' prevents the default of using the first 4 hex characters of the MD5 as a part of the build subdirectory name.

      This default is annoying because it means that if you've loaded the previous intermediate .c and .xs files into your editor, when you make a change and re-build, they become obsolete and you have to go off hunting to find out where their replacements are located.

      By explicitly naming them, when you've done a re-build, the same files get over written and you only need refresh to view the effects of the changes, My editor keeps track of changes to open files and can either notify you or automatically refresh them when you switch to the appropriate tab.

      This helps prevent one source of the "I edited the (wrong) file and nothing changed" gotcha.

    • CLEAN_AFTER_BUILD => 0 prevents the I::C build process from throwing away the intermediate build files.

      Which is almost essential when debugging.

    But the main advantage of using this sequence of exactly 4 lines, is it means that the line numbers produced by the C compiler in its error messages logged to the screen, match exactly with those within the original I::C perl source file. Which means that most of the time there is no need to load the .c/.XS files in order to track down where the errors are, and so avoids another source of the "I edited the (wrong) file and nothing changed" gotcha.

    And that is priceless.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

      It has been a while since I have coded anything extensive (for some definition of extensive) in C, but I seemed to remember being able to tweak the line number and file name reported by the compiler by using #line... directives. A little searching indicates that my memory was correct.

      Not having used Inline::C to this point, this question is being asked from an ignorant position: is Inline::C able to use the #line directive?

      --MidLifeXis

        is Inline::C able to use the #line directive?

        Theoretically yes. But ...

        The XS pre-compiler already uses (something like) this to try and make error messages produce by the C compiler relate to line numbers in the .XS file.

        Inline::C extracts the source code from the .pl file, places it into an .XS file with some requisite pre- and post-amble, and then pre-compiles that to produce the the .c file. That then gets compiled to build a .dll/.so binary that is then dynamically linked back to the perl binary at runtime.

        I don't think anyone has tried to apply two levels of line control simultaneously. I'm not sure we humans would understand the results :)


        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Exploring Inline::C (Generating primes)
by wazoox (Prior) on Oct 25, 2011 at 15:30 UTC
    Funnily, this doesn't work at all on my machine. The first test works fine, the second one ends with "Out of memory" after a long, painful swap to disk (obviously Test::More must be doing something wrong). Maybe it's a 5.14.0 bug?

      Well that's strange. I've tested on the following Perls:

      • Windows Vista Home Premium 64 bit / Strawberry Perl version 5.12.3
      • Ubuntu Linux 32 bit version 11.10 / System Perl version 5.12.4
      • Ubuntu Linux 32 bit version 11.10 / Perlbrew-managed Perl version 5.14.2

      Is it possible that your Inline::C is installed using a different compiler from the one used to compile Perl? That can make a difference. When I installed using cpan Inline::C, I was prompted for which compiler to use, but the default had already detected the compiler used to compile Perl, so I just accepted the default.

      Test::More is used by just about every module you install, so I would be more inclined to put the blame on Inline::C than on Test::More.


      Dave

        Is it possible that your Inline::C is installed using a different compiler from the one used to compile Perl?

        No, I've compiled 5.14 myself on this same machine, so the same compiler was used to build the whole setup. But that maybe indeed the problem : maybe I'm running the original system perl? I'll double check and retry.

      The first test works fine, the second one ends with "Out of memory" after a long, painful swap to disk

      Actually now that I re-read the description of your problem I have to conclude it probably has nothing at all to do with Inline::C. The second test is comparing the results of the pure Perl sub to the results of the sub that invokes an external program. That external program is the C++ program whos source I provided in my example.

      That program is not seen or touched by Inline::C. Inline::C doesn't know or care about it.

      The C++ program has to be saved in its own C++ source file, compiled, and linked to a filename that makes sense for your operating system. In fact whether it's Win32 or Linux, there's no harm in having an .exe suffix in this simple test case. Just compile the C++ source into an executable named 'primes.exe', and put it wherever the script will be able to find it (or specify a fully qualified path within the Perl script's call to primes.exe).

      Maybe you've already done all this. If you haven't, go ahead and do it now.

      The next step in sleuthing what's going wrong would be to invoke primes.exe (the executable built from the C++ source I provided). Invoke it with some smallish integer, like primes.exe 100. Then try it as primes.exe 100000, and again as primes.exe 1000000.

      If it runs properly in all those cases, there's no sane reason it shouldn't work from within your Perl script. If it doesn't run properly, perhaps you have a C++ compiler and library that lacks the Standard Template Library, which is a necessary component of the C++ program.

      If all else fails, you ought to be able to just remove the 2nd test, and remove all mention of the external_cpp() sub within the Perl script (remove the function's declaration/definition, and its use within the cmpthese() benchmark). Then you'll only be comparing the Inline::C function with the pure Perl one; you're taking the C++ program out of the equation.

      Hope this helps...


      Dave

        I've recompiled everything from the start, and it works somewhat better, though not very well in the end :) The c++ code goes well enough, but the Inline::C fails miserably:

        perl test.pl 1..3 /usr/local/bin/perl /usr/local/lib/perl5/5.14.0/ExtUtils/xsubpp -type +map /usr/local/lib/perl5/5.14.0/ExtUtils/typemap test_pl_97a8.xs > +test_pl_97a8.xsc && mv test_pl_97a8.xsc test_pl_97a8.c cc -c -I/home/emmanuel -D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasin +g -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D +_FILE_OFFSET_BITS=64 -O2 -DVERSION=\"0.00\" -DXS_VERSION=\"0.00\" - +fPIC "-I/usr/local/lib/perl5/5.14.0/i686-linux-thread-multi/CORE" t +est_pl_97a8.c test_pl_97a8.xs:6:3: erreur: directive de pré-traitement #Here invalid +e test_pl_97a8.xs:33:3: erreur: directive de pré-traitement #Cross inval +ide make: *** [test_pl_97a8.o] Erreur 1 A problem was encountered while attempting to compile and install your + Inline C code. The command that failed was: make > out.make 2>&1 The build directory was: /home/emmanuel/_Inline/build/test_pl_97a8 To debug the problem, cd to the build directory, and inspect the outpu +t files. at test.pl line 0 INIT failed--call queue aborted. # Looks like your test exited with 2 before it could output anything.
      Maybe it's a 5.14.0 bug?

      No problem for me with 5.14.0 on Windows.
      The second test runs 'primes.exe' - perhaps there's a problem with the way that file is being executed (or built) on your system.

      Cheers,
      Rob
        Nope, the primes binary compiles and executes as expected by itself. It's only that the perl script goes awry...
Re: Exploring Inline::C (Generating primes)
by syphilis (Archbishop) on Oct 27, 2011 at 10:34 UTC
    I really set out to explore Inline::CPP, but was disappointed

    That module has been unmaintained for about 8 years, now.
    It would be really good if some competent person would step forward and take over maintainership - as, I believe, an up-to-date Inline::CPP could be a very handy tool.

    Last time I heard from Neil Watkiss (the original author) he had no intention of ever having any involvement with it again.

    Cheers,
    Rob

      I've taken on Co-maintainership for Inline::CPP. Neil Watkiss seemed happy (or relieved) to have someone take an interest. The latest version will show up on the CPAN mirrors within a few hours as 0.29. It has addressed the "failure to pass its test suite" issue, at least on my Windows and Linux systems, and should work for Mac now too. We'll see when the CPAN testers matrix gets updated. The issue turned out to be some code that appended '.h' to the end of the #include <iostream> preprocessor directive. While that was "the right way" back in 2001, nowadays in 2011 standard C++ doesn't use a .h extension for the core header files.

      I tweaked a couple other items from the bug reports where the application of the fix was pretty obviously a win. I'll try to get to looking at a few other issues in the next couple of weeks.

      If anyone has comments or suggestions, I would appreciate hearing them. As with most things in the Perl and CPAN world, those suggestions that come with a test and a patch will be given higher priority. Bonus points for a test in a TAP compatible '*.t' file format. :)

      Once Inline::CPP version 0.29 shows up on the servers (which should be any time now) I encourage brave people who have familiarity with C++ to give it a try. I'm finding all sorts of little issues that I'll need to look at. One, for example, is that if you try to sv_2mortal( av )... that's a problem as C++'s stricter typing wants sv_2mortal( sv ) only. One item for the ToDo list. ;)


      Dave

        I've taken on Co-maintainership for Inline::CPP

        This is excellent news!!

        I almost established co-maintainership of Inline::CPP a couple of years back, but I kept losing contact with Neil at critical moments, and it never happened. (That was actually quite fortuitous as I'm not the right person for the job, anyway - my CPP skills are best described in terms that don't involve the use of the word "skill" ;-)

        Version 0.29 builds and tests for me on my 32-bit builds of perl (where I'm using the mingw.org port of gcc-4.5.2).

        But ... things don't go quite so well if the compiler to be used is not called 'g++'.
        In CPP.pm we have:
        sub validate { my $o = shift; $o->{ILSM}{MAKEFILE}{CC} ||= 'g++'; # default compiler $o->{ILSM}{MAKEFILE}{LIBS} ||= ['-lstdc++']; # default libs
        That effectively hard-codes in 'g++' and '-lstdc++'.
        You'll note that the Makefile.PL rewrites CPP.pm, replacing the strings '@COMPILER' and '@DEFAULTLIBS' with the selected compiler and libs ... except that there's now *no* such strings as '@COMPILER' and '@DEFAULTLIBS' anywhere in CPP.pm ... so CPP.pm stays exactly as it was ... which is fine if (and only if) you're using 'g++'.

        Do you see what I mean ?

        Cheers,
        Rob

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://933587]
Approved by GrandFather
Front-paged by Arunbear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (6)
As of 2024-03-28 08:37 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found