target_compilation_options moves to parent project

I have C++ project tree with CMakeLists.txt in the root and another CMakeLists.txt in subdirectories with C++ sources/headers.
Subprojects are added with command add_subdirectory(). One of subproject is Botan library which has also it’s own CMakeLists.txt.
The problem is that target_compile_options(Botan PUBLIC…) used in Botan CMakeLists.txt are also set for builds of another projects which are most upper in projects tree.
The workaround to use PRIVATE in target_compile_options(Botan PRIVATE…)
It works but It is unclean for me why compilation settings are propagated to higher levels in tree ? Or is it normal behavior ?

Projects tree looks like this:

root CMakeLists.txt
|___________________ 1-st library CMakeLists.txt
|___________________ 2-nd library CMakeLists.txt
|___________________ …
|________ external libraries folder with CMakeLists.txt
_ |__________ Botan with CMakeLists.txt (COMPILE OPTIONS)
_ |__________ 2-nd external library with CMakeLists.txt

This is expected. PUBLIC flags on the Botan are added to targets which use Botan. I would recommend fixing the Botan library to set the appropriate visibility for the flags it is setting.

Thanks for the answer.
I am now confused with inheritance of compilation settings from Botan in our project tree and inheritance of variable values when used add_subdirectory(). I thought that inheritance is always realized by project tree.
For example this article explains inheritance with add_subdirectory()

Can you please explain or provide some link which can put more light on this ?

They’re called “usage requirements” and are populated via target_link_libraries calls. It is the same mechanism by which linking to a target with a target_include_directories(PUBLIC) will add -I flags for the headers to use the target, just for compile flags instead. Variables are scoped by directory and function, but usage requirements are scoped by target usage.