0

I have a very simply application that tries to build a main.cpp that includes a header file. The CMake file looks like this:

cmake_minimum_required(VERSION 3.21.0)
project(test_app 
    VERSION 0.1.0
    LANGUAGES CXX C
)
set(CXX_STANDARD_REQUIRED 17)

add_executable(test_app)

target_sources(test_app PRIVATE
    main.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/include/myinc.h
)

The project structure is:

.
├── CMakeLists.txt
├── include
│   └── myinc.h
└── main.cpp

main.cpp includes myinc.h, but cannot find it:

main.cpp:2:10: fatal error: myinc.h: No such file or directory

Looking at the compile_commands.json file I see:

"command": "/usr/bin/g++   -g -o CMakeFiles/scrathpad.dir/main.cpp.o -c /home/supal/cppsandbox/main.cpp"

According to https://github.com/Bagira80/More-Modern-CMake/blob/master/OhNoMoreModernCMake.pdf (slide 10), it is recommended to do it this way.

What am I doing wrong?

P.S., my CMake version is 3.22.

SupAl
  • 517
  • 3
  • 12
  • 1
    `target_sources` is a list of files you compile. `target_include_directories` is for setting where compiler should look for `#include`d files (aka the `-I` option for compiler). – Yksisarvinen Jun 10 '23 at 10:37
  • Duplicate? https://stackoverflow.com/questions/13703647/how-to-properly-add-include-directories-with-cmake or https://stackoverflow.com/questions/8304190/cmake-with-include-and-source-paths-basic-setup – Yksisarvinen Jun 10 '23 at 10:44
  • @Yksisarvinen, not a duplicate. This question is not about the common use-case where I can just include the whole include dir, but the specific one where I want to selectively choose what header files I want from a given dir (there is a header name conflict if I include the whole dir). This should be possible with target_sources according to the link I provided. – SupAl Jun 10 '23 at 10:58
  • @Yksisarvinen, take a look at https://github.com/Bagira80/More-Modern-CMake/blob/master/OhNoMoreModernCMake.pdf on slide 10. There it is recommended to include like that. – SupAl Jun 10 '23 at 11:00
  • 1
    @SupAI Slide 10 doesn't say "You only need to add header file to `target_sources`". It says "Add header files also, it will help IDEs to understand the code". You need some combination of `-I` option and `#include` to produce a valid path to file. If you prefer, you can `#include "include/myinc.h` instead of passing `-I` option. – Yksisarvinen Jun 10 '23 at 11:05
  • @Yksisarvinen Thanks for the clarification. As a side note, tt seems that it is now possible to add headers directly via target_sources (for CMake >= 3.23): https://cmake.org/cmake/help/latest/command/target_sources.html – SupAl Jun 10 '23 at 11:14

1 Answers1

2

Adding a header to the list of sources of a target doesn't affect it's availability. It's only used for some generators for influencing the source files associated with a target; e.g. for Visual Studio generators the file will be listed among the Header Files of your target in the solution explorer. (It also has an effect, if the header is generated during the build.)

Note: Even for Visual Studio generators adding the header to the sources won't result in the file being available for the #include directive. Providing specific files for #includeing only would only be possible via compiler specific options, if at all.

For making headers available via #include directive, you need to add a directory via target_include_directories such that the file in this dir using the path provided to #include.

target_include_directories(test_app PRIVATE include) # relative paths can be used here
fabian
  • 80,457
  • 12
  • 86
  • 114
  • This is what I'd usually do, but the include directory is from a 3rd party repo that I don't want to change. The directory contains a config_header.h that I don't want to include (I provide my own in my own repo), and some other headers that I need to include. That's why I tried to selectively include those headers. Any suggestions? Also, why is it recommended to include via target_sources if this is not widely supported? – SupAl Jun 10 '23 at 10:56
  • 2
    @SupAl It's recommended to add the headers,to get the benefit for generators where this does make a difference. It's not unsupported for other generators, it just doesn't have an effect on the project files generated.(Note: even with VS compilation fails.)As for "including headers selectively":This s rarely a good idea. Config headers like this can contain information that results in undefined behaviour,unless combined with the header used during the build of the library. You may want to create a wrapper here and limit the files including the 3rd party header to 1 (or some other small number). – fabian Jun 10 '23 at 11:09
  • So it only for certain generators. This was the answer I was looking for. I know I shouldn't do this normally (i.e., include selectively), but see my comment to Yksis.. above for why I had to do this. – SupAl Jun 10 '23 at 11:12