I have some files in my project, this is the structure:
main.cpp
addition.cpp
division.cpp
print_result.cpp
I write a CMakeLists like below and it can work well:
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(Calculator_Project VERSION 1.0.0)
add_executable(calculator
main.cpp
addition.cpp
division.cpp
print_result.cpp)
or
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(Calculator_Project VERSION 1.0.0)
add_library(my_math addition.cpp division.cpp)
add_library(my_print print_result.cpp)
add_executable(calculator main.cpp)
target_link_libraries(calculator my_math my_print)
However, if I want to add more modules such as multiplication or subtraction... I have to add these modules to the CMakeLists.txt as below, it looks not well.
add_executable(calculator
main.cpp
addition.cpp
division.cpp
multiplication.cpp
subtraction.cpp
print_result.cpp)
or
add_library(my_math
addition.cpp
division.cpp
multiplication.cpp
subtraction.cpp)
I know three is a way like this can solve the problem:
file(GLOB SOURCES "src/*.cpp")
add_executable(calculator ${SOURCES})
but it will add all the source files to one target, this is not a good idea. I just want to get the source files that the target depends on. In particular, if one target depends on many libraries, it is not an easy task to add all relevant dependencies to each target, so I want to ask if there is a better way to simplify it.
Related
When building my project with CMake, I would like it to link to libraries statically (if available). Right now, it finds .dll.a files, regardless of the existence of .a files.
For example, take linking to libpng in a small sample project:
cmake_minimum_required(VERSION 3.15)
project(Test)
add_executable(Test main.cpp)
find_package(PNG REQUIRED)
message(${PNG_LIBRARIES})
target_link_libraries(Test PRIVATE ${PNG_LIBRARIES})
For the message, it outputs
C:/msys64/mingw64/lib/libpng.dll.aC:/msys64/mingw64/lib/libz.dll.a
But the libpng.a and libz.a files are also available in the same directory. How can I tell CMake to link with .a files?
I am using MinGW-w64 with msys64 on Windows 10, but would prefer a solution that is cross-platform.
Here is my source code structure:
cd my_git_repo/
CMakeLists.txt
src/
main.cpp
mylibrary/
a.hpp
b.hpp
a.cpp
b.cpp
CMakeLists.txt
Root CMakeLists.txt:
cmake_minimum_required(VERSION 3.9)
project(myexe CXX)
add_subdirectory(src/mylibrary)
find_library(mylib NAMES mylibrary.so PATHS "./src/mylibrary/mylibrary.so")
add_executable(myexe src/main.cpp)
target_link_libraries(myexe ${mylib})
mylibrary/CMakeLists.txt is very simple. It builds a shared library and installs them.
Ideally, mylibrary target should be built and installed before myexe is built. But this doesn't happen. mylibrary is built followed by myexe. Installation happens later. Because of this, find_library fails. pkg_check_modules() works for other shared libraries but fails here because of the same reason.
I appreciate your help.
Edit:
This question differs from the duplicate because the answers posted to that question seem to be statically linking the library target_link_libraries(game engine). I want to dynamically link the .so library.
The idea in CMake is to build modules and then link them together.
You haven't shared the CMakeLists.txt for my library, so we cannot tell what it is doing. However, assuming that it is something like:
ADD_LIBRARY(mylibrary
file1.cpp
file2.cpp
)
Since you specified that you want mylibrary to always be linked as shared, you need to tell CMake that as well by either setting BUILD_SHARED_LIBS TO ON or by specifying SHARED in add_library:
ADD_LIBRARY(mylibrary SHARED
file1.cpp
file2.cpp
)
This is your library module. We will keep it simple for now and not worry about packing the library archive and installation here.
Now, back to your main CMakeLists.txt and how to make myexe consume it. Since you have already add_subdirectory(src/mylibrary), CMake knows about mylibrary. So simply link it using the module name. There is no need to find_library as you have already defined the module.
add_executable(myexe src/main.cpp)
target_link_libraries(myexe mylibrary)
This should suffice.
Do note, however, this is a very basic example to explain to you how CMake is designed to work. If you aren't building the library, and it is already installed, you would call find_library. Modern CMake is a bit more sophisticated and uses generator expressions, so be sure to read up on that as you progress to more complex projects.
I am currently creating a set of classes that should be used in
different projects using CLion. My question is how do I implement this
functionality. So far I looked into the following related issues
which didn't really solve my problem:
CMake link to external library
Add external libraries to CMakeList.txt c++
CMake reference for add_library(), find_library() which I don't fully understand yet since I am fairly new to CMake
I created two sample projects "TestLib" and "TestProj":
TestLib src Class.h Class.cpp
CMakeList.txt TestProj main.cpp
CMakeList.txt
The CMakeList.txt for "TestLib" currently looks as follows:
cmake_minimum_required(VERSION 3.5)
project(TestLib)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++0x")
set(SOURCE_FILES src/Class.cpp src/Class.h)
add_library(TestLib ${SOURCE_FILES})>
Now, I tried to use this library in "TestProj" using the following
CMakeLists.txt:
cmake_minimum_required(VERSION 3.5)
project(TestProj)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++0x")
find_library(CLASS_LIB TestLib HINTS /home/user/.CLion2016.1/system/cmake/generated/TestLib-7507f101/7507f101/Debug)
set(SOURCE_FILES main.cpp)
add_executable(TestProj ${SOURCE_FILES})
target_link_libraries(TestProj CLASS_LIB)
CMake finds the library but
I dont have access to Class.h of the library
Writing the whole /home/user/.CLion2016.1/...-Path to the library seems to be wrong
Any help is really appreciated. Thank you.
If the goal is to make your library available to multiple other projects, the recommended way to do that would be to have your library project's install procedure generate CMake configuration files. Unfortunately, the procedure to do that is a bit arcane, but https://cmake.org/cmake/help/git-master/manual/cmake-packages.7.html#creating-packages should give you a starting point on how to do this.
You can put at the root of your projects CMakeLists.txt
with such content:
add_subdirectory(TestLib)
add_subdirectory(TestProj)
after that you can write in TestProj's CMakeLists.txt just
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../TestLib)
target_link_libraries(TestProj TestList)
and no need to use find_library
I have the following cmake setup:
colorizer_root
|
|-------colorizer_lib
|-------colorizer_template_project
The colorizer_root contains the top level CMakeLists.txt which is invoked when running cmake:
colorizer_root CMakeLists.txt
project(colorizer_root)
cmake_minimum_required(VERSION 2.8)
set(CMAKE_BUILD_TYPE Debug)
add_subdirectory(colorizer_lib)
add_subdirectory(colorizer_template_project)
As you can see it contains 2 subdirectories each a project on its own. Basically what the colorizer_lib does is create a shared library named libcolorize.so (no executables here!), which then is to be used by the other project colorizer_template_project (the executable is created in this project). Here are the two CMakeLists.txt files for their respective projects:
colorizer_lib CMakeLists.txt
project(colorizer_lib)
cmake_minimum_required(VERSION 2.8)
set(CMAKE_CXX_FLAGS "--std=gnu++11 ${CMAKE_CXX_FLAGS}")
include_directories(. INCLUDES)
add_library(colorizer SHARED colorizer.cpp)
colorizer_template_project CMakeLists.txt
project(colorizer_template_project)
cmake_minimum_required(VERSION 2.8)
find_library(COLORIZER_LIB colorizer
PATHS ${CMAKE_BINARY_DIR}/colorizer_lib
)
aux_source_directory(. SRC_LIST)
add_executable(${PROJECT_NAME} ${SRC_LIST})
target_link_libraries(${PROJECT_NAME} ${COLORIZER_LIB})
I'm having trouble figuring out how the whole lookup thing works. The problem here is that when I run the top level CMakeLists.txt it goes through both (obviously) but during processing the colorizer_template_project it breaks with a complaint:
CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the CMake files:
COLORIZER_LIB
linked by target "colorizer_template_project" in directory /home/USER/Programming/C_Cpp/colorizer/colorizer_template_project
This is an expected behaviour since libcolorizer.so cannot be present at the time of running cmake because it is created after make has been invoked.
How do I tell cmake to first process the first project (including the build step!) and then go to the next one? I know that this works if I add an executable to the project that creates the library and then directly link it to the binary but in this case I want separate projects for the library and the executable that is using it.
PS: I haven't given any details about the sources because they are not important here. It is - I believe - a general question, which is not specific to whether I'm using C, C++ or something similar.
project command doesn't make subprojects independent, so colorizer target is actually accessible for colorizer_template_project, and you can directly link with it:
add_executable(${PROJECT_NAME} ${SRC_LIST})
target_link_libraries(${PROJECT_NAME} colorizer)
I have the following directory structure and library dependencies:
./lib-a
./lib-b (depending on lib-a)
Each directory contains a CMakeLists.txt file for generating its own library.
I am using an out-of-source building policy.
In order to say that lib-b depends on lib-a, I have put the command add_subdirectory(../lib-a lib-a) in ./lib-b/CMakeLists.txt, according to what is taught by the official CMake tutorial. This way I obtain that a subdirectory lib-a is created in ./lib-b/build dir.
This is not the behaviour I desire. What I would like to obtain is CMake making reference to lib-a in generating lib-b and, if lib-a has not been already generated, CMake should generate it inside ./lib-a/build by using the CMakeLists.txt of lib-a (in a behaviour similar to the one of the make tool when dealing with dependencies).
I would also like to add that I am not using a root CMakeLists.txt in my example, but what I would like to have is the lib-b/CMakeLists.txt declaring the dependency on lib-a, thus making lib-a to be compiled, if not already, by using its own lib-a/CMakeLists.txt.
Here is the dirs structure and their contents:
lib-a/
CMakeLists.txt (for compiling lib-a)
src/
test.cpp
include/
test.hpp
lib-b/
main.cpp
CMakeLists.txt (for compiling lib-b; here is the point where I would like to make reference to lib-a, that I need for the generation of lib-b)
lib-b/main.cpp contains also an include of test.hpp of lib-a, because it is using a function of lib-a. This should be taken into consideration in the specification of lib-b/CMakeLists.txt.
What should the content of the two lib-a/CMakeLists.txt and lib-b/CMakeLists.txt files be?
I think you misunderstand the tutorial. The thing that links the libraries together is target_link_library(lib_b lib_a). If the name of the dependency is a library that is part of the build, CMake will magically make the dependencies work. It has nothing to do with subdirectories. In fact, if I have the following directory structure:
./
./a.hpp
./a.cpp
./b.hpp
./b.cpp
./CMakeLists.txt
The following will set the dependencies just fine:
PROJECT(lib_a)
ADD_LIBRARY(lib_a a.hpp a.cpp)
PROJECT(lib_b)
ADD_LIBRARY(lib_b b.hpp b.cpp)
TARGET_LINK_LIBRARIES(lib_b lib_a)
This will work across subdirectory projects as well:
./
./CMakeLists.txt
./lib_a/CMakeLists.txt
./lib_a/a.hpp
./lib_a/a.cpp
./lib_b/CMakeLists.txt
./lib_b/b.hpp
./lib_b/b.cpp
And the list files:
# ./CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
ADD_SUBDIRECTORY(lib_a)
ADD_SUBDIRECTORY(lib_b)
# ./lib_a/CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT(lib_a)
ADD_LIBRARY(lib_a a.hpp a.cpp)
# ./lib_b/CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT(lib_b)
INCLUDE_DIRECTORIES(${lib_a_SOURCE_DIR})
ADD_LIBRARY(lib_b b.hpp b.cpp)
TARGET_LINK_LIBRARIES(lib_b lib_a)