1File::ShareDir::ProjectUDsiesrtDCiorn(t3r)ibuted Perl DoFciulmee:n:tSahtairoenDir::ProjectDistDir(3)
2
3
4

NAME

6       File::ShareDir::ProjectDistDir - Simple set-and-forget using of a
7       '/share' directory in your projects root
8

VERSION

10       version 1.000009
11

DETERRENT

13       STOP!. Before using this distribution, some warnings MUST be
14       considered.
15
16       The primary use-case for this module is targeted at development
17       projects that are NOT intended for "CPAN".
18
19       As such, using it for "CPAN" is generally a bad idea, and better
20       solutions generally involve the less fragile "Test::File::ShareDir",
21       constraining any magical behavior exclusively to where it is needed:
22       Tests.
23
24       Why?
25
26       •   Determining whether or not we are "dev" during "runtime" is a
27           perilous heuristic that routinely fails with even slightly unusual
28           file system layouts.
29
30       •   Auto-magical changing of behavior at "runtime" based on the above
31           leads to many surprising and hard to debug problems.
32
33       For these reason, it is dangerous to rely on this distribution while
34       striving to produce quality code.
35
36       If this documentation is not sufficient to dissuade you, I must
37       strongly implore you to choose the "strict" mechanism, because that
38       substantially reduces the possibilities with regards to false-positive
39       of potential "dev" directories.
40
41       I have in mind to find a better mechanism to deliver the same
42       objective, but no solutions are forthcoming at this time.
43

SYNOPSIS

45         package An::Example::Package;
46
47         use File::ShareDir::ProjectDistDir;
48
49         # during development, $dir will be $projectroot/share
50         # but once installed, it will be wherever File::Sharedir thinks it is.
51         my $dir = dist_dir('An-Example')
52
53       Project layout requirements:
54
55         $project/
56         $project/lib/An/Example/Package.pm
57         $project/share/   # files for package 'An-Example' go here.
58
59       You can use a directory name other than 'share' ( Assuming you make
60       sure when you install that, you specify the different directory there
61       also ) as follows:
62
63         use File::ShareDir::ProjectDistDir ':all', defaults => {
64           projectdir => 'templates',
65         };
66

METHODS

68   import
69           use File::ShareDir::ProjectDistDir (@args);
70
71       This uses "Sub::Exporter" to do the heavy lifting, so most usage of
72       this module can be maximized by understanding that first.
73
74":all"
75
76               ->import( ':all' , .... )
77
78           Import both "dist_dir" and "dist_file"
79
80"dist_dir"
81
82               ->import('dist_dir' , .... )
83
84           Import the dist_dir method
85
86"dist_file"
87
88               ->import('dist_file' , .... )
89
90           Import the dist_file method
91
92"projectdir"
93
94               ->import( .... , projectdir => 'share' )
95
96           Specify what the project directory is as a path relative to the
97           base of your distributions source, and this directory will be used
98           as a "ShareDir" simulation path for the exported methods During
99           development.
100
101           If not specified, the default value 'share' is used.
102
103"filename"
104
105               ->import( .... , filename => 'some/path/to/foo.pm' );
106
107           Generally you don't want to set this, as its worked out by caller()
108           to work out the name of the file its being called from. This file's
109           path is walked up to find the 'lib' element with a sibling of the
110           name of your "projectdir".
111
112"distname"
113
114               ->import( .... , distname => 'somedistname' );
115
116           Specifying this argument changes the way the functions are emitted
117           at installed "runtime", so that instead of taking the standard
118           arguments File::ShareDir does, the specification of the "distname"
119           in those functions is eliminated.
120
121           i.e:
122
123               # without this flag
124               use File::ShareDir::ProjectDistDir qw( :all );
125
126               my $dir = dist_dir('example');
127               my $file = dist_file('example', 'path/to/file.pm' );
128
129               # with this flag
130               use File::ShareDir::ProjectDistDir ( qw( :all ), distname => 'example' );
131
132               my $dir = dist_dir();
133               my $file = dist_file('path/to/file.pm' );
134
135"strict"
136
137               ->import( ... , strict => 1 );
138
139           This parameter specifies that all "dist" "sharedirs" will occur
140           within the "projectdir" directory using the following layout:
141
142               <root>/<projectdir>/dist/<DISTNAME>/
143
144           As opposed to
145
146               <root>/<projectdir>
147
148           This means if Heuristics misfire and accidentally find another
149           distributions "share" directory, it will not pick up on it unless
150           that "share" directory also has that layout, and will instead
151           revert to the "installdir" path in @INC
152
153           This parameter may become the default option in the future
154
155           Specifying this parameter also mandates you MUST declare the
156           "DISTNAME" value in your file somewhere. Doing otherwise is
157           considered insanity anyway.
158
159"defaults"
160
161               ->import( ... , defaults => {
162                   filename => ....,
163                   projectdir => ....,
164               });
165
166           This is mostly an alternative syntax for specifying "filename" and
167           "projectdir", which is mostly used internally, and their
168           corresponding other values are packed into this one.
169
170       Sub::Exporter tricks of note.
171
172       Make your own sharedir util
173
174           package Foo::Util;
175
176           sub import {
177               my ($caller_class, $caller_file, $caller_line )  = caller();
178               if ( grep { /share/ } @_ ) {
179                   require File::ShareDir::ProjectDistDir;
180                   File::ShareDir::ProjectDistDir->import(
181                       filename => $caller_file,
182                       dist_dir => { distname => 'myproject' , -as => 'share' },
183                       dist_dir => { distname => 'otherproject' , -as => 'other_share' , projectdir => 'share2' },
184                       -into => $caller_class,
185                   );
186               }
187           }
188
189           ....
190
191           package Foo;
192           use Foo::Util qw( share );
193
194           my $dir = share();
195           my $other_dir => other_share();
196
197   build_dist_dir
198           use File::ShareDir::ProjectDirDir ( : all );
199
200           #  this calls
201           my $coderef = File::ShareDir::ProjectDistDir->build_dist_dir(
202             'dist_dir' => {},
203             { defaults => { filename => 'path/to/yourcallingfile.pm', projectdir => 'share' } }
204           );
205
206           use File::ShareDir::ProjectDirDir ( qw( :all ), distname => 'example-dist' );
207
208           #  this calls
209           my $coderef = File::ShareDir::ProjectDistDir->build_dist_dir(
210             'dist_dir' => {},
211             { distname => 'example-dist', defaults => { filename => 'path/to/yourcallingfile.pm', projectdir => 'share' } }
212           );
213
214           use File::ShareDir::ProjectDirDir
215             dist_dir => { distname => 'example-dist', -as => 'mydistdir' },
216             dist_dir => { distname => 'other-dist',   -as => 'otherdistdir' };
217
218           # This calls
219           my $coderef = File::ShareDir::ProjectDistDir->build_dist_dir(
220             'dist_dir',
221             { distname => 'example-dist' },
222             { defaults => { filename => 'path/to/yourcallingfile.pm', projectdir => 'share' } },
223           );
224           my $othercoderef = File::ShareDir::ProjectDistDir->build_dist_dir(
225             'dist_dir',
226             { distname => 'other-dist' },
227             { defaults => { filename => 'path/to/yourcallingfile.pm', projectdir => 'share' } },
228           );
229
230           # And leverages Sub::Exporter to create 2 subs in your package.
231
232       Generates the exported 'dist_dir' method. In development environments,
233       the generated method will return a path to the development directories
234       'share' directory. In non-development environments, this simply returns
235       "File::ShareDir::dist_dir".
236
237       As a result of this, specifying the Distribution name is not required
238       during development ( unless in "strict" mode ), however, it will start
239       to matter once it is installed. This is a potential avenues for bugs if
240       you happen to name it wrong.
241
242       In "strict" mode, the distribution name is ALWAYS REQUIRED, either at
243       least at "import" or dist_dir() time.
244
245   build_dist_file
246           use File::ShareDir::ProjectDirDir ( : all );
247
248           #  this calls
249           my $coderef = File::ShareDir::ProjectDistDir->build_dist_file(
250             'dist_file' => {},
251             { defaults => { filename => 'path/to/yourcallingfile.pm', projectdir => 'share' } }
252           );
253
254           use File::ShareDir::ProjectDirDir ( qw( :all ), distname => 'example-dist' );
255
256           #  this calls
257           my $coderef = File::ShareDir::ProjectDistDir->build_dist_file(
258             'dist_file' => {},
259             { distname => 'example-dist', defaults => { filename => 'path/to/yourcallingfile.pm', projectdir => 'share' } }
260           );
261
262           use File::ShareDir::ProjectDirDir
263             dist_file => { distname => 'example-dist', -as => 'mydistfile' },
264             dist_file => { distname => 'other-dist',   -as => 'otherdistfile' };
265
266           # This calls
267           my $coderef = File::ShareDir::ProjectDistDir->build_dist_file(
268             'dist_file',
269             { distname => 'example-dist' },
270             { defaults => { filename => 'path/to/yourcallingfile.pm', projectdir => 'share' } },
271           );
272           my $othercoderef = File::ShareDir::ProjectDistDir->build_dist_file(
273             'dist_file',
274             { distname => 'other-dist' },
275             { defaults => { filename => 'path/to/yourcallingfile.pm', projectdir => 'share' } },
276           );
277
278           # And leverages Sub::Exporter to create 2 subs in your package.
279
280       Generates the 'dist_file' method.
281
282       In development environments, the generated method will return a path to
283       the development directories 'share' directory. In non-development
284       environments, this simply returns "File::ShareDir::dist_file".
285
286       Caveats as a result of package-name as stated in "build_dist_dir" also
287       apply to this method.
288

SIGNIFICANT CHANGES

290   1.000000
291       Strict Mode.
292
293       Using Strict Mode
294
295           use File::ShareDir::ProjectDistDir ':all', strict => 1;
296           use File::ShareDir::ProjectDistDir 'dist_dir' => { strict => 1 };
297
298       Why you should use strict mode
299
300       Starting with 1.000000, there is a parameter "strict" that changes how
301       "sharedir" resolution performs.
302
303       Without strict:
304
305           lib/...
306           share/...
307
308       With strict
309
310           lib/...
311           share/dist/Dist-Name-Here/...
312
313       This technique greatly builds resilience to the long standing problem
314       with "develop" vs "install" heuristic ambiguity.
315
316       Here at least,
317
318           dist_dir('Dist-Name')
319
320       Will instead fall back to
321
322           @INC/auto/share/dist/Dist-Name
323
324       When
325
326           share/dist/Dist-Name
327
328       Does not exist.
329
330       This means if you have a layout like this:
331
332           <DEVROOT>/inc/<a local::lib path here>
333           <DEVROOT>/lib/<development files here>
334
335       Then when "Foo-Bar-Baz" is installed as:
336
337           <DEVROOT>/inc/lib/Foo/Bar/Baz.pm
338           <DEVROOT>/inc/lib/auto/share/dist/Foo-Bar-Baz
339
340       Then "Baz.pm" will not see the "DEVROOT" and assume "Hey, this is
341       development" and then proceed to try finding files in "DEVROOT/share"
342
343       Instead, "DEVROOT" must have "DEVROOT/share/dist/Foo-Bar-Baz" too,
344       otherwise it reverts to "DEVROOT/inc/lib/auto..."
345
346       "Path::Class" interfaces deprecated and dependency dropped.
347
348       If you have any dependence on this function, now is the time to get
349       yourself off it.
350
351       Minimum Changes to stay with "Path::Class" short term.
352
353       As the dependency has been dropped on "Path::Class", if you have "CPAN"
354       modules relying on "Path::Class" interface, you should now at a very
355       minimum start declaring
356
357           { requires => "Path::Class" }
358
359       This will keep your dist working, but will not be future proof against
360       further changes.
361
362       Staying with "Path::Class" long term.
363
364       Recommended approach if you want to stay using the "Path::Class"
365       interface:
366
367           use File::ShareDir::... etc
368           use Path::Class qw( dir file );
369
370           my $dir = dir( dist_dir('Dist-Name') );
371
372       This should future-proof you against anything File::ShareDir may do in
373       the future.
374
375       "Versioning Scheme arbitrary converted to float"
376
377       This change is a superficial one, and should have no bearing on how
378       significant you think this release is.
379
380       It is a significant release, but the primary reason for the version
381       change is simply to avoid compatibility issues in versions themselves.
382
383       However, outside that, "x.y.z" semantics are still intended to be semi-
384       meaningful, just with less "." and more 0 ☺
385
386       "dev" path determination now deferred to call time instead of "use"
387
388       This was essentially a required change to make "strict" mode plausible,
389       because strict mode _requires_ the "distname" to be known, even in the
390       development environment.
391
392       This should not have any user visible effects, but please, if you have
393       any problems, file a bug.
394
395       "file" component determination wrested from "File::ShareDir".
396
397           dist_file('foo','bar')
398
399       Is now simply sugar syntax for
400
401           path(dist_dir('foo'))->child('bar')
402
403       This should have no side effects in your code, but please file any bugs
404       you experience.
405
406       ( return value is still "undef" if the file does not exist, and still
407       "croak"'s if the file is not a file, or unreadable, but these may both
408       be subject to change )
409
410   0.5.0 - Heuristics and Return type changes
411       New "devdir" heuristic
412
413       Starting with 0.5.0, instead of using our simple "lib/../share" pattern
414       heuristic, a more advanced heuristic is used from the new
415       "Path::FindDev" and "Path::IsDev".
416
417       This relies on a more "concrete" marker somewhere at the top of your
418       development tree, and more importantly, checks for the existence of
419       specific files that are not likely to occur outside a project root.
420
421       "lib" and "share" based heuristics were a little fragile, for a few
422       reasons:
423
424       •   "lib" can, and does appear all over UNIX file systems, for purposes
425           other than development project roots.
426
427           For instance, have a look in "/usr/"
428
429               /usr/bin
430               /usr/lib
431               /usr/share  ## UHOH.
432
433           This would have the very bad side effect of anything installed in
434           "/usr/lib" thinking its "in development".
435
436           Fortunately, nobody seems to have hit this specific bug, which I
437           suspect is due only to "/usr/lib" being a symbolic link on most
438           x86_64 systems.
439
440       •   "lib" is also reasonably common within "CPAN" package names.
441
442           For instance:
443
444               lib::abs
445
446           Which means you'll have a hierarchy like:
447
448               $PREFIX/lib/lib/abs
449
450           All you need for something to go horribly wrong would be for
451           somebody to install a "CPAN" module named:
452
453               share::mystuff
454
455           Or similar, and instantly, you have:
456
457               $PREFIX/lib/lib/
458               $PREFIX/lib/share/
459
460           Which would mean any module calling itself "lib::*" would be unable
461           to use this module.
462
463       So instead, as of 0.5.0, the heuristic revolves around certain specific
464       files being in the "dev" directory.
465
466       Which is hopefully a more fault resilient mechanism.
467
468       New Return Types
469
470       Starting with 0.5.0, the internals are now based on "Path::Tiny"
471       instead of "Path::Class", and as a result, there may be a few glitches
472       in transition.
473
474       Also, previously you could get a "Path::Class::*" object back from
475       "dist_dir" and "dist_file" by importing it as such:
476
477           use File::ShareDir::ProjectDistDir
478               qw( dist_dir dist_file ),
479               defaults => { pathclass => 1 };
480
481       Now you can also get "Path::Tiny" objects back, by passing:
482
483           use File::ShareDir::ProjectDistDir
484               qw( dist_dir dist_file ),
485               defaults => { pathtiny => 1 };
486
487       For the time being, you can still get Path::Class objects back, it is
488       deprecated since 1.000000
489
490       ( In fact, I may even make 2 specific sub-classes of "PDD" for people
491       who want objects back, as it will make the "API" and the code much
492       cleaner )
493

AUTHOR

495       Kent Fredric <kentnl@cpan.org>
496
498       This software is copyright (c) 2017 by Kent Fredric <kentnl@cpan.org>.
499
500       This is free software; you can redistribute it and/or modify it under
501       the same terms as the Perl 5 programming language system itself.
502
503
504
505perl v5.38.0                      2023-07-20 File::ShareDir::ProjectDistDir(3)
Impressum