What is the meaning/purpose of the "=" that sometimes appears in the SEARCH_DIR command in binutils' ldscripts? - gnu

When I build binutils, the ldscripts folder contains several files that are used by ld to determine how to link objects for a particular platform. In the scripts I see lines like:
SEARCH_DIR("/Volumes/CaseSensitive/Developer/XCF/x86_64-pc-linux-gnu/gcc47/x86_64-pc-linux-gnu/lib64");
SEARCH_DIR("=/usr/local/lib64"); SEARCH_DIR("=/lib64"); SEARCH_DIR("=/usr/lib64"); SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib");
What is the meaning/purpose of the "=" that appears in the SEARCH_DIR command?
According to the documentation at http://www.sourceware.org/binutils/docs-2.12/ld.info/File-Commands.html,
The SEARCH_DIR command adds path to the list of paths where ld looks for archive libraries. Using SEARCH_DIR(path) is exactly like using -L path on the command line (see Command Line Options). If both are used, then the linker will search both paths. Paths specified using the command line option are searched first.
And, according to the Command Line Options:
Add path searchdir to the list of paths that ld will search for archive libraries and ld control scripts. You may use this option any number of times. The directories are searched in the order in which they are specified on the command line. Directories specified on the command line are searched before the default directories. All -L options apply to all -l options, regardless of the order in which the options appear.
The default set of paths searched (without being specified with -L) depends on which emulation mode ld is using, and in some cases also on how it was configured. See Environment.
The paths can also be specified in a link script with the SEARCH_DIR command. Directories specified this way are searched at the point in which the linker script appears in the command line.
But no where does it state what the meaning/purpose of the "=". None of the folders in my directory structure begin with an "=" sign, so it must have some undocumented significance.
Any help would be greatly appreciated.
Thanks,
Kevin

the = prefixes the path with the sysroot if one is active. if one isn't, then the = is simply dropped.
the docs you're looking at are woefully old. if you consult the latest [1] it clearly documents this behavior:
-L searchdir
--library-path=searchdir
...
If searchdir begins with =, then the = will be replaced by the sysroot prefix, controlled by the `--sysroot' option, or specified when the linker is configured.
...
The paths can also be specified in a link script with the SEARCH_DIR command. Directories specified this way are searched at the point in which the linker script appears in the command line.
[1] https://sourceware.org/binutils/docs/ld/Options.html

Related

Should PATH contain directories or full paths to binaries?

I am trying to set up a correct PATH, but I'm wondering what it should contain. If I have
/usr/bin/ls
/usr/local/bin/ls
and I want to prefer the one in /usr/local/bin, which of the following should I use?
PATH=/usr/local/bin/ls:/usr/bin/ls
PATH=/usr/local/bin:/usr/bin
or something else entirely?
This is not per se a suitable question for Stack Overflow.
I expect this to be closed as General Computing or Too Broad;
but the answer is frequently needed by beginners, so I hope this won't be deleted.
PATH works only with directories, not with single files
From the POSIX standard (emphasis mine)
PATH
This variable shall represent the sequence of path prefixes that certain functions and utilities apply in searching for an executable file known only by a filename. The prefixes shall be separated by a colon ( ':' ). [...] The list shall be searched from beginning to end, applying the filename to each prefix, until an executable file with the specified name and appropriate execution permissions is found.
When you type in ls into your shell and your PATH is set to /usr/local/bin/ls:/usr/bin/ls then your shell will …
… look for an executable with the path /usr/local/bin/ls/ls (note the double ls at the end).
As that path does not exist on your system your shell will proceed to look for an executable with the path /usr/bin/ls/ls (double ls again). That path also doesn't exist.
The shell couldn't find an executable using all paths in PATH so your shell will print something like bash: ls: command not found.
So, what did we learn? Paths listed by PATH have to be directories. You cannot list single files. Therefore the correct answer in your case is PATH=/usr/local/bin:/usr/bin.
Where things get interesting
Imagine the following situation. You have two versions of program c1 and two versions of program c2. The different versions are stored in the directories /a/ and /b/.
/a/c1
/a/c2
/b/c1
/b/c2
How can we set PATH to prefer /a/c1 over /b/c1/ but at the same time /b/c2 over /a/c2?
Sadly, there is no way to achieve this directly as we can only specify directories in PATH. We have to move/rename some files or create symlinks and use the symlinks inside the paths. One possible solution:
mkdir /c
ln -s /a/c1 /c/c1
ln -s /b/c2 /c/c2
export PATH=/c:/a:/b
The trailing :/a:/b is not really necessary here. I included them under the assumption that /a and /b contain more executables than just c1 and c2.
Indeed, as you can easily find out through experimentation, the variable PATH should already contain a list of directories which are consulted in that order. In fact, you should already find that you have /usr/local/bin and /usr/bin in the default PATH, usually in this order (though perhaps with other directories between them, and certainly with more directories around them).
To inspect your current PATH value, try
echo "$PATH"
or for a slightly more human-readable rendering
echo "${PATH//:/$'\n'}" # bash only
or
echo "$PATH" | tr ':' '\012' # any POSIX system
If you managed to set your PATH to an invalid value (which would cause simple commands like ls and cat to no longer be found, and produce command not found errors) you can try
PATH=/usr/local/bin:/usr/bin:/usr
to hopefully at least restore the essential functionality so that you can use cp or a simple system editor to get back to the original, safe, system default PATH.

need to include a new file with 'diff' utility as a patch

When doing "diff -bBupwr" of two directories, dir and dir.orig to capture the differences, the util doesn't include files that exist only in dir, it only reports that e.g. dir/app.c exists only in dir/, but I would like it to be added in a resulting diff file, so that it could be applied as a patch.
I checked 'man diff' but no clues was found. I'd appreciate helpful advises for this. Thanks.
Use the option -N. The man page says:
-N, --new-file
treat absent files as empty

Adding a path to the end of gcc search path

I can see that adding a path to the gcc search path can be done by using the -I flag. However, when using -v I can see that the path is being searched first.
Is there anyway I can have the search path I added, searched at the very end?
The -idirafter option allows you to specify an include directory for consideration only after all regular -I directories and the standard system directories. This is documented here:
https://gcc.gnu.org/onlinedocs/cpp/Invocation.html#Invocation
-idirafter dir
Search dir for header files, but do it after all directories specified with -I and the standard system directories have been exhausted. dir is treated as a system include directory. If dir begins with =, then the = will be replaced by the sysroot prefix; see --sysroot and -isysroot.
There is an explanation here on SO: Manipulating the search path for include files and also here which may help you.
All three methods from above are mentioned in the linked SO post.
Use the -idirafter option to add a directory to the end of the include search path.

Bash tab completion like ncftp?

In ncftp tab completion only shows the differences of matched files. E.g. with the following files
file123 file125 aa
then typing ls fil will first complete to ls file12 and show
3 5
Question
Can the same be done in Bash?
BASH supports tab-completion which is fairly robust. It is implemented through bash_completion. However, be aware that the way bash_completion is configured will depend on what options are set by default by your distribution. As for its basic functionality, it is exactly as you describe for ncftp. When a partial name is entered on the command line and tab is pressed, then a list of name-matched files are displayed. Once you have entered enough characters to make the name unique, tab will complete entry of the unique filename on the command line.
Linux also provides ls, but its behavior is not the same as you describe for ncftp. ls will return the names of files and directories that match the pattern you specified. By default, the name you provide to ls is not expanded. Meaning if you have file123 and file125 in a directory and issue the command ls file, you will be greeted by the error ls: cannot access bash: No such file or directory. But providing a wildcard (filename globbing) with ls file* will return both names.
If you have additional specific questions. Just leave a comment and we will do our best to help.

Linux: Man command in application installed only for current user

Manual files in Linux are stored in /usr/share/man. Before, my application could only be installed by a root user and it put the manual files in this directory. Now, I want to enable non-root installation; to achieve this, all my data and configuration files will be installed under ~/<appname>/. However, manual files copied to home will no longer be accessible by man command.
What are the usual workarounds to this problem?
I've thought in creating a "man" command in my application that runs man -M /<man_path>/<appname>/ (as this is easier to users than running the command by themselves). Is this a good option?
Thanks in advance.
[spatel#ap4004 appname]$ export MANPATH=/home/spatel/appname/man
[spatel#ap4004 appname]$ manpath
/home/spatel/appname/man/en:/home/spatel/appname/man
Other workaround is command alias
[spatel#ap4004 appname]$ alias man='man -M /home/spatel/appname/man'
[spatel#ap4004 appname]$ alias man
alias man='man -M /home/spatel/appname/man'
You'll need to use manpath command.
man has new behaviour by default (at least on Fedora 14 and on) that it searches in paths corresponding to PATH environment variable, i.e. for PATH=/xyz/bin it searches /xyz/bin/man, /xyz/share/man and other nearby places. Unless MANPATH is set.
You need to unset MANPATH at the end of your .bash_profile, some startup scripts in /etc may set it to spite you.
If you don't specify an explicit path list with -M or MANPATH, man develops its own path list based on the contents of the configuration file /etc/man.config. The MANPATH statements in the configuration file identify particular directories to include in the search path.
Furthermore, the MANPATH_MAP statements add to the search path depending on your command search path (i.e. your PATH environment variable). For each directory that may be in the command search path, a MANPATH_MAP statement specifies a directory that should be added to the search path for manual page files. man looks at the PATH variable and adds the corresponding directories to the manual page file search path. Thus, with the proper use of MANPATH_MAP, when you issue the command man xyz, you get a manual page for the program that would run if you issued the command xyz.
In addition, for each directory in the command search path (we'll call it a "command directory") for which you do not have a MANPATH_MAP statement, man automatically looks for a manual page directory "nearby" namely as a subdirectory in the command directory itself or in the parent directory of the command directory.
You can disable the automatic "nearby" searches by including a NOAUTOPATH statement in /etc/man.config.

Resources