stevieb has asked for the wisdom of the Perl Monks concerning the following question:

I'm having a head-scratching moment here. Precursor: this isn't a failure due to anything missing; I'm failing to understand why one thing succeeds and the other doesnt. I'm finding issues installing some of my modules with cpanm and cpan (XS based modules), then, when I pull down the repo locally and to a perl Makefile.PL and make all is well. Then when I do make test, it fails miserably (I have boldfaced the actual error so you don't have to wade through the other stuff if it isn't necessary):

spek@sequoia ~/repos/rpi-dac-mcp4922 $ make test PERL_DL_NONLAZY=1 "/home/spek/perl5/perlbrew/perls/perl-5.24.1/bin/per +l" "-MExtUtils::Command::MM" "-MTest::Harness" "-e" "undef *Test::Har +ness::Switches; test_harness(0, 'blib/lib', 'blib/arch')" t/*.t t/00-load.t ....... 1/? Bailout called. Further testing stopped: # Failed test 'use RPi::DAC::MCP4922;' # at t/00-load.t line 10. # Tried to use 'RPi::DAC::MCP4922'.
# Error: Can't load '/home/spek/perl5/perlbrew/perls/perl-5.24.1/ +lib/site_perl/5.24.1/x86_64-linux/auto/WiringPi/API/API.so' for modul +e WiringPi::API: /usr/local/lib/libwiringPi.so: undefined symbol: shm +_open at /home/spek/perl5/perlbrew/perls/perl-5.24.1/lib/5.24.1/XSLoa +der.pm line 96.
# at /home/spek/perl5/perlbrew/perls/perl-5.24.1/lib/site_perl/5.24.1 +/x86_64-linux/WiringPi/API.pm line 9. # Compilation failed in require at /home/spek/repos/rpi-dac-mcp4922/bl +ib/lib/RPi/DAC/MCP4922.pm line 9. # BEGIN failed--compilation aborted at /home/spek/repos/rpi-dac-mcp492 +2/blib/lib/RPi/DAC/MCP4922.pm line 9. # Compilation failed in require at t/00-load.t line 10. # BEGIN failed--compilation aborted at t/00-load.t line 10. Use of uninitialized value $RPi::DAC::MCP4922::VERSION in concatenatio +n (.) or string at t/00-load.t line 13. # Testing RPi::DAC::MCP4922 , Perl 5.024001, /home/spek/perl5/perlbrew +/perls/perl-5.24.1/bin/perl # Looks like you failed 1 test of 1. FAILED--Further testing stopped. Makefile:1029: recipe for target 'test_dynamic' failed make: *** [test_dynamic] Error 1

However, prove t/*.t doesn't catch the problem and goes on its merry way:

spek@sequoia ~/repos/rpi-dac-mcp4922 $ prove t/*.t t/00-load.t ....... 1/? # Testing RPi::DAC::MCP4922 2.36.1, Perl 5.024 +001, /home/spek/perl5/perlbrew/perls/perl-5.24.1/bin/perl t/00-load.t ....... ok t/manifest.t ...... skipped: Author tests not required for installatio +n t/pod-coverage.t .. skipped: Author tests not required for installatio +n t/pod.t ........... skipped: Author tests not required for installatio +n All tests successful. Files=4, Tests=1, 1 wallclock secs ( 0.05 usr 0.00 sys + 0.23 cusr + 0.02 csys = 0.30 CPU) Result: PASS

I know what the problem is, where the problem is (at least iirc without looking at the code yet), so I just want to know why one fails and the other doesn't.

Replies are listed 'Best First'.
Re: "make test" catches a C undefined symbol, but "prove" doesn't
by davido (Cardinal) on Feb 22, 2017 at 06:30 UTC

    The common mantra is:

    perl Makefile.PL make make test make install

    The first line, perl Makefile.PL invokes a tool in ExtUtils::MakeMaker that creates a Makefile. The next step, make then builds the distribution according to the rules set forth in the makefile. It will be built into ./blib/ for now.

    The next line, make test runs the test target in Makefile, which runs the suite against the version of the module built into blib. Later you would run make install, which runs a target in the Makefile that copies the contents of blib/ into the appropriate final destination -- where your Perl modules live.

    The reason for blib/'s existence, and why you typically wouldn't test against the lib/ that ships with the distribution is that Makefile.PL, and more appropriately, the make step can and often do all sorts of work to build the module. Whatever lives in lib/ should be considered just part of the template for the final blib/ version. For example, if the module contained XS or C code, that code couldn't possibly be useful prior to the make phase, where it gets compiled. Once compiled, the resulting components will also go somewhere under blib/. make is pretty powerful. And ExtUtils::MakeMaker exposes much of that power. Another example is that the module itself could be entirely written by the make phase. make could even invoke a Perl script that produces output that becomes the module. This is the build process, and the result of the build goes into blib/.

    So as I mentioned, make test runs the tests against the module that lives in blib/. On the other hand, prove runs the tests against lib/ unless directed otherwise prove -l runs the tests against ./lib, and prove without library-influencing flags runs the tests using standard @INC semantics. prove -b runs the tests against the version that was built into blib/.

    So when you run make, you are running against different code than when you run prove. To run against the same code, use prove -b.


    Dave

      > prove runs the tests against lib/ unless directed otherwise

      That's not true. prove -l does that, prove on its own uses the code found in @INC.

      ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,

        Thank you for clarifying. You are correct. I'll update my post accordingly.


        Dave

Re: "make test" catches a C undefined symbol, but "prove" doesn't
by stevieb (Canon) on Feb 22, 2017 at 14:52 UTC

    Ok, so it turns out after some searching that I needed to build against the rt library as in add it to the LIBS aref in my Makefile.PL:

    LIBS => ['-lwiringPi -lwiringPiDev -lrt'],

    After I added that, make test does The Right Thing (no more error about shm_open() being an undefined symbol.

    I'm going to do some research as to how prove doesn't break, and if nobody else has an answer by then, I'll update here for completeness.

Re: "make test" catches a C undefined symbol, but "prove" doesn't
by stevieb (Canon) on Feb 22, 2017 at 02:49 UTC

    Now, I'm even more confused, and although I don't desire to, feel if I can't get this soon, I should take this out of Perlmonks as it's beyond Perl code by far.

    I've added #include <sys/mman.h> per the docs in my header files, *and* verified they are in the wiringPi libs, to no avail.

    I'll sleep on it.

Re: "make test" catches a C undefined symbol, but "prove" doesn't
by Anonymous Monk on Feb 22, 2017 at 01:59 UTC
    because -b is for blib

      Ok, so where is that, or where should that be applied? I'm not understanding... are you saying that in one of the two test runs that API.so is being read out of blib and the other isn't?

      There's no API.so or API.pm in the blib dir I'm building:

      spek@sequoia ~/repos/rpi-dac-mcp4922 $ find . -name API.so spek@sequoia ~/repos/rpi-dac-mcp4922 $ spek@sequoia ~/repos/rpi-dac-mcp4922 $ find . -name API.pm spek@sequoia ~/repos/rpi-dac-mcp4922 $

      ...and:

      spek@sequoia ~/repos/rpi-dac-mcp4922 $ ll | grep blib drwxr-xr-x 8 spek spek 4096 Feb 21 18:11 blib/ -rw-r--r-- 1 spek spek 0 Feb 21 18:44 pm_to_blib

      So can you please elaborate?

      Thanks,

      -stevieb

        make test runs in blib as your output shows:
        # Compilation failed in require at /home/spek/repos/rpi-dac-mcp4922/bl +ib/lib/RPi/DAC/MCP4922.pm line 9. ~~ +~~

        To run prove in the same way, you need to add the -b switch. You didn't add -l , either, so what you're testing are the newest tests, but the installed versions of the libraries, pure Perl or XS.

        ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,