chore(cmake): carry option-driven defines on pybind11_headers INTERFACE (#6130)

* chore(cmake): carry option-driven defines on pybind11_headers INTERFACE

PYBIND11_DISABLE_HANDLE_TYPE_NAME_DEFAULT_IMPLEMENTATION and
PYBIND11_SIMPLE_GIL_MANAGEMENT were directory-scoped
add_compile_definitions, which only reached the master-project test
build. On the pybind11_headers INTERFACE (like
PYBIND11_INTERNALS_VERSION) they also apply in add_subdirectory mode
and in the exported/installed targets.

Assisted-by: ClaudeCode:claude-fable-5

* test(cmake): verify option-driven defines reach consumer targets

Extend subdirectory_target and installed_target to check that
PYBIND11_DISABLE_HANDLE_TYPE_NAME_DEFAULT_IMPLEMENTATION and
PYBIND11_SIMPLE_GIL_MANAGEMENT propagate through the pybind11_headers
usage requirements. Fails without the parent commit.

Assisted-by: ClaudeCode:claude-fable-5
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6f3f8be..65f794a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -109,13 +109,6 @@
 endif()
 option(PYBIND11_USE_CROSSCOMPILING "Respect CMAKE_CROSSCOMPILING" OFF)
 
-if(PYBIND11_DISABLE_HANDLE_TYPE_NAME_DEFAULT_IMPLEMENTATION)
-  add_compile_definitions(PYBIND11_DISABLE_HANDLE_TYPE_NAME_DEFAULT_IMPLEMENTATION)
-endif()
-if(PYBIND11_SIMPLE_GIL_MANAGEMENT)
-  add_compile_definitions(PYBIND11_SIMPLE_GIL_MANAGEMENT)
-endif()
-
 cmake_dependent_option(
   USE_PYTHON_INCLUDE_DIR
   "Install pybind11 headers in Python include directory instead of default installation prefix"
@@ -307,6 +300,13 @@
     target_compile_definitions(
       pybind11_headers INTERFACE "PYBIND11_INTERNALS_VERSION=${PYBIND11_INTERNALS_VERSION}")
   endif()
+  if(PYBIND11_DISABLE_HANDLE_TYPE_NAME_DEFAULT_IMPLEMENTATION)
+    target_compile_definitions(pybind11_headers
+                               INTERFACE PYBIND11_DISABLE_HANDLE_TYPE_NAME_DEFAULT_IMPLEMENTATION)
+  endif()
+  if(PYBIND11_SIMPLE_GIL_MANAGEMENT)
+    target_compile_definitions(pybind11_headers INTERFACE PYBIND11_SIMPLE_GIL_MANAGEMENT)
+  endif()
 else()
   # It is invalid to install a target twice, too.
   set(PYBIND11_INSTALL OFF)
diff --git a/tests/test_cmake_build/CMakeLists.txt b/tests/test_cmake_build/CMakeLists.txt
index ce63a69..a4d2544 100644
--- a/tests/test_cmake_build/CMakeLists.txt
+++ b/tests/test_cmake_build/CMakeLists.txt
@@ -20,6 +20,15 @@
     list(APPEND build_options "-DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}")
   endif()
 
+  # Forward option-driven defines so the nested projects can verify they propagate
+  # through the pybind11_headers usage requirements.
+  foreach(opt IN ITEMS PYBIND11_DISABLE_HANDLE_TYPE_NAME_DEFAULT_IMPLEMENTATION
+                       PYBIND11_SIMPLE_GIL_MANAGEMENT)
+    if(${opt})
+      list(APPEND build_options "-D${opt}=ON")
+    endif()
+  endforeach()
+
   if(NOT ARG_INSTALL)
     list(APPEND build_options "-Dpybind11_SOURCE_DIR=${pybind11_SOURCE_DIR}")
   else()
diff --git a/tests/test_cmake_build/installed_target/CMakeLists.txt b/tests/test_cmake_build/installed_target/CMakeLists.txt
index 6ee0169..a66f8ad 100644
--- a/tests/test_cmake_build/installed_target/CMakeLists.txt
+++ b/tests/test_cmake_build/installed_target/CMakeLists.txt
@@ -8,6 +8,15 @@
 add_library(test_installed_target MODULE ../main.cpp)
 
 target_link_libraries(test_installed_target PRIVATE pybind11::module)
+
+# If a pybind11 option is on, main.cpp checks that the matching macro reached this
+# consumer target via the installed pybind11_headers usage requirements.
+foreach(opt IN ITEMS PYBIND11_DISABLE_HANDLE_TYPE_NAME_DEFAULT_IMPLEMENTATION
+                     PYBIND11_SIMPLE_GIL_MANAGEMENT)
+  if(${opt})
+    target_compile_definitions(test_installed_target PRIVATE "EXPECT_${opt}")
+  endif()
+endforeach()
 set_target_properties(test_installed_target PROPERTIES OUTPUT_NAME test_cmake_build)
 
 # Make sure result is, for example, test_installed_target.so, not libtest_installed_target.dylib
diff --git a/tests/test_cmake_build/main.cpp b/tests/test_cmake_build/main.cpp
index 640449c..adbaace 100644
--- a/tests/test_cmake_build/main.cpp
+++ b/tests/test_cmake_build/main.cpp
@@ -1,4 +1,16 @@
 #include <pybind11/pybind11.h>
+
+#ifdef EXPECT_PYBIND11_DISABLE_HANDLE_TYPE_NAME_DEFAULT_IMPLEMENTATION
+#    ifndef PYBIND11_DISABLE_HANDLE_TYPE_NAME_DEFAULT_IMPLEMENTATION
+#        error "PYBIND11_DISABLE_HANDLE_TYPE_NAME_DEFAULT_IMPLEMENTATION did not propagate"
+#    endif
+#endif
+#ifdef EXPECT_PYBIND11_SIMPLE_GIL_MANAGEMENT
+#    ifndef PYBIND11_SIMPLE_GIL_MANAGEMENT
+#        error "PYBIND11_SIMPLE_GIL_MANAGEMENT did not propagate"
+#    endif
+#endif
+
 namespace py = pybind11;
 
 PYBIND11_MODULE(test_cmake_build, m, py::mod_gil_not_used()) {
diff --git a/tests/test_cmake_build/subdirectory_target/CMakeLists.txt b/tests/test_cmake_build/subdirectory_target/CMakeLists.txt
index 88d73f6..29b0234 100644
--- a/tests/test_cmake_build/subdirectory_target/CMakeLists.txt
+++ b/tests/test_cmake_build/subdirectory_target/CMakeLists.txt
@@ -15,6 +15,15 @@
 
 target_link_libraries(test_subdirectory_target PRIVATE pybind11::module)
 
+# If a pybind11 option is on, main.cpp checks that the matching macro reached this
+# consumer target via the pybind11_headers usage requirements.
+foreach(opt IN ITEMS PYBIND11_DISABLE_HANDLE_TYPE_NAME_DEFAULT_IMPLEMENTATION
+                     PYBIND11_SIMPLE_GIL_MANAGEMENT)
+  if(${opt})
+    target_compile_definitions(test_subdirectory_target PRIVATE "EXPECT_${opt}")
+  endif()
+endforeach()
+
 # Make sure result is, for example, test_installed_target.so, not libtest_installed_target.dylib
 pybind11_extension(test_subdirectory_target)