How does perl know it's environment.

S

Sam Holden

I find it hard to believe that perl has that information built in.
More likely it has some mechaqnism to find out where.

How hard you find something to believe has little bearing on whether it is true:

; strings `which perl` | grep /usr
/usr/share/perl/5.8
/usr/bin
/usr/local/lib/perl/5.8.4
/usr/local/share/perl/5.8.4
/usr/lib/perl5
/usr/share/perl5
/usr/lib/perl/5.8
/usr/local/lib/site_perl
 
J

Joe Smith

TLOlczyk said:
I've scoured the documentation and have not been able to find
an an answer to the following question.

It's documented in the procedure to compile perl from its sources.
Assuming there are no environmental variables set specifically
for perl. How does perl know where to find it's installed
packages, where to install packages, location of the library etc.
Especially in a custom build where the locationsd are in
nontradfitional packages.

On Unix-type systems, the value of @INC is compiled into the binary.

linux% perl -le 'print "@INC"'
/usr/lib/perl5/5.8.3/i586-linux /usr/lib/perl5/5.8.3
/usr/lib/perl5/site_perl/5.8.3/i586-linux /usr/lib/perl5/site_perl/5.8.3
/usr/lib/perl5/site_perl .
linux% strings /usr/bin/perl | grep 'lib/perl'
/usr/lib/perl5/5.8.3
/usr/lib/perl5/site_perl
/usr/lib/perl5/5.8.3/i586-linux
/usr/lib/perl5/site_perl/5.8.3/i586-linux
/usr/lib/perl5/site_perl/5.8.3

The command
perl -V
displays some of the compiled-in values, and uses the contents
of %Config (defined in Config.pm) to display the other values.

At one time, the perl for Windows had dummy values compiled into @INC;
its installer would rewrite those strings to the correct value.
-Joe
 
A

Alan Stewart

But yet another false one - on Unix, at least.


"ldd /usr/bin/perl" gives:
libperl.so => /usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE/libperl.so (0x40017000)
(among other libraries -- and no, that path doesn't change just by copying
/usr/bin/perl somewhere else; it's hardcoded into the binary)

I assume that if you just copied /usr/bin/perl somewhere, that it
found libperl.so in LD_LIBRARY_PATH, not from something built into
/usr/bin/perl

What I suggested was copying both /usr/bin/perl AND libperl.so
somwhere. And you probably need to change LD_LIBRARY_PATH to point
there temporarily to do that. In Windows, I just let it find the lib
in "." first without modifying PATH.

I don't have Unix, so I don't know if it's true there or not. I am
just inferring from reading the doc on ldd. What do you see if you
move both and try "perl -V"?
Further, a search through the above shared library file finds:

What kind of search?
/usr/lib/perl5/5.8.0
/usr/lib/perl5/site_perl
/usr/lib/perl5/vendor_perl
/usr/lib/perl5/5.8.0/i386-linux-thread-multi
/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi
/usr/lib/perl5/site_perl/5.8.0
/usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi
/usr/lib/perl5/vendor_perl/5.8.0

... which very much looks like the initial @INC contents.

In Windows it could well be that some locations can be determined by
the installation location of the actual binary file;

See the example in my reply to Jonathan. At least Windows can. I
always assume that Unix can do at least as much :)
in Unix side it's
pretty much impossible to even find out where the "currently running"
executable is located in the directory hierarchy (especially given the
facts that a single file may have multiple directory entries in various
places across the directory structure, and that the file might not have
_any_ directory entry by the time it tries to determine from where it was
run).

I would expect the OS knows which of many possible paths it used to
fetch an executable file, even if it is not readily determined by an
application programmer. Again, I am only inferring from the Windows
example. A perl program may get misleading info as to the path of the
perl script, but Windows certainly knows where the perlxx.dll came
from and that is available inside the dll code.

Alan
 
A

Alan Stewart

How hard you find something to believe has little bearing on whether it is true:

; strings `which perl` | grep /usr
/usr/share/perl/5.8
/usr/bin
/usr/local/lib/perl/5.8.4
/usr/local/share/perl/5.8.4
/usr/lib/perl5
/usr/share/perl5
/usr/lib/perl/5.8
/usr/local/lib/site_perl

I hate to be argumentative, especially when I may be dead wrong, but
just because you found those strings somewhere in perl, doesn't say
how or when they are used.

Do you have an example of perl (and libperl.so) being relocated and
still using the same installed perl paths and modules? If these things
are hard-coded in, that should be possible.

Alan
 
A

Alan Stewart

It's documented in the procedure to compile perl from its sources.


On Unix-type systems, the value of @INC is compiled into the binary.

linux% perl -le 'print "@INC"'
/usr/lib/perl5/5.8.3/i586-linux /usr/lib/perl5/5.8.3
/usr/lib/perl5/site_perl/5.8.3/i586-linux /usr/lib/perl5/site_perl/5.8.3
/usr/lib/perl5/site_perl .
linux% strings /usr/bin/perl | grep 'lib/perl'
/usr/lib/perl5/5.8.3
/usr/lib/perl5/site_perl
/usr/lib/perl5/5.8.3/i586-linux
/usr/lib/perl5/site_perl/5.8.3/i586-linux
/usr/lib/perl5/site_perl/5.8.3

The command
perl -V
displays some of the compiled-in values, and uses the contents
of %Config (defined in Config.pm) to display the other values.

At one time, the perl for Windows had dummy values compiled into @INC;
its installer would rewrite those strings to the correct value.
-Joe

Thank you.

Looking at the file INSTALL, it would appear that it is set from
LD_RUN_PATH at compile time, and looking elsewhere that, on Windows,
LD_RUN_PATH is always empty. Thus the difference in behavior between
Windows and Unix.

Also stated, either LD_LIBRARY_PATH or LD_PRELOAD (depending on the
OS) can override the hardcoded values at runtime, which may explain to
the OP (and me) how a perl with paths hardcoded in can be relocated.

Alan
 
T

Tassilo v. Parseval

Also sprach Alan Stewart:
I hate to be argumentative, especially when I may be dead wrong, but
just because you found those strings somewhere in perl, doesn't say
how or when they are used.

Now this discussion is getting surreal. Once and for all, you are dead
wrong. :)

From config.h of my recently compiled 5.8.4:

/* ARCHLIB:
* This variable, if defined, holds the name of the directory in
* which the user wants to put architecture-dependent public
* library files for perl5. It is most often a local directory
* such as /usr/local/lib. Programs using this variable must be
* prepared to deal with filename expansion. If ARCHLIB is the
* same as PRIVLIB, it is not defined, since presumably the
* program already searches PRIVLIB.
*/
/* ARCHLIB_EXP:
* This symbol contains the ~name expanded version of ARCHLIB, to be used
* in programs that are not prepared to deal with ~ expansion at run-time.
*/
#define ARCHLIB "/usr/opt/perldb/lib/5.8.4/i686-linux" /**/
#define ARCHLIB_EXP "/usr/opt/perldb/lib/5.8.4/i686-linux" /**/

.....

/* PRIVLIB:
* This symbol contains the name of the private library for this package.
* The library is private in the sense that it needn't be in anyone's
* execution path, but it should be accessible by the world. The program
* should be prepared to do ~ expansion.
*/
/* PRIVLIB_EXP:
* This symbol contains the ~name expanded version of PRIVLIB, to be used
* in programs that are not prepared to deal with ~ expansion at run-time.
*/
#define PRIVLIB "/usr/opt/perldb/lib/5.8.4" /**/
#define PRIVLIB_EXP "/usr/opt/perldb/lib/5.8.4" /**/

[ and so on ]

And now from perl.c:

#else
#ifndef PRIVLIB_EXP
# define PRIVLIB_EXP "/usr/local/lib/perl5:/usr/local/lib/perl"
#endif
#if defined(WIN32)
incpush(PRIVLIB_EXP, TRUE, FALSE, TRUE);
#else
incpush(PRIVLIB_EXP, FALSE, FALSE, TRUE);
#endif

#ifdef SITEARCH_EXP
/* sitearch is always relative to sitelib on Windows for
* DLL-based path intuition to work correctly */
# if !defined(WIN32)
incpush(SITEARCH_EXP, FALSE, FALSE, TRUE);
# endif
#endif

#ifdef SITELIB_EXP
# if defined(WIN32)
/* this picks up sitearch as well */
incpush(SITELIB_EXP, TRUE, FALSE, TRUE);
# else
incpush(SITELIB_EXP, FALSE, FALSE, TRUE);
# endif
#endif

#ifdef SITELIB_STEM /* Search for version-specific dirs below here */
incpush(SITELIB_STEM, FALSE, TRUE, TRUE);
#endif

where incpush() is S_incpush which eventually does after some checks and
transformations:

/* finally push this lib directory on the end of @INC */
av_push(GvAVn(PL_incgv), libdir);
Do you have an example of perl (and libperl.so) being relocated and
still using the same installed perl paths and modules? If these things
are hard-coded in, that should be possible.

Why an example? It's all in the source. Besides, that's how Perl
behaves.

ethan:/usr/opt# ls -l
total 32
drwxr-xr-x 5 root root 4096 Oct 14 2003 perl-5.8.1
drwxr-xr-x 5 root root 4096 Dec 11 2003 perl-maint
drwxr-xr-x 5 root root 4096 Sep 2 2003 perl5.5.3
drwxr-xr-x 5 root root 4096 Dec 9 2003 perl5.6.0
drwxr-xr-x 5 root root 4096 Mar 20 2003 perl5.6.1
drwxr-xr-x 5 root root 4096 Nov 14 2003 perl5.8.2
drwxr-xr-x 5 root root 4096 Aug 6 2003 perl_autobox
drwxr-xr-x 4 root root 4096 Jun 17 05:34 perldb
ethan:/usr/opt# perl5.6.1/bin/perl -V
Summary of my perl5 (revision 5.0 version 6 subversion 1) configuration:
...
ethan:/usr/opt# mv perl5.6.1/ perl5.6.1_
ethan:/usr/opt# perl5.6.1_/bin/perl -V
Can't locate Config.pm in @INC (@INC contains:
/usr/opt/perl5.6.1/lib/5.6.1/i686-linux /usr/opt/perl5.6.1/lib/5.6.1
/usr/opt/perl5.6.1/lib/site_perl/5.6.1/i686-linux
/usr/opt/perl5.6.1/lib/site_perl/5.6.1
/usr/opt/perl5.6.1/lib/site_perl .).
BEGIN failed--compilation aborted.

Tassilo
 
J

Joe Smith

Alan said:
I would expect the OS knows which of many possible paths it used to
fetch an executable file, even if it is not readily determined by an
application programmer.

No, it doesn't. A Unix-like OS knows the inode number of the file that
the currently executing binary came from, but not the name.
(The file's directory may have been renamed while the program was
running. The file itself may have been deleted while the program
was running.) Unix works in a manner a lot different than Windows.
-Joe
 
J

Joe Smith

Alan said:
Looking at the file INSTALL, it would appear that it is set from
LD_RUN_PATH at compile time, and looking elsewhere that, on Windows,
LD_RUN_PATH is always empty. Thus the difference in behavior between
Windows and Unix.

LD_LIBRARY_PATH and LD_RUN_PATH affect how *.so (sharable objects; the
Unix equivalent of DLLs) are located. It does not affect @INC,
and therefore does not affect the way the perl locates modules
for 'use' and 'require'.
-Joe
 
J

Juha Laiho

Alan Stewart said:
I assume that if you just copied /usr/bin/perl somewhere, that it
found libperl.so in LD_LIBRARY_PATH, not from something built into
/usr/bin/perl

LD_LIBRARY_PATH will be used, if the library is not found from the path
built into the binary, yes. But for packages like Perl (that are rather
straightforward to compile, and compiler tools tend to be readily
available), use of LD_LIBRARY_PATH doesn't make sense. If you build
perl, you install it like you stated in the configure.
I don't have Unix, so I don't know if it's true there or not. I am
just inferring from reading the doc on ldd. What do you see if you
move both and try "perl -V"?

The other include paths stay the same, they don't change.
What kind of search?

strings libperl.so | grep /usr/lib

(so, "strings" will dump all printable sequences of characters
out of a binary file, and "grep" just filters the output to the
lines containing text /usr/lib)
I would expect the OS knows which of many possible paths it used to
fetch an executable file, even if it is not readily determined by an
application programmer.

The OS (depending on the Unix variant) may or may not retain that
information, but generally it's of no use, as it cannot be relied upon
(and the information shouldn't be considered to be available for the
application programs).

This is one place where the mindset for Unix and Windows software
developments differ.

In Unix, the location of an executable file shouldn't be used for
locating any corresponding configuration or other auxiliary files.
Either the main configuration file is in some fixed (compiled-in)
location, or the configuration file location is specified by an
environment variable or a command-line parameter. The idea is to
have executable binaries for all programs in one directory (or in
a certain set of directories), and the configuration and auxiliary
files in another set of directories. This f.ex. facilitates the use of
network-shared drives for storing the executables, thus leaving the
configuration files local for each separate machine running the same
set of executables.

In Windows, there's a way for a program to find out from where it
was launched (and as I understand, it's pretty much impossible to do
anything to an executable program while it is in use), so it makes
sense to some extent to use the executable file location for locating
the auxiliary files (but then, doing this makes it harder to share
the executables for several machines while still having per-machine
configuration files).
 
A

Alan Stewart

On Fri, 16 Jul 2004 10:43:25 +0200, "Tassilo v. Parseval"

[snipped]
Why an example? It's all in the source. Besides, that's how Perl
behaves.

ethan:/usr/opt# ls -l
total 32
drwxr-xr-x 5 root root 4096 Oct 14 2003 perl-5.8.1
drwxr-xr-x 5 root root 4096 Dec 11 2003 perl-maint
drwxr-xr-x 5 root root 4096 Sep 2 2003 perl5.5.3
drwxr-xr-x 5 root root 4096 Dec 9 2003 perl5.6.0
drwxr-xr-x 5 root root 4096 Mar 20 2003 perl5.6.1
drwxr-xr-x 5 root root 4096 Nov 14 2003 perl5.8.2
drwxr-xr-x 5 root root 4096 Aug 6 2003 perl_autobox
drwxr-xr-x 4 root root 4096 Jun 17 05:34 perldb
ethan:/usr/opt# perl5.6.1/bin/perl -V
Summary of my perl5 (revision 5.0 version 6 subversion 1) configuration:
...
ethan:/usr/opt# mv perl5.6.1/ perl5.6.1_
ethan:/usr/opt# perl5.6.1_/bin/perl -V
Can't locate Config.pm in @INC (@INC contains:
/usr/opt/perl5.6.1/lib/5.6.1/i686-linux /usr/opt/perl5.6.1/lib/5.6.1
/usr/opt/perl5.6.1/lib/site_perl/5.6.1/i686-linux
/usr/opt/perl5.6.1/lib/site_perl/5.6.1
/usr/opt/perl5.6.1/lib/site_perl .).
BEGIN failed--compilation aborted.

Tassilo

Thank you for providing the source pointers. The source is always the
ultimate place to go, but I hope that having read all the source (or
even being able to) hasn't become a prerequisite to asking questions
about the behavior of perl.

Thanks also for providing the example I asked for. As I said, I don't
have the appropriate OS available to observe this behavior, so what is
obvious to you was not to me. And it is counter to what I have
observed for Windows. I see that difference also in the source comment
regarding DLL-based intuiting.

The only reason I jumped into this thread is because I work on PAR and
test it under Windows. PAR works by unzipping copies of modules and
libraries into a non-installation temp dir for execution, thus
triggering the situation I have been trying to understand here. PAR is
cross platform, so I hoped to gain some knowledge of the differences
between the way Unix/Linux perl and Windows perl determine what's
going on in a non-standard environment.

If I had multiple platforms, or enough time to study the source, I'd
figure it out by myself. But I will be more careful to caveat my
statements to what I have seen. I didn't intend to argue about Unix,
but to get a comparison.

As the OP said, you can read a lot of docs and know what, but not how.

Alan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,565
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top