Virtual environment for C library development - c

Original
I am looking for a way to create a non-isolated development environment for a C-library.
I will most likely use cmake to build the library and my IDE is a simple text editor.
The problem now is that I do not only create the library but also some sample "applications" using the library.
Therefore I need to install the library's headers and the shared object (I'm using GNU/Linux) somewhere and I do not want to install it to /usr/local/lib or (the even worse) /usr/lib.
Is there a way to create a virtual environment similar to python's pyvenv (and similar) where I can install the everything to but still have access to the host libraries?
Also I do not want to rewrite my $PATH/$LD_LIBRARY_PATH, setup a VM, container, or chroot.
The usage would then look like:
# switch to environment somehow
loadenv library1
# for library
cd library
make && make install
# for application
cd ../application1
make && ./application1
Is this possible?
Edit 1
So basically my directory structure will look like this:
library/
library/src/
library/src/<files>.c
library/include/<files>.h
application/
application/src/
application/src/<files>.c
First I need to compile the library and install the binary and header files.
These should be installed in a fake system-location.
Then I can compile the application and run it.
Edit 2
I thought a bit about it and it seems all I need is a filesystem sandbox.
So basically I want to open up a shell where every write to disk is not committed to the filesystem but rather temporarily saved in e.g. a ramfs/tmpfs just to be dropped when the shell exits.
This way I can exactly test how everything would behave if compiled, deployed and executed on the real machine without any danger to existing files or directories and without accidentally creating files or directories without cleaning them up.

You don't really need to 'install' the library, you can work in the development tree.
(1) for compilation all you need to do is use -I flag to specify where the libraries header files are, and this can be a relative path, for example in your case you could do -I../../library/include
(2) for linking you need to tell the linker where the library is located at, you can use the -L flag append to the library search order.
(3) for testing the application, you are correct that the application needs to be able to find the library. You have a couple of options:
(a) make sure the library and the executable are in the same directory
(b) you can temporarily modify your LD_LIBRARY_PATH, in your current shell only, for testing:
export LD_LIBRARY_PATH=abs_path_to_library:$LD_LIBRARY_PATH
note that this will only effect the current shell (command terminal) you are working in. Any other shells you may have open, or open later will have your normal LD_LIBRARY_PATH. I know you specified that you don't want to modify your PATH or LD_LIBRARY_PATH, but being local to the shell that the command is executed it is a nice, easy way to do this.
(c) embed the path to the library in the client executable. To do this you need to pass an option to the linker. The command for gcc is:
-Wl,-rpath,$(DEFAULT_LIB_INSTALL_PATH)
see this how-to

Related

CMake, how to set different value in a configure_file in Build vs Install

I have a simple CMake project with CTest and CPack. It uses the Lua C API to load and execute an script file called script.lua.
This script will be in different location when built vs when installed/packed, it's location would be:
[build] : ${CMAKE_CURRENT_SOURCE_DIR}/src/scripts
[install]: ../scripts (relative to app which is in bin directory)
What I'm trying to achieve here is to have install step regenerate configure_file then rebuild using new configure_file and only then proceed to do the normal install step and of course revert the configure_file back to it's original state afterwards.
Any help regarding this issue is appreciated.
My understanding is that CMake's configure_file command has its full effect during the execution of the cmake program. It has no representation in generated makefiles, or whatever other build system components cmake generates. Thus, if you want to configure a file differently for installation than for pre-installation testing,
You would need to perform completely separate builds (starting with executing cmake) for the two cases, and
You would need to use some attribute of the cmake command line or execution environment to convey the wanted information, such as using a -D option to define a CMake variable on the command line.
I advise you not to pursue this route. Aside from being overcomplicated, it's also poor form to install a different build of the software than is tested.
You have a variety of alternatives that could serve better. Among those are
Give the program itself the ability to accept a custom location for the Lua script. That is, make it recognize a command-line argument or environment variable that serves this purpose. Make use of that during pre-installation testing.
If indeed the program is using a relative path to locate the script at runtime, then just (have CMake) put a copy of the script at the appropriate location in the build tree, so that the program will find it normally during testing.

Compiling in a dynamic C library (dylib) into a program on OS X

I've written a little C program which uses libusb. Now I want to distribute this program to "normal" (not dev) Mac OS X computers. But when I ported the compiled file to a test machine I got the following error:
dyld: Library not loaded: /opt/local/lib/libusb-0.1.4.dylib
Referenced from: /Users/kitty/myprogram
Reason: image not found
Trace/BPT trap: 5
When I copy the files (works only with all the files)
/opt/local/lib/libusb-0.1.4.dylib /opt/local/lib/libusb-1.0.a
/opt/local/lib/libusb.a
/opt/local/lib/libusb-1.0.0.dylib /opt/local/lib/libusb-1.0.dylib
/opt/local/lib/libusb.dylib
from my machine to the target machine the program works flawlessly.
But I really want to create or compile everything into a single executable. How is this possible?
Using -static while compiling does not work since not all libraries can be compiled into the final app statically (see this SO question here).
So how can I make a single neat little application file?
You can convert a static library to a dynamic library, but I'm not aware of a way to do the reverse as you want it.
If you're building an app with a bundle, you need to put the library you want to distribute inside your bundle, in the Frameworks directory, and link against that.
If you are not building a bundle-based app, just a single binary, you may need to provide instructions for your users on how to install the library on their system (e.g. via Homebrew).
Here's how you do it for bundle-based apps:
Apple has a document about run-path dependent libraries but doesn't actually explain how to set this up for a newbie.
Here's how it should work:
Add the libusb.dylib you want to use to your project.
It should automatically get added to your "Link Binary with Libraries" phase in your project's "Build Phases". If not, add it here.
Add a new "Copy Files" build phase.
In the "Destination" drop-down box, select "Frameworks". This is the
Frameworks directory in your app's final bundle.
Then press the "+" icon in that copy build phase and add your library.
If you had any manual linking options like -L/usr/local/lib and -lusb, remove them.
Clean and build.
When you now look into your app bundle, you'll see that the library is copied to <bundle_path>/Contents/Frameworks/. You can now start the app from wherever you want, the dynamic link loader knows it needs to look at <path_to_binary>/../Frameworks/ to find your library.
But: you may need to rebuild your libusb to have the install_name set to #rpath/../Frameworks/libusb.dylib or use the install_name_tool CLI tool fix that path for your copy of libusb.dylib that you added to your project.

Distribute .so file on linux?

I have a shared library that my application needs (a .so) and I am wondering what is the best way to distribute it?
It's not something that can be apt-get installed and I need it in the LD path's in order to run the application.
In the past I've needed to include a separate "launcher script" that the user would click on instead of clicking on the Linux executable directly. The launcher script would set up LD_LIBRARY_PATH to include the directory where the shared library was stored, and then launch the executable. Here's the script, for reference (it assumes that the executable and the shared library are hidden away in a sub-folder named "bin", and that the executable's name is the same as the script's name except without the ".sh" suffix):
#!/bin/bash
appname=$(basename "$0" .sh)
dirname=$(dirname "$0")
cd "$dirname/bin"
export LD_LIBRARY_PATH=$(pwd):$LD_LIBRARY_PATH
./$appname "$#"
Distribute it the same way you distribute the executable that depends upon it; bundle the two together.
If you didn't write the library, make sure you're complying with its license terms for redistribution.

shared library - how to permanently set the path

I am using a program that has some shared library that are usually installed to /usr/lib.
However for some reason i have to have these libs locally. So to make my program run (which depends on the former) I need to export LD_LIBRARY_PATH= ... or add my local path permanently. This is ok for me but users of my software don't know this and for them this is too complicated. So my question: is there a way to automatically set the local path to my shared libs which are called by my program at runtime.
is there a way to automatically set the local path to my shared libs
Maybe.
If you are on Linux, and your application is installed together with shared library into say /some/prefix/bin/app and /some/prefix/lib/libsharedlib.so, then linking your application with:
gcc -o app -Wl,--rpath='$ORIGIN/../lib' main.o ... -lsharedlib
will achieve exactly the result you want (note: you can move both app and library into /another/dir, and it will still work so long as both the lib and bin directories are moved together).
Note: single quotes around $ORIGIN are required.
If you are on a platform that doesn't support $ORIGIN, the other common technique is to wrap the application in a shell script, which looks at $0, sets LD_LIBRARY_PATH appropriately, then execs the real application (which is often called app.bin, or app.exe).

Linking a library built from source code to a program managed by autotools

I have a c program which needs a library named libnuma to be installed. But I dont have root access in the parallel machine in which I need to run this program. So I downloaded the source code of libnuma and compiled it. I have a libnuma.a file which i assume is the library. I need to link this library with the c program that I have. This program uses autotools for generating the configuration files and the makefile. I am new to autotools. Please tell me what I have to do to link this library without being root.
Ajay.
It should be sufficient to set CPPFLAGS and LDFLAGS. First, try:
$ ./configure LDFLAGS=-L/path/to/lib CPPFLAGS=-I/path/to/include
(where libnuma.a is /path/to/lib/libnuma.a and numa.h is /path/to/include/numa.h.
That is, specify the directories.) If that does not work, check config.log to see what went wrong. If the configure script for the program you are using was built with an old version of autoconf, you may need to do:
$ LDFLAGS=-L/path/to/lib CPPFLAGS=-I/path/to/include ./configure
instead. (The second invocation will only work in Bourne shells. With csh/tcsh, you will need to set the environment variables some other way, for example with env.) You also have the option of making those settings in the environment of your shell (eg, in a .bashrc) or in a config.site file.

Resources