The timing for using `target_include_directories` and `target_link_libraries`

According to this project #include errors detected

I want to know the usage timing for target_include_directories and target_link_libraries

situation 1:
I build a third party lib.so or lib.dll
And using it on my project.
The situation 1 is using the *.so or *.dll , and it doesnt use the library include file.
Because I already use the *.so or *.dll.

CMakeList.txt

find_package(LibDataChannelREQUIRED)
add_executable(iam ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp)
target_link_libraries(iam PRIVATE LibDataChannel::LibDataChannel)

situation 2:
If I put the third party source code into my project.
Maybe I just only use target_link_libraries and then I dont build the third party?

You still need to build it as part of your project. If you do vendor it (i.e., put it in your source tree) consider:

  • updating is a manual process
  • using FetchContent so that other projects wanting to vendor it can coordinate on using a single copy

I’d recommend using find_package and the target rather than messing with target_include_directories.

Your previous question was about VSCode being able to pick up headers when browsing your project’s code. When you’re in that situation:

  1. The library headers absolutely are used — they’re how your downstream code knows the API of the shared library. You can’t use a C/C++ shared library without a header file to define the public API.

  2. From a VSCode perspective, what really matters isn’t when, how, or in what form your dependencies are incorporated into the project. What matters is that the compile_commands.json file CMake generates contains all of the correct -I flags (or -isystem) with the paths to your libraries’ header files. VSCode will read the commands in that file to determine where it should look for headers named in #include lines.

Any method of getting the include paths into your build commands will work for VSCode. For the purposes of code browsing/editing, it doesn’t matter if the headers are installed somewhere else on the system, inside your own source directory, or generated inside the build directory. (As long as they’re generated during the cmake run, so that they exist for the tools to find them!)

Using targets for external dependencies, with the INTERFACE_INCLUDE_DIRECTORIES property defined, is strongly recommended as the easiest and most maintainable method, for sure. But that’s more important from the perspective of building and maintaining your project code. In terms of what VSCode sees, by the time cmake is done those targets are already gone, and all of their properties have been turned into compiler commands.

@ferdnyc Does VS Code really use compile_commands.json, or does it use the CMake file API now?

Thanks everyone give me the detail information.

Is *.so or *.dll include the “header files”?

I think I get it.

For target_link_libraries

I have to build the *.so or *.dll

# CMakeLists.txt
find_package(nlohmann_json 3.2.0 REQUIRED)

add_executable(test_app ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp)

target_link_libraries(test_app PRIVATE nlohmann_json::nlohmann_json)

For target_include_directories

I have to put the json.hpp of Releases · nlohmann/json · GitHub
into my project.

where ${NLOHMANNJSON_INCLUDE_DIRS} is the location for nlohmann_json on my project.

# CMakeLists.txt

add_executable(test_app ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp)
target_include_directories(test_app PUBLIC 
    ${NLOHMANNJSON_INCLUDE_DIRS}
)

For set TARGET

I have to put the json.hpp of Releases · nlohmann/json · GitHub
into my project.

# CMakeLists.txt

find_path(
	NLOHMANNJSON_INCLUDE_DIRS
	NAMES nlohmann/json.hpp
	PATHS "deps/nlohmann_json/include"
)

if(json_FOUND)
  if(NOT TARGET nlohmann_json::nlohmann_json)
    add_library(nlohmann_json::nlohmann_json INTERFACE IMPORTED)
    set_target_properties(nlohmann_json::nlohmann_json PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${NLOHMANNJSON_INCLUDE_DIRS}")
  endif()
endif()

add_executable(test_app ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp)
target_link_libraries(test_app PRIVATE nlohmann_json::nlohmann_json)

here is my project structure
deps/nlohmann_json/include/nlohmann

- project
  - .gitignore
  - README.md
  - LICENSE.md
  - CMakeLists.txt
  - cmake
    - FindSomeLib.cmake
    - something_else.cmake
  - include
    - project
      - lib.hpp
  - src
    - CMakeLists.txt
    - lib.cpp
  - apps
    - CMakeLists.txt
    - app.cpp
  - tests
    - CMakeLists.txt
    - testlib.cpp
  - docs
    - CMakeLists.txt
  - extern
    - googletest
  - scripts
    - helper.py
  - deps
     - nlohmann_json
        - include
            - nlohmann

conclusion

By using the above methods
I can use the header files

# main.cpp

#include<iostream>
#include <nlohmann/json.hpp>

int main() {

    nlohmann::json message = {{"id", 1}};
    std::cout << message.dump(4) << std::endl;

}

Is it right?

This should be what you need.

You shouldn’t need to do this. If you use target_link_libraries() as shown further above, that will add any required header search paths, compiler options, etc. as usage requirements to any target that links to nlohmann_json::nlohmann_json (which is test_app in this example). As long as you’re not using an old nlohmann_json version that predates adding those details to nlohman_json::nlohmann_json, you should be fine.

Not sure what you’re trying to do here. You shouldn’t be creating this target yourself. You should be using find_package(nlohmann_json) instead, which would provide the nlohmann_json::nlohmann_json target for you. Alternatively, you could use FetchContent, which would download nlohmann_json from GitHub and add it directly to your project:

include(FetchContent)
FetchContent_Declare(
    nlohmann_json
    GIT_REPOSITORY https://github.com/nlohmann/json.git
    GIT_TAG v3.11.3
)
FetchContent_MakeAvailable(nlohmann_json)

I fix the content for For set TARGET