CMake with Xcode: configured header file (.h.in) not found - c++

I'm working through the CMake tutorial and I'm up to the Adding a Version Number and Configured Header File section. Unfortunately Xcode isn't recognising the generated header file:
The error:
The header file was generated by CMake ok:
TutorialConfig.h.in
// the configured options and settings for Tutorial
#define Tutorial_VERSION_MAJOR #Tutorial_VERSION_MAJOR#
#define Tutorial_VERSION_MINOR #Tutorial_VERSION_MINOR#
CMakeLists.txt
cmake_minimum_required (VERSION 2.6)
project (Tutorial)
# The version number.
set (Tutorial_VERSION_MAJOR 1)
set (Tutorial_VERSION_MINOR 0)
# configure a header file to pass some of the CMake settings
# to the source code
configure_file (
"${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
"${PROJECT_BINARY_DIR}/TutorialConfig.h"
)
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
include_directories("${PROJECT_BINARY_DIR}/src")
# add the executable
add_executable(Tutorial src/tutorial.cpp)
This is the tutorial I'm working from.

I don't use Xcode, but another IDE that's Linux based. But maybe I can help you a bit. I'm just wondering -- does your program compile? That's perhaps more important.
My IDE often complains about header files such as your's -- that is, configuration files that are generated by CMake. Such warnings (at least for me) can be ignored. I usually do because my build/ directory is sometimes empty. So when I've opened up the source file, there wouldn't be TutorialConfig.h yet.
In fact, the IDE can never know about such header files. That's because it doesn't know which build/ directory you're going to compile your program in.
If you are worried by the warning, then there is probably a place where you can specify to Xcode which build/ directory to search for header files. That will remove the warning, after you've run CMake once. However, removing such a warning is unreliable because you can always build in another directory that would have TutorialConfig.h missing.
Hope this helps!

Oh, haha. I changed #include "src/TutorialConfig.h" to #include "TutorialConfig.h" and all is well. I figured it out by checking out the project settings:

Related

Crow microframework - CMake Error: The following variables are used in this project, but they are set to NOTFOUND

Here is the full error message:
Error 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:
C:/Users/DELL/source/repos/CMakeProject1/CMakeProject1/CROW_INCLUDE_DIRS
used as include directory in directory C:/Users/DELL/source/repos/CMakeProject1/CMakeProject1 C:\Users\DELL\source\repos\CMakeProject1\ used as include directory in directory C
I am trying to use the Crow microframework but can't seem to make it work. I have downloaded the Crow package off of Github : https://github.com/ipkn/crow and used CMake to run a hello world from the Crow port. This is what I got in my .txt file
cmake_minimum_required (VERSION 3.8)
find_path(CROW_INCLUDE_DIRS "crow.h")
add_executable (CMakeProject1 "example_with_all.cpp" "crow_all.h")
target_include_directories(CMakeProject1 PRIVATE ${CROW_INCLUDE_DIRS})
My header file is crow_all.h which contains all the libraries and this is where the error is located. The compiler does not recognize all the "#include" used in this header file. I believed it would work because I had downloaded the entire Github repo and included it in my files.
My cpp file just includes the header file and does a Hello World.
I am a beginner at CMake, thank you for the help!
You should check out https://github.com/CrowCpp/Crow. It's an actively maintained version of the framework with a new build system (you should be able to just link it via CMake)
P.S. I suggest you use the master branch since it has quite a few improvements over the latest release.
Wow, crow's build is so broken that its own instructions fail on my system... it also hasn't been updated since 2017 (five years...). Assuming you still want to use it, I would just copy their amalgamated header, crow_all.h, into my source tree under, say, third_party/crow/crow_all.h and then write:
cmake_minimum_required(VERSION 3.22)
project(example)
add_executable(app "example_with_all.cpp")
target_include_directories(app PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/third_party/crow")

Is there "includePath" option in clangd?

I used to work with VSCode C/C++ extension. there was a feature in this extension(in a json file), called "includePath", which I could set the paths for my headers, so without execution of CMake or make, I would have the suggestion of my headers and code completion from those.
now I have switched to neovim and clangd as the language server for code completion. I searched a lot to find the corresponding feature in clangd options but I could not find anything more than this link.
since the clangd is a powerful language server, I am in wonder if there is not such a feature in it. so I want to know is there actually such a feature in clangd? and if YES how can I use that?
Note: I use a language client, called "coc-clangd". I don't know if it matters or not.
Clangd uses compile_commands.json database file which contains flags (such as include directories) for each file in project. But this file is auto-generated, so all modifications to it will be overwritten eventually. You can ask CMake to add any custom compile flags with -DCMAKE_CXX_FLAGS command line argument.
Example for system headers (#include <file.h>):
cmake -DCMAKE_CXX_FLAGS="-isystem /path/to/includes" /path/to/source
For project headers (#include "file.h"):
cmake -DCMAKE_CXX_FLAGS=-Ipath/to/includes /path/to/source
Additionally, you can set CXXFLAGS environment variable:
export CXXFLAGS="-isystem /path/to/includes"
cmake path/to/sources
After that new flags should appear in your compile_commands.json file.
Maybe this is useful: https://clangd.llvm.org/config
Create a file called '.clangd' in the top-level of the source directory.
Add those content.
CompileFlags: # Tweak the parse settings
Add:
- "-I=[folder]"
But I think this is not recommend, all include directories should be add in CMakeLists.txt file.
You can add includePath to clangd.fallbackFlags into vscode's settings.json like this:
"clangd.fallbackFlags": [
"-I${workspaceFolder}/include",
"-I/my/include"
]
To use code completion provided by Clangd, let Clangd retrieve include paths from compiler_commands.json with compiler calls used by CMake. Set the CMAKE_EXPORT_COMPILE_COMMANDS option in CMakeLists.txt, it will output compiler_commands.json to the build directory when CMake is run:
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
Copy the generated compiler_commands.json to the project source directory. Clangd will now source this file.

How to print/show included directories in CMakeList

I am trying to build a trivial proof of concept project using CMake, and I am rapidly getting tired of it - to the point that I think it may have been a better idea to handcraft my own damn Makefile.
I have a directory structure that looks something like this:
project:
/extproj
/src/file.cpp
/include/file1.h
My CMakeLists.txt file contains the following section, which I, having read the CMake documentation, rather naively believed, will be specifying the include directories for the project:
INCLUDE_DIRECTORIES (include/
extproj/sdk/math/linearalg/
extproj/sdk/math/nonlinearsolvers/
)
I am trying to build it using the following command
COMMAND ${CMAKE_CXX_COMPILER} ${CMAKE_CXX_FLAGS} ${ALL_SOURCES}
Where ${ALL_SOURCES} is a list variable that contains all the C++ files I need to compile. I have verified that this variable contains the correct files.
I can't however, for the life of me, work out what on earth is being passed to the compiler as the include directories.
I searched online, and so a post that recommended using get_directory_properties. I tried that and of course CMake immediately failed to generate the Makefile and complained:
Unknown CMake command "get_directory_properties".
When I create a Makefile and run make on it, the compiler barfs immediately, with the error message:
/path/to/project/src/file1.cpp:1:10: fatal error: 'file1.h' file not
found
Is there ANY WAY, I can find out what on earth is being used as the include paths being passed to my compiler?
I believe the correct way to compile the source files is using
add_executable(executableName ${SRCS}. Then the directories added using include_directories(...) get passed to the compiler automatically.
If you are using a custom command to compile you need to change your CMakeLists.txt file.
set(MY_INCLUDE_DIRS_FLAGS "-Iinclude/ -Iextproj/sdk/math/linearalg/ -Iextproj/sdk/mat/nonlinearsolvers/")
set(MY_COMPILE_COMMAND ${CMAKE_CXX_COMPILER} ${MY_INCLUDE_DIRS_FLAGS} ${CMAKE_CXX_FLAGS} ${ALL_SOURCES}

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.

The right way to structure my c++ project with cmake?

I have been struggling with this for quite a while, and my adventures with cmake have only resulted in hackish solutions that I am pretty sure are not correct.
I created a library that consists of several files, as follows:
-libfolder
-codepart1folder
-CMakeLists.txt
-codepart1.cpp
-codepart1.hpp
-codepart2folder
-codepart3folder
-lib.cpp
-lib.hpp
-CMakeLists.txt
I wrote a CMakeLists file to compile the library (after some experimentation), and I can generate a lib.a file. Now I would like to include this code as a library in other projects, and access it through the interface in lib.hpp. What is the best way to do this, in terms of directory structure, and what I need to put into CMakeLists.txt in my root project?
My current attempt has been to add -libfolder as a subfolder to my current project, and add the commands:
include_directories(${PROJECT_SOURCE_DIR}/libfolder)
link_directories(${PROJECT_BINARY_DIR}/libfolder)
add_subdirectory(libfolder)
target_link_libraries(project lib)
When I run make, the library compiles fine, but when project.cpp compiles, it complains that it cannot find codepart1.hpp (which is included in lib.hpp, included from project.cpp).
I suspect that this is the wrong way about doing this, but I cannot wade through the CMake documentation and find a good tutorial on setting up projects like this. Please help, CMake gurus!
The clean way to import one CMake project into another is via the find_package command. The package declaration is done by using the export command. An advantage of using find_package is that it eliminates the need to hard-code paths to the package's files.
Regarding the missing hpp file, you didn't include codepart1folder, so it's not on the include path.
Ok, so after consulting a coworker of mine who is a CMake guru, it seems CMake does not have support for what I am trying to do, leaving one with 3 options:
Add all of the dependencies to the parent projects CMakeLists.txt - not very clean, but it will get the thing to work. You'll have to do this for every project you add the code to, and go back and fix things if your library changes.
clean up your library headers. This is done through some compiler hackery. The idea is to forward-declare every class, and use only pointers or boost::shared_ptr, and then include the dependencies only in the cpp file. That way you can build the cpp file using all the findpackage stuff, and you get the bonus of being able to use the lib by only including the header and linking to the library.
Look into build systems. Having portable code and fast code compilation with complex dependencies is not a solved problem! From my investigations it turned out to be quite complicated. I ended up adopting my coworkers build system which he created himself in cmake, using things he picked up from Google.
Looking at your post you don't seem to add 'codepart1folder' to the includes anywhere. How are you including codepart1.hpp as:
#include <codepart1.hpp>
#include "codepart1folder/codepart1.hpp"
I don't think there is a standard accepted way to structure cmake projects. I've looked at a bunch of cmake repos and they tend to have differences. Personally I do the following:
-project
CMakeLists.txt
-build
-cmake
OptionalCmakeModule.cmake
-src
-Main
Main.cpp
Main.hpp
-DataStructs
SomeTree.hpp
SomeObject.hpp
-Debug
Debug.hpp
-UI
Window.hpp
Window.cpp
Basically that dumps all the source code into 1 directory, then you perform an out of source build with: 'mkdir build && cd build && cmake .. && make' in the projects root folder.
If you have separate libs as part of your project, then you might want a separate libs directory with another subfolder for your specific lib.
I have some of my repos on: https://github.com/dcbishop/ if you want to look at the CMakeLists.txt files.
The main problems with my project structure are that I use the FILE_GLOB which is apparently the 'wrong' way to do things (if you add files after running 'cmake ..' then they won't be picked up hen you do a 'make'). I haven't figured out what the 'right' way to do it is (from what I can see it involves keeping a separate list of files) I also only use 1 CMakeLists.txt file.
Some projects also choose to separate their cpp and hpp files into separate directories. So you would have an include and src folders (at least for the hpp files that are intended to be used externally). I think that would mainly be for projects that are mainly large libraries. Would also make installing header files much easier.
You are probably missing
include_directories(${PROJECT_SOURCE_DIR}/libfolder/codepart1folder)
In such a case you might want to set( CMAKE_INCLUDE_CURRENT_DIR on) to add all folders to the include directory path variable.
Check cmake's output on the command line whether the correct include folders are set or not. Additionally you can always use message() as "print debugging" for cmake variables.
In case of include directories however you need to read the directory property to see what is actually in the include directories.
get_property(inc_dirs DIRECTORY PROPERTY INCLUDE_DIRECTORIES)
message("inc_dirs = ${inc_dirs}")
I hope this helps you figuring out what is missing.
Edit
I just saw your comment about added codepart1folder in the libfolder. It is only available in the libfolder's include_directory path and not propagated to the root folder.
Since the include codepart1.hpp is present in the lib.hpp however you need to have it also available in the project path otherwise you will get missing declaration errors when you build your project.