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

Hi Perl Monks,

I have a Makefile.PL which creates a module say 'My_Config.pm' (Makefile.PL prompts for user password and stores it in 'My_Config.pm)' under the lib directory using some predefined template.

Upon perl Makefile.PL && make the file 'My_Config.pm' is created under lib/ When performing make install the 'My_Config.pm' is not always installed. Even if the file contains changes, the file is not always installed.

I am using File::ShareDir::Install 'postamble';

Any hints on what may be the problem here?

TIA

Edit 1:

My_Config.tmpl

package My::Module::Name::My_Config; use strict; use warnings; use Exporter; our @ISA = 'Exporter'; our @EXPORT_OK = 'MY_PASSWORD'; our %EXPORT_TAGS =(CONSTANTS => ['MY_PASSWORD']);
Makefile.PL
use strict; use warnings; use ExtUtils::MakeMaker; WriteMakeFile( NAME => 'My::Module::Name', AUTHOR => 'XYZ', VERSION_FROM => 'lib/My/Module/Name.pm' ); package MY; sub xs_o { my $pass = MM->prompt('Enter password'); chomp($pass); my $tmpl = 'My_Config.tmpl'; my $config = 'lib/My/Module/Name/My_Config.pm'; return <<END; all: myconfig myconfig: \tperl -e 'open(IN, "<" , "$tmpl"); open(OUT, ">", "$config"); while(< +IN>) { print OUT $_; } close(IN); close(OUT);' \tperl -e 'open(OUT, ">>", "$config"); print OUT "use constant MY_PASS +WORD => qq($pass);\\n1;"; close(OUT);' END } use File::ShareDir::Install 'postamble';

Replies are listed 'Best First'.
Re: Makefile.PL does not always install changed file
by haukex (Archbishop) on Jun 12, 2019 at 18:42 UTC
      have added a snippet of what i am doing.

        Thank you for updating your post, but unfortunately, I don't think it's representative, since it doesn't seem to reproduce the issue: it doesn't run because WriteMakeFile should be WriteMakefile, and at least on my version of make, the all: myconfig line causes problems. Anyway, the following jumps out at me:

        return <<END; \tperl -e 'open(IN, "<" , "$tmpl"); open(OUT, ">", "$config"); while(< +IN>) { print OUT $_; } close(IN); close(OUT);' END

        Because the $_ will be interpolated, i.e. the generated Makefile will look like "while(<IN>) { print OUT ; }" (or worse, if $_ happens to contain a value, that'll become part of the Makefile). To get what you intended in the Makefile, you need to write print OUT \$\$_; - the \$ to escape the backslashes for Perl, and the $$ to escape the $ for make.

        However, this is still brittle in several ways. Simply interpolating "$tmpl" and "$config" will fail if those variables contain any characters special to Perl or make, and you're not checking the open for errors. Plus, the command I quoted above is really just a cp. The first of those issues could theoretically be solved by using a module such as Data::Dump to write the $tmpl and $config variables to a Perl file, but I agree with stevieb that this might be better handled using a configuration file in a different format.

        Getting back to the problem you describe in the root node, since this doesn't seem to be a representative example, I can only guess: perhaps the myconfig target isn't getting called every time?

Re: Makefile.PL does not always install changed file
by stevieb (Canon) on Jun 12, 2019 at 22:07 UTC

    haukex already stated the procedure for showing us how to help you, but I've got another tidbit aside from that...

    ...don't put user particulars in an executable file. Put that stuff in a config file (JSON, INI etc) or an environment variable. Your functions/methods should handle properly input from a config file, but in a file that can literally be executed while being loaded, anyone can put anything in there, and go completely rogue.

Re: Makefile.PL does not always install changed file
by daxim (Curate) on Jun 13, 2019 at 08:55 UTC

      This works out of the box with Module::Build. Time to switch?

      die SPAM;

Re: Makefile.PL does not always install changed file ( postamble )
by Anonymous Monk on Jun 14, 2019 at 01:02 UTC

    Hi

    postamble? esp from File::ShareDir::Install ?

    Don't do that.

    Do this instead

    use ExtUtils::MakeMaker 'prompt'; MyConfigStuff(); WriteMakeFile( ...