Skip to content

Instantly share code, notes, and snippets.

@kovrov
Created May 4, 2025 03:48
Show Gist options
  • Save kovrov/cf92eb57318f561465a91ef8b6910681 to your computer and use it in GitHub Desktop.
Save kovrov/cf92eb57318f561465a91ef8b6910681 to your computer and use it in GitHub Desktop.
cmake modules
find_package(PkgConfig REQUIRED)
function(add_wayland_client_protocol_library LIBRARY_NAME)
if(ARGN STREQUAL "")
message(FATAL_ERROR "add_wayland_client_protocol_library: No protocol files specified")
endif()
pkg_check_modules(WAYLAND_PROTOCOLS QUIET wayland-protocols)
if(WAYLAND_PROTOCOLS_FOUND)
pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir)
endif()
find_program(WAYLAND_SCANNER wayland-scanner)
set(PROTOCOL_SOURCES)
set(PROTOCOL_HEADERS)
set(PROTOCOL_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}/${LIBRARY_NAME}/include")
set(PROTOCOL_SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/${LIBRARY_NAME}/src")
file(MAKE_DIRECTORY ${PROTOCOL_INCLUDE_DIR} ${PROTOCOL_SOURCE_DIR})
foreach(PROTOCOL_FILE ${ARGN})
if (IS_ABSOLUTE ${PROTOCOL_FILE})
message(FATAL_ERROR "'${PROTOCOL_FILE}' is an absolute path.")
endif()
unset(FULL_PROTOCOL_PATH)
find_file(FULL_PROTOCOL_PATH ${PROTOCOL_FILE}
PATHS
"${CMAKE_CURRENT_SOURCE_DIR}"
"${WAYLAND_PROTOCOLS_DIR}"
NO_CACHE
NO_DEFAULT_PATH
REQUIRED
)
get_filename_component(PROTOCOL_NAME ${PROTOCOL_FILE} NAME_WE)
get_filename_component(PROTOCOL_DIR ${PROTOCOL_FILE} DIRECTORY)
set(OUTPUT_DIR "${PROTOCOL_INCLUDE_DIR}/${PROTOCOL_DIR}")
file(MAKE_DIRECTORY ${OUTPUT_DIR})
set(PROTOCOL_HEADER "${OUTPUT_DIR}/${PROTOCOL_NAME}.h")
set(OUTPUT_DIR "${PROTOCOL_SOURCE_DIR}/${PROTOCOL_DIR}")
file(MAKE_DIRECTORY ${OUTPUT_DIR})
set(PROTOCOL_SOURCE "${OUTPUT_DIR}/${PROTOCOL_NAME}.c")
add_custom_command(
OUTPUT ${PROTOCOL_HEADER}
COMMAND ${WAYLAND_SCANNER} client-header ${FULL_PROTOCOL_PATH} ${PROTOCOL_HEADER}
DEPENDS ${FULL_PROTOCOL_PATH}
COMMENT "Generating Wayland protocol header for ${PROTOCOL_FILE}"
VERBATIM
)
add_custom_command(
OUTPUT ${PROTOCOL_SOURCE}
COMMAND ${WAYLAND_SCANNER} private-code ${FULL_PROTOCOL_PATH} ${PROTOCOL_SOURCE}
DEPENDS ${FULL_PROTOCOL_PATH} ${PROTOCOL_HEADER}
COMMENT "Generating Wayland protocol code for ${PROTOCOL_FILE}"
VERBATIM
)
list(APPEND PROTOCOL_SOURCES ${PROTOCOL_SOURCE})
list(APPEND PROTOCOL_HEADERS ${PROTOCOL_HEADER})
endforeach()
add_library(${LIBRARY_NAME} STATIC ${PROTOCOL_SOURCES} ${PROTOCOL_HEADERS})
target_include_directories(${LIBRARY_NAME}
PUBLIC
$<BUILD_INTERFACE:${PROTOCOL_INCLUDE_DIR}>
$<INSTALL_INTERFACE:include>
)
target_link_libraries(${LIBRARY_NAME} PUBLIC Wayland::Client)
set_target_properties(${LIBRARY_NAME} PROPERTIES
PUBLIC_HEADER "${PROTOCOL_HEADERS}"
)
endfunction()
if(NOT Wayland_FIND_COMPONENTS)
set(Wayland_FIND_COMPONENTS Client EGL Server Cursor)
if(Wayland_FIND_REQUIRED)
foreach(_component ${Wayland_FIND_COMPONENTS})
set(Wayland_FIND_REQUIRED_${_component} TRUE)
endforeach()
endif()
endif()
set(_found_components)
foreach(_component ${Wayland_FIND_COMPONENTS})
string(TOLOWER wayland-${_component} _module_spec)
pkg_check_modules(WAYLAND_${_component} QUIET IMPORTED_TARGET ${_module_spec})
if(WAYLAND_${_component}_FOUND)
set(Wayland_${_component}_FOUND TRUE)
list(APPEND _found_components ${_component})
else()
set(Wayland_${_component}_FOUND FALSE)
if(Wayland_FIND_REQUIRED_${_component})
message(WARNING "'${_component}' not found via pkg-config (looked for '${_module_spec}')")
endif()
endif()
endforeach()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Wayland
HANDLE_COMPONENTS
)
foreach(_component ${_found_components})
if(NOT TARGET Wayland::${_component})
add_library(Wayland::${_component} INTERFACE IMPORTED)
target_link_libraries(Wayland::${_component} INTERFACE PkgConfig::WAYLAND_${_component})
endif()
endforeach()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment