CMake installing or exporting in monorepo

What is the difference between installing and exporting? I have a monorepo with few libs and apps added with add_subdirectory() to root CMakeLists.txt. I want to be able to open a single app project separately (without need for clangd to read all libs and other apps). But this project should be able to link and find headers to existing libs set as a dependencies with target_link_libraries(). What is the best solution here?

Installing places your build artifacts in some “prefix” in a (hopefully) standard layout relevant for the platform. Exporting, in CMake, is putting information about the targets your build makes in a form that other projects can use them (usually through a find_package() call). You can export to the build tree (the export() command) or to the install tree (using install(EXPORT)). They are different because they each have different paths in them (e.g., where headers live).

Ok, so if I want to edit file in place I should use export() ?

What do you mean? These files are written by CMake and not meant to be edited afterwards.

No, I mean I have

├── LibA/
│   ├── CMakeLists.txt
│   ├── include/
│   │   └── libA.hpp
│   └── src/
│       └── ...
└── AppFoo/
    ├── CMakeLists.txt
    └── src/
        ├── main.cpp
        └── ...

Then I want to run CMake against LibA once which should install or export this library, and then open only AppFoo/CMakeLists.txt in my IDE. Then I ctrl+click on the LibA::SomeClass in the main.cpp and jump to LibA/libA.hpp file inside MyMonorepo, but not inside some temporary build directory. Does this makes sense?

That sounds more like an IDE support thing. However, exports don’t contain that kind of information (sources are generally not mentioned in exported targets).

Include paths must be mentioned in the exported targets.

Ah, yes, that will get you headers. If you use the build tree, you’ll get the actual headers. If you use the installed export, you’ll get the installed header copies.

@ben.boeckel yes that’s clear now thanks! So using export() instead of install() in the use-case I’ve explained above make sense, right?