1# GLibTools.cmake 2# 3# Provides functions to run glib tools. 4# 5# Functions: 6# 7# glib_mkenums_multiple(_output_filename_noext _define_name _enums_header ...) 8# runs glib-mkenums to generate enumtypes .h and .c files from multiple 9# _enums_header. It searches for files in the current source directory and 10# exports to the current binary directory. 11# 12# glib_mkenums(_output_filename_noext _enums_header _define_name) 13# runs glib-mkenums to generate enumtypes .h and .c files from _enums_header. 14# It searches for files in the current source directory and exports to the current 15# binary directory. 16# 17# An example call is: 18# glib_mkenums(camel-enumtypes camel-enums.h CAMEL_ENUMTYPES_H) 19# which uses camel-enums.h as the source of known enums and generates 20# camel-enumtypes.h which will use the CAMEL_ENUMTYPES_H define 21# and also generates camel-enumtypes.c with the needed code. 22# 23# glib_genmarshal(_output_filename_noext _prefix _marshallist_filename) 24# runs glib-genmarshal to process ${_marshallist_filename} to ${_output_filename_noext}.c 25# and ${_output_filename_noext}.h files in the current binary directory, using 26# the ${_prefix} as the function prefix. 27# 28# gdbus_codegen(_xml _interface_prefix _c_namespace _files_prefix _list_gens) 29# runs gdbus-codegen to generate GDBus code from _xml file description, 30# using _interface_prefix, _c_namespace and _files_prefix as arguments. 31# The _list_gens is a list variable are stored expected generated files. 32# 33# An example call is: 34# set(GENERATED_DBUS_LOCALE 35# e-dbus-localed.c 36# e-dbus-localed.h 37# ) 38# gdbus_codegen(org.freedesktop.locale1.xml org.freedesktop. E_DBus e-dbus-localed GENERATED_DBUS_LOCALE) 39# 40# gdbus_codegen_custom(_xml _interface_prefix _c_namespace _files_prefix _list_gens _args) 41# The same as gdbus_codegen() except allows to pass other arguments to the call, 42# like for example --c-generate-object-manager 43# 44# add_gsettings_schemas(_target _schema0 ...) 45# Adds one or more GSettings schemas. The extension is supposed to be .gschema.xml. The schema file generation 46# is added as a dependency of _target. 47# 48# glib_compile_resources _sourcedir _outputprefix _cname _inxml ...deps) 49# Calls glib-compile-resources as defined in _inxml and using _outputprefix and_cname as other arguments 50# beside _sourcedir. The optional arguments are other dependencies. 51 52include(PkgConfigEx) 53include(UninstallTarget) 54 55find_program(GLIB_MKENUMS glib-mkenums) 56if(NOT GLIB_MKENUMS) 57 message(FATAL_ERROR "Cannot find glib-mkenums, which is required to build ${PROJECT_NAME}") 58endif(NOT GLIB_MKENUMS) 59 60function(glib_mkenums_multiple _output_filename_noext _define_name _enums_header0) 61 set(HEADER_TMPL " 62/*** BEGIN file-header ***/ 63#ifndef ${_define_name} 64#define ${_define_name} 65 66#include <glib-object.h> 67 68G_BEGIN_DECLS 69/*** END file-header ***/ 70 71/*** BEGIN file-production ***/ 72 73/* Enumerations from \"@basename@\" */ 74 75/*** END file-production ***/ 76 77/*** BEGIN enumeration-production ***/ 78#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type()) 79GType @enum_name@_get_type (void) G_GNUC_CONST; 80 81/*** END enumeration-production ***/ 82 83/*** BEGIN file-tail ***/ 84 85G_END_DECLS 86 87#endif /* ${_define_name} */ 88/*** END file-tail ***/") 89 90 file(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/enumtypes-${_output_filename_noext}.h.tmpl" "${HEADER_TMPL}\n") 91 92 foreach(_enums_header ${_enums_header0} ${ARGN}) 93 list(APPEND _enums_headers "${CMAKE_CURRENT_SOURCE_DIR}/${_enums_header}") 94 endforeach(_enums_header) 95 96 add_custom_command( 97 OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${_output_filename_noext}.h 98 COMMAND ${GLIB_MKENUMS} --template "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/enumtypes-${_output_filename_noext}.h.tmpl" ${_enums_headers} >${CMAKE_CURRENT_BINARY_DIR}/${_output_filename_noext}.h 99 DEPENDS ${_enums_headers} 100 ) 101 102set(SOURCE_TMPL " 103/*** BEGIN file-header ***/ 104#include \"${_output_filename_noext}.h\" 105/*** END file-header ***/ 106 107/*** BEGIN file-production ***/ 108/* enumerations from \"@basename@\" */ 109#include \"@basename@\" 110 111/*** END file-production ***/ 112 113/*** BEGIN value-header ***/ 114GType 115@enum_name@_get_type (void) 116{ 117 static gsize the_type__volatile = 0; 118 119 if (g_once_init_enter (&the_type__volatile)) { 120 static const G\@Type\@Value values[] = { 121/*** END value-header ***/ 122 123/*** BEGIN value-production ***/ 124 { \@VALUENAME\@, 125 \"@VALUENAME@\", 126 \"@valuenick@\" }, 127/*** END value-production ***/ 128 129/*** BEGIN value-tail ***/ 130 { 0, NULL, NULL } 131 }; 132 GType the_type = g_\@type\@_register_static ( 133 g_intern_static_string (\"@EnumName@\"), 134 values); 135 g_once_init_leave (&the_type__volatile, the_type); 136 } 137 return the_type__volatile; 138} 139 140/*** END value-tail ***/") 141 142 file(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/enumtypes-${_output_filename_noext}.c.tmpl" "${SOURCE_TMPL}\n") 143 144 add_custom_command( 145 OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${_output_filename_noext}.c 146 COMMAND ${GLIB_MKENUMS} --template "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/enumtypes-${_output_filename_noext}.c.tmpl" ${_enums_headers} >${CMAKE_CURRENT_BINARY_DIR}/${_output_filename_noext}.c 147 DEPENDS ${_enums_headers} 148 ) 149endfunction(glib_mkenums_multiple) 150 151function(glib_mkenums _output_filename_noext _enums_header _define_name) 152 glib_mkenums_multiple (${_output_filename_noext} ${_define_name} ${_enums_header}) 153endfunction(glib_mkenums) 154 155find_program(GLIB_GENMARSHAL glib-genmarshal) 156if(NOT GLIB_GENMARSHAL) 157 message(FATAL_ERROR "Cannot find glib-genmarshal, which is required to build ${PROJECT_NAME}") 158endif(NOT GLIB_GENMARSHAL) 159 160function(glib_genmarshal _output_filename_noext _prefix _marshallist_filename) 161 add_custom_command( 162 OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${_output_filename_noext}.h 163 COMMAND ${GLIB_GENMARSHAL} --header --skip-source --prefix=${_prefix} "${CMAKE_CURRENT_SOURCE_DIR}/${_marshallist_filename}" >${CMAKE_CURRENT_BINARY_DIR}/${_output_filename_noext}.h.tmp 164 COMMAND ${CMAKE_COMMAND} -E rename ${CMAKE_CURRENT_BINARY_DIR}/${_output_filename_noext}.h.tmp ${CMAKE_CURRENT_BINARY_DIR}/${_output_filename_noext}.h 165 DEPENDS ${_marshallist_filename} 166 ) 167 168 add_custom_command( 169 OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${_output_filename_noext}.c 170 COMMAND ${CMAKE_COMMAND} -E echo " #include \\\"${_output_filename_noext}.h\\\"" >${CMAKE_CURRENT_BINARY_DIR}/${_output_filename_noext}.c.tmp 171 COMMAND ${GLIB_GENMARSHAL} --body --skip-source --prefix=${_prefix} "${CMAKE_CURRENT_SOURCE_DIR}/${_marshallist_filename}" >>${CMAKE_CURRENT_BINARY_DIR}/${_output_filename_noext}.c.tmp 172 COMMAND ${CMAKE_COMMAND} -E rename ${CMAKE_CURRENT_BINARY_DIR}/${_output_filename_noext}.c.tmp ${CMAKE_CURRENT_BINARY_DIR}/${_output_filename_noext}.c 173 DEPENDS ${_marshallist_filename} 174 ) 175endfunction(glib_genmarshal) 176 177find_program(GDBUS_CODEGEN gdbus-codegen) 178if(NOT GDBUS_CODEGEN) 179 message(FATAL_ERROR "Cannot find gdbus-codegen, which is required to build ${PROJECT_NAME}") 180endif(NOT GDBUS_CODEGEN) 181 182function(gdbus_codegen_custom _xml _interface_prefix _c_namespace _files_prefix _list_gens _args) 183 add_custom_command( 184 OUTPUT ${${_list_gens}} 185 COMMAND ${GDBUS_CODEGEN} 186 ARGS --interface-prefix ${_interface_prefix} 187 --c-namespace ${_c_namespace} 188 --generate-c-code ${_files_prefix} 189 --generate-docbook ${_files_prefix} 190 ${_args} 191 ${CMAKE_CURRENT_SOURCE_DIR}/${_xml} 192 MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/${_xml} 193 VERBATIM 194 ) 195endfunction(gdbus_codegen_custom) 196 197function(gdbus_codegen _xml _interface_prefix _c_namespace _files_prefix _list_gens) 198 gdbus_codegen_custom(${_xml} ${_interface_prefix} ${_c_namespace} ${_files_prefix} ${_list_gens} "") 199endfunction(gdbus_codegen) 200 201add_printable_option(ENABLE_SCHEMAS_COMPILE "Enable GSettings regeneration of gschemas.compile on install" ON) 202 203if(CMAKE_CROSSCOMPILING) 204 find_program(GLIB_COMPILE_SCHEMAS glib-compile-schemas) 205else(CMAKE_CROSSCOMPILING) 206 pkg_check_variable(GLIB_COMPILE_SCHEMAS gio-2.0 glib_compile_schemas) 207endif(CMAKE_CROSSCOMPILING) 208 209if(NOT GLIB_COMPILE_SCHEMAS) 210 message(FATAL_ERROR "Cannot find glib-compile-schemas, which is required to build ${PROJECT_NAME}") 211endif(NOT GLIB_COMPILE_SCHEMAS) 212 213set(GSETTINGS_SCHEMAS_DIR "${SHARE_INSTALL_PREFIX}/glib-2.0/schemas/") 214 215macro(add_gsettings_schemas _target _schema0) 216 set(_install_code) 217 218 foreach(_schema ${_schema0} ${ARGN}) 219 string(REPLACE ".xml" ".valid" _outputfile "${_schema}") 220 get_filename_component(_outputfile "${_outputfile}" NAME) 221 222 get_filename_component(_schema_fullname "${_schema}" DIRECTORY) 223 get_filename_component(_schema_filename "${_schema}" NAME) 224 if(_schema_fullname STREQUAL "") 225 set(_schema_fullname ${CMAKE_CURRENT_SOURCE_DIR}/${_schema}) 226 else(_schema_fullname STREQUAL "") 227 set(_schema_fullname ${_schema}) 228 endif(_schema_fullname STREQUAL "") 229 230 add_custom_command( 231 OUTPUT ${_outputfile} 232 COMMAND ${GLIB_COMPILE_SCHEMAS} --strict --dry-run --schema-file=${_schema_fullname} 233 COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_schema_fullname}" "${CMAKE_CURRENT_BINARY_DIR}/${_outputfile}" 234 DEPENDS ${_schema_fullname} 235 VERBATIM 236 ) 237 add_custom_target(gsettings-schemas-${_schema_filename} ALL DEPENDS ${_outputfile}) 238 add_dependencies(${_target} gsettings-schemas-${_schema_filename}) 239 if(ENABLE_SCHEMAS_COMPILE) 240 # this is required to compile gsettings schemas like after 'make install, 241 # because there is no better way in CMake to run a code/script after 242 # the whole `make install` 243 set(_install_code "${_install_code} 244 COMMAND ${CMAKE_COMMAND} -E copy_if_different \"${_schema_fullname}\" \"${GSETTINGS_SCHEMAS_DIR}\"" 245 ) 246 endif(ENABLE_SCHEMAS_COMPILE) 247 248 # Do both, to have 'uninstall' working properly 249 install(FILES ${_schema_fullname} 250 DESTINATION ${GSETTINGS_SCHEMAS_DIR}) 251 endforeach(_schema) 252 253 if(_install_code) 254 # Compile gsettings schemas and ensure that all of them are in the place. 255 install(CODE 256 "if(\"\$ENV{DESTDIR}\" STREQUAL \"\") 257 execute_process(${_install_code} 258 COMMAND ${CMAKE_COMMAND} -E chdir . \"${GLIB_COMPILE_SCHEMAS}\" \"${GSETTINGS_SCHEMAS_DIR}\" 259 ) 260 endif(\"\$ENV{DESTDIR}\" STREQUAL \"\")") 261 endif(_install_code) 262endmacro(add_gsettings_schemas) 263 264# This is called too early, when the schemas are not installed yet during `make install` 265# 266# compile_gsettings_schemas() 267# Optionally (based on ENABLE_SCHEMAS_COMPILE) recompiles schemas at the destination folder 268# after install. It's necessary to call it as the last command in the toplevel CMakeLists.txt, 269# thus the compile runs when all the schemas are installed. 270# 271if(ENABLE_SCHEMAS_COMPILE) 272 add_custom_command(TARGET uninstall POST_BUILD 273 COMMAND ${CMAKE_COMMAND} -E chdir . "${GLIB_COMPILE_SCHEMAS}" "${GSETTINGS_SCHEMAS_DIR}" 274 COMMENT "Recompile GSettings schemas in '${GSETTINGS_SCHEMAS_DIR}'" 275 ) 276endif(ENABLE_SCHEMAS_COMPILE) 277 278find_program(GLIB_COMPILE_RESOURCES glib-compile-resources) 279if(NOT GLIB_COMPILE_RESOURCES) 280 message(FATAL_ERROR "Cannot find glib-compile-resources, which is required to build ${PROJECT_NAME}") 281endif(NOT GLIB_COMPILE_RESOURCES) 282 283macro(glib_compile_resources _sourcedir _outputprefix _cname _inxml) 284 add_custom_command( 285 OUTPUT ${_outputprefix}.h 286 COMMAND ${GLIB_COMPILE_RESOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/${_inxml} --target=${_outputprefix}.h --sourcedir=${_sourcedir} --c-name ${_cname} --generate-header 287 DEPENDS ${_inxml} ${ARGN} 288 VERBATIM 289 ) 290 add_custom_command( 291 OUTPUT ${_outputprefix}.c 292 COMMAND ${GLIB_COMPILE_RESOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/${_inxml} --target=${_outputprefix}.c --sourcedir=${_sourcedir} --c-name ${_cname} --generate-source 293 DEPENDS ${_inxml} ${ARGN} 294 VERBATIM 295 ) 296endmacro(glib_compile_resources) 297