# Copyright 2019 The IREE Authors
#
# Licensed under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

# external_cc_library()
#
# CMake function to imitate Bazel's cc_library rule.
# This is used for external libraries (from third_party, etc) that don't live
# in the IREE namespace.
#
# Parameters:
# PACKAGE: Name of the package (overrides actual path)
# NAME: Name of target (see Note)
# ROOT: Path to the source root where files are found
# HDRS: List of public header files for the library
# SRCS: List of source files for the library
# DATA: List of other targets and files required for this binary
# DEPS: List of other libraries to be linked in to the binary targets
# COPTS: List of private compile options
# DEFINES: List of public defines
# INCLUDES: Include directories to add to dependencies
# SYSTEM_INCLUDES: Include directories that should be used with "SYSTEM" scope,
#   which makes them more tolerant to certain classes of warnings and issues.
# LINKOPTS: List of link options
# PUBLIC: Add this so that this library will be exported under ${PACKAGE}::
# Also in IDE, target will appear in ${PACKAGE} folder while non PUBLIC will be
# in ${PACKAGE}/internal.
# TESTONLY: When added, this target will only be built if user passes
#    -DIREE_BUILD_TESTS=ON to CMake.
#
# Note:
# By default, external_cc_library will always create a library named
# ${PACKAGE}_${NAME}, and alias target ${PACKAGE}::${NAME}. The ${PACKAGE}::
# form should always be used. This is to reduce namespace pollution.
#
# external_cc_library(
#   PACKAGE
#     some_external_thing
#   NAME
#     awesome
#   ROOT
#     "third_party/foo"
#   HDRS
#     "a.h"
#   SRCS
#     "a.cc"
# )
# external_cc_library(
#   PACKAGE
#     some_external_thing
#   NAME
#     fantastic_lib
#   ROOT
#     "third_party/foo"
#   SRCS
#     "b.cc"
#   DEPS
#     some_external_thing::awesome # not "awesome" !
#   PUBLIC
# )
#
# iree_cc_library(
#   NAME
#     main_lib
#   ...
#   DEPS
#     some_external_thing::fantastic_lib
# )
function(external_cc_library)
  cmake_parse_arguments(_RULE
    "PUBLIC;TESTONLY"
    "PACKAGE;NAME;ROOT"
    "HDRS;SRCS;COPTS;DEFINES;LINKOPTS;DATA;DEPS;INCLUDES;SYSTEM_INCLUDES"
    ${ARGN}
  )

  if(_RULE_TESTONLY AND NOT IREE_BUILD_TESTS)
    return()
  endif()

  # Prefix the library with the package name.
  string(REPLACE "::" "_" _PACKAGE_NAME ${_RULE_PACKAGE})
  set(_NAME "${_PACKAGE_NAME}_${_RULE_NAME}")

  # Wrap user specified INCLUDES in the $<BUILD_INTERFACE:>
  # generator.
  list(TRANSFORM _RULE_INCLUDES PREPEND "$<BUILD_INTERFACE:")
  list(TRANSFORM _RULE_INCLUDES APPEND ">")
  list(TRANSFORM _RULE_SYSTEM_INCLUDES PREPEND "$<BUILD_INTERFACE:")
  list(TRANSFORM _RULE_SYSTEM_INCLUDES APPEND ">")

  # Prefix paths with the root.
  list(TRANSFORM _RULE_HDRS PREPEND ${_RULE_ROOT})
  list(TRANSFORM _RULE_SRCS PREPEND ${_RULE_ROOT})

  # Check if this is a header-only library.
  # Note that as of February 2019, many popular OS's (for example, Ubuntu
  # 16.04 LTS) only come with cmake 3.5 by default.  For this reason, we can't
  # use list(FILTER...)
  set(_CC_SRCS "${_RULE_SRCS}")
  foreach(_SRC_FILE IN LISTS _CC_SRCS)
    if(${_SRC_FILE} MATCHES ".*\\.(h|inc)$")
      list(REMOVE_ITEM _CC_SRCS "${_SRC_FILE}")
    endif()
  endforeach()
  if("${_CC_SRCS}" STREQUAL "")
    set(_RULE_IS_INTERFACE 1)
  else()
    set(_RULE_IS_INTERFACE 0)
  endif()

  if(NOT _RULE_IS_INTERFACE)
    add_library(${_NAME} STATIC "")
    target_sources(${_NAME}
      PRIVATE
        ${_RULE_SRCS}
        ${_RULE_HDRS}
    )
    target_include_directories(${_NAME}
      PUBLIC
        "$<BUILD_INTERFACE:${IREE_SOURCE_DIR}>"
        "$<BUILD_INTERFACE:${IREE_BINARY_DIR}>"
        ${_RULE_INCLUDES}
    )
    target_include_directories(${_NAME}
      SYSTEM PUBLIC
        ${_RULE_SYSTEM_INCLUDES}
    )
    target_compile_options(${_NAME}
      PRIVATE
        ${_RULE_COPTS}
        ${IREE_DEFAULT_COPTS}
      INTERFACE
        ${IREE_INTERFACE_COPTS}
    )
    target_link_options(${_NAME}
      PRIVATE
        ${IREE_DEFAULT_LINKOPTS}
        ${_RULE_LINKOPTS}
    )
    target_link_libraries(${_NAME}
      PUBLIC
        ${_RULE_DEPS}
    )
    target_compile_definitions(${_NAME}
      PUBLIC
        ${_RULE_DEFINES}
    )
    iree_add_data_dependencies(NAME ${_NAME} DATA ${_RULE_DATA})

    # Add all external targets to a a folder in the IDE for organization.
    if(_RULE_PUBLIC)
      set_property(TARGET ${_NAME} PROPERTY FOLDER third_party)
    elseif(_RULE_TESTONLY)
      set_property(TARGET ${_NAME} PROPERTY FOLDER third_party/test)
    else()
      set_property(TARGET ${_NAME} PROPERTY FOLDER third_party/internal)
    endif()

    # INTERFACE libraries can't have the CXX_STANDARD property set
    set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD ${IREE_CXX_STANDARD})
    set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
  else()
    # Generating header-only library
    add_library(${_NAME} INTERFACE)
    target_include_directories(${_NAME}
      INTERFACE
        "$<BUILD_INTERFACE:${IREE_SOURCE_DIR}>"
        "$<BUILD_INTERFACE:${IREE_BINARY_DIR}>"
    )
    foreach(_include ${_RULE_INCLUDES})
      target_include_directories(${_NAME}
        INTERFACE
          "$<BUILD_INTERFACE:${_include}>"
      )
    endforeach()
    foreach(_include ${_RULE_SYSTEM_INCLUDES})
      target_include_directories(${_NAME}
        SYSTEM INTERFACE
          "$<BUILD_INTERFACE:${_include}>"
      )
    endforeach()
    target_link_libraries(${_NAME}
      INTERFACE
        ${_RULE_DEPS}
    )
    iree_add_data_dependencies(NAME ${_NAME} DATA ${_RULE_DATA})
    target_compile_definitions(${_NAME}
      INTERFACE
        ${_RULE_DEFINES}
    )
  endif()

  iree_install_targets(
    TARGETS ${_NAME}
    HDRS ${_RULE_HDRS}
  )

  iree_add_alias_library(${_RULE_PACKAGE}::${_RULE_NAME} ${_NAME})
  # If the library name matches the final component of the package then treat it
  # as a default. For example, 'foo::bar' library 'bar' would end up as
  # 'foo::bar'.
  string(REGEX REPLACE "^.*::" "" _PACKAGE_DIR ${_RULE_PACKAGE})
  if(${_PACKAGE_DIR} STREQUAL ${_RULE_NAME})
    iree_add_alias_library(${_RULE_PACKAGE} ${_NAME})
  endif()
endfunction()
