I want to create a shared *.dll library using a *.a Static library
Below is my CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(Projects)
set(CMAKE_CXX_STANDARD 11)
include_directories(../msys64/mingw64/include)
include_directories("../Program Files/Java/jdk1.8.0_151/include" "../Program Files/Java/jdk1.8.0_151/include/win32")
add_library(Projects1 SHARED main.cpp HelloWorld.cpp )
add_library(libgdal STATIC IMPORTED)
set_target_properties(libgdal PROPERTIES IMPORTED_LOCATION ../msys64/mingw64/lib/libgdal.a)
target_link_libraries(Projects1 A libgdal C )
it gives me below error:
*** No rule to make target '../msys64/mingw64/lib/libgdal.a', needed by 'libProjects1.dll'. Stop.
although when I try to create a Static Lib changing as below it works fine.
add_library(Projects1 STATIC main.cpp HelloWorld.cpp )
I am not sure how to create a Shared Library using a Static Library
Thanks for all the help in advance
Related
I'm new to cmake, so I'm having trouble figuring out how to model the following:
My program requires a third party library that I only have access to in the form of headers and *.so files. It also ships many of its dependencies as *.so files. How do I make sure that everything compiles and links correctly, ideally in the "correct" cmake way?
I've tried this
cmake_minimum_required (VERSION 3.8)
project ("Test")
add_executable (MyApp "MyApp.cpp")
link_directories("/path/to/lib")
target_include_directories(MyApp PUBLIC "/path/to/headers")
This compiles but fails at the linking stage.
Then I tried
cmake_minimum_required (VERSION 3.8)
project ("Test")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
add_executable (MyApp "MyApp.cpp")
find_package(Library REQUIRED)
target_link_libraries(MyApp PUBLIC Library::Library)
And cmake/FindLibrary.cmake following https://pabloariasal.github.io/2018/02/19/its-time-to-do-cmake-right/ (truncated):
...
if(Library_FOUND AND NOT TARGET Library::Library)
add_library(Library::Library SHARED IMPORTED)
set_target_properties(Library::Library PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${Library_INCLUDE_DIR}"
)
set_target_properties(Library::Library PROPERTIES
IMPORTED_LOCATION "/path/to/library.so"
)
endif()
This compiles and links, but the required other *.so files are not found at runtime. I suppose I need to add them also as libraries somehow, although I don't want them to be exported in FindLibrary.cmake. How do I do this correctly?
You can use IMPORTED libraries:
add_library(externalLib SHARED IMPORTED GLOBAL)
set_property(TARGET externalLib PROPERTY IMPORTED_LOCATION "/path/to/lib.so")
target_include_directories(externalLib INTERFACE "/path/to/headers")
target_link_directories(externalLib INTERFACE /path/to/libs)
target_link_libraries(externalLib INTERFACE -ldep1 -ldep2)
Then you can just depend on it:
target_link_libraries(MyApp PRIVATE externalLib)
I am building project using some libraries and CMake.
There are two projects; first is library using *.so" file and second is library and executable based on the first.
But when I run executable file of second project,
I get the following error:
my_library: error while loading shared libraries: my_lib.so.0: cannot open shared object file: No such file or directory
CMakeLists.txt of FirstProject:
add_library(my_lib SHARED IMPORTED)
set_property(TARGET my_lib PROPERTY IMPORTED_LOCATION lib/my_lib/my_lib.so)
add_library(my_first_lib SHARED my_first_lib.cpp)
target_link_libraries(my_first_lib my_lib)
CMakeLists.txt of SecondProject:
add_library(my_second_lib my_second_lib.cpp)
target_link_libraries(my_second_lib ${my_first_lib_LIBRARIES})
add_executable(my_second_exe my_second_exe.cpp)
target_link_libraries(my_second_exe my_second_lib)
How to link "*.so" file properly?
I've created a shared library with library.h and library.cpp. Then wrote a CMakeLists.txt file to build it as a shared library.
CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(test_pro)
set(CMAKE_CXX_STANDARD 11)
add_library(test_pro SHARED library.cpp library.h)
after building the library, I was able to get a .so file as /home/user/projects/test_lib/bin/libtest_pro.so
Then I tried linking the created library to another project in /home/user/projects/testproject
CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(testproject)
set(CMAKE_CXX_STANDARD 11)
link_directories(
/home/user/projects/test_lib/bin
)
add_executable(testproject main.cpp)
target_link_libraries (testproject test_pro)
It successfully builds the testproject (ldd command shows it has linked correctly), but I'm unable to use the library I've created in it.
In the main.cpp I've tried,
#include "library.h"
#include "test_pro"
#include <test_pro>
#include <test_pro/library.h>
But all the above gave build failures (fatal error: xxx: No such file or directory). How do I use this created library?
Just like you set link_directories() you have to specify include_directories(). And it is recommended not to use link_directories() at all, instead pass absolute path to the library into target_link_libraries().
My problem is relatively simple to explain. I have a CMake project(using CLion) running mainly on Windows.
A main CMakeLists.txt project, linking 2 subdirectories
src/Library shared library
src/Executable executable linking Library
See the project structure below.
# main CMakeLists.txt
cmake_minimum_required(VERSION 3.8)
project(TestTest)
set(CMAKE_CXX_STANDARD 11)
add_subdirectory(src/Library)
add_subdirectory(src/Executable)
# src/Library/CMakeLists.txt
add_subdirectory(include)
add_subdirectory(src)
add_library(TestLib SHARED ${TESTLIB_H_FILES} ${TESTLIB_SRC_FILES} )
target_include_directories(TestLib PUBLIC include)
#src/Executable/CMakeLists.txt
add_subdirectory(src)
add_executable(Executable ${EXECUTABLE_SRC_FILES})
target_link_libraries(Executable PUBLIC TestLib)
My problem is that the executable can't find the shared library at runtime.
I tried to add link_directories( ${CMAKE_CURRENT_BINARY_DIR}/src/Library) but didn't work.
What am I missing?
Please note: I wouldn't like to copy the shared library next to the executable manually/automatically by CMake, since I believe I would loose the debugging "capability" of the shared library. I will be getting the following error message by the GDB: No source file named C:/Users/flatron/CLionProjects/TestTest/src/Library/src/library.cpp.
All suggestions are really welcome and appreciated,
Thank you for your help
I suggest to use the following cmake command:
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
This will build all executables and shared libraries into the bin folder.
So there is no need to copy anything by hand.
I want to statically compile my program against another static library, for this example I'm using zeromq. Here is my CMakeLists.txt
cmake_minimum_required(VERSION 2.6)
add_executable( test test.cpp )
find_library(ZMQ NAMES libzmq.a)
message(STATUS ${ZMQ})
target_link_libraries( test ${ZMQ} )
It finds the .a file when I run mkdir build && cd build && cmake ..
-- /usr/local/lib/libzmq.a
However, if I examine the link.txt file, the library is dynamically linked:
/usr/bin/c++ CMakeFiles/test.dir/test.cpp.o \
-o test -rdynamic /usr/local/lib/libzmq.a
The weird bit is that if I move the file to a different directory, say /usr/lib and run cmake .. once more, it locates the new path to the library:
-- /usr/lib/libzmq.a
But now it has magically changed to static linking:
/usr/bin/c++ CMakeFiles/test.dir/test.cpp.o \
-o test -rdynamic -Wl,-Bstatic -lzmq -Wl,-Bdynamic
The same thing applies to other libraries I'm linking to.
Why are all my libraries in /usr/local/lib being dynamically linked?
You should not use the path directly, and create an imported target instead, so you can explicitly declare it static:
cmake_minimum_required(VERSION 2.6)
add_executable( test test.cpp )
find_library(zmq_location NAMES libzmq.a)
message(STATUS ${zmq_location})
add_library(zmq STATIC IMPORTED)
set_target_properties(zmq PROPERTIES IMPORTED_LOCATION ${zmq_location})
target_link_libraries( test zmq )
This may lead to a situation where the library appears to be linked dynamically, but the cmake source code has the answer:
If the target is not a static library make sure the link
type is shared. This is because dynamic-mode linking can handle
both shared and static libraries but static-mode can handle only
static libraries. If a previous user item changed the link type to
static we need to make sure it is back to shared.
Essentially, it's letting the linker handle detecting that the library is static if currently in dynamic-mode.
The answer to my original question about the difference between /usr/local/lib and /usr/lib is that, by default, /usr/local/lib is not one of the implicit link directories. Therefore, a quick fix is to include this line in the config:
set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES /usr/local/lib ${CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES})
However, as pointed out in this other answer, referencing files directly is not the way to go, instead one should use add_library.
Here is my DEMO:
find_library(VLQ_LIB NAMES vlq-shared PATHS /usr/local/lib/ REQUIRED)
find_path(VLQ_HEADER vlq.hpp /usr/local/include)
target_link_libraries(myproj PUBLIC VLQ_LIB)
target_include_directories(myproj PUBLIC VLQ_HEADER)
but during run, you still need to copy the shared lib to /lib/ folder, for static lib, you can keep it under /usr/lib