I am able to do this without CMake using a handwritten Makefile, like so:
g++ $(CXSCINC) -c -fPIC cellComplex_extern.cpp -o cellComplex_extern.o
g++ $(CXSCINC) -shared -Wl -o cellComplex_lib.so cellComplex_extern.o $(CXSCLIB) -lcxsc
This gets me shared library cellComplex_lib.so, which then gets picked up by ctypes as a dynamically linked library (lib = ctypes.cdll.LoadLibrary('./cellComplex_lib.so') for later use.
My project has moved to CMake as a build system and I am looking to emulate the functionality of my Makefile above.
So far I have discovered the add_library() command for CMakeLists.txt, but the link to the CXSC library is never made (as evidenced by horrible complaining when I run make after cmake.
How can I tell CMake to build cellComplex_lib with the third-party library CXSC?
-- non-working CMakeLists.txt --
add_library(include/python/cellComplex_extern OBJECT
include/python/cellComplex_extern.cpp ${all_headers})
add_library(include/python/cellComplex_lib SHARED
include/python/cellComplex_extern)
target_link_libraries(include/python/cellComplex_lib ${CXSC_LIB_DIR}/libcxsc.a)
Result of running cmake followed by make:
.
.
.
[ 75%] Built target include/python/cellComplex_extern
Linking CXX shared library libinclude/python/cellComplex_lib.dylib
ld: can't open output file for writing: libinclude/python/cellComplex_lib.dylib, errno=2 for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [libinclude/python/cellComplex_lib.dylib] Error 1
make[1]: *** [CMakeFiles/include/python/cellComplex_lib.dir/all] Error 2
make: *** [all] Error 2
I think you need to use target_link_libraries
target_link_libraries(include/python/cellComplex_lib ${CXSLIB})
This is what I use during Win32 development:
link_directories(${LIB_ROOT_DIR}/lib ${LIB_ROOT_DIR2}/lib/morelibs)
add_library(MyDll1 SHARED File1.cpp File2.cpp)
add_library(MyDll2 SHARED File3.cpp File4.cpp)
add_dependencies(MyDll2 Dll1)
target_link_libraries(MyDll2 Dll1 some.lib another.lib)
Here you specify that Dll2 requires Dll1 and two other external lib's.
Related
I'm interested in statically linking PROJ to a library created with pybind11.
but, I get error by cmake.
Why am I getting this error and how can I fix it?
My CMakeLists.txt is this.
cmake_minimum_required(VERSION 3.4)
project(myearth LANGUAGES CXX)
add_subdirectory(pybind11)
pybind11_add_module(myearth MyEarth.cpp)
include_directories(${CMAKE_SOURCE_DIR}/PROJ/include)
add_library(proj4 STATIC IMPORTED)
set_target_properties(proj4 PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/PROJ/lib/libproj.a)
target_link_libraries(myearth PRIVATE proj4)
CMake Error.
I think fPIC option is for shared library. so, libproj.a is not necessary this option because this is static library.
(venv) ~/Projects/LinkLibTest/MySample/build$ make
[ 50%] Building CXX object CMakeFiles/myearth.dir/MyEarth.cpp.o
[100%] Linking CXX shared module myearth.cpython-36m-x86_64-linux-gnu.so
/usr/bin/ld: ../PROJ/lib/libproj.a(proj_4D_api.o): relocation R_X86_64_PC32 against symbol `pj_errno' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: bad value
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/myearth.dir/build.make:98: myearth.cpython-36m-x86_64-linux-gnu.so] Error 1
make[1]: *** [CMakeFiles/Makefile2:100: CMakeFiles/myearth.dir/all] Error 2
make: *** [Makefile:91: all] Error 2
(venv) ~/Projects/LinkLibTest/MySample/build$
I created libproj.a by the following command.
$ ./configure --prefix=/output --disable-shared
$ sudo make
$ sudo make install
Linux Mint 20.3 64bit
CMake v3.22.2
PROJ v5.2.0 (https://proj.org/)
Python v3.6.8
Thank you.
Shared libraries must have position independent code, but your version of PROJ was built without it; you will have to rebuild PROJ with PIC.
$ ./configure --prefix=/output --with-pic
I'm trying to add ZipLip into my project using Clion on ubuntu, but I have this output:
====================[ Build | TryZip | Debug ]==================================
/home/david/Snap/clion-2019.2.4/bin/cmake/linux/bin/cmake --build
/home/david/CLionProjects/TryZip/cmake-build-debug --target TryZip -- -j 2
[ 13%] Built target bzip2
[ 31%] Built target zlib
[ 83%] Built target lzma
[ 95%] Built target ZipLib
Scanning dependencies of target TryZip
[ 97%] Linking CXX executable ../bin/TryZip
/usr/bin/ld: cannot find -lExternalLibrary/ZipLib
collect2: error: ld returned 1 exit status
CMakeFiles/TryZip.dir/build.make:102: recipe for target '../bin/TryZip' failed
make[3]: *** [../bin/TryZip] Error 1
CMakeFiles/Makefile2:109: recipe for target 'CMakeFiles/TryZip.dir/all' failed
make[2]: *** [CMakeFiles/TryZip.dir/all] Error 2
CMakeFiles/Makefile2:116: recipe for target 'CMakeFiles/TryZip.dir/rule' failed
make[1]: *** [CMakeFiles/TryZip.dir/rule] Error 2
Makefile:131: recipe for target 'TryZip' failed
make: *** [TryZip] Error 2
This is my Cmakefile.txt
cmake_minimum_required(VERSION 3.15)
project(TryZip)
if(BOOST_FILESYSTEM)
include_directories(${BOOST_INCLUDE_DIR})
link_directories(${BOOST_LIB_DIR})
add_definitions(-DUSE_BOOST_FILESYSTEM)
else()
if(MSVC)
add_definitions(-DFILESYSTEM_EXPERIMENTAL)
endif()
endif()
if(BOOST_FILESYSTEM)
if(UNIX)
find_package(Boost COMPONENTS system filesystem REQUIRED)
target_link_libraries(${Boost_FILESYSTEM_LIBRARY}
${Boost_SYSTEM_LIBRARY})
endif()
endif()
add_subdirectory(ExternalLibrary/ZipLib)
link_libraries(ExternalLibrary/ZipLib)
include_directories(ExternalLibrary/ZipLib)
set(CMAKE_CXX_STANDARD 17)
add_executable(TryZip main.cpp ExternalLibrary/ZipLib/ZipFile.cpp)
target_link_libraries(TryZip ZipLib)
Can someone help me to solve this please?
My ZipLib folder is in the same folder as my cmakefile.txt file.
The call to link_libraries() appears to accept the wrong arguments in this case. The link_libraries() command takes arguments of existing CMake targets, or library names. It is also redundant with your target_link_libraries() call, as this already links ZipLib to TryZip.
Try removing the call to link_libraries(), as this CMake function is deprecated and its use is highly discouraged. The include_directories() call is similarly deprecated, in favor of the target-specific command, so consider using target_include_directories() instead.
Assuming your added sub-directory ExternalLibrary/ZipLib contains an additional CMakeLists.txt file for configuring the ZipLib target, you should not need to add the ZipFile.cpp file again. If this file is already compiled in the sub-directory into the target ZipLib, you do not need to compile it again into TryZip.
add_subdirectory(ExternalLibrary/ZipLib)
set(CMAKE_CXX_STANDARD 17)
add_executable(TryZip main.cpp)
target_include_directories(TryZip PRIVATE ExternalLibrary/ZipLib)
target_link_libraries(TryZip PRIVATE ZipLib)
EDIT: Based on your feedback, it appears ZipLib also depends on pthread but somehow it is not getting linked correctly. You might try to add the following to your ExternalLibrary/ZipLib/CMakeLists.txt file (if it doesn't already exist), to utilize CMake's FindThreads module:
find_package(Threads REQUIRED)
...
target_link_libraries(ZipLib PUBLIC Threads::Threads)
I am working on quickrank: https://github.com/hpclab/quickrank. when I compile it I get error
cmake .. -DCMAKE_CXX_COMPLIER=/usr/bin/g++ -DCMAKE_BUILD_TYPE=Release
You have called ADD_LIBRARY for library pugixml without any source files. This typically indicates a problem with your CMakeLists.txt file
-- Configuring done
CMake Error: Cannot determine link language for target "pugixml".
CMake Error: CMake can not determine linker language for target: pugixml
CMake Error: CMake can not determine linker language for target: pugixml
-- Generating done
-- Build files have been written to: /home/students/s4438236/quickrank/build_
s4438236#moss:~/quickrank/build_$ make
make[2]: *** No rule to make target `CMakeFiles/pugixml.dir/build'. Stop.
make[1]: *** [CMakeFiles/pugixml.dir/all] Error 2
make: *** [all] Error 2
I do find source file under the lib\pugixml folder, how can I fix this error?
When you call the add_library CMake command, you must provide source files for this target. If we examine the top-level CMakeLists.txt file, we see where the error is occurring:
# external libraries
file(GLOB_RECURSE pugixml_sources ${CMAKE_SOURCE_DIR}/lib/pugixml/src/*.cpp)
add_library(pugixml STATIC ${pugixml_sources})
The CMake error suggests that the pugixml_sources variable is empty, which hints that the /lib/pubixml may have also been empty. If you initially didn't run the git clone command with --recursive, you would not have gotten the pugixml submodule.
Seeing as you said the pugixml sources are now there, I would suggest deleting your CMake cache and the CMake build folder. Running CMake again from scratch will likely allow it to see the pugixml source files.
I have a Cmake executable that has been created using ADD_EXECUTABLE.
The executable needs (links to) shared libraries that have been created
also part of the project.
As a final step I want to run this executable as part of the build process to
create some additional files for the build.
so
ADD_EXECUTABLE(foo)
ADD_CUSTOM_COMMAND(OUTPUT out1
WORKING_DIRECTORY dir1
COMMAND foo args
...)
However when the custom command runs it gives an error
.../foo: error while loading shared libraries: libbar.so.1: cannot open shared object file: No such file or directory
make[2]: *** [out1] Error 127
make: *** [all] Error 2
The problem is that the LD_LIBRARY_PATH is not set for the executable to load the library
libbar.so.1. How do in a cross-platform manner set the load library settings in cmake.
I don't want to use RPATH because it actually embeds those paths in the executable, which I
don't want.
On the command line, the following produces an executable:
g++ -o a.out main.cpp class1.cc class2.cc /usr/lib/libgsl.a /usr/lib/libgslcblas.a
However I am unsure how to get cmake to work properly.
When I add a line like
include_directories(/usr/lib/)
link_libraries(usr/lib/libgsl.a usr/libgslcblas.a)
the configuring seems to work but building fails:
CMakeFiles/kmv.dir/main.o: In function `main':
main.cpp:27: undefined reference to `gsl_matrix_alloc'
main.cpp:35: undefined reference to `gsl_matrix_fscanf'
collect2: ld returned 1 exit status
make[2]: *** [kmv] Error 1
make[1]: *** [CMakeFiles/kmv.dir/all] Error 2
make: *** [all] Error 2
*** Failed ***
Seems to be a synthax problem. Any hint is welcome. Thank you.
Instead of
include_directories(/usr/lib)
link_libraries(usr/lib/libgsl.a usr/libgslcblas.a)
try
add_executable (targetName main.cpp class1.cc class2.cc)
target_link_libraries(targetName gsl gslcblas)
Where targetName is the name of the output binary you intend to create. The path /usr/lib should already be in the default library search path for CMake, so you shouldn't have to specify that, but if you did have to specify a custom library path, you would do it like so
link_directories(/some/custom/library/path)
The include_directories CMake directive is used for adding header search paths, not library search paths...
Probably, link_libraries is deprecated
http://www.cmake.org/pipermail/cmake/2009-April/028439.html
Try using target_link_libraries instead.