Sat Dec 21 06:52:52 2013: Request 91530 was acted upon.
Transaction: Correspondence added by RSCHUPP
       Queue: Module-ScanDeps
     Subject: Missing MIME\types.db from pp-generated code
   Broken in: 1.12
    Severity: (no value)
       Owner: RSCHUPP
  Requestors: [email protected]
      Status: open
 Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=91530 >


On 2013-12-19 19:46:55, [email protected] wrote:
> 
> I've an issue, for a missing of MIME:Types.db from code generated via pp 
> of PAR::Packer.
> ...
> Can't say whether this is an issue or a pitfall on my side; whatever the 
> case, any suggestion/workaround is greatly appreciated.

Definitely an issue, but it's complicated. 
If you don't want to read through my ramblings below, skip to the bottom for a 
workaround :)

When a pp-packed executable is missing a module or data file, this can usually
be worked around by using pp options -M (for a missing module) or -a (for a 
plain file), though to get the latter "right" may need some experimentation
(or insight how some module searches for its data file).

BTW, even if your workaround works, you might submit a bug report for
Module::ScanDeps (which is used by pp to scan your script for all modules
it uses). I can usually make the workaround unnecessery by adding another
explicit rule to Module::ScanDeps.

In your case, MIME::Types (it's not in MIME::Lite, but used by MIME::Lite
under the hood) uses the data file MIME/types.db.
Your idea to use "pp -a ..." to pack this file explicitly is correct,
but can't work because MIME::Types does the following to open this file:

  open FH, "<:encoding(utf8)", File::Spec->catfile(dirname(__FILE__), 
"types.db")
  
This assumes that (when perl parses MIME/Types.pm) __FILE__ is set to the
absolute pathname where MIME/Types.pm was found. This is probably true for
99% of all use cases, but it always breaks in a packed executable.
The reason is that any module is transformed ("filtered") when it is packed.
The default filter (PodStrip) strips POD from the module. To compensate for that
(so that a die() or warn() from inside the module shows the "correct" line 
number)
it adds "# line N ..." statements. Especially it adds 

# line 1 "MIME/Types.pm"

at the start of the packed MIME/Types.pm. As a side effect this sets 
__FILE__ to "MIME/Types.pm". So we must use the following options for pp:

  -a '/path/to/your/MIME/types.db;lib/MIME/types.db'

to pack MIME/types.db as a "sibling" of MIME/Types.pm AND suppress 
the application of the PodStrip filter for MIME/Types.pm:

  -F PatchContent=MIME/Types.pm

(or set PAR_VERBATIM=1 in the environment when packing to generally suppress 
filtering).

But wait, there's more :( With the above you will still get

  cannot open type database in 
/tmp/par-726f646572696368/cache-5be06ead4dff6a6e16c2df7d03b59c0dbf5a8c02/inc/lib/MIME/types.db:
 No such file or directory

even though this file exists! The reason is the argument "<:encoding(utf8)"
to open(). It implicitly does "require PerlIO::encoding". Since this module 
hasn't been packed, open() fails even before actually trying to open the file.
Actually, this is a bug in Module::ScanDeps, it's supposed to look out for
for patterns like this and infer a dependency on PerlIO and PerlIO::encoding.
I've fixed this in Module::ScanDeps, but until its next release the workaround
is to use the pp option

  -M PerlIO::encoding

So the whole workaround is

  pp -a "/path/to/your/MIME/types.db;lib/MIME/types.db" \
     -F PatchContent=MIME/Types.pm \
     -M PerlIO::encoding ...

(use forward slashes even under Windows)

Cheers, Roderich

















Reply via email to