Linking library with G++ - hyperlink

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

Related

How to make use of OpenCV source codes instead of shared libraries

I have a project at hand which I want to use one of the opencv modules (specifically dnn).
Instead of building the dnn module I want to use the source code of this modules in my project. by doing so, I can change the source code live and see the results at the same time.
I have a very simple scenario with one only source file:
main.cpp
#include "iostream"
#include <opencv2/dnn.hpp>
int main(int argc, char *argv[])
{
std::string ConfigFile = "tsproto.pbtxt";
std::string ModelFile = "tsmodel.pb";
cv::dnn::Net net = cv::dnn::readNetFromTensorflow(ModelFile,ConfigFile);
return 0;
}
now this function "cv::dnn::readNetFromTensorflow" is in dnn module. I tried many different methods to embedded the dnn source codes inside my project but all of them failed !
for example, the first time I tried to include every cpp and hpp file in the module/dnn/ folder of opencv in my project but I ended up in errors like
/home/user/projects/Tensor/tf_importer.cpp:28: error: 'CV__DNN_EXPERIMENTAL_NS_BEGIN' does not name a type
#include "../precomp.hpp" no such file or directory
HAVE_PROTOBUF is undefined
and ....
I tried to solve these errors but some more errors just happened, more undefined MACROs and more undefined hpp files !
#include "../layers_common.simd.hpp" no such file or directory
and many many more errors !
It seems that I'm stuck in a while(true) loop of errors !!! Is it really that hard to use opencv modules source code ?
P.S.
For those who are asking about why I want to use opencv source code instead of using the shared libraries I have to say that I want to import a customized tensorflow model which opencv read function doesn't support and I want to know where exactly it crashesh so I can fix it.
By the way, I am only using c++11 functions and gcc as compiler in Ubuntu 16.04

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.

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.

Shared libraries with a path on names

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.

Qmake and passing $ORIGIN to linker option -rpath

I would like to use the -rpath linker option to set the .so search path. I'd like it to search [app_path]/../lib. I've tried add this to my qmake .pro file:
QMAKE_LFLAGS += -Wl,-rpath=$ORIGIN/../lib/
But qmake links my project this way:
g++ -Wl,-rpath=RIGIN/../lib/ -Wl,-O1 -o myoutput main.o [...]
How can I escape the $ORIGIN?
I found here a way to properly escape it:
QMAKE_LFLAGS += '-Wl,-rpath,\'\$$ORIGIN/../mylibs\''
If you want $ORIGIN to be (properly) evaluated while building you can simply add this to your .pro file:
QMAKE_RPATHDIR += $ORIGIN/../mylibs
This is a really old question, but for people getting here through a search: the methods described in the old answers are not needed anymore. Modern Qt versions (5.9 in my case), allow you to just use this:
QMAKE_RPATHDIR += lib
This will add the needed entries (including $ORIGIN and -Wl,-z,origin where needed) automatically to the makefile, as long as you're using a relative directory. Meaning that lib will produce the needed "origin" entries, while something like /lib will not. Any relative directory you add to QMAKE_RPATHDIR will be made relative to $ORIGIN automatically.
DOLLAR=$
QMAKE_LFLAGS += -Wl,-rpath=$${DOLLAR}$${DOLLAR}ORIGIN/../myLibs

Resources