Automake: how to build shared library without installing it - automake

With Automake you can build a shared library (.so) like this:
lib_LTLIBRARIES = libyeah.la
libyeah_la_SOURCES = yeah.c
Then libyeah.so is installed to $(libdir) with make install.
When you specify the noinst_ prefix (instead of lib_) to avoid installing the library, it's not built as a shared object (only an archive, .a). It seems that the library is never actually linked.
I need a shared object, without installing it, for project tests (a test plugin which is dynamically loaded by the test program).
I tried to add -module and -shared to libyeah_la_LDFLAGS without success.

You can bypass the default libdir and install it in some other directory instead of /usr/local/lib:
make DESTDIR=/home/user/staging install
will install your lib in /home/user/staging/usr/local/lib (if you used the default --prefix at configure time). Then (on Linux -- you didn't specify what your underlying platform is) you can:
LD_LIBRARY_PATH=/home/user/staging/usr/local/lib test_libyeah
to run your test.

Related

How to dynamically link your nim-application against musl?

I've written a web-server in nim using the prologue framework. I would like to deploy that application using an alpine-docker-container.
As far as I'm aware, compiling means you dynamically link against your system libraries for whatever you need, that system library on any normal distro being glibc.
On alpine however you do not use glibc, you use musl, so dynamically linking against glibc means my application will expect glibc functions with glibc names that do not exist since there are only musl functions.
The big question that arises out of this for me as a python developer that jumped onto nim and knows very little about compilers:
How do I compile, so that I link dynamically against musl?
The folks from nim discord's brought me to the answer. It consists of passing flags to the nim-compiler to swap out the compiler nim normally uses for its generated C-code, in order to use musl-gcc. This can be done by using the --gcc.exe:"musl-gcc" and --gcc.linkerexe:"musl-gcc" flags.
Here an example for Linux:
1. install musl to get access to musl-gcc
download the tar file from the official musl page
Unpack the tar file somewhere
Run bash configure in the unpacked directory. WARNING: Make sure that you do NOT install musl with --prefix being /usr/local, as that may adversely affect your system. Use somewhere else where it is unlikely to override files, e.g. /usr/local/musl. This path will further be referred to as <MUSL_INSTALL_PATH>
Run make && make install in the unpacked directory
Add <MUSL_INSTALL_PATH> to your PATH environment variable
Validate whether you set everything up correctly by opening a new terminal and seeing whether you have access to the musl-gcc command
2. Compile with musl
Create a compile command with --gcc.exe:"musl-gcc" to swap out gcc with musl-gcc and --gcc.linkerexe:"musl-gcc" to swap out the default linker with musl-gcc as well. An example can look like this:
nim c \
--gcc.exe:"musl-gcc" \
--gcc.linkerexe:"musl-gcc" \
--define:release \
--threads:on \
--mm:orc \
--deepcopy:on \
--define:lto \
--outdir:"." \
<PATH_TO_YOUR_MAIN_PROJECT_FILE>.nim
run the command
This should generate a binary that is dynamically linked against musl and thus can run within an alpine docker container.

bitbake do_rootfs install fails with shared library symlink in bbappend

I am trying to add a shared library package to a Yocto Krogoth image from a custom recipe that is dependent on libudev.so.0 but the openembedded-core layer's eudev recipe only provides libudev.so.1.6.3 and a libudev.so.1 symlink:
libudev.so.1 -> libudev.so.1.6.3
I have added a eudev_%.bbappend recipes_core recipe that creates the symlink
do_install_append() {
ln -srf ${D}${base_libdir}/libudev.so.1 ${D}${base_libdir}/libudev.so.0
}
and I can confirm the libudev.so.0 file is added to the libudev package in
tmp/work/HOST/eudev/3.1.5-r0/image/lib/libudev.so.0
tmp/work/HOST/eudev/3.1.5-r0/package/lib/libudev.so.0
tmp/work/HOST/eudev/3.1.5-r0/packages-split/lib/libudev.so.0
tmp/work/HOST/eudev/3.1.5-r0/sysroot-destdir/lib/libudev.so.0
and installed to the image's tmp/sysroots/MACHINE/lib/libudev.so.0 directory when building the image and is present in the resultant tmp/deploy/images/MACHINE/IMAGENAME.tar.bz2 rootfs archive. The issue is that with the above in place I cannot add my shared library package to the image as it results in the following error:
do_rootfs: ...
Computing transaction...error: Can't install MYRECIPE#HOST: no package provides libudev.so.0
The custom recipe does have RDEPENDS_${PN} = libudev set.
Why is the do_rootfs error generated as the installed libudev package clearly does provide the libudev.so.0 library? Bitbaking the custom recipe independently has no issue, but that obviously does not attempt to install the resultant package into an image.
Why is the do_rootfs error generated as the installed libudev package
clearly does provide the libudev.so.0 library?
I'm pretty sure the the relevant code isn't looking at file names but actual symbols needed by your library -- there's packaging magic that looks at all the libraries and executables and figures out their runtime dependencies based on the symbols they need (this is how the correct dependency libraries end up on the rootfs). I believe the error message is trying to say that no available library exports the symbols that your library needs.
You can check the soname your udev exports with
readelf -a libudev.so.1 | grep SONAME
0x000000000000000e (SONAME) Library soname: [libudev.so.1]
I've not confirmed that this is what the rootfs code checks for but it's quite likely.
Are you expecting a library linked with libudev.so.0 to just work with libudev.so.1 without even a recompile? I'm not familiar with udev but in general libraries are unlikely to work like that.
The custom recipe does have RDEPENDS_${PN} = libudev set.
This is not normally needed -- if your software dynamically links to a library, the runtime dependency is found automatically.

Including GTK# Dlls with Statically Linked (mkbundle)Mono Exe on Mac

I have an application coded in c# using the Mono Framework and GTK# for UI.Im trying to create a static bundle for MacOSX (including gtk# and mono runtime)
I just bundled Mono with my exe file using
mkbundle --static hello.exe -o --deps hello2.exe
I got the exe file but when i drag it and put it on the terminal i get System.DllNotFound Exception:glibsharpglue-2
I understand that i need to include the gtk# libraries.But i dont know how to do that with a statically linked mono runtime.Is there an option to do that using mkbundle.All i need to get is a final standalone package ready to run on Mac.
Please help me out.
UPDATE:
The shell script I'm currently using with Platypus to make the .app package
export DYLD_FALLBACK_LIBRARY_PATH="/Library/Frameworks/Mono.framework/Versions/Current/lib:$DYLD_FALLBACK_LIBRARY_PATH:/usr/lib"
exec /Library/Frameworks/Mono.framework/Versions/Current/bin/mono myapp.exe
Im currently using the option provided in platypus to include myapp.exe file.How can i include the dlls required for GTK? Please help me out.
The error is from not finding the GTK shared object libraries (SO/dylib).
Using mkbundle:
If using 32-bit Mono you will need to assign the arch type for AS and CC. By default, clang will compile and link x86_64 which may not match your installed Mono's arch type.
export AS="as -arch i386"
export CC="cc -arch i386 -framework CoreFoundation -lobjc -liconv"
mkbundle gtkdesigner.exe --deps -o gtkdemo
The resulting executable will still require Mono (and any dependant shared objects/dylibs) to be installed.
Or adding --static to statically link to mono libs and thus invoking the LGPL of Mono (you will need to distribute your original CIL images so the user can upgrade the version of Mono that is running your app, unless you have a license from Xamarin)
mkbundle --static gtkdesigner.exe --deps -o gtkdemo
The resulting executable will not require Mono to be installed, but any dependant shared objects/dylibs will still be required.
GTK/GTK# based applications:
A GTK# based application will still require the GTK shared objects/dylibs to be installed and accessible by the resulting executable (i.e. gtkdemo in this case):
Thus if you try to run ./gtkdemo it will need to find shared libraries such as libc.dylib, libgtksharpglue-2.so, etc, etc... otherwise the error you are getting will be shown.
Set the dylib library path to your GTK libraries, not the C# CIL binding library (GTK#), but the native shared object libraries. Since you have Mono installed on OS-X, it also installs its own version of GTK that can be found at /Library/Frameworks/Mono.framework/Versions/Current/lib. If you are installing your own version GTK to a different location just change the path to that location. You also will be to include the location of the OS's std C library.
export DYLD_FALLBACK_LIBRARY_PATH="/Library/Frameworks/Mono.framework/Versions/Current/lib:/usr/lib"
./gtkdemo
Note: You can package this gtkdemo application into a normal OS-X app by using a packager tool such as http://sveinbjorn.org/platypus. Package all the GTK libraries and any other required so/dylibs into the app and provide a shell script that assigns the DYLIB path in order to find those app based GTK libs. Then you can distribute the self-contained app and the end-user just double-clicks it to run you GTK-based app.
Since gkt# is an open-source library why not download the code?
You would need to install git and do:
git clone https://github.com/mono/gtk-sharp
Then, you can reference those donwloaded gtk-sharp projects directly in your solution.
Note: i believe you still need the native OSXs gtk libraries since gtk-sharp is a wrapper of those libs.

CMake: wrong zlib found - how to build zlib from src (with main project CMakeLists.txt) and link it?

// brief version
How can I make CMake to use my supplied zlib (which it also has to build from source) instead of the one found by the finder without breaking the finder for other libs (OpenGL)?
ZLib needs to be used by the main project and also libPNG which comes as source as well.
Primary target platform is Windows.
// longer version:
In my project I need to link against libpng, zlib and OpenGL. With libpng being dependent on zlib. But zlib is also required by the main project.
I need to supply sourcecode for all libs except OpenGL, and build those libraries along with
the main project to assert linking the correct version and simplify building on Windows.
I found ways to do all this with custom libraries where no built-in finder exists, but I can't override the finder properly for just zlib. If I change the search path for libs, then OpenGL is not found.
However I can't get cmake to use my supplied zlib instead of a rouge zlib.DLL that the package finder finds somewhere in my system. (The one from tortoise git)
I tried to set ZLIB_LIBRARY to a specific filepath, but that only works on MinGW, and I also think this is not the way to do it.
(And also I had to explicitly link to png16_static instead of just libpng, for an inexplicable reason.)
Any help on this is much appreciated. Maybe I'm taking this on the wrong way?
Target&Development Platform:
Windows7
Visual Studio 2010
and MinGW (both need to work)
My (simplified example) CMakeLists.txt:
cmake_minimum_required (VERSION 2.6)
project (MyProject)
find_package(OpenGL)
add_executable(MyProject main.cpp)
include_directories(${INCLUDE_DIRECTORIES} "${PROJECT_BINARY_DIR}")
include_directories(${INCLUDE_DIRECTORIES} "external_libs/lpng162")
include_directories(${INCLUDE_DIRECTORIES} "external_libs/zlib-1.2.8")
include_directories(${INCLUDE_DIRECTORIES} "${PROJECT_BINARY_DIR}/external_libs/zlib-1.2.8")
add_subdirectory("external_libs/zlib-1.2.8")
link_directories(${LINK_DIRECTORIES} "${PROJECT_BINARY_DIR}/external_libs/zlib-1.2.8")
# libpng will not build correctly if this not set
set (ZLIB_ROOT "${PROJECT_SOURCE_DIR}/external_libs/zlib-1.2.8")
# manually set this to prevent cmake from finding the tortiose-git zlib.dll first
# DOES NOT WORK CORRECTLY, only with mingw32
set (ZLIB_LIBRARY "${PROJECT_BINARY_DIR}/external_libs/zlib-1.2.8/libzlib.dll")
add_subdirectory("external_libs/lpng162")
TARGET_LINK_LIBRARIES(MyProject png16_static zlib ${OPENGL_LIBRARY})
Project (simplified example) structure:
./main.cpp
./CMakeLists.txt
./external_libs/zlib-1.2.8/ <- contains respective source
./external_libs/lpng162/ <- contains respective source
Third-party libraries most likely call FindZLIB.cmake to determine the location of CMake. You already had the right idea by setting the ZLIB_LIBRARY manually, but were not quite getting it right:
add_subdirectory(<path_to_zlib_src_dir>)
set(ZLIB_INCLUDE_DIR "<path_to_zlib_src_dir>" "${CMAKE_BINARY_DIR}/<path_to_zlib_build_dir>")
set(ZLIB_LIBRARY zlib)
add_subdirectory(<path_to_lpng_src_dir>)
The include directory needs to contain both src and build path as zconf.h is build by CMake
The library name is only the CMake-target name, not the complete path to the resulting file.
On Windows dlls are not automatically copied by CMake. You might want to add some additional code to make sure that the zlib and lpng dlls end up in the right place.
You can call find_package(zlib) yourself to make sure it behaves as expected
In the rare case that a third-party lib does not use the find script, you will have to dig into that project's CMakeLists to find out what is going on

AIX- Does not install shared lib

I am able to build the shared object successfully using the holy native compiler "xlc" on AIX.It does build the shared object library but does not install the shared object library.
Configure command is:
./configure --prefix=/PATH/to/install --exec-prefix=/PATH/to/install --enable-shared --enable-static=no --enable-module=so --build=powerpc-ibm-aix5.3.0.0 --host=powerpc-ibm-aix5.3.0.0 LDFLAGS="-G -shared"
Any help would be appreciated?
So you are trying to compile to the shared library location.
I would suggest seeing if you can compile/link to your local directory.
If that works, try copying the new library to the correct directory. It may be that the oldshared library is open by some process and therefore can't be overwritten.
Are you getting any error messages?
I could install the shared library successfully when i had to exclusively export LDFLAGS as "-brtl -L/path/to/install".
Under AIX, there are two types of shared libraries, AIX style, and SysV compat libs.
AIX style libs are archvies that can contain static libraries as well as multiple versions of shared libraries, and have names like libFOO.a
SysV-compat libs have names like libFoo.so and are more like what you would find on Linux.
Libtool will build either type. If you want SysV-compat libs, add -Wl,-brtl to LDFLAGS.
My guess is that you see /PATH/to/install/lib/libFOO.a and are assuming that it's a static library, when in fact, it's an AIX shared library.

Resources