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

IP::Country::Fast library

by edatawiz (Novice)
on Mar 19, 2009 at 06:49 UTC ( #751634=perlquestion: print w/replies, xml ) Need Help??

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

Hi ! I am trying to compile an exe file using pp which has IP::Country::Fast libary usage. The .pl script works fine but when I run the .exe it ends up with an error: E:\xxx\test>findlinks.exe couldn't read country database: No such file or directory at IP/Country/ line 36. Compilation failed in require at script/ line 9. BEGIN failed--compilation aborted at script/ line 9. How do I resolve this ?

Replies are listed 'Best First'.
Re: IP::Country::Fast library
by Anonymous Monk on Mar 19, 2009 at 11:32 UTC
    You could patch the module to use PAR::read_file() to read database (after making sure it gets packed, see PAR/pp for details). You could also ask PAR developers why $INC{'module/'} contains /loader/HASH(0xa4af9c)/module/ instead of real path.

      Obviously, you found out the following already, but here it's for those reading along:

      IP::Country::Fast puts its database files (aptly named with a .gif extension -- what the...?) into the lib/ hierarchy of the distribution. This has the result that they're installed into the normal Perl library paths along with the code.

      Now, this is an inexplicably bad thing to do. You don't want arbitrary data cruft to reside in your library tree. But it gets worse. In order to *find* that file, the module goes on to access the place where IP::Country::Fast has been loaded from using $INC{"IP/Country/"}. This breaks in the PAR context (and always will) because the module *might not even have been loaded from a file*, but from memory after unzipping from the PAR archive!

      There are several solutions to this. One would be to put the database (in base64 encoded form or similar) into the __DATA__ section of a real .pm file and simply load that and ask it for its *DATA file handle. This is what's done with PAR::StrippedPARL::* for example.

      Another solution -- the elegant one -- is to NOT put that database in the lib/ hierarchy at all but to include it as a shared file. For details, check out the documentation of the excellent File::ShareDir module and specifically the section about using it for module-specific data. Now, to make this PAR-packaging friendly, you simply use the File::ShareDir::PAR wrapper of File::ShareDir instead which knows how to access such shared data files from PAR archives.

      If all these solutions seem too difficult, then you should try to think about what makes them difficult. There is no good separation of code/logic and data where there should be a separation. CPAN distributions have never been very good at this and the File::ShareDir approach is an attempt to fix that. PAR is put in a much more problematic position again because it suddenly has to deal with that separation as well. It was devised mostly for dealing with logic.

      To sum this up, this is a problem that requires an upstream solution. I very much doubt you can fix it in PAR/pp.


      I am new to this whole stuff. Can you explain to me in detail. ?

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://751634]
Approved by rovf
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (2)
As of 2022-08-16 22:13 GMT
Find Nodes?
    Voting Booth?

    No recent polls found