Shared libraries with a path on names - path

I'm making a project which uses lots of it's own shared libraries; my intention is to create a library name within a directory, so, e.g., instead of -lfoo (to find /usr/lib/libfoo.so or /opt/lib/libfoo.so or so on), I would use -lfoo/bar (to find /usr/lib/libfoo/bar.so or /opt/lib/libfoo/bar.so or so on).
I made a real small code to test:
const char *mylib(void) {
return "it woooorks! =D";
};
And compiled it with: gcc -fPIC -shared -Wl,-rpath,libfoo/ lib.c -o /usr/lib/libfoo/bar.so.
Then, in the test program, I use gcc -lfoo/bar test.c, and it compiles (it finds the mylib() symbol from my library), but when I try to run the program (./a.out), the dynamic linker complains that it can't find the library. In my case, using Mac OS X Lion:
dyld: Library not loaded: bar.so
Referenced from: /Users/takanuva/tmp/lib/./a.out
Reason: image not found
Trace/BPT trap: 5
What am I doing wrong? Maybe the answer is "everything", so... how should I accomplish the desired effect, to look for libfoo/bar.so instead of libfoo.so on the library paths?
Thanks in advance. :)

If the library is not located in a standard path (and /opt is such a path that is normally not searched), you must specify the paths with -L/-rpath, as in gcc blah.c -L/opt/whatever -Wl,-rpath,/opt/whatever -lbar. Do NOT attempt to use path separators in the -l argument.

Related

What is build object file extension in iOS?

When I build java object class in a project, build file will be created with .class extension and human unreadable; What about swift build files?
example:
car.java --> build --> car.class
what would be after build?
car.swift --> build --> ?
The compilation process is a bit different with Swift to Java, so there isn't necessarily a direct equivalent.
As the build proceeds though each Swift file will get compiled in to an 'Object' file, ending in a .o extension. Then once they're all built they get linked together to form the binary. If you unpick an iOS app's IPA file, you won't see the individual .o files like how you can see the .class files inside a Java jar file.
One thing I know is that Swift uses LLVM just like Objective-C.
So in Java, we have this (source: W3schools).
And here, for Swift (source: Swift.org)
I hope this helps!
Mach-O format
[LLVM]
In iOS world every sources file - .m, .h, .swift are compiled into executable byte code that is understandable by CPU. These files are also called Mach object(.o) - ABI Mach-O[About] file which contains nexts grouped bytes with a meta-information
Mach-O header - general information like cpu type(CPU_TYPE)
Load Commands - table of contents
Raw segment data - code
__LLVM - bitcode[About]
This groups are repeated for every architecture(Universal library)[About]
`*.swift` -> `*.o` (Mach-O object file)
For example if you created a static library - myLibrary.a. You can use nm[About] command to display name list (symbol table).
nm path/myLibrary.a
As a result you will see a list of *.o files with methods, variables names etc.
To investigate Mach-O file you can use otool[About]
[Mach-O Type]
[Xcode build process]

How to get the path where the library is installed

I am working in Linux and I have a library written in Fortran 90 (written by 3rd party), that is reading from a file in the current working directory. I would like to be able to call the resulting library from other folders, hence I need to read the path where the library is installed. How can I know the path to the compiled library within the Fortran code?
I need to store in a variable the path within the code.
For who knows python, I want to achieve the same as
import os
os.path.dirname(os.path.abspath(__file__))
but in f90 (see Get location of the .py source file)
Using the suggestions in the comment I have done the following:
export DATAPATH=`pwd`
make
in the Makefile
ifort -O3 -fpic -fpp -DDATAPATH -c mysource.f90
in mysource.f90
subroutine mysub
character(len=100)::dpath
#ifdef DATAPATH
dpath=DATAPATH
#endif
open(10,file=trim(dpath)//'initialise.dat')
....
....
the problem is that at compile time I get
mysource.f90(42): error #6054: A CHARACTER data type is required in this context. [1]
dpath=1
----------^
compilation aborted for mysource.f90 (code 1)
If you wish you can fix the path at compile time. Something like
gfortran -cpp mylib.f90 -DPREFIX=\"/usr/local/\"
open(newunit=u,file=PREFIX//'mylib/initialise.dat')
You must than make sure the library is indeed installed in that place PREFIX/mylib/
You can create an environment variable containing the path of your data. This variable can be set by hand, in your .bashrc or .bash_profile or in the system /etc/profile.d/ or /etc/bash.bashrc, there are manyways and they depend if the library is just for one user or for all users of some large computer.
For example
export MYLIB_PATH='/usr/local/mylib'
Then you can read the variable in Fortran as
CALL get_environment_variable("MYLIB_PATH", mylib_path, status=stat)
and the path is now in variable mylib_path. You can check the success by checking if stat==0.
This is not the only possible approach. You can also have a configuration file for your library in your home directory:
mkdir $HOME/.config/mylib/
echo "/usr/local/mylib" > $HOME/.config/mylib/path
and then you can try to read the path from this file if the environment variable was not set
if (stat/=0) then
CALL get_environment_variable("HOME", home_dir)
open(newunit=path_unit, file=home_dir//'/.config/mylib/path',status='old',action='read',iostat=stat)
if (stat/=0) complain
read(path_unit,'(a)',iostat=stat) mylib_path
if (stat/=0) complain
end if
So when you compiled with -DDATAPATH you have not passed the variable DATAPATH into your code only declared a symbol called DATAPATH as being true, so ifort will substitute DATAPATH as 1. What you need to do is pass it as a value:
-DDATAPATH="$(DATAPATH)"
For the compilation to work.

Linking library with G++

Sorry for asking this newbie question but I can't get off this s***t...
In the same directory I have 4 files : ctacs.ini; ct_api.h; libctacs.a and main.cpp.
My cpp file contains #include "ct_api.h" and when I try to compile with :
g++ -lctacs main.cpp -o main
I got undefined references to the functions which are defined in my library -__-
Could you please tell what did I wrong ? I search on the internet but the option -lctacs seems to be the right way to proceed...
Thank you very much
Some compilers and linkers resolve references to functions by searching the object files/sources files/libraries left-to-right on the command line. This means that files that call externally-defined functions should appear before the object files/libraries/source files that contain their definitions.
You happen to have a linker that does indeed depend on this ordering. You need to put the library after main.cpp so that the function definitions can be found:
g++ main.cpp -lctacs -o main

Remove the path in objcopy symbol names

I need to include a binary program in my project. I use objcopy to create an object file from a binary file. The object file can be linked in my program. objcopy creates appropriate symbols to access the binary data.
Example
objcopy -I binary -O elf32-littlearm --binary-architecture arm D:\Src\data.jpg data.o
The generated symbols are:
_binary_D__Src_data_jpg_end
_binary_D__Src_data_jpg_size
_binary_D__Src_data_jpg_start
The problem is that the symbols include the path to the binary file D__Src_. This may help when binary files are included from different location. But it bothers me that the symbols changes when I get the file from a different location. Since this shall run on several build stations, the path can't be stripped with the --redefine-sym option.
How do I get rid of the path in the symbol name?
I solved this problem by using this switch in objcopy:
--prefix-sections=abc
This gives a way to uniquely identify the data in your binary object file (ex. binary.o)
In your linker script you can then define your own labels around where you include the binary.o. Since you are no longer referencing anything in binary.o the binary will be thrown out by the linker if you use -gc-sections switch. The section in binary.o will now be abc.data. Use KEEP in your linker script to tell the linker not to throw out binary.o. Your linker script will contain the following:
__binary_start__ = .;
KEEP(*(abc.data))
binary.o
*(abc.data)
. = ALIGN(4);
__binary_end__ = .;
The switch --localize-symbols works for me.

CMake FIND_LIBRARY vars are set to -NOTFOUND when finding Mac OS X Frameworks

I'm trying to add Mac OS X framework usage to my program, which includes some files with Objective-c++ code.
It DOES work with SET (CMAKE_EXE_LINKER_FLAGS "-framework CoreMedia -framework ... "), but i don't really like this way and it seems just wrong.
That's the CMake part of actual adding, but it doesn't work and i dont really know what i'm missing :( I tried using the
link_directories("${CMAKE_OSX_SYSROOT}/System/Library/Frameworks")
include_directories("${CMAKE_OSX_SYSROOT}/System/Library/Frameworks")
but it didn't help at all. So here's the code:
add_executable(myprogram src/myprogram.cpp)
FIND_LIBRARY(COREMEDIA_LIB NAMES CoreMedia)
FIND_LIBRARY(COREVIDEO_LIB NAMES CoreVideo)
FIND_LIBRARY(FOUNDATION_LIB NAMES Foundation)
FIND_LIBRARY(AVFOUNDATION_LIB NAMES AVFoundation)
target_link_libraries(myprogram ${COREMEDIA_LIB})
target_link_libraries(myprogram ${COREVIDEO_LIB})
target_link_libraries(myprogram ${FOUNDATION_LIB})
target_link_libraries(myprogram ${AVFOUNDATION_LIB})
It produces the cmake errors:
CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the CMake files:
AVFOUNDATION_LIB
linked by target "myprogram" in directory <some directory containing app>
<... other 3 are here aswell ...>
Ok, got it. I need to specify PATHS variable to ${CMAKE_OSX_SYSROOT}/System/Library. I don't know why but it can't find it in this folder automatically, thought it's a standard folder though...
so call like this:
for example, when i link AVFoundation framework:
add_executable(myprogram)
find_library(SOME_VAR
NAMES AVFoundation
PATHS ${CMAKE_OSX_SYSROOT}/System/Library
PATH_SUFFIXES Frameworks
NO_DEFAULT_PATH)
and then
target_link_libraries(myprogram "${SOME_VAR}/AVFoundation")
Hope it will help someone.
This is working for me:
IF (APPLE)
find_library(COREMIDI_LIBRARY CoreMIDI)
find_library(COREFOUNDATION_LIBRARY CoreFoundation)
target_link_libraries(myprogram ${COREFOUNDATION_LIBRARY} ${COREMIDI_LIBRARY})
ENDIF (APPLE)

Resources