Inhibit default library paths with gcc - c

Is there a way to inhibit the default library path search with gcc? -nostdinc does this for the include path search, but -nostdlib, either by omission or by design, only inhibits the -lc -lgcc etc. but not the library search paths.

You should be able to do this with spec files (although fiddling with these seems like something of a dark art to me...).
If you look at the output of gcc -dumpspecs, the link_command spec is the one that builds the actual command that is invoked. Digging through some of the other specs it references, the link_libgcc spec, which is usually defined (for native compilers at least) as:
*link_libgcc:
%D
is the culprit:
%D
Dump out a -L option for each directory that GCC believes might contain startup files. If the target supports multilibs then the current multilib directory will be prepended to each of these paths.
You can override it by creating a file (e.g. my.specs) which substitutes paths of your choice:
*link_libgcc:
-L/foo/bar -L/blah/blah
and then passing -specs=my.specs to gcc.

Supposing the underlying loader is ld you might be able to redirect its whole load path with
--sysroot=directory
(I don't remember the option that you have to use to pass loader arguments to gcc, but there is one...)
You could either have "directory" be something bogus, where no libraries are found, or mimic the directory layout for your own project.

You can try -nodefaultlibs to avoid all the default libraries, then use -L and -l to add-back the libraries you want in the directories you want.
Directories specified on the command-line with the -L option should have priority over the default directories.

How about just setting the LIBRARY_PATH environment variable?
If I understand the question correctly, you want to do something like forcing the linker to look at a local library path before the default path, so you can just explicitly set that variable to control the order.

Related

What are the "STANDARD SYSTEM DIRECTORIES" that gcc refers to? (On a unix like system)

I've been exploring compilers and cross compilers. I'm reading the GCC manual.
Specifically, there are these statements in the manual that I have queries regarding:
The linker searches a standard list of directories for the library. The directories searched include several standard system directories plus any that you specify with -L.
The -isystem and -idirafter options also mark the directory as a system directory, so that it gets the same special treatment that is applied to the standard system directories.
Alright, what are these "system directories"? On a Linux machine, what are the system directories for the native compiler?
And if I've built a cross compiler (like the one shown here: https://wiki.osdev.org/GCC_Cross-Compiler), what are the "system directories" with respect to this compiler?
Can I change the system directory when I build GCC? Moreover, Where does sysroot come into the picture?
The "standard" system directories aren't specific directories - it may vary across installations/distributions.
gcc has an option -print-search-dirs. Using which you can get the list of directories, it looks for.
Something like:
gcc -print-search-dirs | grep libraries | sed 's/libraries: =//g' | tr ':' '\n' | xargs readlink -f
It's the same for cross compiler's too (you'd call cross compiler's front-end instead of plain gcc).
--sysroot is straightward:
--sysroot=dir Use dir as the logical root directory for headers and libraries. For example, if the compiler normally searches for headers
in /usr/include and libraries in /usr/lib, it instead searches
dir/usr/include and dir/usr/lib.
If you use both this option and the -isysroot option, then the
--sysroot option applies to libraries, but the -isysroot option applies to header files.
The GNU linker (beginning with version 2.16) has the necessary support
for this option. If your linker does not support this option, the
header file aspect of --sysroot still works, but the library aspect
does not.
GCC is nothing if not configurable.
When you build an instance GCC, you need to completely specify the target environment. (Fortunately, most of this has already been done for you.) If necessary, you can tweak any of these settings before you do the build. The settings are described in detail in the GCC internals manual, but the particular ones you're interested in are in the chapter describing Target Macros, and particularly the section on Controlling the Compilation Driver. In this last section, you'll find descriptions of the various macros which define include paths. (Search for the word "include" in that page. Read everything you find :-); GCC documentation is not a tutorial.)

GCC header search path deprecated

I have found an unusual C makefile setup that relies upon a deprecated feature of GCC that appears to have no modern replacement.
This system needs to preprocess or 'cook' the local header files before including them. The makefiles take care of this and put the cooked versions in local './prepared/' directories. The header files are included as normal in the c using their normal names eg #include "name.h". The system simply needs './prepared/' to occur in the GCC header file search path before '.'.
Gcc used to offer the -I- option to remove the default '.' and allow the addition of header search path entries before it, but this option is deprecated.
From the gcc docs:
GCC looks for headers requested with #include "file" first in
the directory containing the current file, then in the directories
as specified by -iquote options, then in the same places it would
have looked for a header requested with angle brackets. For example,
if /usr/include/sys/stat.h contains #include "types.h", GCC looks
for types.h first in /usr/include/sys, then in its usual search path.
Is there no way to control the C header search path properly in gcc any more? Or is there another sensible way forward? I don't want to use a deprecated feature that may disappear. Right now I am sadly filtering the gcc deprecated feature warning messages to hide them. I didn't create the build environment, and it would be unpopular to solve the problem in a way that breaks the 'cookery'.
As far as I can tell, GCC provides no other means than the one you've described to avoid having each source file's directory first in the include search path used when compiling that file.
The best solution is probably to fix the headers and build system to get rid of header cooking. Such a scheme is very unusual -- pretty much everybody else gets by without.
If you must continue to rely on header cooking, then you probably should move the original headers to a directory that is not in the include search path. For example, create an "include" subdirectory of the main source directory, and put them there.
Edited to add:
Another alternative is to switch from the quoted include style to the angle-bracketed include style, and rely on -I options to set up the needed internal include directories however you want.

How does Solaris decide the library path?

On Solaris, I can use crle command to configure library path like this:
crle -c /var/ld/ld.config -l /lib:/usr/lib:/usr/local/lib:/opt/DSI/32
I can also use the traditional LD_LIBRARY_PATH method, like this:
LD_LIBRARY_PATH="/export/home/donald/mysql-5.0.91-installed/lib/mysql/:/lib:/usr/lib"
How does Solaris decide the library path? For example, does Solaris select from crle path first, then LD_LIBRARY_PATH? I try to google, but can't find the answers.
The answer is in the manual (man ld.so.1).
The runtime linker uses a prescribed search path for locat-
ing the dynamic dependencies of an object. The default
search paths are the runpath recorded in the object, fol-
lowed by a series of defaults. For 32-bit objects, the
defaults are /lib followed by /usr/lib. For 64-bit objects,
the defaults are /lib/64 followed by /usr/lib/64. These
defaults component can be modified using a configuration
file that is created with crle(1). The runpath is specified
when the dynamic object is constructed using the -R option
to ld(1). The environment variable LD_LIBRARY_PATH can be
used to indicate directories to be searched before the
default directories.
So, the order is:
LD_LIBRARY_PATH
shared object RPATH
crle defaults

Is there a way to load user library's from specific location ONLY on running the binary

I have a shared library's libmyworld.so in /opt/my_prog/lib and also in /home/user1/lib
Irrespective of the order I specified in LD_LIBRARY_PATH (LD_LIBRARY_PATH=/home/user1/lib;/opt/myprog/lib); my binary SHOULD always look for libmyworld.so FIRST in /opt/my_prog/lib;
Can this be done using GCC during compilation time? without modifying my_prog binary. Thanks in advance.
The search order for dynamic libraries in Linux (from ld.so man page) is the following
Using the DT_RPATH dynamic section attribute of the binary
if present and DT_RUNPATH attribute does not exist. Use of
DT_RPATH is deprecated.
Using the environment variable LD_LIBRARY_PATH. Except if
the executable is a setuid/setgid binary, in which case it
is ignored.
Using the DT_RUNPATH dynamic section attribute of the binary
if present.
From the cache file /etc/ld.so.cache which contains a
compiled list of candidate libraries previously found in the
augmented library path. If, however, the binary was linked
with -z nodeflib linker option, libraries in the default
library paths are skipped.
In the default path /lib, and then /usr/lib. If the binary
was linked with -z nodeflib linker option, this step is
skipped.
When linking, to set
DT_RUNPATH: use -Wl,--enable-new-dtags -Wl,-R$(RUNPATH)
DT_RPATH: use -Wl,--disable-new-dtags -Wl,-R$(RPATH)
In theory, it is better to use DT_RUNPATH as the LD_LIBRARY_PATH, on which the user has a control, has precedence. But here you want to avoid the user control, so use the DT_RPATH. In you link line:
-Wl,--disable-new-dtags -Wl,-R/opt/my_prog/lib
You can always launch your binary (here called foo) with
$ LD_LIBRARY_PATH=/opt/my_prog/lib foo
or make a shell script with the line above.
While compiling your source code use the below command
gcc -o [desired_executable_file_name] -L [Your shared library path] -l [your shared library name] -I [Header file path]
for example in your case
gcc -o my_word_exe -L /opt/my_prog/lib -lmyworld -I [header path if their]
Then it"ll take libmyworld.so in /opt/my_prog/lib this path
Use LD_PRELOAD.
LD_PRELOAD=/home/lib/libmyworld.so mybinary
The advantage is that you don't fiddle with LD_LIBRARY_PATH - your binary may depend on other shared libraries and it may need proper LD_LIBRARY_PATH/ld.so.conf/whatever.
PS. This is the least invasive and flexible solution, because does not affect loading of other libraries and does not hardcode paths in the user executable.

New .h file in /usr/include linux

I developed small c application in linux. For this application i placed .h file in
linux standard path (/usr/include). Again i am compiling the same program
Output:
FATA ERROR : xyz.h(my own header file) not found
Do i need to update any variable in gcc or way to solve this problem
Thank You
Place the header file in the same directory as your .c file and use -I. when compiling
gcc -I. main.c -o myprog
You shouldn't place your header files in /usr/include that is meant for the system headers.
Note: you don't actually need the -I. because the current directory is searched by default, nevertheless, it doesn't hurt to add it.
Files specified by include directives are meant to be located in one of the search paths of the complier which are specified with the -I option in many cases (at least for gcc, is it the same for other compilers?). The search paths are verified in the order of definition in the command line.
There are 2 kinds of include directives:
double quoted ones (#include "xyz.h")
angle bracket ones (#include <xyz.h>)
IIRC, the default and first search path for the former is the working directory. For the later, it's compiler dependant, but it's usually /usr/include/.
Depending of the include directive you used, you should pick the right location for your file. Or better, put your file in a good location (say the same place as the including file), and add a search path to your gcc command.
You should separate your header .h files, from system and repository built headers so you don't break anything.
I would recommend making a folder in your home directory called include and just adding it to your path, that way you never have to worry about it again and no need for the -I/flag

Resources