qmake : Build library without the symlinks and 'lib' prefix - c++

I require a very simple mechanism in my application, where my project is built as a shared library '.so' or '.dll', but what I want is:
ExampleAppOne.so
I get:
libExampleAppOne.so -> libExampleAppOne.so.1.0.0
libExampleAppOne.so.1 -> libExampleAppOne.so.1.0.0
libExampleAppOne.so.1.0 -> libExampleAppOne.so.1.0.0
I don't even want the 'lib' prefix. In the .pro file, all I can do is change the INSTALLS variable (that is because my third requirement IS that the library be built in a specific directory).
Also, I have a fourth, related requirement: When I ask QLibrary to load the library, I want it to specifically search for a library in a very specific path and a library that matches the EXACT name given to it. No 'lib' prefix matching, no 'version string' searching, no looking into LD_LIBRARY_PATH...
Any help is appreciated.
Regards,
rohan

add the following to you .pro file
# disables the lib prefix
CONFIG += no_plugin_name_prefix
# disable symlinks & versioning
CONFIG += plugin

Adding plugin to the CONFIG variable should disable versioning and the generation of symbolic links to the library.
I don't know of a simple way to disable the lib prefix though. You way want to dig into the provided QMake spec files to see how the default processing is implemented.

Related

CMake with 3rd party libraries that need to be built along with the project

I am confused on the right way to get an external library integrated into my own Cmake project (This external project needs to be built along with my project, it's not installed separately, so we can't use find_library, or so I think)
Let's assume we have a project structure like this (simplified for this post):
my_proj/
--CMakeLists.txt
--src/
+---CMakeLists.txt
+---my_server.cpp
That is, we have a master CMakeLists.txt that basically sits at root and invokes CMakeLists for sub directories. Obviously, in this example, because its simplified, I'm not showing all the other files/directories.
I now want to include another C++ GitHub project in my build, which happens to be this C++ bycrypt implementation: https://github.com/trusch/libbcrypt
My goal:
While building my_server.cpp via its make process, I'd like to include the header files for bcrypt and link with its library.
What I've done so far:
- I added a git module for this external library at my project root:
[submodule "third_party/bcrypt"]
path = third_party/bcrypt
url = https://github.com/trusch/libbcrypt
So now, when I checkout my project and do a submodule update, it pulls down bcrypt to ${PROJ_ROOT}/third_party
Next up, I added this to my ROOT CMakeLists.txt
# Process subdirectories
add_subdirectory(third_party/bcrypt)
add_subdirectory(src/)
Great. I know see when I invoke cmake from root, it builds bcrypt inside third_party. And then it builds my src/ directory. The reason I do this is I assume this is the best way to make sure the bcrypt library is ready before my src directory is built.
Questions:
a) Now how do I correctly get the include header path and the library location of this built library into the CMakeLists.txt file inside src/ ? Should I be hardcoding #include "../third_party/bcrypt/include/bcrypt/bcrypt.h" into my_server.cpp and -L ../third_party/libcrypt.so into src/CMakeLists.txt or is there a better way? This is what I've done today and it works, but it looks odd
I have, in src/CMakeLists.txt
set(BCRYPT_LIB,"../third_party/bcrypt/libbcrypt.so")
target_link_libraries(my app ${MY_OTHERLIBS} ${BCRYPT_LIB})
b) Is my approach of relying on sequence of add_directory correct?
Thank you.
The best approach depends on what the bcrypt CMake files are providing you, but it sounds like you want to use find_package, rather than hard-coding the paths. Check out this answer, but there are a few different configurations for find_package: MODULE and CONFIG mode.
If bcrypt builds, and one of the following files gets created for you:
FindBcrypt.cmake
bcrypt-config.cmake
BcryptConfig.cmake
that might give you an idea for which find_package configuration to use. I suggest you check out the documentation for find_package, and look closely at how the search procedure is set up to determine how CMake is searching for bcrypt.

How to use hdfk library into qt?

How can I use HKDF library in my qt project? I found this library seems appropriate in qt (I checked with my source), but I couldn't include this header to project.
Adding a library to a Qt project is actually quite simple. In your qmake .pro file you need the following:
# This is the search location for the compiler to look for headers that accompany your library.
# For system libraries that typically resides under **/usr/include** or **/usr/local/include** if you used `make install`.
INCLUDEPATH+="/path/of/headers/for/library"
# This is the search location for the compiler/linker to look for the library itself.
# For system libraries this is usually somewhere under **/usr/lib** or **/usr/local/lib**
LIBS+= -L/path/of/library/itself
# This is the name of the library to include at link time
# without the **lib** prefix and the **.so** / **.a** / **.lib** / **.dll** extension.
LIBS+= -lMyLibraryName
# This is the full path of the library file itself
# *including* the aforementioned **lib** prefix and the **.so** / **.a** / **.lib** / **.dll** extension.
# This is used by qmake to look for changes to the library at build time,
# to make sure it is re-linked on change and other dependency related stuff
PRE_TARGETDEPS += /path/and/filename/of/library/itself/libMyLibraryName.lib
TIP: All the paths, unless they are specified as absolute paths (starting with '/') will be relative to the build directory. This might be the project directory, but in the case of shadow builds, it will be the shadow build directory. As a tip, simply prepend the following to your relative paths to make them relative to project directory: $$_PRO_FILE_PWD_/ so if for example your lib resides in /my/qt/project/libs/mylib you could make your project resilient to moving by using $$_PRO_FILE_PWD_/libs/mylib instead. Please note that the "project dir" is the location of the qmake .pro file.
I use CryptoPP HKDF implementation by https://www.cryptopp.com
Firstly, build static lib for valid architecture and for your platform (MacOS, Android, iOS, etc). CryptoPP Wiki has working manuals and scripts.
Then, just add 2 lines to your qmake *.pro file:
INCLUDEPATH += $$DEV_LIBS_PATH/cryptopp/$$ANDROID_ARCH/include
LIBS += -L$$DEV_LIBS_PATH/cryptopp/$$ANDROID_ARCH/lib -lcryptopp
as you can understand, I used qmake variables DEV_LIBS_PATH and ANDROID_ARCH which are just compose right path to relevant headers and static library libcryptopp.a.

When defining external dependencies in meson, can you add search paths?

When defining a target in meson, you can declare dependencies on external projects using the following syntax:
zdep = dependency('zlib', version : '>=1.2.8')
exe = executable('zlibprog', 'prog.c', dependencies : zdep)
This checks the standard include locations, which works well on Linux, but not so well on other platforms.
Is there a way to add additional include and library paths for meson to check when declaring dependencies?
As the documentation says: dependency() "Finds an external dependency [...] with pkg-config if possible and with library-specific fallback detection logic otherwise."
So, if you mean to set PKG_CONFIG_PATH, you can do that as usual:
$ export PKG_CONFIG_PATH=/wherever/your/installed/dir/is/
$ meson ....
Or, you can use back-end specific variables, ie. BOOST_ROOT. Check the doc for more info.
If you ment to find other libraries not using pkg-config, you can add a dirs keyword argument to point to the directory your libraries are in.

cmake - find_library - custom library location

I'm currently trying to get CMake running for my project (on windows). I want to use a custom location where all libraries are installed. To inform CMake about that path I tried to do that:
set(CMAKE_PREFIX_PATH D:/develop/cmake/libs)
But when I try to find the library with
find_library(CURL_LIBRARY NAMES curl curllib libcurl_imp curllib_static)
CMake can't find it.
When I set my prefix path to
set(CMAKE_PREFIX_PATH D:/develop/cmake/libs/curl)
... the library is located.
So my question is:
How can I configure CMake properly to work with a directory structore at a custom location which looks like that:
D:/develop/cmake/libs/
-> libA
-> include
-> lib
-> libB
-> include
-> lib
-> ...
-> include
-> lib
In "include" lie the public headers and in "lib" are the compiled libraries.
edit:
The current workaround for me is, to do this before i search for libraries:
set(CUSTOM_LIBRARY_PATH D:/develop/cmake/libs)
file(GLOB sub-dir ${CUSTOM_LIBRARY_PATH}/*)
foreach(dir ${sub-dir})
if(IS_DIRECTORY ${dir})
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH};${dir})
endif()
endforeach()
But that way the default module for boost wont find it until it because the directory structore of boost is a bit different.
boost -> include -> boost-1_50 -> *.hpp
When I move the content if "boost-1_50" to "include" the library can be found but that way it's not possible to handle multiple versions right?
The simplest solution may be to add HINTS to each find_* request.
For example:
find_library(CURL_LIBRARY
NAMES curl curllib libcurl_imp curllib_static
HINTS "${CMAKE_PREFIX_PATH}/curl/lib"
)
For Boost I would strongly recommend using the FindBoost standard module and setting the BOOST_DIR variable to point to your Boost libraries.
I saw that two people put that question to their favorites so I will try to answer the solution which works for me:
Instead of using find modules I'm writing configuration files for all libraries which are installed. Those files are extremly simple and can also be used to set non-standard variables. CMake will (at least on windows) search for those configuration files in
CMAKE_PREFIX_PATH/<<package_name>>-<<version>>/<<package_name>>-config.cmake
(which can be set through an environment variable).
So for example the boost configuration is in the path
CMAKE_PREFIX_PATH/boost-1_50/boost-config.cmake
In that configuration you can set variables. My config file for boost looks like that:
set(boost_INCLUDE_DIRS ${boost_DIR}/include)
set(boost_LIBRARY_DIR ${boost_DIR}/lib)
foreach(component ${boost_FIND_COMPONENTS})
set(boost_LIBRARIES ${boost_LIBRARIES} debug ${boost_LIBRARY_DIR}/libboost_${component}-vc110-mt-gd-1_50.lib)
set(boost_LIBRARIES ${boost_LIBRARIES} optimized ${boost_LIBRARY_DIR}/libboost_${component}-vc110-mt-1_50.lib)
endforeach()
add_definitions( -D_WIN32_WINNT=0x0501 )
Pretty straight forward + it's possible to shrink the size of the config files even more when you write some helper functions. The only issue I have with this setup is that I havn't found a way to give config files a priority over find modules - so you need to remove the find modules.
Hope this this is helpful for other people.
Use CMAKE_PREFIX_PATH by adding multiple paths (separated by semicolons and no white spaces). You can set it as an environmental variable to avoid having absolute paths in your cmake configuration files
Notice that cmake will look for config file in any of the following folders
where is any of the path in CMAKE_PREFIX_PATH and name is the name of the library you are looking for
<prefix>/ (W)
<prefix>/(cmake|CMake)/ (W)
<prefix>/<name>*/ (W)
<prefix>/<name>*/(cmake|CMake)/ (W)
<prefix>/(lib/<arch>|lib|share)/cmake/<name>*/ (U)
<prefix>/(lib/<arch>|lib|share)/<name>*/ (U)
<prefix>/(lib/<arch>|lib|share)/<name>*/(cmake|CMake)/ (U)
In your case you need to add to CMAKE_PREFIX_PATH the following two paths:
D:/develop/cmake/libs/libA;D:/develop/cmake/libB
There is no way to automatically set CMAKE_PREFIX_PATH in a way you want. I see following ways to solve this problem:
Put all libraries files in the same dir. That is, include/ would contain headers for all libs, lib/ - binaries, etc. FYI, this is common layout for most UNIX-like systems.
Set global environment variable CMAKE_PREFIX_PATH to D:/develop/cmake/libs/libA;D:/develop/cmake/libs/libB;.... When you run CMake, it would aautomatically pick up this env var and populate it's own CMAKE_PREFIX_PATH.
Write a wrapper .bat script, which would call cmake command with -D CMAKE_PREFIX_PATH=... argument.
You have one extra level of nesting.
CMAKE will search under $CMAKE_PREFIX_PATH/include for headers and $CMAKE_PREFIX_PATH/libs for libraries.
From CMAKE documentation:
For each path in the CMAKE_PREFIX_PATH list, CMake will check
"PATH/include" and "PATH" when FIND_PATH() is called, "PATH/bin" and
"PATH" when FIND_PROGRAM() is called, and "PATH/lib and "PATH" when
FIND_LIBRARY() is called.
I've encountered a similar scenario. I solved it by adding in this following code just before find_library():
set(CMAKE_PREFIX_PATH /the/custom/path/to/your/lib/)
then it can find the library location.

Include a (header-only) library in an autotools project

I want to integrate a header-only C++ library in my Autotools project. Since the library uses Autoconf and Automake, I use AC_CONFIG_SUBDIRS in configure.ac and added the library dir to the SUBDIRS = line in Makefile.am.
My question is: how do I prevent the header library from being installed by make install? I'm building a single binary, so my users don't need these headers.
I'd prefer not to tamper with the library, so I can fetch upgrade by just untarring the new version.
Here is an idea.
Move all the third-party libraries you do not want to see installed into a subdirectory called noinst/. So for instance if you want to ship your project with something like Boost, unpack it into the directory noinst/boost/. Use AC_CONFIG_SUBDIRS([noinst/boost]). Inside noinst/Makefile.am, do something like this:
SUBDIRS = boost
# Override Automake's installation targets with the command ":" that does nothing.
install:; #:
install-exec:; #:
install-data:; #:
uninstall:; #:
The effect is that whenever some of the recursive "make install*" or "make uninstall" commands are run from the top-level directory, the recursion will stop in noinst/ and not visit its subdirectories. Other recursive commands (like "make", "make clean" or "make dist") will still recurse into the subdirectories.
You could of course override install: and friends directly into the third-party package, and avoid the extra noinst/ directory. But if you are like me, you don't want to tamper with third-party packages to ease their update.
Also a nice property of the above setup is that if someone goes into noinst/boost/ and decide to run make install, it will work. It just does not occur by default when they install your package.
just came across a similar problem and found the solution in the automake manual:
noinst_HEADERS would be the right variable to use in a directory containing only headers and no associated library or program
Andreas
Don't use SUBDIRS then. The following hack may work:
all-local:
${MAKE} -C thatlib all
Of course it would be best if the library remained in its own directory outside of your project, and you just point to it via CFLAGS/LIBS flags.