I'm having the following project structure in a C++ project. I am depending on an external library (libA as for the following) and I'm cloning the external library into the include folder using a shell script.
include/
libA
src/
source.c
lib/
include/
libA.a
src/
fileA.cpp
main.cpp
CMakeLists.txt
The command given to compile the program is
clang -I include/libA/lib/include main.cpp fileA.cpp include/libA/src/source.c include/libA/src/libA.a
I have seen on stackoverflow that in order to add this external library I have to create a separate CMakeLists.txt in the external library folder and use add_library(). And in the main CMakeLists.txt file use add_subdirectory().
Is there a way to do this without a seperate CMakeLists.txt.
My current main CMakeLists.txt file. (This works but I think I'm missing something)
cmake_minimum_required(VERSION 3.16.3)
project(test)
add_executable(${PROJECT_NAME} src/main.cpp src/fileA.cpp include/libA/src/source.c )
include_directories(include/libA/lib/include)
target_link_libraries(${PROJECT_NAME} /include/libA/libA.a )
target_include_directories(${PROJECT_NAME} PUBLIC include/libA/lib/include)
I have a C++ project that I want to build using CMake with Makefile Generators. I created a simple CMakeLists that only contains executable and directory configuration. The project was built and run successfully.
cmake_minimum_required(VERSION 3.17)
project(proj)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin)
add_executable(proj
${PROJECT_SOURCE_DIR}/catch2/catch.cpp
${PROJECT_SOURCE_DIR}/test.cpp
)
The linking process generates an archive file under the executable target folder CMakeFiles/proj.dir. The auto-generated link.txt file that is used in the link process contains these lines.
"cmake.exe" -E rm -f CMakeFiles\proj.dir/objects.a
ar.exe cr CMakeFiles\proj.dir/objects.a #CMakeFiles\proj.dir\objects1.rsp
g++.exe -g -Wl,--whole-archive CMakeFiles\proj.dir/objects.a -Wl,--no-whole-archive -o ..\bin\proj.exe -Wl,--out-implib,libproj.dll.a -Wl,--major-image-version,0,--minor-image-version,0 #CMakeFiles\proj.dir\linklibs.rsp
As far as I understand, by default CMake generates an archive and then creates an executable from that archive. Is there a way to simplify this step? I just want to link objects as an executable not generate an additional archive file. The expected link.txt file should be like that:
g++.exe -g -o ..\bin\proj.exe #CMakeFiles\proj.dir\objects1.rsp
when I use CMakeLists.txt with:
find_library(cryptoppV libcryptopp.a)
target_link_libraries(${PROJenter code hereECT_NAME} ${cryptoppV})
then i can find a library under /usr/local/lib,and make the C++ programe right and got the right result.
but when i replace it with:
-- find_library(cryptoppV libcryptopp.a)
target_link_libraries(${PROJECT_NAME} cryptopp)
then i got the error message:
ld: library not found for -lcryptopp
why cmake do not link /usr/local/lib by default? did i do something wrong?
-- add by aijinsong Oct 7, 2018 6:37 AM
i'm in more confused. when the CMakeLists.txt was:
set(SOURCE_FILES main.cpp)
add_executable(${PROJECT_NAME} ${SOURCE_FILES})
find_package(Boost 1.58 REQUIRED thread)
target_link_libraries(${PROJECT_NAME} Boost::thread)
find_library(cryptoppV libcryptopp.a)
target_link_libraries(${PROJECT_NAME} ${cryptoppV})
the compiler can find cryptopp/sha.h. but when the CMakeLists.txt was:
set(SOURCE_FILES main.cpp)
add_executable(${PROJECT_NAME} ${SOURCE_FILES})
## find_package(Boost 1.58 REQUIRED thread)
## target_link_libraries(${PROJECT_NAME} Boost::thread)
find_library(cryptoppV libcryptopp.a)
target_link_libraries(${PROJECT_NAME} ${cryptoppV})
the error message was:
fatal error: 'cryptopp/sha.h' file not found
#include <cryptopp/sha.h>
when the CMakeLists.txt was:
set(SOURCE_FILES main.cpp)
add_executable(${PROJECT_NAME} ${SOURCE_FILES})
find_package(Boost 1.58 REQUIRED thread)
## target_link_libraries(${PROJECT_NAME} Boost::thread)
find_library(cryptoppV libcryptopp.a)
target_link_libraries(${PROJECT_NAME} ${cryptoppV})
the error message was still:
fatal error: 'cryptopp/sha.h' file not found
#include <cryptopp/sha.h>
why i use cryptopp that the cmake ask me to link with library Boost::thread? i'm in more confused.
-- add by aijinsong Oct 7, 2018 11:56 AM
And if i use g++ main.cpp -o main -lcryptopp, i can get the right result. This shows that the library cryptopp has been installed correcttly, and g++ can find the library. why when i do it by make, it can't find the library?
-- add for KamilCuk start
-- add by aijinsong at Oct 7, 2018 3:27 PM
when i make it by make VERBOSE=1, i got the following message:
cd /Users/aijinsong/Documents/projects/com.aijs.cxx/bolochain/src && /usr/local/Cellar/cmake/3.12.3/bin/cmake -E cmake_link_script CMakeFiles/bolochain.dir/link.txt --verbose=1
and the text in link.txt is:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ -g -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk -Wl,-search_paths_first -Wl,-headerpad_max_install_names CMakeFiles/bolochain.dir/main.cpp.o -o bolochain /usr/local/lib/libboost_thread-mt.dylib -lcryptopp /usr/local/lib/libboost_chrono-mt.dylib /usr/local/lib/libboost_system-mt.dylib /usr/local/lib/libboost_date_time-mt.dylib /usr/local/lib/libboost_atomic-mt.dylib
this command cause the failure link but when i edit it like following, then c++ link command process very well:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ -g -Wl,-search_paths_first -Wl,-headerpad_max_install_names CMakeFiles/bolochain.dir/main.cpp.o -o bolochain /usr/local/lib/libboost_thread-mt.dylib -lcryptopp /usr/local/lib/libboost_chrono-mt.dylib /usr/local/lib/libboost_system-mt.dylib /usr/local/lib/libboost_date_time-mt.dylib /usr/local/lib/libboost_atomic-mt.dylib
just delete:
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk
I'm still working on this problem.
-- add for KamilCuk end
Fist, Thanks #Kamil Cuk. The argument -VERBOSE=1 was so useful that I can get more detail messages that show me what happens when I use make.
The point is that when I use cmake under OSX system. It will generate a txt be named 'link.txt' which includes commands and part of it is as the following:
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk
when I delete this part, the commands will execute right. but when I add this line, the commands execute wrong. so the point is that this line maybe limited the search path of c++. Thanks #tsyvarev . You are right, -isysroot limited the c++ linkers searches /usr/local/lib.
Second, I did't find out how to remove the line -isysroot ... generated by OSX cmake. So, I need to find another solution.
When I search more information about find_package/include_directories/target_link_libraries, I found out that find_package need a FindXXX.cmake file to help it to find out the header file and libraries of the target. So I googled a FindCyptoPP.cmake file. and in this file it find out tow vars, one hold the value of cryptopp's header directory path, and one hold the value of cryptopp's library path. Then I use include_directories/target_link_libraries as following, the problem
war solved.
find_package(CryptoPP)
include_directories(${CRYPTOPP_INCLUDE_DIRS})
target_link_libraries(${PROJECT_NAME} ${CRYPTOPP_LIBRARIES})
and then when I use make -VERBOSE = 1, I fond that the output was a little different when I use the CMakeLists.txt as following:
target_link_libraries(${PROJECT_NAME} cryptopp)
When I use three lines, the output contains a line /usr/local/lib/libcryptopp.dylib. When I use one line, the output contains a line -lcryptopp.
So, with the command line -isysroot, the command line -lcryptopp will search library under the directory defined by -isysroot, and under the directory, there is no library named cryptopp but under /usr/local/lib. But with command line /usr/local/lib/libcryptopp.dylib, it gaves the absolute path of the library, so the linkes just do the linking task and need not search. Thanks #Kamil Cuk again.
Thrid, I knew include_directories/target_link_libraries are two separate steps which one is used for include header file and one is used for link libraries.
Still, there were some problems not soled:
- how to remove -isysroot?
- how to create a FindXXX.cmake file?
- how to make /usr/local/lib as a default search directory and was it a practice way to do so?
I will continue working on them, and come back a few days or weeks later.
I've got a project which was originally using a makefile which i'm now converting to a Cmake project to use with CLion. I need to import gtk+1.2.10 and glib-1.2.10 both of which are located in /usr/local. I have attempted to include them but all attempts have resulted in messagees saying it cannot find gtk/gtk.h. My CMakeList.txt is
cmake_minimum_required(VERSION 3.9)
project(src)
set(CMAKE_CXX_STANDARD 11)
set(Library "../usr/local")
include_directories(${Library})
include(FindPkgConfig)
add_custom_target(src COMMAND make -C ${src_SOURCE_DIR}
CLION_EXE_DIR=${PROJECT_BINARY_DIR})
link_directories("/usr/local/gtk+-1.2.10/lib")
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
set(glib_DIT "/usr/local/glib-1.2.10/lib/libgmodule.so")
find_package(GTK 1.2.10)
IF (glib-1.2.10_FOUND)
INCLUDE_DIRECTORIES(${glib-1.2.10_INCLUDE_DIR})
ENDIF()
include_directories(/usr/local/glib-1.2.10/lib)
include_directories(/usr/local/gtk+-1.2.10/lib)
The MakeFile is
gcc -Bstatic -L /usr/local/gtk+-1.2.10/lib -L /usr/local/glib-1.2.10/lib -lgtk -lglib -I ../ -I /usr/local/glib-1.2.10/lib/glib/include -I /usr/local/glib-1.2.10/include/glib-1.2/ -I /usr/local/gtk+-1.2.10/include/gtk-1.2/
What can I do to be able to these libraries inside of CLion.
EDIT: I have created a p.c file called gtk with contents
prefix = /usr/local/gtk+-1.2.10
exec_prefix=${prefix}
includedir=${prefix}/include
libdir=${exec_prefix}/lib
Name:GTK
Description:WORKS FFS
Version:1.2.10
Cflags: -I{includedir}/gtk-1.2 -lgdk -l
Libs: -L{libsdir} -Lgtk
And my current cmake file is
cmake_minimum_required(VERSION 3.9)
project(src C)
#set(CMAKE_CXX_STANDARD 11)
set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:/usr/local/gtk+-1.2.10/bin")
include(FindPkgConfig)
pkg_check_modules(gtk REQUIRED gtk)
Even with these changes the outcome is the same
I have the following code structure
Project->
project.cxx
CMakeLists.txt
meta->
CMakeLists.txt
first->
first.cxx
CMakeLists.txt
second->
second.cxx
CMakeLists.txt
where first/CMakeLists.txt contains:
FILE(GLOB first_sources "*.cxx")
ADD_LIBRARY(first OBJECT ${first_sources})
second/CMakeLists.txt contains:
FILE(GLOB second_sources "*.cxx")
ADD_LIBRARY(second OBJECT ${second_sources})
meta/CMakeLists.txt contains:
ADD_SUBDIRECTORY(first)
ADD_SUBDIRECTORY(second)
ADD_LIBRARY(meta OBJECT $<TARGET_OBJECTS:first> $<TARGET_OBJECTS:second>)
and finally, Project/CMakeLists.txt containts:
ADD_SUBDIRECTORY(meta)
FILE(GLOB Project_SOURCES "*.cxx")
ADD_LIBRARY(Project SHARED ${Project_SOURCES} $<TARGET_OBJECTS:meta>)
However,
ADD_LIBRARY(meta OBJECT $<TARGET_OBJECTS:first> $<TARGET_OBJECTS:second>)
fails given that OBJECT library expects c/cxx sources instead of object files.
What I am trying to achieve is a relocatable object file that combines both first.o and second.o into a meta.o as:
ld -r first.o second.o -o meta.o
What would be the CMake alternative for the same?