# # Copyright(c) 2021 to 2022 ZettaScale Technology and others # # This program and the accompanying materials are made available under the # terms of the Eclipse Public License v. 2.0 which is available at # http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License # v. 1.0 which is available at # http://www.eclipse.org/org/documents/edl-v10.php. # # SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause # function(IDLC_GENERATE) set(options NO_TYPE_INFO WERROR) set(one_value_keywords TARGET DEFAULT_EXTENSIBILITY BASE_DIR OUTPUT_DIR) set(multi_value_keywords FILES FEATURES INCLUDES WARNINGS) cmake_parse_arguments( IDLC "${options}" "${one_value_keywords}" "${multi_value_keywords}" "" ${ARGN}) set(gen_args ${IDLC_UNPARSED_ARGUMENTS} TARGET ${IDLC_TARGET} BASE_DIR ${IDLC_BASE_DIR} FILES ${IDLC_FILES} FEATURES ${IDLC_FEATURES} INCLUDES ${IDLC_INCLUDES} WARNINGS ${IDLC_WARNINGS} OUTPUT_DIR ${IDLC_OUTPUT_DIR} DEFAULT_EXTENSIBILITY ${IDLC_DEFAULT_EXTENSIBILITY}) if(${IDLC_NO_TYPE_INFO}) list(APPEND gen_args NO_TYPE_INFO) endif() if(${IDLC_WERROR}) list(APPEND gen_args WERROR) endif() idlc_generate_generic(${gen_args}) endfunction() function(IDLC_GENERATE_GENERIC) set(options NO_TYPE_INFO WERROR) set(one_value_keywords TARGET BACKEND DEFAULT_EXTENSIBILITY BASE_DIR OUTPUT_DIR) set(multi_value_keywords FILES FEATURES INCLUDES WARNINGS SUFFIXES DEPENDS) cmake_parse_arguments( IDLC "${options}" "${one_value_keywords}" "${multi_value_keywords}" "" ${ARGN}) # find idlc binary if(CMAKE_CROSSCOMPILING OR NOT BUILD_IDLC) find_program(_idlc_executable idlc NO_CMAKE_FIND_ROOT_PATH REQUIRED) if(_idlc_executable) set(_idlc_depends "") else() message(FATAL_ERROR "Cannot find idlc executable") endif() else() if (CMAKE_PROJECT_NAME STREQUAL "CycloneDDS") # By using the internal target when building CycloneDDS itself, prevent using an external idlc # This prevents a problem when an installed cyclone is on your prefix path when building cyclone again set(_idlc_executable idlc) set(_idlc_depends idlc) else() set(_idlc_executable CycloneDDS::idlc) set(_idlc_depends CycloneDDS::idlc) endif() endif() if(NOT IDLC_TARGET AND NOT IDLC_FILES) # assume deprecated invocation: TARGET FILE [FILE..] list(GET IDLC_UNPARSED_ARGUMENTS 0 IDLC_TARGET) list(REMOVE_AT IDLC_UNPARSED_ARGUMENTS 0 IDLC_) set(IDLC_FILES ${IDLC_UNPARSED_ARGUMENTS}) if (IDLC_TARGET AND IDLC_FILES) message(WARNING " Deprecated use of idlc_generate. \n" " Consider switching to keyword based invocation.") endif() # Java based compiler used to be case sensitive list(APPEND IDLC_FEATURES "case-sensitive") endif() if(NOT IDLC_TARGET) message(FATAL_ERROR "idlc_generate called without TARGET") elseif(NOT IDLC_FILES) message(FATAL_ERROR "idlc_generate called without FILES") endif() # remove duplicate features if(IDLC_FEATURES) list(REMOVE_DUPLICATES IDLC_FEATURES) endif() foreach(_feature ${IDLC_FEATURES}) list(APPEND IDLC_ARGS "-f" ${_feature}) endforeach() # add directories to include search list if(IDLC_INCLUDES) foreach(_dir ${IDLC_INCLUDES}) list(APPEND IDLC_INCLUDE_DIRS "-I" ${_dir}) endforeach() endif() # generate using which language (defaults to c)? if(IDLC_BACKEND) string(APPEND _language "-l" ${IDLC_BACKEND}) endif() # set dependencies if(IDLC_DEPENDS) list(APPEND _depends ${_idlc_depends} ${IDLC_DEPENDS}) else() set(_depends ${_idlc_depends}) endif() if(IDLC_DEFAULT_EXTENSIBILITY) set(_default_extensibility ${IDLC_DEFAULT_EXTENSIBILITY}) list(APPEND IDLC_ARGS "-x" ${_default_extensibility}) endif() if(IDLC_WARNINGS) foreach(_warn ${IDLC_WARNINGS}) list(APPEND IDLC_ARGS "-W${_warn}") endforeach() endif() if(IDLC_NO_TYPE_INFO) list(APPEND IDLC_ARGS "-t") endif() if(IDLC_WERROR) list(APPEND IDLC_ARGS "-Werror") endif() if(IDLC_BASE_DIR) if(${CMAKE_VERSION} VERSION_LESS "3.19.0") get_filename_component(_base_dir_abs ${IDLC_BASE_DIR} REALPATH) else() file(REAL_PATH ${IDLC_BASE_DIR} _base_dir_abs) endif() list(APPEND IDLC_ARGS "-b${_base_dir_abs}") endif() if(IDLC_OUTPUT_DIR) set(_dir ${IDLC_OUTPUT_DIR}) else() set(_dir ${CMAKE_CURRENT_BINARY_DIR}) endif() list(APPEND IDLC_ARGS "-o${_dir}") set(_target ${IDLC_TARGET}) foreach(_file ${IDLC_FILES}) get_filename_component(_path ${_file} ABSOLUTE) list(APPEND _files "${_path}") endforeach() # set source suffixes (defaults to .c and .h) if(NOT IDLC_SUFFIXES) set(IDLC_SUFFIXES ".c" ".h") endif() set(_outputs "") foreach(_file ${_files}) get_filename_component(_name ${_file} NAME_WLE) get_filename_component(_name_ext ${_file} NAME) # Determine middle path for directory reconstruction if(IDLC_BASE_DIR) file(RELATIVE_PATH _file_path_rel ${_base_dir_abs} ${_file}) # Hard Fail if(_file_path_rel MATCHES "^\\.\\.") message(FATAL_ERROR "Cannot use base dir with different file tree from input file (${_base_dir_abs} to ${_file} yields ${_file_path_rel})") endif() string(REPLACE ${_name_ext} "" _mid_dir_path ${_file_path_rel}) string(REGEX REPLACE "[\\/]$" "" _mid_dir_path "${_mid_dir_path}") endif() set(_file_outputs "") foreach(_suffix ${IDLC_SUFFIXES}) if(IDLC_BASE_DIR) list(APPEND _file_outputs "${_dir}/${_mid_dir_path}/${_name}${_suffix}") else() list(APPEND _file_outputs "${_dir}/${_name}${_suffix}") endif() endforeach() list(APPEND _outputs ${_file_outputs}) add_custom_command( OUTPUT ${_file_outputs} COMMAND ${_idlc_executable} ARGS ${_language} ${IDLC_ARGS} ${IDLC_INCLUDE_DIRS} ${_file} DEPENDS ${_files} ${_depends}) endforeach() add_custom_target("${_target}_generate" DEPENDS "${_outputs}") add_library(${_target} INTERFACE) target_sources(${_target} INTERFACE ${_outputs}) target_include_directories(${_target} INTERFACE "${_dir}") add_dependencies(${_target} "${_target}_generate") endfunction()