Howto use an external shared lib?
-
wrote on 4 Sept 2021, 03:23 last edited by
Hi,
I actually have the problem, that I don't know how to add a shared library from an external project to my qt application.
From the external project I have the shared library only. No static lib to link to.So adding -L<lib-location> and l<libname> does not work. Linker says, that it can't find "libname". Guess this works for static libs only.
So I tried to add the shared library to the OBJECTS var, which seemed to work at first sight. But on full rebuild the shared lib was removed :(
So I'm looking for the right way to add that shared lib.
I digged into qmake manuals, but wasn't successful.
I would like to do something similar than qt module configuration, where I finally only have to write something like CONFIG += extProjectbut it seems, as if I'm to stupid to understand qmake manual. I then searched for prf-files of qt - but what I found is so complicated - no chance to follow.
So how can I get into that config stuff using small steps?
-
wrote on 4 Sept 2021, 07:33 last edited by
You do it with qmake by adding the relevant linker switches to the LIBS variable in your PRO file:
LIBS += -L<lib-location> -l<libname> e.g. LIBS += -L/usr/local/lib -lopencv
Notice that the lib name is without the lib prefix on UNIX-like systems: this would be a common mistake.
If that is not the issue then, in all likelihood your problem is not qmake but the absence of the pieces needed for the linker to do its work.
I am assuming you are on a Windows platform. On this platform that there are two components to a dynamically loaded library: a run-time DLL file and matching import (link-time) library that documents the entry points to the run-time library for the linker. The exact naming of the components is dependent on compiler: MSVC .dll and .lib, MingW .dll and .a (I think).
On a Linux platform the .so file fills both roles.
-
wrote on 4 Sept 2021, 07:42 last edited by
Thank you for your attention.
I wasn't precise with my first post, but of cause, I added -L and -l options to the LIBS variable.
So in my case it does not work.
When I list the files from the provided path, the shared lib is there. But the linker shouts, that he could not find the given lib.
-
wrote on 4 Sept 2021, 21:36 last edited by
Can you show your .pro project file and the error you are getting?
-
Thank you for your attention.
I wasn't precise with my first post, but of cause, I added -L and -l options to the LIBS variable.
So in my case it does not work.
When I list the files from the provided path, the shared lib is there. But the linker shouts, that he could not find the given lib.
wrote on 5 Sept 2021, 00:16 last edited by@django-Reinhard The (compile-time) linker does not use the shared library on Windows. The linker uses the import library, which has the same extension as a static library but contains only enough information to ensure that the resulting binary can link the dynamic library at run time. Parties providing a binary DLL (e.g. a MSVC runtime) and expecting developers to use it will generally have to provide a matching import library (often in a related SDK). If you do not have the import library then you are in for some difficulty. In some cases, very dependent on the library, you can reverse engineer the import library.
Please confirm you are on Windows and what libraries are involved.
-
wrote on 5 Sept 2021, 03:31 last edited by
@ChrisW67 said in Howto use an external shared lib?:
Please confirm you are on Windows and what libraries are involved.
No, I'm NOT at windows.
I use linux, precisely debian 11 (bullseye).
@mchinand said in Howto use an external shared lib?:
Can you show your .pro project file and the error you are getting?
error message:
/usr/bin/ld: cannot find -lnml collect2: error: ld returned 1 exit status
I added a link to the external project to my projects root, so the shared library is located at ./lc/lib/libnml.so
Together with the statements from pro-file:LIBS += -Llc/lib -lnml
this should be as recommended.
@ChrisW67 said in Howto use an external shared lib?:
You do it with qmake by adding the relevant linker switches to the LIBS variable in your PRO file:
Looks like that's not working.
AFAIK shared libs should be added to the OBJECTS list.If you look at the linker statement (some o-files removed):
g++ -Wl,-rpath,/opt/qt5.15/5.15.2/gcc_64/lib -Wl,-rpath-link,/opt/qt5.15/5.15.2/gcc_64/lib -o QtUi main.o ... moc_toolinfodockable.o -Wl,-rpath=$ORIGIN/libs -Llc/lib -lm -lnml /opt/qt5.15/5.15.2/gcc_64/lib/libQt5UiTools.a -L/home/qt/openssl-1.1.1g/lib /opt/qt5.15/5.15.2/gcc_64/lib/libQt5Widgets.so /opt/qt5.15/5.15.2/gcc_64/lib/libQt5Gui.so /opt/qt5.15/5.15.2/gcc_64/lib/libQt5Test.so /opt/qt5.15/5.15.2/gcc_64/lib/libQt5Core.so -lGL -lpthread
you can see, that shared libs from qt are NOT added like libraries, but added after the project objects as if they where just object files.
Don't remember, where I got this tip from (it was in this forum so) - but looks like the recommended additionunix:!mac { LIBS += -Wl,-rpath=\$$ORIGIN/libs }
does not work and will not be recognized/expanded.
On another project using external shared libs I wrote the Makefile manually like this:
LC_FLAGS = -DLOCALE_DIR=\"/usr/share/locale\" \ -DPACKAGE=\"linuxcnc\" \ $(TOOL_NML_FLAG) \ -L$(abspath lc/lib) \ -Wl,-rpath,$(abspath lc/lib) \ -Xlinker -Map=libLinuxCNC.map \ -L/usr/X11R6/lib -lm -lGL NML_OBJS = $(abspath lc/src/objects/libnml/nml/nml.o) \ $(abspath lc/src/objects/libnml/nml/cmd_msg.o) \ $(abspath lc/src/objects/libnml/nml/nml_mod.o) \ $(abspath lc/src/objects/libnml/nml/nml_oi.o) \ $(abspath lc/src/objects/libnml/nml/nml_srv.o) \ $(abspath lc/src/objects/libnml/nml/nmldiag.o) \ $(abspath lc/src/objects/libnml/nml/nmlmsg.o) \ $(abspath lc/src/objects/libnml/nml/stat_msg.o) ifeq ($(TOOL_NML),yes) LC_OBJS = $(abspath lc/src/objects/emc/nml_intf/emc.o) \ $(abspath lc/src/objects/emc/nml_intf/emcops.o) \ $(abspath lc/src/objects/emc/rs274ngc/modal_state.o) \ $(abspath lc/src/objects/emc/tooldata/tooldata_common.o) \ $(abspath lc/src/objects/emc/tooldata/tooldata_nml.o) \ $(abspath lc/src/objects/emc/tooldata/tooldata_db.o) else LC_OBJS = $(abspath lc/src/objects/emc/nml_intf/emc.o) \ $(abspath lc/src/objects/emc/nml_intf/emcops.o) \ $(abspath lc/src/objects/emc/rs274ngc/modal_state.o) \ $(abspath lc/src/objects/emc/tooldata/tooldata_common.o) \ $(abspath lc/src/objects/emc/tooldata/tooldata_mmap.o) \ $(abspath lc/src/objects/emc/tooldata/tooldata_db.o) endif %.o : %.cc $(GCC) -c $(CC_FLAGS) -o $@ $< TestNML: TestNML.o $(LC_OBJS) $(NML_OBJS) $(GCC) $(LC_FLAGS) -o $@ $^
building that app works without issue.
So I'd like to ask again:
Is there a way to add files to qmake object list, that don't get removed at running clean command?
-
wrote on 5 Sept 2021, 04:39 last edited by
Hi,
I found the solution by myself.
@ChrisW67 said in Howto use an external shared lib?:
You do it with qmake by adding the relevant linker switches to the LIBS variable in your PRO file:
You where right.
The point of evil is - this works for absolute paths only!
... and I didn't want to hardcode the location of external projects.so - qmake variable "_PRO_FILE_PWD_" was the key :)
... and that leaded to these statements in pro file:
unix:!mac { LIBS += -Wl,-rpath=$${_PRO_FILE_PWD_}/lc/lib } LIBS += \ -L$${_PRO_FILE_PWD_}/lc/lib \ -lnml
Thanks!
-
wrote on 6 Sept 2021, 01:30 last edited by
Glad you found it. Relative paths are fragile beasts. Qt Creator, for example, will default to a shadow build which means that a library in a location relative to the source is not in the same location relative to the build area. Building in-source, from the command line would possibly have worked (though not recommended).
In your manual Makefile from the other project you had gone out of your way to determine the
abspath
of the library directory.
1/8