User defined hooks for CMake "events" (design discussion)
I maintain a CMake framework (smth like KDE's ECM) which is a basic dependency for around a hundred C++ projects in the company. It simplifies "end-user" `CMakeLists.txt` in many aspects. One of the things I'm thinking about (wishing) for a long time is _user-defined hooks for CMake events_. Events like the following: - entering/leaving directory by `add_subdrectory()` - adding/modifying a target - entering/leaving a project scope Examples, - _on entering a unit tests directory_ (`*/tests`) it's very common to have `paths.cpp.in` (having definitions of some filesystem paths required by tests here) which must be rendered with `configure_file()` - _on adding an executable target_ which name suffixed with `*_unit_tests` the `main.cpp` file must be rendered and added to the sources. As well as the `${CMAKE_CURRENT_BINARY_DIR}/paths.cpp` if exists - we have quite formal rules for grouping sources of targets and it'll be nice to apply `source_group()` for every target defined _on leaving a directory_ - for every _adding target_ we have the rule to make an alias depending on the target type - for every _adding target_ we have a bunch of properties to assign (including `INTERFACE_*` and `COMPATIBLE_INTERFACE_*`) that indicates vital build features - for every _project added_ we have a well know list of variables to set (sometimes depending on project properties) like top project options (so all our projects have the same set of them), rendering CMake configs for `find_package()`, common CPack related stuff... - ... etcetera The framework provides a bunch of functions an "end-user" have to call at **specific points** of arbitrary `CMakeLists.txt` in the project's subdirectory. This approach has a quite regular set of functions to call per sub-directory but at the same time is error-prone. Trying to simplify it even more as the last resort I could write a `super_function_that_do_all_the_job_in_any_subdirectory()` that do magic^W _all things that have to be done in a single call_. Having very formal rules it's quite possible... However, this function gonna have zillion parameters weakly related to each other and for sure gonna look not very nice. That is why I'm thinking about how nice it gonna be to have smth like this: ```cmake function(my_entering_subdirectory DIRNAME) if(DIRNAME MATCHES ".*/tests$") # Render `*.in` files` ... endif() endfunction() list(APPEND CMAKE_USER_HOOKS_ENTERING_SUBDIRECTORY my_entering_subdirectory) function(my_leaving_subdirectory DIRNAME) ... endfunction() list(APPEND CMAKE_USER_HOOKS_LEAVING_SUBDIRECTORY my_leaving_subdirectory) function(my_adding_target TARGET) ... endfunction() list(APPEND CMAKE_USER_HOOKS_ADDING_TARGET my_adding_target) function(my_modifying_target TARGET [WHAT_HAS_CHANGED ...]) ... endfunction() list(APPEND CMAKE_USER_HOOKS_MODIFYING_TARGET my_modifying_target) ... add_subdirectory(blah-blah) ``` So, any `CMakeLists.txt` in the subdirectory gonna have a "clean" CMake instructions: `add_library` or `add_executable` plus `target_blah_blah()` commands. And all that magic gonna happened in the user defined hooks (OK, provided by the framework %). Some of that magic could be done via watching (`variable_watch()`) CMake specific variables but this way is not increasing configuration speed for sure and personally I consider it as **abuse**. I would be happy to have a "legal" (straightforward) way to do that... Thoughts?
issue