How to use CMake to update library path? - linux

I am writing a shared library for GNU/Linux, which will install for now with "sudo make install". I have CMake recipes to create the files and install them in '/usr/local/lib/app', and the libraries and links are created correctly.
But the library path is not updated and I must run "sudo ldconfig /usr/local/lib/app' manually to make the library available.
Several other packages on my system put their libraries in a specific folder under /usr/local/lib, so I am assuming that's proper.
How then to have CMake update the library path for the system as well as create the files and install them? What is the proper way to do this?
I'd also like it accomplished so that the library path update survives a system restart.
Thanks,
bcw

I'd also like it accomplished so that the library path update survives a system restart.
I'm not aware of any CMake-specific facility. However, you should be able to add rules such as the following in order to make the change persistent.
echo "/usr/local/bret/lib" > /etc/ld.so.conf.d/bret-i386.conf
echo "/usr/local/bret/lib64" > /etc/ld.so.conf.d/bret-x86_64.conf
/sbin/ldconfig
You'll still need to re-run the ldconfig when you overwrite files in bret/lib{,64}.

Related

How to make Cmake globally available

I just installed Cmake from git clone wget http://www.cmake.org/files/v2.8/cmake-2.8.3.tar.gz in a new folder on a Linux server. The compilation worked but cmake command is not recognized from other paths. Should I copy the entire contents of cmake-2.8.0 folder to usr/local/bin? Or is the contents of bin folder that need to be copied?
Thanks
On Linux and other Unix-based systems, a common arrangement is to install packages to /opt and add relevant entries to the PATH environment variable to make them available. This is intended for packages not provided by the native package manager or distribution. By choosing an appropriate directory structure, this can be done in a way which also allows different versions to be installed simultaneously and the user can pick which one they want by adding the relevant directory to the PATH.
For the specific case of CMake asked about in the question, you can use a directory structure like /opt/cmake/<version> and then add the relevant /opt/cmake/<version>/bin directory to your PATH (e.g. /opt/cmake/3.8.2/bin for the 3.8.2 CMake release). You can even just download the official pre-built CMake tarballs, unpack them and move the top level directory into the /opt/cmake area as the particular version you downloaded. I've used this successfully on Linux, MacOS and Solaris, as I'm sure have many others.
Note that once you've run CMake on a particular source tree, the cmake executable doesn't need to be on the PATH any more. If cmake needs to be re-run, the build will do so itself and it records the full path to the cmake executable in its own cache, so the PATH isn't even consulted (this is essential in ensuring the same version of CMake continues to be used for all builds regardless of the PATH, since PATH can change between login sessions, etc.). You would only need cmake on your PATH if you intend to invoke cmake manually or for the first time you run it on a source tree, but in both of these cases you can always just use the full path to the cmake executable if you preferred.
I should also add that the entire set of files provided in the CMake package are required, not just the bin directory. CMake makes extensive use of files in its other directories, such as the various modules it comes with. If you are building CMake from source, you may want to build the package target so you get a relocatable tarball or similar which will contain everything that should be included when you provide a CMake package on your system.
After the build, use 'sudo make install'. This will make sure the correct libraries and binaries are copied to their proper places.
Usually this will install the binary to /usr/local/bin.
Make sure the PATH variable has this included.
sudo make install did not copy to /usr/local/bin/ for some reason, so I copied the content of CMAKE /bin. to usr/local/bin an it worked.
cp –a bin/. /usr/local/bin/

Debian / Ubuntu package installed in root as default

Created a simple debian/ubuntu package with some library files (*.so).
Works fine except, it installs them as default in the root path "/".
Since I've recreated my Makefile to output to $DESTDIR/ instead of "the usual" directory that I provide in the Makefile, when compiling from source, how do I now set the path of where the files should be installed now? I know there are several choices when using dh_make to create the package, "s" being the default one. Still, can't seem to find anything on where to tell dpkg to put the installed files.
Secondly, a Deb Library package containing only ".so" files should still be a "Single binary" since I gather that using the Library is for development purposes? Since this is a library, I just wanna make sure that's not the cause of the files being installed in the wrong location. What I mean is .so files and header files installation?
What I've used:
dh_make -e my#email.com -f ../myfile-1.0.tar.gz
dpkg-buildpackage -rfakeroot
and some configurations set i debian/control, $DESTDIR in Makefile.
Seems that it was fairly simple, yet very confusing. This works, not sure if there is a better solution.
In my makefile I have a few variables
InstallTo = /usr/lib
install:
mkdir -p $(DESTDIR)$(InstallTo)
cp $FILE_TO_COPY $(DESTDIR)$(InstallTo)
This way it will create the directory tree inside the *.deb file. I had some trouble using /usr/local/lib instead of /usr/lib/ and rmdir complained when trying to delete it and it had no files (just directories). Not sure why, but changed it to /usr/lib instead.
Since someone voted this up, I'm guessing someone were also looking for the answer and this is my solution. Perhaps someone can provide a better one if there is one.
Just a note, $DESTDIR variable is the variable that dh_make suggest the user to use in our Makefile. It's the path to where dpkg will build the program and where it will install it so it can be included in the .deb file.

Can I avoid exporting LD_LIBRARY_PATH by hardcoding library paths in the executable?

I'm zipping a pre-built (no source/object files) binary application for distribution. The binary application requires a couple of libraries not included by default. The only way I seem to be able to get the application to start on the end-user is by including a run.sh that sets the library path to the current directory:
export LD_LIBRARY_PATH=./:$LD_LIBRARY_PATH
./MyApp.out
However, I'd really like to allow the user to just unzip the zip and doubleclick MyApp.out (without the shell script). Can I edit MyApp.out to search the current directory for the library? I've done something similar on OSX using install_name_tool, but that tool isn't available here.
You want to set the rpath. See this answer. So link using
gcc yourobjects*.o -L/some/lib/dir/ -lsome -Wl,-rpath,.
But you might want even to use -Wl,-rpath,$PWD or perhaps -Wl,-rpath,'$ORIGIN'. See this.
You could also (and this should work for a pre-built executable) configure your /etc/ld.so.conf by adding a line there with an absolute path (of the directory containing the lib), then running ldconfig -v ... See ldconfig(8)
I would suggest adding /usr/local/lib into /etc/ld.so.conf and making a symlink from /usr/local/lib/libfoo.so to e.g. $HOME/libfoo.so etc... (then run ldconfig ...). I don't think adding a user specific directory to /etc/ld.so.conf is reasonable ...
PS. What you really want is to package your application (e.g. as a *.deb package for Debian or Ubuntu, or an *.rpm for Fedora or Redhat). Package management systems handle dependencies!

Run time installation directory of debian package contents

I have a debian package that I built that contains a tar ball of the files, a control file, and a postinst file. Its built using dpkg-deb and it installs properly using dpkg.
The modification I would like to make is to have the installation directory of the files be determined at runtime based on an environment variable that will be set when dpkg -i is run on the deb file. I echo out the environment variable in the postinst script and I can see that its set properly.
My questions:
1) Is it possible to dynamically determine the installation directory at runtime?
2) If its possible how would I go about this? I have read about the rules file and the mypackage.install files but I don't know if either of these would allow me to accomplish this.
I could hack it by copying the files to the target location in the posinst script but I would prefer to do it the right way if possible.
Thanks in advance!
So this is what I found out about this problem over the past couple of weeks.
With prepackaged binaries you can't build a debian package with a destination directory dynamicall determined at runtime. I believe that this might be possible if installing a package that is built from source where you can set the install directory using configure. But in this case since these are embedded Ubuntu machines they don't have make so I didn't pursue such an option. I did work out a non traditional method (hack) for installing that did work. Since debian packages simply contain a tar ball relative to / simply build your package relative to a directory under /tmp. In the postinst script you can then determine where to copy the files from the archive into a permanent location.
I expected that after rebooting and the automatic deletion of the subdirectory under /tmp that dpkg might not know that the file package existed. This wasn't a problem. When I ran 'dpkg -l myapp' it showed as still installed. Updating the package using dpkg/apt-get also worked without a hitch.
What I did find is that if you attempted to remove the package using 'dpkg -r myapp' that dpkg would try and remove /tmp which wasn't good. However /tmp isn't easily removed so it never succeeded. Plus in our situation we never remove packages but instead simply upgrade them.
I eventually had to abandon the universal package due to code differences in the sources resulting in having to recompile per platform but I would have left it this way and it did work.
I tried using --instdir to change the install directory of the package and it does relocate the files but dpkg fails since the dpkg file can't be found relative to the new instdir. Using --instdir is sort of like a chroot. I also tried --admindir and --root in various combinations to see if I could use the dpkg system relative to / but install relocate the files but they didn't work. I guess rpm has a relocate option that works but not Ubuntu.
You can also write a script that runs dpkg-deb with a different environment for 6 times, generating 6 different packages. When you make a modification, you simply have to run your script, and all 6 packages gets generated and you can install them on your machines avoiding postinst hacking!
Why not install to a standard location, and simply use a postinst script to create symbolic links to the desired location? This is much cleaner, and shouldn't break anything in dpk -I.

Make install, but not to default directories?

I want to run 'make install' so I have everything I need, but I'd like it to install the things in their own folder as opposed to the system's /usr/bin etc. is that possible? even if it references tools in the /usr/bin etc.?
It depends on the package. If the Makefile is generated by GNU autotools (./configure) you can usually set the target location like so:
./configure --prefix=/somewhere/else/than/usr/local
If the Makefile is not generated by autotools, but distributed along with the software, simply open it up in an editor and change it. The install target directory is probably defined in a variable somewhere.
Since don't know which version of automake you can use DESTDIR environment variable.
See Makefile to be sure.
For example:
export DESTDIR="$HOME/Software/LocalInstall" && make -j4 install
make DESTDIR=./new/customized/path install
This quick command worked for me for opencv release 3.2.0 installation on Ubuntu 16. DESTDIR path can be relative as well as absolute.
Such redirection can also be useful in case user does not have admin privileges as long as DESTDIR location has right access for the user. e.g /home//
It could be dependent upon what is supported by the module you are trying to compile. If your makefile is generated by using autotools, use:
--prefix=<myinstalldir>
when running the ./configure
some packages allow you to also override when running:
make prefix=<myinstalldir>
however, if your not using ./configure, only way to know for sure is to open up the makefile and check. It should be one of the first few variables at the top.
If the package provides a Makefile.PL - one can use:
perl Makefile.PL PREFIX=/home/my/local/lib LIB=/home/my/local/lib
make
make test
make install
* further explanation: https://www.perlmonks.org/?node_id=564720
I tried the above solutions. None worked.
In the end I opened Makefile file and manually changed prefix path to desired installation path like below.
PREFIX ?= "installation path"
When I tried --prefix, "make" complained that there is not such command input. However, perhaps some packages accepts --prefix which is of course a cleaner solution.
try using INSTALL_ROOT.
make install INSTALL_ROOT=$INSTALL_DIRECTORY

Resources