|  | # This CMake include file defines utility functions for handling generated files | 
|  | # that are required in another CMake directory other than the one where it was | 
|  | # generated. | 
|  | # | 
|  | # Key functions: | 
|  | # | 
|  | # * ADD_FILE_TARGET - Creates a file target.  All source files, whether | 
|  | #   generated or not should call this function. | 
|  | # * GET_FILE_TARGET - Given a absolute or local source path, what is the target | 
|  | #   that will build this file. | 
|  | # * GET_REL_TARGET - Given a absolute or local source path and prefix | 
|  | #   generates target name in a form $prefix_$file. | 
|  | # * GET_FILE_LOCATION - Given a absolute or local source path, what is the | 
|  | #   actual location of the file. | 
|  | # | 
|  | # When writing targets that rely on files using these functions, never use a raw | 
|  | # source path, e.g. ${CMAKE_CURRENT_SOURCE_DIR}/example_dir/example.file or | 
|  | # example.file.  Instead always call GET_FILE_LOCATION on the path.  This is | 
|  | # because the actual source location may not be in the source tree, but instead | 
|  | # be in the build tree. | 
|  | # | 
|  | # When writing targets that rely on files using these functions, always DEPEND | 
|  | # on both the file location (from GET_FILE_LOCATION) and the file target (from | 
|  | # GET_FILE_TARGET).  If you only DEPEND on the file location, the file will not | 
|  | # be generated the first time through the build. | 
|  | # | 
|  | # Utility functions: | 
|  | # | 
|  | # * APPEND_FILE_LOCATION - Appends to a list the file location of specified | 
|  | #   file. | 
|  | # * APPEND_FILE_DEPENDENCY - Appends to a list both the file location and file | 
|  | #   target of specified file. | 
|  | function(GET_REL_TARGET var prefix src_file) | 
|  | if(${src_file} MATCHES "^/") | 
|  | set(SOURCE_LOCATION ${src_file}) | 
|  | else() | 
|  | set(SOURCE_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/${src_file}) | 
|  | endif() | 
|  |  | 
|  | get_filename_component(CANON_LOCATION ${SOURCE_LOCATION} | 
|  | ABSOLUTE | 
|  | BASE_DIR ${f4pga-arch-defs_SOURCE_DIR} | 
|  | ) | 
|  |  | 
|  | string( | 
|  | REPLACE | 
|  | "${f4pga-arch-defs_SOURCE_DIR}" | 
|  | "" | 
|  | REL_CANON_LOCATION | 
|  | ${CANON_LOCATION} | 
|  | ) | 
|  | string( | 
|  | REPLACE | 
|  | "/" | 
|  | "_" | 
|  | TARGET_PATH | 
|  | ${REL_CANON_LOCATION} | 
|  | ) | 
|  | set(${var} ${prefix}${TARGET_PATH} PARENT_SCOPE) | 
|  | endfunction() | 
|  |  | 
|  | function(GET_FILE_TARGET var src_file) | 
|  | get_rel_target(TARGET_PATH file ${src_file}) | 
|  | set(${var} ${TARGET_PATH} PARENT_SCOPE) | 
|  | endfunction() | 
|  |  | 
|  | function(GET_FILE_LOCATION var src_file) | 
|  | # Sets var in PARENT_SCOPE to file location for given src_file. | 
|  | get_file_target(SRC_TARGET ${src_file}) | 
|  | get_target_property(SRC_LOCATION ${SRC_TARGET} LOCATION) | 
|  | if("${SRC_LOCATION}" STREQUAL "NOT_FOUND") | 
|  | message( | 
|  | FATAL_ERROR | 
|  | "File ${src_file} is not a valid verilog target, missing LOCATION." | 
|  | ) | 
|  | endif() | 
|  |  | 
|  | set(${var} ${SRC_LOCATION} PARENT_SCOPE) | 
|  | endfunction() | 
|  |  | 
|  | function(APPEND_FILE_LOCATION var src_file) | 
|  | # Appends to list var in PARENT_SCOPE both file location for | 
|  | # given src_file. | 
|  | get_file_target(SRC_TARGET ${src_file}) | 
|  | get_target_property(SRC_LOCATION ${SRC_TARGET} LOCATION) | 
|  | if("${SRC_LOCATION}" STREQUAL "NOT_FOUND") | 
|  | message( | 
|  | FATAL_ERROR | 
|  | "File ${src_file} is not a valid verilog target, missing LOCATION." | 
|  | ) | 
|  | endif() | 
|  |  | 
|  | list(APPEND ${var} ${SRC_LOCATION}) | 
|  | set(${var} "${${var}}" PARENT_SCOPE) | 
|  | endfunction() | 
|  |  | 
|  | function(APPEND_FILE_DEPENDENCY var src_file) | 
|  | # Appends to list var in PARENT_SCOPE both file location and file target for | 
|  | # given src_file. | 
|  | get_file_target(SRC_TARGET ${src_file}) | 
|  | get_target_property(SRC_LOCATION ${SRC_TARGET} LOCATION) | 
|  | if("${SRC_LOCATION}" STREQUAL "NOT_FOUND") | 
|  | message( | 
|  | FATAL_ERROR | 
|  | "File ${src_file} is not a valid verilog target, missing LOCATION." | 
|  | ) | 
|  | endif() | 
|  |  | 
|  | list(APPEND ${var} ${SRC_TARGET}) | 
|  | list(APPEND ${var} ${SRC_LOCATION}) | 
|  |  | 
|  | get_target_property(INCLUDE_FILES ${SRC_TARGET} INCLUDE_FILES) | 
|  | foreach(SRC ${INCLUDE_FILES}) | 
|  | append_file_dependency(${var} ${SRC}) | 
|  | endforeach() | 
|  | set(${var} "${${var}}" PARENT_SCOPE) | 
|  | endfunction() | 
|  |  | 
|  | function(APPEND_FILE_INCLUDES var src_file) | 
|  | # Appends to list var in PARENT_SCOPE both includes listed for file target for | 
|  | # given src_file. | 
|  | get_file_target(SRC_TARGET ${src_file}) | 
|  | get_target_property(SRC_INCLUDES ${SRC_TARGET} INCLUDES) | 
|  | if("${SRC_INCLUDES}" STREQUAL "NOT_FOUND") | 
|  | message( | 
|  | FATAL_ERROR | 
|  | "File ${SRC} is not a valid verilog target, missing INCLUDES list." | 
|  | ) | 
|  | endif() | 
|  |  | 
|  | list(APPEND ${var} ${SRC_INCLUDES}) | 
|  | set(${var} "${${var}}" PARENT_SCOPE) | 
|  | endfunction() | 
|  |  | 
|  | function(GET_VERILOG_INCLUDES var file) | 
|  | # Appends to list var in PARENT_SCOPE all verilog source dependency based on | 
|  | # scanning input at configure time. | 
|  | # | 
|  | # Note this function cannot be used at generation time because execute_process | 
|  | # is called during configure step and generated files don't exist yet. | 
|  | execute_process( | 
|  | COMMAND | 
|  | ${PYTHON_EXECUTABLE} ${f4pga-arch-defs_SOURCE_DIR}/utils/deps_verilog.py | 
|  | --file_per_line ${CMAKE_CURRENT_SOURCE_DIR}/${file} | 
|  | WORKING_DIRECTORY ${f4pga-arch-defs_SOURCE_DIR} | 
|  | OUTPUT_VARIABLE INCLUDES | 
|  | ) | 
|  |  | 
|  | string( | 
|  | REPLACE | 
|  | "\n" | 
|  | ";" | 
|  | INCLUDES_LIST | 
|  | "${INCLUDES}" | 
|  | ) | 
|  | foreach(INCLUDE ${INCLUDES_LIST}) | 
|  | string(STRIP ${INCLUDE} INCLUDE) | 
|  | if(NOT "${INCLUDE}" STREQUAL "") | 
|  | get_filename_component( | 
|  | ABS_PATH_TO_INCLUDE | 
|  | ${INCLUDE} | 
|  | ABSOLUTE | 
|  | BASE_DIR | 
|  | ${f4pga-arch-defs_SOURCE_DIR} | 
|  | ) | 
|  | list(APPEND ${var} ${ABS_PATH_TO_INCLUDE}) | 
|  | endif() | 
|  | endforeach() | 
|  | set(${var} "${${var}}" PARENT_SCOPE) | 
|  | endfunction() | 
|  |  | 
|  | function(GET_XML_INCLUDES var file) | 
|  | # Appends to list var in PARENT_SCOPE all xml source dependency based on | 
|  | # scanning input at configure time. | 
|  | # | 
|  | # Note this function cannot be used at generation time because execute_process | 
|  | # is called during configure step and generated files don't exist yet. | 
|  | execute_process( | 
|  | COMMAND | 
|  | ${PYTHON_EXECUTABLE} ${f4pga-arch-defs_SOURCE_DIR}/utils/deps_xml.py | 
|  | --file_per_line ${CMAKE_CURRENT_SOURCE_DIR}/${file} | 
|  | WORKING_DIRECTORY ${f4pga-arch-defs_SOURCE_DIR} | 
|  | OUTPUT_VARIABLE INCLUDES | 
|  | ) | 
|  |  | 
|  | string( | 
|  | REPLACE | 
|  | "\n" | 
|  | ";" | 
|  | INCLUDES_LIST | 
|  | "${INCLUDES}" | 
|  | ) | 
|  | foreach(INCLUDE ${INCLUDES_LIST}) | 
|  | string(STRIP ${INCLUDE} INCLUDE) | 
|  | if(NOT "${INCLUDE}" STREQUAL "") | 
|  | get_filename_component( | 
|  | ABS_PATH_TO_INCLUDE | 
|  | ${INCLUDE} | 
|  | ABSOLUTE | 
|  | BASE_DIR | 
|  | ${f4pga-arch-defs_SOURCE_DIR} | 
|  | ) | 
|  | list(APPEND ${var} ${ABS_PATH_TO_INCLUDE}) | 
|  | endif() | 
|  | endforeach() | 
|  | set(${var} "${${var}}" PARENT_SCOPE) | 
|  | endfunction() | 
|  |  | 
|  | function(ADD_FILE_TARGET) | 
|  | # ~~~ | 
|  | # ADD_FILE_TARGET( | 
|  | #   FILE <source file location> | 
|  | #   [GENERATED | SCANNER_TYPE <verilog|xml>] | 
|  | #   [ABSOLUTE] | 
|  | #   ) | 
|  | # ~~~ | 
|  | # | 
|  | # Creates new file target for given source location.  Even if ADD_FILE_TARGET | 
|  | # is being called on a file that is located in the binary directory, always | 
|  | # pass the source location it would have if the source and binary directories | 
|  | # were the same.  This is important for dependency definitions that assume all | 
|  | # inputs are in one folder. | 
|  | # | 
|  | # ADD_FILE_TARGET ensures that all sources are in one folder, because of how | 
|  | # the verilog include directive is defined. | 
|  | # | 
|  | # SCANNER_TYPE argument can be used if GENERATED or ABSOLUTE are not set.  Valid | 
|  | # SCANNER_TYPE are "verilog" and "xml". | 
|  | # ABSOLUTE parameter must be used to mark passed path is absolute | 
|  | # | 
|  | # GENERATED must be passed if the source file is generated and is placed | 
|  | # within the binary directory. | 
|  | set(options GENERATED ABSOLUTE) | 
|  | set(oneValueArgs FILE SCANNER_TYPE) | 
|  | set(multiValueArgs) | 
|  | cmake_parse_arguments( | 
|  | ADD_FILE_TARGET | 
|  | "${options}" | 
|  | "${oneValueArgs}" | 
|  | "${multiValueArgs}" | 
|  | ${ARGN} | 
|  | ) | 
|  |  | 
|  | get_file_target(TARGET_NAME ${ADD_FILE_TARGET_FILE}) | 
|  |  | 
|  | set(INCLUDE_FILES "") | 
|  | if(NOT ${ADD_FILE_TARGET_GENERATED}) | 
|  | if("${ADD_FILE_TARGET_SCANNER_TYPE}" STREQUAL "") | 
|  |  | 
|  | elseif("${ADD_FILE_TARGET_SCANNER_TYPE}" STREQUAL "verilog") | 
|  | get_verilog_includes(INCLUDE_FILES ${ADD_FILE_TARGET_FILE}) | 
|  | elseif("${ADD_FILE_TARGET_SCANNER_TYPE}" STREQUAL "xml") | 
|  | get_xml_includes(INCLUDE_FILES ${ADD_FILE_TARGET_FILE}) | 
|  | else() | 
|  | message( | 
|  | FATAL_ERROR "Unknown SCANNER_TYPE=${ADD_FILE_TARGET_SCANNER_TYPE}." | 
|  | ) | 
|  | endif() | 
|  | endif() | 
|  |  | 
|  | set(INCLUDE_FILES_TARGETS "") | 
|  | foreach(INCLUDE ${INCLUDE_FILES}) | 
|  | append_file_dependency(INCLUDE_FILES_TARGETS ${INCLUDE}) | 
|  | endforeach() | 
|  |  | 
|  | if(NOT ${ADD_FILE_TARGET_GENERATED} AND NOT ${ADD_FILE_TARGET_ABSOLUTE}) | 
|  | get_filename_component(DEST_PATH ${CMAKE_CURRENT_BINARY_DIR}/${ADD_FILE_TARGET_FILE} DIRECTORY) | 
|  | add_custom_command( | 
|  | OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ADD_FILE_TARGET_FILE} | 
|  | COMMAND | 
|  | ${CMAKE_COMMAND} -E make_directory | 
|  | ${DEST_PATH} | 
|  | COMMAND | 
|  | ${CMAKE_COMMAND} -E create_symlink | 
|  | ${CMAKE_CURRENT_SOURCE_DIR}/${ADD_FILE_TARGET_FILE} | 
|  | ${CMAKE_CURRENT_BINARY_DIR}/${ADD_FILE_TARGET_FILE} | 
|  | ) | 
|  | endif() | 
|  |  | 
|  | if(${ADD_FILE_TARGET_ABSOLUTE}) | 
|  | set(FILE_PATH ${ADD_FILE_TARGET_FILE}) | 
|  | else() | 
|  | set(FILE_PATH ${CMAKE_CURRENT_BINARY_DIR}/${ADD_FILE_TARGET_FILE}) | 
|  | endif() | 
|  |  | 
|  | add_custom_target( | 
|  | ${TARGET_NAME} | 
|  | DEPENDS | 
|  | ${FILE_PATH} | 
|  | ${INCLUDE_FILES_TARGETS} | 
|  | ) | 
|  |  | 
|  | set_target_properties( | 
|  | ${TARGET_NAME} | 
|  | PROPERTIES LOCATION ${FILE_PATH} | 
|  | ) | 
|  | set_target_properties(${TARGET_NAME} PROPERTIES INCLUDE_FILES "${INCLUDE_FILES}") | 
|  | set_target_properties(${TARGET_NAME} PROPERTIES INCLUDES "") | 
|  | set_target_properties(${TARGET_NAME} PROPERTIES INCLUDE_FILES "${INCLUDE_FILES}") | 
|  | endfunction(ADD_FILE_TARGET) |