Adding a path to the end of gcc search path - linux

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.

Related

setting file paths for using the "gf" command

I just learned of the gf command. and I am trying to use it but I have questions about how it defines it's paths.
if I am in foo.c which has the header foo.h in the same directory, gf works as expected. However if from foo.h, I try to get to foo_I.h, which is located in ../includes, it tells me it cannot find the file in the path. I'm not surprised it doesn't, but is there anyway I can add paths to this list?
http://vimdoc.sourceforge.net/htmldoc/editing.html#gf
Uses the 'path' option as a list of directory names to look for the file. See the 'path' option for details about relative directories and wildcards.
I.e., set path+=../includes

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.

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

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

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

How to exclude multiple directories with Exuberant ctags?

I have looked and tried to use exuberant ctags with no luck with what I want to do. I am on a Mac trying to work in a project where I want to exclude such directories as .git, node_modules, test, etc. When I try something like ctags -R --exclude=[.git, node_modules, test] I get nothing in return. I really only need to have it run in my core directory. Any ideas on how to accomplish this?
The --exclude option does not expect a list of files. According to ctags's man page, "This option may be specified as many times as desired." So, it's like this:
ctags -R --exclude=.git --exclude=node_modules --exclude=test
Read The Fantastic Manual should always be the first step of any attempt to solve a problem.
From $ man ctags:
--exclude=[pattern]
Add pattern to a list of excluded files and directories. This option may
be specified as many times as desired. For each file name considered by
both the complete path (e.g. some/path/base.ext) and the base name (e.g.
base.ext) of the file, thus allowing patterns which match a given file
name irrespective of its path, or match only a specific path. If appro-
priate support is available from the runtime library of your C compiler,
then pattern may contain the usual shell wildcards (not regular expres-
sions) common on Unix (be sure to quote the option parameter to protect
the wildcards from being expanded by the shell before being passed to
ctags; also be aware that wildcards can match the slash character, '/').
You can determine if shell wildcards are available on your platform by
examining the output of the --version option, which will include "+wild-
cards" in the compiled feature list; otherwise, pattern is matched
against file names using a simple textual comparison.
If pattern begins with the character '#', then the rest of the string is
interpreted as a file name from which to read exclusion patterns, one per
line. If pattern is empty, the list of excluded patterns is cleared.
Note that at program startup, the default exclude list contains "EIFGEN",
"SCCS", "RCS", and "CVS", which are names of directories for which it is
generally not desirable to descend while processing the --recurse option.
From the two first sentences you get:
$ ctags -R --exclude=dir1 --exclude=dir2 --exclude=dir3 .
which may be a bit verbose but that's what aliases and mappings and so on are for. As an alternative, you get this from the second paragraph:
$ ctags -R --exclude=#.ctagsignore .
with the following in .ctagsignore:
dir1
dir2
dir3
which works out to excluding those 3 directories without as much typing.
You can encapsulate a comma separated list with curly braces to handle multiples with one --exclude option:
ctags -R --exclude={folder1,folder2,folder3}
This appears to only work for folders in the root of where you're issuing the command. Excluding nested folders requires a separate --exclude option.
The other answers were straight to the point, and I thought a little example may help:
You should add an asterisk unix-like style to exclude the whole directory.
ctags -R --exclude={.git/*,.env/*,.idea/*} ./
A bit late but following on romainl response, you could use your .gitignore file as a basis, you only need to remove any leading slashes from the file, like so:
sed "s/\///" .gitignore > .ctagsignore
ctags -R --exclude=#.ctagsignore
I really only need to have it run in my core directory.
Simply remove the -R (recursion) flag!!!

Resources