My current project structure looks like this:
Project
--src/
--CMakeLists.txt
--Graph.cpp
--Graph.hpp
--main.cpp
--build/
--CMakeLists.txt
The CMakeLists.txt in the Project folder lookalike this:
cmake_minimum_required(VERSION 3.18)
project(GRAPHTHEORY VERSION 1.0.0)
set (CMAKE_CXX_STANDARD 17)
add_subdirectory(src)
the CMakeLists.txt in src file looks like this:
add_library(Graph Graph.hpp Graph.cpp)
add_executable(graph_theory main.cpp)
target_link_libraries(graph_theory PRIVATE Graph )
When I go into the build/ directory, and run cmake .. and then make, the executable graph_theory is in a new src/ directory within build
I am not sure why a new src/ directory is being created in my `build/' directory.
Edit:
So what I was trying to do is replicate running
cmake -S src/ -B build/ from Project directory.
When I do the above and then cd into build/ and then run make, the executable is created in build/ directory.
Build artifacts and cache is kept in a directory that reflect the subdirectory you added in CMake with the add_subdirectory command.
However, you can change where the final target end up by changing the default value of RUNTIME_OUTPUT_DIRECTORY. For example, this code will put it in the bin directory:
set_target_properties(graph_theory
PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/"
)
Related
I am working in a project which uses jsoncpp for parsing and cmake for compilation. I added the jsoncpp official git repository as a submodule to my project with git submodule add REPO_URL external/jsoncpp, so as to keep every dependency together.
When running cmake -B out/build, it works normally. But when I do make, I get the following error:
/usr/bin/ld: cannot find -ljsoncpp: No such file or directory.
The files are organized the following way:
- root
- out/build
- external
- jsoncpp (cloned repo)
- include
foo.h
bar.h
- src
foo.cpp
bar.cpp
main.cpp
CMakeLists.txt
The CMakeLists.txt is like this:
cmake_minimum_required(VERSION 3.22.1)
project(ants)
# ".cpp" files in folder "src" into cmake variable "SOURCE"
file(GLOB SOURCE "src/*.cpp")
# Executable
add_executable(${PROJECT_NAME} ${SOURCE})
# Directory where cmake will look for include files
include_directories(include)
# Tells cmake to compile jsoncpp
add_subdirectory(external/jsoncpp)
# Tells cmake where to look for jsoncpp include files
target_include_directories(${PROJECT_NAME}
PUBLIC external/jsoncpp/include
)
target_link_libraries(${PROJECT_NAME} jsoncpp)
The jsoncppConfig.cmake defines property INTERFACE_INCLUDE_DIRECTORIES for targets jsoncpp_lib and jsoncpp_lib_static.
You need to query the target property and set it manually:
get_target_property(JSON_INC_PATH jsoncpp_lib INTERFACE_INCLUDE_DIRECTORIES)
include_directories(${JSON_INC_PATH})
Linking is done via:
target_link_libraries(${PROJECT_NAME} jsoncpp_lib)
Source.
Try this:
cmake_minimum_required(VERSION 3.22.1)
project(ants)
# ".cpp" files in folder "src" into cmake variable "SOURCE"
file(GLOB SOURCE "src/*.cpp")
# Executable
add_executable(${PROJECT_NAME} ${SOURCE})
# Directory where cmake will look for include files
include_directories(include)
# Tells cmake to compile jsoncpp
add_subdirectory(external/jsoncpp)
get_target_property(JSON_INC_PATH jsoncpp_lib INTERFACE_INCLUDE_DIRECTORIES)
include_directories(${JSON_INC_PATH})
target_link_libraries(${PROJECT_NAME} jsoncpp_lib)
I am using the Unity testing library in my project. Ideally, I would like to automatically download the source code from GitHub and put it in the external/ directory, build the library once, regardless of how many different CMake configurations I have (one Debug and one Release CMake configuration), and link the library with my application.
I have tried to use FetchContent, ExternalProject, and add_subdirectory but none of these seem to work quite right.
The issues I am currently facing right now are:
The library is installed in the _deps/ subdirectory of my build/ directory. I want it to be downloaded to a directory called external/ in the project root.
"cmake --build ." builds the library every time. I just want the library to be built once.
"cmake --install ." installs my application and the Unity library. I only want install to install my application when this command is run. The library would be installed in lib/ and include/ before my application is built.
This is my project structure:
project/ <-- Project root
|-- bin/ <-- Application executable
|-- build/ <-- CMake build files
| |-- _deps/ <-- Where Unity is built
|-- doc/ <-- Documentation from Doxygen
|-- include/ <-- Unity header files
|-- lib/ <-- Unity library file
|-- module/ <-- Application source code
|-- CMakeLists.txt <-- CMake configuration file
This is my CMakeLists.txt:
cmake_minimum_required(VERSION 3.15)
project(Project VERSION 1.0.0)
set(CMAKE_INSTALL_PREFIX ${PROJECT_SOURCE_DIR})
include_directories(${PROJECT_SOURCE_DIR}/include)
add_subdirectory(module)
# Add Unity testing framework from GitHub
include(FetchContent)
FetchContent_Declare(
unity
GIT_REPOSITORY https://github.com/ThrowTheSwitch/Unity.git
GIT_TAG v2.5.1
)
FetchContent_MakeAvailable(unity)
FetchContent_GetProperties(unity)
if (NOT unity_POPULATED)
FetchContent_Populate(unity)
add_subdirectory(${unity_SOURCE_DIR} ${unity_BINARY_DIR})
endif()
enable_testing()
add_subdirectory(tests)
I really have no idea how to accomplish this. I looked at this other question and this link but it didn't seem to do everything I wanted it to do. Any help is appreciated.
I was able to make it work using ExternalProject. This is what my CMakeLists.txt looks like now:
include(ExternalProject)
set(UNITY unity_project)
ExternalProject_Add(
unity_project
GIT_REPOSITORY https://github.com/ThrowTheSwitch/Unity.git
GIT_TAG cf949f45ca6d172a177b00da21310607b97bc7a7
PREFIX ${PROJECT_SOURCE_DIR}/external/${UNITY}
CONFIGURE_COMMAND cmake ../${UNITY}
BUILD_COMMAND cmake --build .
INSTALL_COMMAND cmake --install . --prefix ${PROJECT_SOURCE_DIR}
UPDATE_COMMAND ""
)
add_library(unity STATIC IMPORTED)
set_property(TARGET unity PROPERTY IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/lib/libunity.a)
add_dependencies(unity unity_project)
The first issue was solved by the line:
PREFIX ${PROJECT_SOURCE_DIR}/external/${UNITY}
The second issue was solved by the line:
UPDATE_COMMAND ""
The third issue was solved by the line:
INSTALL_COMMAND cmake --install . --prefix ${PROJECT_SOURCE_DIR}
As an example suppose four folders(app1, app2, app3 and main) such as below
main
|__ CMakeLists.txt
\__ module1
|______ CMakeLists.txt
|______ sub1.cpp
|______ sub1.h
\__ library5
|______ CMakeLists.txt
|______ sub5.cpp
|______ sub5.h
\__app1
\__app2
\__app3
Which output of module1 is module1.dll and output of library5 is lib5.dll. Folder of app1 must contain module1.dll and lib5.dll, app2 needs lib5.dll and finally app3 needs module1.dll(number of apps, modules and libs are more than this example and as I explain below we don't want to change modules/libraries's CMakeLists.txt, just main's CMakeLists.txt is ours).
PS:
I have a cmake project which has several libraries and modules. They included in my project using add_subdirectory command (note that my project just made up from multiple modules and it has not any add_library or add_target).
I need to copy outputs of libraries/modules without changing their CMakeLists.txt (add_custom_command with POST_BUILD option actually is not a good choice because at this point I need to change CMakeLists.txt of libraries/modules which they are not just belong to my project). On the other hand it must done in outer(major) CMakeLists.txt which has others(libraries/modules).
I tried some other commands such as file (COPY ) and configure_file() but I think they operate in generating cmake-cache phase and just can copy resource files which are exist in pre-build phase.
Moreover, In another approach I write a bash script file to copy the files and call it in major CMakeLists.txt via bellow command.
add_custom_target (copy_all
COMMAND ${CMAKE_SOURCE_DIR}/copy.sh ${files}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
The files has the list of files. But the copy not performed! I manually test the script which works as desired. But I don't have any idea why it can not operate at call in CMakeLists.txt.
What can I do to copy sub-projects outputs to some locations from major CMakeLists.txt?
The Setup
To simplify it a little, let's say you have:
CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project(PostBuildCopyFromRoot)
add_subdirectory(module)
module/CMakeLists.txt
file(WRITE "module.h" "int ModuleFunc();")
file(WRITE "module.cpp" "int ModuleFunc() { return 1; }")
add_library(module SHARED "module.cpp" "module.h")
target_include_directories(module PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
set_target_properties(module PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS 1)
app/app.mexw64
The Problem
If you now just add to following to the root CMakeLists.txt:
add_custom_command(
TARGET module
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
"$<TARGET_FILE:module>"
"app/$<TARGET_FILE_NAME:module>"
)
You will get from CMake:
CMake Warning (dev) at CMakeLists.txt:8 (add_custom_command):
Policy CMP0040 is not set: The target in the TARGET signature of
add_custom_command() must exist. Run "cmake --help-policy CMP0040" for
policy details. Use the cmake_policy command to set the policy and
suppress this warning.
TARGET 'module' was not created in this directory.
Solutions
You can always overwrite command behaviors:
function(add_library _target)
_add_library(${_target} ${ARGN})
add_custom_command(
TARGET ${_target}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
"$<TARGET_FILE:${_target}>"
"${CMAKE_SOURCE_DIR}/app/$<TARGET_FILE_NAME:${_target}>"
)
endfunction()
NOTE: Put the code snippets before the add_subdirectory() call
References
Copying executable and DLLs to User specified location using CMake in windows
Parent CMakeLists.txt overwriting child CMakeLists.txt output directory options
Proper usage of CMAKE_*_OUTPUT_DIRECTORY
Is there a way to include and link external libraries throughout my project only editing my top level CMakeList?
I am new to cmake file creation. I have c++ code in list of directory, each directory has its own CMakeLists.txt file. For compile and create executable in each directory, I have to go inside directory and execute following two command on terminal.
$ cmake .
$ make
Example directory structure:
Each directory 1, 2 ...41 has its own `CMakeLists.txt'.
Example inside each directory file structure:
For compile and create executable in each directory, i have to follow those tow command.
But now i have to write either python script/ cmake script to do above this action in each directory and capture the output and store in log file.
Kindly anyone to guide me to solve my issue. Thanks in advance.
My each directory CMakeLists.txt like this:
project(foundations)
cmake_minimum_required(VERSION 2.6)
include_directories($ENV{GMOCK_HOME}/include $ENV{GMOCK_HOME}/gtest/include)
link_directories($ENV{GMOCK_HOME}/mybuild $ENV{GMOCK_HOME}/gtest/mybuild)
add_definitions(-std=c++11)
set(sources main.cpp RetweetCollectionTest.cpp)
add_executable(test ${sources})
target_link_libraries(test pthread)
target_link_libraries(test gmock)
target_link_libraries(test gtest)
add_subdirectory https://cmake.org/cmake/help/v3.0/command/add_subdirectory.html is exactly what you need.
EDIT:
For example:
add_subdirectory(1 1)
Where the first parameter is source dir, and the second is binary dir. So, the names should not overlap.
Also, check this: https://stackoverflow.com/a/7788165/934691
But, if you don't want to rewrite your CMakeLists, a simple bash script like
for dir in ls ; do cd $dir; cmake . && make; cd ..; done
will be more appropriate for you.
Consider the following setup:
-project
--src
---CMakeLists.txt
---main.cpp
---Application.cpp
---Application.hpp
---subfolder
----SomeClass.cpp
----SomeClass.hpp
--bin
And consider this CMakeLists.txt
project(SampleProject)
cmake_minimum_required(VERSION 2.8)
aux_source_directory(. SRC_LIST)
# Include directories
INCLUDE_DIRECTORIES("subfolder")
# Executable
add_executable(${PROJECT_NAME} ${SRC_LIST})
Now, as long as I had all my classes in the same folder (src) everything worked perfectly fine.
But now I want to restructure my application a bit. I want to build a folder-hierarchy that represents the namespaces.
Of course in my includes I would then use
#include "subfolder/SomeClass.hpp"
but it doesn't work that way. I had a look at the manpage but there are so many options in CMake and it's often talking about standalone libraries that have their own CMakeLists.txt... I'm not that far yet. I just want to add a subfolder, that's all.
Until now I've used QMake for my C++ projects, but I wanted to dive into CMake now.
Are there any useful tutorials out there? I've found a few, but they they don't cover the basics.
The recommened way is to use a CMakeLists.txt for every subdirectory in existence. If you want to have subdirectories and organize them without having to create multiple CMakeLists.txt files, you can create one in the main directory with those contents:
project(SampleProject)
cmake_minimum_required(VERSION 2.8)
include_directories(src)
file(GLOB_RECURSE SRC_LIST *.c* *.h*)
# Executable
add_executable(${PROJECT_NAME} ${SRC_LIST})
Using aux_source_directory is used mainly for template related things. Also it's common practice to use a toplevel CMakeLists.txt, which includes the further files, has common project settings etc.:
<project>
|
+- CMakeLists.txt
|
+- src/
|
+-- CMakeLists.txt
|
+-- main.cpp
|
…
So this would look like:
CMakeLists.txt (Project dir):
project(SampleProject)
cmake_minimum_required(VERSION 2.8)
include_directories(src) # Add 'src' to include paths
subdirs(src) # Includes the 'src' directory and its cmake file
# ...
Now you can use the include path as expected.
CMakeLists.txt (src dir):
# Better add src files this way:
add_executable(${PROJECT_NAME} main.cpp Application.cpp)
subdirs(subfolder) # TODO: handle subfolder
The subfolder can be added through an additional library target, that is linked to your executable. Usually there's another CMakeLists.txt file in there.
Also make sure your cmake cache is updated; best you recreate it.