How to set up sub directory includes in CMake/CLion? - c++

This is similar to Including directories in Clion, but after following the accepted answer there I made no progress.
I'm trying to edit a large OSS project in CLion. It does not use CMake, so CLion has generated a CMakeLists.txt file. When I open a source file, it is unable to resolve includes that use sub directories:
The file this screenshot is from is in the same "opto" subdirectory it is importing from. If I change the imports to not include "opto" it works fine, but I can't do that, since this is a major project and I'm just wanting to write a small patch:
$ find . -type f | wc -l
10532
I've added the file I'm importing directly to add_executable as suggested in the other answer:
# CMakeLists.txt
add_executable(hotspot
[lots of other files]
src/share/vm/opto/compile.hpp
)
And I've added the opto directory to include_directories as outlined in the second answer to the other question:
# CMakeLists.txt
include_directories(
src
src/share/vm/opto)
Neither is helping CLion resolve imports via the opto subdirectory.
What am I missing?

Using include_directories() must do, but you have to mention each sub_directory separately. Below i have included two directories in the same way where one of it is sub_directory.
The Header files have successfully been detected by CLion.

Related

spdlog.h isn't found in CMake project

I am trying to integrate spdlog, a header only logging library into a C++ project but I am having trouble getting CMake to recognise the include paths properly. I am using the latest CLion with CMake 3.10.2 on Ubuntu 18.04.
My project structure looks like this:
Project Dir
|- libs
| |- spdlog #this is the include directory taken straight from GitHub
|
|- src
| |-...
|- CMakeLists.txt
In the CMakeLists.txt file I define the include directory:
include_directories("libs/")
Now when I attempt to write #include <spdlog/spdlog.h> in a header file located in src/ CLion complains that it cannot find spdlog.h even though I have checked and the file is definitely in the spdlog folder. Using quotation marks instead of angled brackets in the include statement does not fix the problem however using the path relative to the file (e.g. ../libs/spdlog/spdlog.h) works as it should. What is more confusing to me is that in the source file corresponding to the header I can include the file no problem.
I haven't been able to find anything like this issue anywhere and I'm struggling to understand what is causing CMake or CLion to behave like this.
EDIT: As per Matthieu Brucher's suggestion I have tried using fully qualified paths to the include folder but it still does not work. The problem seems to be that folders seem to not be recognised in headers, as they work in source files.
EDIT2: Here is the entire CMakeLists.txt I am using. It is nested into a different directory than the top level CMakeLists.txt for the entire project as this was the only solution I have found online to get something akin to VS's multiple projects in a solution in CLion. However since all paths are relative I don't think this would be a problem. I also know that spdlog is a C++11 library but I will need some C++14 features elsewhere in the near future.
cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
project(TokenEngine VERSION 0.0.1 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 14)
set(SOURCE_FILES src/Application.cpp src/Application.hpp src/EntryPoint.hpp src/Logger.cpp src/Logger.hpp)
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/libs/")
add_library(TokenEngine SHARED ${SOURCE_FILES})
#Expose the public API of the engine to any project that might use it
target_include_directories(TokenEngine PUBLIC include)
EDIT3: When I attempted to recreate the error to show the full message given somehow the it was gone, being replaced by a different one totally unrelated to CMake...
You may want to use fully qualified paths:
include_directories(${CMAKE_SOURCE_DIR}/libs/)
You also have to add the include folder to the include paths to be able to include via #include <spdlog/spdlog.h>. This should look like
include_directories(${CMAKE_SOURCE_DIR}/libs)
But I prefer using
target_include_directories(yourTarget PUBLIC ${CMAKE_SOURCE_DIR}/libs)
where yourTarget is the target where you want to use spdlog. Like that you will have the include directories also available if you are going to link your yourTarget to something else. If you need spdlog just in yourTargets cpp files you can change the PUBLIC to PRIVATE. See cmake doc.

CMake Error: "add_subdirectory not given a binary directory"

I am trying to integrate Google Test into the subproject of bigger project and I cannot find the solution that would be satisfying for me.
I have two constraints:
the source code of Google Test is already somewhere in the project structure (thus using URL to download it from git repository is not an option)
the source code of Google Test is not a subdirectory of my subproject (and never will)
So when I tried to do something like this:
add_subdirectory( ${GOOGLETEST_PROJECT_LOCATION})
I received:
CMake Error at unit_tests/CMakeLists.txt:10 (add_subdirectory):
add_subdirectory not given a binary directory but the given source
directory "${GOOGLETEST_PROJECT_LOCATION}" is not a subdirectory of
"${UNIT_TEST_DIRECTORY}". When
specifying an out-of-tree source a binary directory must be explicitly
specified.
On the other hand maybe ExternalProject_Add could be a solution but I do not know how shall I use it when I do not want to download sources at all and use sources from specific location in the project.
Project structure looks more or like like this:
3rdparty
|--googletest
...
subproject
|--module1
|--file1.cpp
|--CMakeLists.txt
|--module2
|--file2.cpp
|--CMakeLists.txt
|--include
|--module1
|--file1.h
|--module2
|--file2.h
|--unit_test
|--module1
|--file1test.cpp
|--module2
|--file2test.cpp
|--CMakeLists.txt
|--CMakeLists.txt
CMakeLists.txt
The error message is clear - you should also specify build directory for googletest.
# This will build googletest under build/ subdirectory in the project's build tree
add_subdirectory( ${GOOGLETEST_PROJECT_LOCATION} build)
When you give relative path (as a source directory) to add_subdirectory call, CMake automatically uses the same relative path for the build directory.
But in case of absolute source path (and when this path isn't in your source tree), CMake cannot guess build directory, and you need to provide it explicitly:
See also documentation for add_subdirectory command.
I feel obligated to comment on this because this was the top search result when I was googling this error.
For me, I'm apparently an idiot: I had modified the CMakeLists.txt file in the src directory of my project, but I didn't realize the file was locked and VS Code wasn't actually saving even when I hit Ctrl+S. Check the file tab in VS Code and see if there's a white dot there, indicating the file isn't saved. Hit Ctrl+S and see if you get a pop-up in the lower-right corner prompting you to try again as superuser.
I've still got errors, but they're new errors that make sense for my project.

CMake not building a library when added as a subdirectory

I added the xgboost library as a git submodule of my project and I'm trying to add it to cmake as a subdirectory. Unfortunately it's not working. A simple hello world project with the following CMakeLists.txt replicates the error that I'm getting.
cmake_minimum_required(VERSION 3.2)
project(foo)
add_subdirectory(xgboost)
add_executable(${PROJECT_NAME} foo.cpp)
target_link_libraries(${PROJECT_NAME} xgboost)
After building the library there is nothing in the xgboost/lib directory so I get the following error.
clang: error: no such file or directory:
'/Users/.../myproject/xgboost/lib/libxgboost.dylib'
I think that the problem is generated in their CMakeLists file since they have two different targets. Maybe cmake is choosing the wrong target but I'm not familiar enough with cmake to figure it out. The following code is from xgboost's CMakeLists.
# Executable
add_executable(runxgboost $<TARGET_OBJECTS:objxgboost> src/cli_main.cc)
set_target_properties(runxgboost PROPERTIES
OUTPUT_NAME xgboost
)
set_output_directory(runxgboost ${PROJECT_SOURCE_DIR})
target_link_libraries(runxgboost ${LINK_LIBRARIES})
# Shared library
add_library(xgboost SHARED $<TARGET_OBJECTS:objxgboost>)
target_link_libraries(xgboost ${LINK_LIBRARIES})
set_output_directory(xgboost ${PROJECT_SOURCE_DIR}/lib)
#Ensure these two targets do not build simultaneously, as they produce outputs with conflicting names
add_dependencies(xgboost runxgboost)
My questions in order of importance are:
Is there any way to fix it without modifying xgboost's CMakeLists.txt file?
Is it reasonable to try to add xgboost to my project as a git submodule?
Is there any reason cmake is not instructing to build the library?
Note: There were several edits to this question since I tried to narrow down the problem and to provide more information.
(I would love to ask for few things beforehand in the comment section, but I have too low reputation to do so, so I will just give it a shot ;))
I have few suspects, and one of them is ${CMAKE_SOURCE_DIR} of the submodule's root CMakeLists.txt. Although the paths are set properly when you run that CMakeLists.txt alone, cmake gets confused the moment you add it as your subdirectory. Have you looked into another directories for your output binaries?
First I would suggest testing this hypothesis, and then I would suggest writing similar, but separate CMakeLists.txt file for xgboost library, and then substitute it in the project temporarily. Unfortunately the CMakeLists.txt filename is hardcoded and there is no possibility to have two files of that kind in one directory; so it seems that the answer to 1) is, that you rather have to change the file.
For the 2): as long as it does not require huge additional logic in your CMakeLists.txt, it makes sense. Other viable option is to create an install target, which you can use to install your xgboost library locally (using CMAKE_INSTALL_PREFIX(doc) variable), and then add the installation path to your CMAKE_LIBRARY_PATH(doc).

CMake Difference between include_directories and add_subdirectory?

I'm learning CMake for building C++ code, and struggling with the following concept. On my root level directory I have some cpp files and a CMakeLists.txt that succesfully generates some thrift code in a gen-cpp directory. My root level CMakeLists.txt contains :
include_directories("path-to-root"/gen-cpp). (along with the relevant thrift auto-generating and includes.
Everything compiles ok but I get run time dynamic library linked errors for undefined symbol referencing a class defined in the gen-cpp directory. When I move the files in the directory to the root level, it runs fine. what am I missing? (I had also adjusted the #include in the root level cpp directorie s to point to "path-to-root"/gen-cpp).
Is this a misunderstanding of using include_directory, where I should be using add_subdirectory. If the latter, would the code in gen-cpp needs its own CMakeLists.txt? Why is this additional file not needed, when the contents of said directory are root level?
add_subdirectory(source_dir): Used to add a subdirectory to the build. There is also a CMakeLists.txt file in the source_dir. This CMakeLists.txt file in the specified source directory will be processed immediately by CMake before processing in the current input file continues beyond this command.
include_directories(dir): Add the given directories to those the compiler uses to search for include files. These directories are added to the directory property INCLUDE_DIRECTORIES for the current CMakeLists file.
The include_directories() is used for adding headers search paths (-I flag) and add_subdirectory() will make no difference in this case.
I suppose, you need to list *.cpp files from gen-cpp folder in add_executable() or add_library() calls, in which you wish these symbols to be.
Alternatively, you can compile all thrift sources into the library and link it with your code.

How can I build a C++ project with multiple interdependent subdirectories?

I have a C++ project where I've used directories as more of an organizational element -- the way one might use packages in Java or directories in PHP. Directories are not intended to be self-sufficient elements, but rather just a way of organizing the whole of the project and keeping me from being overwhelmed by sources. How can I construct my CMakeLists.txt files to deal with this? Making the directories libraries doesn't seem to fit here, since they are all interdependent and not intended to be used that way.
As a related issue, most of the examples I've seen of multiple subdirectories in CMake (and there aren't very many of those) have ignored or glossed over the issue of setting include_directories, which is something I've been having trouble with. Short of combing my source files to determine which file depends on which and in what directory, is there anyway to just set all directories under /src/ as potential include directories and let CMake work out which ones are actually dependent?
Here's an example structure:
--src
--top1
--mid1
--bot1
--src1.cpp
--hdr1.h
--bot2
--src2.cpp
--hdr2.h
--mid2
--bot3
--src3.cpp
--src4.cpp
--hdr3.h
--top2
--mid3
--src5.cpp
--hdr4.h
So on and so forth. How can I structure my CMakeLists.txt files to handle this sort of structure?
Since the directory structure in your project is just there to keep your files organized, one approach is to have a CMakeLists.txt that automatically finds all sources files in the src directory and also adds all directories as include directories that have a header file in them. The following CMake file may serve as a starting point:
cmake_minimum_required(VERSION 3.12)
project (Foo)
file (GLOB_RECURSE Foo_SOURCES CONFIGURE_DEPENDS "src/*.cpp")
file (GLOB_RECURSE Foo_HEADERS CONFIGURE_DEPENDS "src/*.h")
set (Foo_INCLUDE_DIRS "")
foreach (_headerFile ${Foo_HEADERS})
get_filename_component(_dir ${_headerFile} PATH)
list (APPEND Foo_INCLUDE_DIRS ${_dir})
endforeach()
list (REMOVE_DUPLICATES Foo_INCLUDE_DIRS)
add_executable(FooExe ${Foo_SOURCES})
target_include_directories(FooExe PRIVATE ${Foo_INCLUDE_DIRS})
The two file(GLOB_RECURSE ... commands determine the set of source and header files. The foreach loop computes the set of include directories from the list of all header files. The CONFIGURE_DEPENDS flags tells CMake to re-run the glob command at build time.
One drawback with computing the set of source files is that CMake will not automatically detect when new files are added to your source tree. You manually have to re-create your build files then.
Though #sakra gave a good answer to this question, I believe it is more proper to approach it more in depth.
We want to separate our code into modules and libraries for many reasons. Like code encapsulation, re usability, easier debugging etc. This idea would propagate in compiling process too.
In other word, we want to divide the compilation process into little compilation steps, each belong to one module. So every module must have its own compilation procedure. This is why we use one CMakeLists.txt file per directory. Hence every directory would have its own compilation commands and there would be one master CMakeLists.txt file in the root directory of your project.
Here is an example. Consider the following structure of a project:
src/
|
- main.cpp
|
_sum/
|
- sum.h
|
- sum.cpp
We would have one CmakeLists.txt Per directory. First directory is the root directory of the project which src/ folder is in it. here is content for that file:
cmake_minimum_required(VERSION 3.4)
project(multi_file)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS "-Wall")
add_subdirectory(src)
Next CMakeLists.txt would located in src/ directory:
add_subdirectory("sum")
add_executable(out main.cpp)
target_link_libraries(out sum)
And the last one will be in the sum/ directory:
add_library(sum SHARED sum.cpp)
I hope this helps. I created a github repository in case you feel you need to see the code or you need further explanation.
I'm not an expert on CMake but since there are no other answers I'll take a look at the documentaton and give it a go. Organizing source and include files in different directories is pretty much the norm.
It looks like CMake allows you to give a list of include directories:
http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:include_directories
So something like:
include_directories("src/top1/mid1/bot1" "src/top1/mid1/bot2/" ... )
These are passed to the compiler so it can find the header files and will be passed for each of the source files. So any of your source files should be able to include any of the header files (which I think is what you're asking for).
Similar to that you should be able to list all your source files in the add_executable command:
add_executable(name "src/top1/mid1/bot1/src1.cpp" "src/top1/id1/bot2/src2.cpp" ...)
So this would be a naive way of getting everything to build. Each source file will be compiled and will look for headers in all those directories and then the object files will get linked together. Consider if there is any way of simplifying this such that you don't need so many include folders, maybe there are only a few common header files that need to be referenced by all source files. If things get more complex you can buiild sub-hierarchies into libraries etc. Also consider seperating source files and headers (e.g. in src and include).