ClickHouse/cmake/sanitize_targets.cmake
Azat Khuzhin c3f3078884 Sanitize thirdparty libraries for public flags
Public flags, especially -Wxx (i.e. -Wno-XX) can hide some warnings,
that had been added in the main cmake rules of ClickHouse.

This patch had been tested manually with the following patch:

    ```patch
    diff --git a/contrib/jemalloc-cmake/CMakeLists.txt b/contrib/jemalloc-cmake/CMakeLists.txt
    index d5ea69d4926..7e79fba0c16 100644
    --- a/contrib/jemalloc-cmake/CMakeLists.txt
    +++ b/contrib/jemalloc-cmake/CMakeLists.txt
    @@ -158,6 +158,7 @@ target_include_directories(_jemalloc SYSTEM PRIVATE
         "${CMAKE_CURRENT_BINARY_DIR}/${JEMALLOC_INCLUDE_PREFIX}/jemalloc/internal")

     target_compile_definitions(_jemalloc PRIVATE -DJEMALLOC_NO_PRIVATE_NAMESPACE)
    +target_compile_options(_jemalloc INTERFACE -Wno-error) # also PUBLIC had been checked

     if (CMAKE_BUILD_TYPE_UC STREQUAL "DEBUG")
         target_compile_definitions(_jemalloc PRIVATE
    ```

And cmake gave:

    CMake Error at cmake/sanitize_targets.cmake:69 (message):
      _jemalloc set INTERFACE_COMPILE_OPTIONS to -Wno-error.  This is forbidden.
    Call Stack (most recent call first):
      cmake/sanitize_targets.cmake:79 (sanitize_interface_flags)
      CMakeLists.txt:595 (include)

Fixes: #12447
Signed-off-by: Azat Khuzhin <a.khuzhin@semrush.com>
2022-11-16 07:20:24 +01:00

82 lines
3.4 KiB
CMake

# https://stackoverflow.com/a/62311397/328260
macro (get_all_targets_recursive targets dir)
get_property (subdirectories DIRECTORY ${dir} PROPERTY SUBDIRECTORIES)
foreach (subdir ${subdirectories})
get_all_targets_recursive (${targets} ${subdir})
endforeach ()
get_property (current_targets DIRECTORY ${dir} PROPERTY BUILDSYSTEM_TARGETS)
list (APPEND ${targets} ${current_targets})
endmacro ()
# When you will try to link target with the directory (that exists), cmake will
# skip this without an error, only the following warning will be reported:
#
# target_link_libraries(main /tmp)
#
# WARNING: Target "main" requests linking to directory "/tmp". Targets may link only to libraries. CMake is dropping the item.
#
# And there is no cmake policy that controls this.
# (I guess the reason that it is allowed is because of FRAMEWORK for OSX).
#
# So to avoid error-prone cmake rules, this can be sanitized.
# There are the following ways:
# - overwrite target_link_libraries()/link_libraries() and check *before*
# calling real macro, but this requires duplicate all supported syntax
# -- too complex
# - overwrite target_link_libraries() and check LINK_LIBRARIES property, this
# works great
# -- but cannot be used with link_libraries()
# - use BUILDSYSTEM_TARGETS property to get list of all targets and sanitize
# -- this will work.
function (get_all_targets var)
set (targets)
get_all_targets_recursive (targets ${CMAKE_CURRENT_SOURCE_DIR})
set (${var} ${targets} PARENT_SCOPE)
endfunction()
function (sanitize_link_libraries target)
get_target_property(target_type ${target} TYPE)
if (${target_type} STREQUAL "INTERFACE_LIBRARY")
get_property(linked_libraries TARGET ${target} PROPERTY INTERFACE_LINK_LIBRARIES)
else()
get_property(linked_libraries TARGET ${target} PROPERTY LINK_LIBRARIES)
endif()
foreach (linked_library ${linked_libraries})
if (TARGET ${linked_library})
# just in case, skip if TARGET
elseif (IS_DIRECTORY ${linked_library})
message(FATAL_ERROR "${target} requested to link with directory: ${linked_library}")
endif()
endforeach()
endfunction()
get_all_targets (all_targets)
foreach (target ${all_targets})
sanitize_link_libraries(${target})
endforeach()
#
# Do not allow to define -W* from contrib publically (INTERFACE/PUBLIC).
#
function (get_contrib_targets var)
set (targets)
get_all_targets_recursive (targets ${CMAKE_CURRENT_SOURCE_DIR}/contrib)
set (${var} ${targets} PARENT_SCOPE)
endfunction()
function (sanitize_interface_flags target)
get_target_property(target_type ${target} TYPE)
get_property(compile_definitions TARGET ${target} PROPERTY INTERFACE_COMPILE_DEFINITIONS)
get_property(compile_options TARGET ${target} PROPERTY INTERFACE_COMPILE_OPTIONS)
if (NOT "${compile_options}" STREQUAL "")
message(FATAL_ERROR "${target} set INTERFACE_COMPILE_OPTIONS to ${compile_options}. This is forbidden.")
endif()
if ("${compile_definitions}" MATCHES "-Wl,")
# linker option - OK
elseif ("${compile_definitions}" MATCHES "-W")
message(FATAL_ERROR "${target} contains ${compile_definitions} flags in INTERFACE_COMPILE_DEFINITIONS. This is forbidden.")
endif()
endfunction()
get_contrib_targets (contrib_targets)
foreach (contrib_target ${contrib_targets})
sanitize_interface_flags(${contrib_target})
endforeach()