# - Precompilation of Vala/Genie source files into C sources # Makes use of the parallel build ability introduced in Vala 0.11. Derived # from a similar module by Jakob Westhoff and the original GNU Make rules. # Might be a bit oversimplified. # # This module defines three functions. The first one: # # vala_init (id # [DIRECTORY dir] - Output directory (binary dir by default) # [PACKAGES package...] - Package dependencies # [OPTIONS option...] - Extra valac options # [CUSTOM_VAPIS file...]) - Custom vapi files to include in the build # [DEPENDS targets...]) - Extra dependencies for code generation # # initializes a single precompilation unit using the given arguments. # You can put files into it via the following function: # # vala_add (id source.vala # [DEPENDS source...]) - Vala/Genie source or .vapi dependencies # # Finally retrieve paths for generated C files by calling: # # vala_finish (id # [SOURCES sources_var] - Input Vala/Genie sources # [OUTPUTS outputs_var] - Output C sources # [GENERATE_HEADER id.h - Generate id.h and id_internal.h # [GENERATE_VAPI id.vapi] - Generate a vapi file # [GENERATE_SYMBOLS id.def]]) - Generate a list of public symbols # #============================================================================= # Copyright Přemysl Janouch 2011 # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY # OF SUCH DAMAGE. #============================================================================= find_package (Vala 0.20 REQUIRED) include (CMakeParseArguments) function (vala_init id) set (_multi_value PACKAGES OPTIONS CUSTOM_VAPIS DEPENDS) cmake_parse_arguments (arg "" "DIRECTORY" "${_multi_value}" ${ARGN}) if (arg_DIRECTORY) set (directory ${arg_DIRECTORY}) if (NOT IS_DIRECTORY ${directory}) file (MAKE_DIRECTORY ${directory}) endif (NOT IS_DIRECTORY ${directory}) else (arg_DIRECTORY) set (directory ${CMAKE_CURRENT_BINARY_DIR}) endif (arg_DIRECTORY) set (pkg_opts) foreach (pkg ${arg_PACKAGES}) list (APPEND pkg_opts "--pkg=${pkg}") endforeach (pkg) set (VALA_${id}_DIR "${directory}" PARENT_SCOPE) set (VALA_${id}_ARGS ${pkg_opts} ${arg_OPTIONS} ${arg_CUSTOM_VAPIS} PARENT_SCOPE) set (VALA_${id}_DEPENDS ${arg_DEPENDS} PARENT_SCOPE) set (VALA_${id}_SOURCES "" PARENT_SCOPE) set (VALA_${id}_OUTPUTS "" PARENT_SCOPE) set (VALA_${id}_FAST_VAPI_FILES "" PARENT_SCOPE) set (VALA_${id}_FAST_VAPI_ARGS "" PARENT_SCOPE) endfunction (vala_init) function (vala_add id file) cmake_parse_arguments (arg "" "" "DEPENDS" ${ARGN}) if (NOT IS_ABSOLUTE "${file}") set (file "${CMAKE_CURRENT_SOURCE_DIR}/${file}") endif (NOT IS_ABSOLUTE "${file}") get_filename_component (output_name "${file}" NAME) get_filename_component (output_base "${file}" NAME_WE) set (output_base "${VALA_${id}_DIR}/${output_base}") # XXX: It would be best to have it working without touching the vapi # but it appears this cannot be done in CMake. add_custom_command (OUTPUT "${output_base}.vapi" COMMAND ${VALA_COMPILER} "${file}" "--fast-vapi=${output_base}.vapi" COMMAND ${CMAKE_COMMAND} -E touch "${output_base}.vapi" DEPENDS "${file}" COMMENT "Generating a fast vapi for ${output_name}" VERBATIM) set (vapi_opts) set (vapi_depends) foreach (vapi ${arg_DEPENDS}) if (NOT IS_ABSOLUTE "${vapi}") set (vapi "${VALA_${id}_DIR}/${vapi}.vapi") endif (NOT IS_ABSOLUTE "${vapi}") list (APPEND vapi_opts "--use-fast-vapi=${vapi}") list (APPEND vapi_depends "${vapi}") endforeach (vapi) add_custom_command (OUTPUT "${output_base}.c" COMMAND ${VALA_COMPILER} "${file}" -C ${vapi_opts} ${VALA_${id}_ARGS} COMMAND ${CMAKE_COMMAND} -E touch "${output_base}.c" DEPENDS "${file}" ${vapi_depends} ${VALA_${id}_DEPENDS} WORKING_DIRECTORY "${VALA_${id}_DIR}" COMMENT "Precompiling ${output_name}" VERBATIM) set (VALA_${id}_SOURCES ${VALA_${id}_SOURCES} "${file}" PARENT_SCOPE) set (VALA_${id}_OUTPUTS ${VALA_${id}_OUTPUTS} "${output_base}.c" PARENT_SCOPE) set (VALA_${id}_FAST_VAPI_FILES ${VALA_${id}_FAST_VAPI_FILES} "${output_base}.vapi" PARENT_SCOPE) set (VALA_${id}_FAST_VAPI_ARGS ${VALA_${id}_FAST_VAPI_ARGS} "--use-fast-vapi=${output_base}.vapi" PARENT_SCOPE) endfunction (vala_add) function (vala_finish id) set (_one_value SOURCES OUTPUTS GENERATE_VAPI GENERATE_HEADER GENERATE_SYMBOLS) cmake_parse_arguments (arg "" "${_one_value}" "" ${ARGN}) if (arg_SOURCES) set (${arg_SOURCES} ${VALA_${id}_SOURCES} PARENT_SCOPE) endif (arg_SOURCES) if (arg_OUTPUTS) set (${arg_OUTPUTS} ${VALA_${id}_OUTPUTS} PARENT_SCOPE) endif (arg_OUTPUTS) set (outputs) set (export_args) if (arg_GENERATE_VAPI) if (NOT IS_ABSOLUTE "${arg_GENERATE_VAPI}") set (arg_GENERATE_VAPI "${VALA_${id}_DIR}/${arg_GENERATE_VAPI}") endif (NOT IS_ABSOLUTE "${arg_GENERATE_VAPI}") list (APPEND outputs "${arg_GENERATE_VAPI}") list (APPEND export_args "--internal-vapi=${arg_GENERATE_VAPI}") if (NOT arg_GENERATE_HEADER) message (FATAL_ERROR "Header generation required for vapi") endif (NOT arg_GENERATE_HEADER) endif (arg_GENERATE_VAPI) if (arg_GENERATE_SYMBOLS) if (NOT IS_ABSOLUTE "${arg_GENERATE_SYMBOLS}") set (arg_GENERATE_SYMBOLS "${VALA_${id}_DIR}/${arg_GENERATE_SYMBOLS}") endif (NOT IS_ABSOLUTE "${arg_GENERATE_SYMBOLS}") list (APPEND outputs "${arg_GENERATE_SYMBOLS}") list (APPEND export_args "--symbols=${arg_GENERATE_SYMBOLS}") if (NOT arg_GENERATE_HEADER) message (FATAL_ERROR "Header generation required for symbols") endif (NOT arg_GENERATE_HEADER) endif (arg_GENERATE_SYMBOLS) if (arg_GENERATE_HEADER) if (NOT IS_ABSOLUTE "${arg_GENERATE_HEADER}") set (arg_GENERATE_HEADER "${VALA_${id}_DIR}/${arg_GENERATE_HEADER}") endif (NOT IS_ABSOLUTE "${arg_GENERATE_HEADER}") get_filename_component (header_path "${arg_GENERATE_HEADER}" PATH) get_filename_component (header_name "${arg_GENERATE_HEADER}" NAME_WE) set (header_base "${header_path}/${header_name}") get_filename_component (header_ext "${arg_GENERATE_HEADER}" EXT) list (APPEND outputs "${header_base}${header_ext}" "${header_base}_internal${header_ext}") list (APPEND export_args "--header=${header_base}${header_ext}" "--internal-header=${header_base}_internal${header_ext}") endif (arg_GENERATE_HEADER) if (outputs) add_custom_command (OUTPUT ${outputs} COMMAND ${VALA_COMPILER} -C ${VALA_${id}_ARGS} ${export_args} ${VALA_${id}_FAST_VAPI_ARGS} DEPENDS ${VALA_${id}_FAST_VAPI_FILES} COMMENT "Generating vapi/headers/symbols" VERBATIM) endif (outputs) endfunction (vala_finish id) function (vapi_gen id) set (_one_value LIBRARY INPUT) set (_multi_value PACKAGES) cmake_parse_arguments (arg "" "${_one_value}" "${_multi_value}" ${ARGN}) set(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${id}.vapi") if (arg_LIBRARY) set (OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${arg_LIBRARY}.vapi") endif (arg_LIBRARY) set("${id}_OUTPUT" ${OUTPUT} PARENT_SCOPE) set(PACKAGE_LIST) foreach(PACKAGE ${arg_PACKAGES}) list(APPEND PACKAGE_LIST "--pkg" ${PACKAGE}) endforeach() add_custom_command( OUTPUT ${OUTPUT} COMMAND ${VAPI_GEN} ${PACKAGE_LIST} --library=${arg_LIBRARY} ${arg_INPUT} DEPENDS ${arg_INPUT} VERBATIM ) add_custom_target(${id} ALL DEPENDS ${OUTPUT}) endfunction (vapi_gen id)