1function(collect_object_file_deps target result)
2  set(all_deps "")
3  get_target_property(target_type ${target} "TARGET_TYPE")
4  if(NOT target_type)
5    return()
6  endif()
7
8  if(${target_type} STREQUAL ${OBJECT_LIBRARY_TARGET_TYPE})
9    list(APPEND all_deps ${target})
10    get_target_property(deps ${target} "DEPS")
11    foreach(dep IN LISTS deps)
12      collect_object_file_deps(${dep} dep_targets)
13      list(APPEND all_deps ${dep_targets})
14    endforeach(dep)
15    set(${result} ${all_deps} PARENT_SCOPE)
16    return()
17  endif()
18
19  if(${target_type} STREQUAL ${ENTRYPOINT_OBJ_TARGET_TYPE})
20    set(entrypoint_target ${target})
21    get_target_property(is_alias ${entrypoint_target} "IS_ALIAS")
22    if(is_alias)
23      get_target_property(aliasee ${entrypoint_target} "DEPS")
24      if(NOT aliasee)
25        message(FATAL_ERROR
26                "Entrypoint alias ${entrypoint_target} does not have an aliasee.")
27      endif()
28      set(entrypoint_target ${aliasee})
29    endif()
30    list(APPEND all_deps ${entrypoint_target})
31    get_target_property(deps ${target} "DEPS")
32    foreach(dep IN LISTS deps)
33      collect_object_file_deps(${dep} dep_targets)
34      list(APPEND all_deps ${dep_targets})
35    endforeach(dep)
36    set(${result} ${all_deps} PARENT_SCOPE)
37    return()
38  endif()
39
40  if(${target_type} STREQUAL ${ENTRYPOINT_EXT_TARGET_TYPE})
41    # It is not possible to recursively extract deps of external dependencies.
42    # So, we just accumulate the direct dep and return.
43    get_target_property(deps ${target} "DEPS")
44    set(${result} ${deps} PARENT_SCOPE)
45    return()
46  endif()
47endfunction(collect_object_file_deps)
48
49# A rule to build a library from a collection of entrypoint objects.
50# Usage:
51#     add_entrypoint_library(
52#       DEPENDS <list of add_entrypoint_object targets>
53#     )
54#
55# NOTE: If one wants an entrypoint to be available in a library, then they will
56# have to list the entrypoint target explicitly in the DEPENDS list. Implicit
57# entrypoint dependencies will not be added to the library.
58function(add_entrypoint_library target_name)
59  cmake_parse_arguments(
60    "ENTRYPOINT_LIBRARY"
61    "" # No optional arguments
62    "" # No single value arguments
63    "DEPENDS" # Multi-value arguments
64    ${ARGN}
65  )
66  if(NOT ENTRYPOINT_LIBRARY_DEPENDS)
67    message(FATAL_ERROR "'add_entrypoint_library' target requires a DEPENDS list "
68                        "of 'add_entrypoint_object' targets.")
69  endif()
70
71  get_fq_deps_list(fq_deps_list ${ENTRYPOINT_LIBRARY_DEPENDS})
72  set(all_deps "")
73  foreach(dep IN LISTS fq_deps_list)
74    get_target_property(dep_type ${dep} "TARGET_TYPE")
75    if(NOT ((${dep_type} STREQUAL ${ENTRYPOINT_OBJ_TARGET_TYPE}) OR (${dep_type} STREQUAL ${ENTRYPOINT_EXT_TARGET_TYPE})))
76      message(FATAL_ERROR "Dependency '${dep}' of 'add_entrypoint_collection' is "
77                          "not an 'add_entrypoint_object' or 'add_entrypoint_external' target.")
78    endif()
79    collect_object_file_deps(${dep} recursive_deps)
80    list(APPEND all_deps ${recursive_deps})
81  endforeach(dep)
82  list(REMOVE_DUPLICATES all_deps)
83  set(objects "")
84  foreach(dep IN LISTS all_deps)
85    list(APPEND objects $<TARGET_OBJECTS:${dep}>)
86  endforeach(dep)
87
88  add_library(
89    ${target_name}
90    STATIC
91    ${objects}
92  )
93  set_target_properties(${target_name}  PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
94endfunction(add_entrypoint_library)
95
96# Rule to build a shared library of redirector objects.
97function(add_redirector_library target_name)
98  cmake_parse_arguments(
99    "REDIRECTOR_LIBRARY"
100    ""
101    ""
102    "DEPENDS"
103    ${ARGN}
104  )
105
106  set(obj_files "")
107  foreach(dep IN LISTS REDIRECTOR_LIBRARY_DEPENDS)
108    # TODO: Ensure that each dep is actually a add_redirector_object target.
109    list(APPEND obj_files $<TARGET_OBJECTS:${dep}>)
110  endforeach(dep)
111
112  # TODO: Call the linker explicitly instead of calling the compiler driver to
113  # prevent DT_NEEDED on C++ runtime.
114  add_library(
115    ${target_name}
116    EXCLUDE_FROM_ALL
117    SHARED
118    ${obj_files}
119  )
120  set_target_properties(${target_name}  PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
121  target_link_libraries(${target_name}  -nostdlib -lc -lm)
122  set_target_properties(${target_name}  PROPERTIES LINKER_LANGUAGE "C")
123endfunction(add_redirector_library)
124
125set(HDR_LIBRARY_TARGET_TYPE "HDR_LIBRARY")
126
127# Rule to add header only libraries.
128# Usage
129#    add_header_library(
130#      <target name>
131#      HDRS  <list of .h files part of the library>
132#      DEPENDS <list of dependencies>
133#    )
134function(add_header_library target_name)
135  cmake_parse_arguments(
136    "ADD_HEADER"
137    "" # No optional arguments
138    "" # No Single value arguments
139    "HDRS;DEPENDS" # Multi-value arguments
140    ${ARGN}
141  )
142
143  if(NOT ADD_HEADER_HDRS)
144    message(FATAL_ERROR "'add_header_library' target requires a HDRS list of .h files.")
145  endif()
146
147  get_fq_target_name(${target_name} fq_target_name)
148
149  set(FULL_HDR_PATHS "")
150  # TODO: Remove this foreach block when we can switch to the new
151  # version of the CMake policy CMP0076.
152  foreach(hdr IN LISTS ADD_HEADER_HDRS)
153    list(APPEND FULL_HDR_PATHS ${CMAKE_CURRENT_SOURCE_DIR}/${hdr})
154  endforeach()
155
156  set(interface_target_name "${fq_target_name}.__header_library__")
157
158  add_library(${interface_target_name} INTERFACE)
159  target_sources(${interface_target_name} INTERFACE ${FULL_HDR_PATHS})
160  get_fq_deps_list(fq_deps_list ${ADD_HEADER_DEPENDS})
161  if(ADD_HEADER_DEPENDS)
162    add_dependencies(${interface_target_name} ${fq_deps_list})
163  endif()
164
165  add_custom_target(${fq_target_name})
166  add_dependencies(${fq_target_name} ${interface_target_name})
167  set_target_properties(
168    ${fq_target_name}
169    PROPERTIES
170      "TARGET_TYPE" "${HDR_LIBRARY_TARGET_TYPE}"
171      "DEPS" "${fq_deps_list}"
172  )
173endfunction(add_header_library)
174