8

I maintain multiple Perl written (unix-ish) applications whose current installation process consists of a manually written Makefile and installs configuration files into /etc/.

I'd really like to switch their development to use Dist::Zilla, but so far I haven't found any Dist::Zilla plugin or feature which allows me to put given files into /etc/ when the make install (or ./Build install in case of using Module::Build instead of ExtUtils::MakeMaker) is run by the local administrator who's installing my application.

With pure ExtUtils::MakeMaker, I could define additional make targets in MY::postamble and the let the install target depend on one of them via the depend { install => … } attribute. Doing something similar, but via dzil build, would probably suffice, but I'd appreciate a more obvious way.

One orthogonal approach would be to make the application not to require the files under /etc/ to exist, but for just switching to Dist::Zilla that seems to much change in the actual code despite I only want to change the build system for now.

For the curious: the two applications I currently have in mind for switching to Dist::Zilla are xen-tools and unburden-home-dir.

Miller
  • 34,962
  • 4
  • 39
  • 60
Axel Beckert
  • 6,814
  • 1
  • 22
  • 23

2 Answers2

4

The best thing to do is to avoid installing files into /etc from any Perl distribution. You cannot ensure that the cpan client (or the installing user) has permissions to install there, and there can be multiple Perls installed on a system, so each one of them would clobber the /etc files of another install. You can't really prevent the file from being overwritten by a subsequent install, so you shouldn't put config data there that you don't want to lose.

You could put the config file in /etc/, if the application knows to look for it there, but you should allow for that path to be customized (say on a test system, look for the file in the local directory, or in a user's home directory).

For installing read-only module-specific data, the best practice in Perl is to install into a Perl-install-specific location, and the module to do that is File::ShareDir::Install. You can use it from Dist::Zilla using the [ShareDir] plugin, Dist::Zilla::Plugin::ShareDir. It is even included in the [@Basic] plugin bundle, so if you use [@Basic] in your dist.ini, you don't need to do anything at all, other than drop your data files into the share/ directory in your distribution repository.

To access the contents of the sharedir from code, use File::ShareDir.

sebthebert
  • 12,196
  • 2
  • 26
  • 37
Ether
  • 53,118
  • 13
  • 86
  • 159
  • 1
    Another way to put it: Allow users to write to `/etc/`, but make it user responsbility to write to `/etc/`, and then, only if they want to override the defaults. If they don't want to override the defaults, then they're happy using whatever your distributions ships in its `share/` directory which you can obiliterate at will without any crying. – Kent Fredric Sep 29 '14 at 18:05
  • Of course the install path for configuration files needs to be configurable for those cases where there's no write permission. I though have not yet a good idea about the overwriting thing. So far that's handled by the distribution packagers for those two applications, but the packagers need/prefer the application to install configuration files to `$PREFIX/etc/` as that's where they put it. Read-only module-specific data is a different topic, but a no-brainer indeed. – Axel Beckert Sep 29 '14 at 19:33
2

For porting a complex module installer to Dist::Zilla, I recommend my plugins MakeMaker::Custom or ModuleBuild::Custom, depending on which installer you prefer. These allow you to keep your existing Makefile.PL or Build.PL and just have Dist::Zilla plug in necessary bits like the dependencies.

cjm
  • 61,471
  • 9
  • 126
  • 175
  • Hrm. According to the synopsis of Dist::Zilla::Plugin::MakeMaker::Custom, it requires quite a lot of boilerplate code (of which I'm not yet sure what all of it actually does). I see that one feature is that the `Makefile.PL` still works without `dzil build`, but I don't need that at all and rather expected something which would just have `##{ $ALL_EXCEPT_WriteMakefile ##}` then adding very few lines of additional code which maybe modifies `%args`, and a final `WriteMakefile(%args);`, i.e. with the whole file not needing more than a few lines plus my additions. – Axel Beckert Sep 25 '14 at 15:04
  • 1
    @XTaran, most of the boilerplate is just what a traditional `Makefile.PL` looks like. All the `unless ... eval` stuff is doing is adding compatibility with old versions of [ExtUtils::MakeMaker](https://metacpan.org/pod/ExtUtils::MakeMaker). Instead, you could either raise the minimum version of ExtUtils::MakeMaker or just not try to use those features at all. – cjm Sep 25 '14 at 15:11
  • Thanks, that makes it way shorter and comprehensible. :-) I suggest to add that information to the POD _before_ the paragraph "Of course, your Makefile.PL should be more complex than that, or you don't need this plugin." which more or less suggests that it can be complexer, but not less complex. And maybe replace that "should" with "could" and drop the phrase "or you don't need this plugin". – Axel Beckert Sep 25 '14 at 15:16