How to find "my" lib directory? - c++

I'm developing a C++ program under Linux. I want to put some stuff (to be specific, LLVM bitcode files, but that's not important) in libraries, so I want the following directory structure:
/somewhere/bin/myBin
/somewhere/lib/myLib.bc
How do I find the lib directory? I tried to compute a relative part from argv[0], but if /somewhere is in my PATH, argv[0] will just contain myBin. Is there some way to get this path? Or do I have to set it at compile time?
How do GNU autotools deal with this? What happens exactly if I supply the --prefix option to ./configure?
Edit: The word library is a bit misleading in my case. My library consist of LLVM bitcode, so it's not an actual (shared) object file, just a file I want to open from my program. You can think of it as an image or text file.

maybe what you want is :
/usr/lib
unix directory reference: http://www.comptechdoc.org/os/linux/usersguide/linux_ugfilestruct.html

Assume your lib directory is "../lib" relative to executable
First you need to identify where myBin located, You can get it by reading /proc/self/exe
Then concat your binary file path with "../lib" will give you the lib directory.

You will have to use a compiler flag to tell the program. For example, if you have a plugin dir:
# Makefile.am
AM_CPPFLAGS = -DPLUGIN_DIR=\"${pkglibdir}\"
bin_PROGRAMS = awesome_prog
pkglib_LTLIBRARIES = someplugin.la

The list of directories to be searched is stored in the file /etc/ld.so.conf.
In Linux, the environment variable LD_LIBRARY_PATH is a colon-separated set of directories where libraries should be searched for first, before the standard set of directories; this is useful when debugging a new library or using a nonstandard library for special purposes.
LD_LIBRARY_PATH is handy for development and testing:
$ export LD_LIBRARY_PATH=/path/to/mylib.so
$ ./myprogram
[read more]

Addressing only the portion of the question "how to GNU autotools deal with this?"...
When you assign a --prefix to configure, basically two things happen: 1) it instructs the build system that everything is to be installed in ${prefix}, and 2) it looks in ${prefix}/share/config.site for any additional information about how the system is set up (it is common for that file not to exist.) It does absolutely nothing to help find libraries, but depends on the user having set up the tool chain properly. If you want to use a library in /foo/lib, you must have your toolchain set up to look there (eg, by putting /foo/lib in /etc/ld.so.conf, or by putting -L/foo/lib in LDFLAGS and "/foo/lib" in LD_LIBRARY_PATH)
The configure script relies on you to have the environment set up. It does not help you set up that environment, but does help by alerting you that you have not done so.

You could use the readlink system call on /proc/self/exe to get the path of your executable. You might then use realpath etc.

Related

Unable to load shared library : libxerces.so

While running the application developed by other person, getting the following error
./appln: error while loading shared libraries: libxerces-c.so.28: cannot open shared object file: No such file or directory
And if I run ldd command:
# ldd appln
linux-gate.so.1 => (0x00e20000)
libdl.so.2 => /lib/libdl.so.2 (0x00a61000)
libxerces-c.so.28 => not found
I already have that libxerces-c.so.28 file in current folder. Please help me how to resolve that error
You need to put libxerces-c.so somewhere in the library path. Probably current folder is not searched for libraries. Try putting it in /usr/local/lib
Evidently "the current folder" isn't in the run time search path used by your executable. I'm assuming that you are on linux (linux-gate.so.1).
You need to ensure that "the current" directory is under the search path. You can do this at link time by using the -rpath option to the linker (-R is also accepted) or -Wl,-rpath,<dir> if you are invoking the linker through the compiler front end. This embeds a search path to be used at run time into your program.
Consider how you want the program to be installed, though. There's no point in adding a path that is specific to your development environment. You might want to consider using $ORIGIN or a $ORIGIN relative path which tells the run time linker to look for shared objects in the location containing (or relative to) the executable. You should always avoid adding . to the run time search path; your program shouldn't behave differently depending on the current directory of the process which invokes it.
As a temporary measure you can set the environment variable LD_LIBRARY_PATH to override the embedded and system search paths but it is normally a bad idea to rely on LD_LIBRARY_PATH overrides for a final installation.
By default .so files are NOT being searched in the current folder (they should be in /usr/lib, etc).
To add the current directory for .so lookup use:
LD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH ./appln
When adding new "local system" libraries (e.g. in /usr/local/lib/) you better add that directory (/usr/local/lib/) once in your /etc/ld.so.conf and you should run ldconfig to update the linker cache (every time you add something inside /usr/local/lib/)
See ldconfig(8), ld.so(8), ldd(1), dlopen(3)
If you want your own libraries, set LD_LIBRARY_PATH to a directory containing them (e.g. $HOME/lib/ and to standard directories, e.g.
export LD_LIBRARY_PATH=$HOME/lib:/usr/lib:/usr/local/lib
in your ~/.bashrc (but I dislike that confusing practice, and prefer to manage my /usr/local/lib/).
You could also use some -Wl,-rpath argument but I really dislike that also.
Read also Program Library HowTo and Drepper's paper: How To Write Shared Libraries

Linux - SO file not found

I have a program which requires liblog4cpp installed to run.
Now, I want the program to run on another machine without liblog4cpp. So I just find the log4cpp.so and move it to the same directory of my program. But at running error reported:
error while loading shared libraries: liblog4cpp.so.4: cannot open
shared object file: No such file or directory
Am I doing it right? How can I tell the program to find the SO file just beside it?
In addition to what others are suggesting, consider adding the file to the dynamic linker's cache. You can do it like this:
ldconfig -l /path/to/lib/liblog4.so.4
To add it to the loader's cache use the following command: ldconfig
Then in order to verify that it was correctly added, run this:
ldconfig -v | grep liblog
Check your LD_LIBRARY_PATH environment variable... One of the directories on the path should point to the location of your log4cpp.so file; also the linux command ldd is handy for determining which shared object libraries are being used in your executable. The syntax is ldd <executable>.
assuming that the path where the .so file/s is available is /path you can also avoid to export an environment variable and just use
LD_LIBRARY_PATH=/path ./myProgram
beware the fact that if you do:
export LD_LIBRARY_PATH=/path
you are resetting LD_LIBRARY_PATH to a single value /path and losing anything you added before to this environment variable. If you want to add a value without losing the previous ones
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path
export LD_LIBRARY_PATH to the path of the library. This env variable works much like the PATH variable. It can contain multiple paths separated by :.
In the rc script from where you are launching your program, you should set the LD_LIBRARAY_PATH before launching the application. Remember, the .so are the shared libraries, it is required at the run time to link. Thus, it should be available in the standard path like /usr/lib before launching.
In case it is not copied in the standard path like /usr/lib then specify the path by using the following.
export LD_LIBRARY_PATH=<new_path_of_so>:$(LD_LIBRARY_PATH)
Ideally, I would have placed this .so in the standard path like /usr/lib. If it is installed in the standard path, then there is no need to set the above path. Remember, to make your program better, put the new path in ldconfig.conf.
You can debug such errors by using the following.
$strace <binary_name>
to know the so dependencies
$ldd <binary_name>
For further, check the below link.
http://www.tune2wizard.com/sharedobject-crash/
After adding shared objects (or shared libraries lib*.so*, or such symbolic links) to system directories like /usr/lib or /lib known to the dynamic linker ld-linux.so(8) (or ld.so) you need to run ldconfig(8)
You could also add them to /usr/local/lib/ but then be sure that /etc/ld.so.conf (or some file /etc/ld.so.conf.d/*.conf) .mentions that directory (and run ldconfig after changing it)

How to install programs on Linux from a makefile? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What should Linux/Unix 'make install' consist of?
I'm making a program that can be invoked from the command line, like ./prog arg1 arg2. I was wondering, how can I make it so that I can run it from anywhere on the system? I know that I could put prog into /usr/bin/, but what if my program needs resources from its install directory (that can be wherever the user downloaded it)?
put the directory in which your program resides into the path environment variable or move your program into one of the directories already in path (usually requires superuser permission, which I gather you don't have for then you wouldn't ask this question).
to add a directory to the front of the search path and have the system refresh its database on tcsh, say
setenv "my/directory:"$PATH
rehash
on bash, I think, it's
PATH=/my/directory:$PATH
export PATH
(no need to rehash). Note that the above commands put your directory at the top of the search path, i.e. these will be searched before any other. Thus, if your program is called "gcc", then your program will be executed rather than the GNU C compiler. Alternatively, you can add your directory to the end of the search path, in which case your program will only be picked up if no other program of the same name is found in any of the other directories in the search path.
You probably also want to become familiar with the Linux Filesystem Hierarchy: the standard definition for "what goes where". Here's more information:
https://superuser.com/questions/90479/what-is-the-conventional-install-location-for-applications-in-linux
Environment variables can be defined globally ("for everybody", e.g. /etc/profile), or locally ("per user", e.g. ~/.bashrc). Here's a good summary of some of your options:
https://wiki.archlinux.org/index.php/Environment_Variables
When you execute a programme using prog arg1 arg2, it's thanks to your shell, which search in the $PATH environement variable for folders where programs are. (Try env | grep PATH to see those folder).
You need eather to add a new directory in this variable (export PATH="/new/directory/path/:$PATH" if under bash, setenv PATH "/new/directory/path/:$PATH" if with tcsh) or copy your program and all the files it need to execute in one of the PATH folder.
There are two ways of dealing with this (and Makefiles have nothing to do with them)
Your installer could just put the files where it wants them, so your program doesn't have to search -- it can use hardcoded paths. Or you could put the path to the data directory into yet another file, which would be hardcoded (like /etc/programname.config).
You put all your stuff into one directory (often something like /opt/programname). You can hardcode that too, of course, or your program can readlink() the /proc/pid/exe file for a good chance (no guarantee, though. In particular, it works if for example a symlink is used to point from /usr/bin/programname to your /opt/programname/bin/programname or whatever, but it won't work if that's a hardlink)
to get the path to the executable. From there you should be able to reach your data files.
If prefer the second solution, but that's just me. The first solution works well with package managers, and it's less overkill if you don't really have a lot of data files.

Cygwin GCC C++ compiler - Why ./? [closed]

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 12 years ago.
Improve this question
If you look at point (6) here: http://www2.warwick.ac.uk/fac/sci/moac/students/peter_cock/cygwin/part3/
Why should we type ./ before the .exe file in order for it to run?
Why cannot we type hello.exe immediately?
Thanks.
Usually because intelligent people don't have their current directory . on the path :-)
The path is an environment variable like /bin:/usr/bin:/usr/sbin, and it's a list of directories to look in for finding executables, such as when you type in hello.
Unlike Windows, many UNIX shells don't automatically search the current directory for an executable. They must be listed in the path otherwise they are not run.
That's because to do otherwise is actually an attack vector. For example, if you create an ls program in your home directory and tell one of the administrators that there's a funny file in there, they may go to your directory and enter ls to see what's in there.
For a silly administrator that has the current directory before the "real" location of ls, they are now compromised, because your code is running with their full privileges.
That's why they tend not to do that.
Some people (not I) will put . on their path to make their lives easier but, even then, they'll put it at the end so that other locations are searched first.
Administrators don't have the luxury of being that trusting.
Because the current working directory is not in the PATH?
Or at least, that's how things are setup on Unix-style systems, I assume CYGWIN does the same.
On Windows, the current directory is always in the search path for an executable. The search order is "look in the current dir, if not found, look in the directories listed in the PATH environment variable".
From MS site:
The operating system always searches
in the current directory first, before
it searches the directories in the
command path.
(which makes all the warning here of not putting the . in your PATH irrelevant, IMHO)
On Linux this is not the case (for current dir). So, to run an executable which is in your current dir you need to write ./exe_name.
As Cygwin, again AFAIK, is for Windows, the ./ is not needed and seems to be just a copy/paste or preserving the unix-style the writer is used to.
EDIT: this is the issue of the command processor (the shell) as pointed out in comments and as I explain below, so if you are using a Unix-like shell on Windows, you still may need this style.
EDIT: elaborating on .\
. (not ./ to be exact) is an alias to the current directory. On Unix, every newly created directory is not "born" empty but contains 2 children: ., which is a self-reference, and .. which is a reference to the parent directory. Both are just regular directories, as any other. You don't see them when you run the ls command (same as dir on Windows) because names starting with . are special in the sense that they are not displayed by default. However, you can see them by ls -a.
When you run a command at the prompt, if the command is only a (file) name, the system (actually, the shell) searches the PATH for the file with this name.
If the command contains a path (not necessarily an absolute path, e.g. subdir1/exe) the system looks for the executable where you specified. Hence, writing ./exe means file exe in the current dir.
Cygwin is a Unix-like runtime environment and as such follows the way paths are searched for executables in such environments. The default executable search path of Unices does not contain the current directory. Thus if one wants to run an executable not located in one of the directories set in PATH a full path must be given. ./ is a shorthand for the current directory, also called process working directory (pwd). Be advised that it's a very bad idea to have the pwd being included in the executable search path.
Cygwin follows the Unix limitations on executing files in the current working directory. In Unix style terminal environments an executable must have ./ prepended if it is to be executed from the current directory. This is because the current directory "." is not part of the PATH environmment in order to limit the damage done by malware. Cygwin is simply following this convention, it has nothing per say to do with C++ programs
That's just an issue with your 'path' or 'PATH' variable in your shell. (probably your shell is bash, so it'd be PATH.)
echo $PATH
A typical 'user' path to do what you want would start with "." as a path element. This is a minor security risk of course.

C++ How to get a filename (and path) of the executing .so module in Unix

C++ How to get a filename (and path) of the executing .so module in Unix?
Something similar to GetModuleFileName on Windows.
Although it is not a POSIX standard interface, the dladdr() function is available on many systems including Linux, Solaris, Darwin/Mac OS X, FreeBSD, HP-UX, and IRIX. This function takes an address, which could be a pointer to a static function within the module for example (if cast to void *), and fills in a Dl_info structure with information including the path name of the shared object containing that address (in the dli_fname member).
Unfortunately, there is no way to do that using UNIX or POSIX. If you need to use it to look up some sort of data, you should use the $PATH environment variable and search for the data in a path that is relative to each entry in $PATH. For example, it is not uncommon to store binaries in "installdir/bin" for some installation directory "installdir" and to store the associated data in "installdir/share/name_of_program" for some installation directory and some program named "name_of_program". If that is the case, then looking at "../share/name_of_program/name_of_resource_file" relative to each entry in getenv("PATH") is a good way of searching for resources. Another thing you could do is allow the necessary information to be provided on the commandline or in some configuration file, and only perform the search if needed as a fallback option.
Edit
Now that you've stated your rationale for this, I would advise you to simply use the QSettings class from Qt for your configuration information, as it uses the preferred native mechanism for each platform (the registry on Windows, a PLIST file on Mac OS X, the Gnome GConf database on Linux). You may want to take a look at my C++ Project Template as it uses Qt to do just this, and it provides simple commandline options to easily tweak the configuration settings ("--prefset", "--prefget", and "--preflist" manipulate QSettings).
That said, if you absolutely must use an XML configuration file of your own instead of using the preferred native mechanism, I strongly advise you to place the system-wide configuration in "installdir/etc" while placing your library in "installdir/lib" for some installation directory "installdir", as that is the typical place for configuration files on UNIX systems, and "installdir/lib" should ONLY be used for library files, not for configuration files and other errata. I suggest you place a user-specific version of the configuration file in "$XDG_CONFIG_HOME" (if it is defined) or in "$HOME/.config" (where "$HOME" is the user's home folder).
When searching for the system-wide configuration file, I would recommend that you search within $XDG_CONFIG_DIRS if it is defined; if it isn't defined, then falling back to "/etc/xdg" or searching for "../etc/name_of_your_program.conf.xml" relative to "$PATH" and possibly also relative to the "$LD_LIBRARY_PATH", "$DYLD_LIBRARY_PATH", "$DYLD_FALLBACK_LIBRARY_PATH"), the contents of "/etc/ld.so.conf" if it exists, and the contents of "/etc/ld.so.conf.d/*.conf" if those files exist, halting your search as soon as you encounter the first valid such configuration file would be a sensible approach.
Credit goes to Roger for pointing out the XDG Basedir Spec and for his excellent constructive criticisms.
Possible solutions:
You can read the /proc/{PID}/mmap file for the list of shared libraries. Where {PID} is the process pid (you can get it using getpid()).
Call the command line tool ldd for the program binary file (stored in argv[0]).
If you write a solution from scratch take a look of ldd commands source code from uClibc how to get the list of shared libs from an elf binary.