xref: /llvm-project/libc/cmake/modules/LLVMLibCHeaderRules.cmake (revision 5e4b41c1d534c90a4591b840a4f1b2f7bf59279f)
1# A rule for self contained header file targets.
2# This rule merely copies the header file from the current source directory to
3# the current binary directory.
4# Usage:
5#     add_header(
6#       <target name>
7#       HDR <header file>
8#     )
9function(add_header target_name)
10  cmake_parse_arguments(
11    "ADD_HEADER"
12    ""             # No optional arguments
13    "HDR;DEST_HDR" # Single value arguments
14    "DEPENDS"
15    ${ARGN}
16  )
17  if(NOT ADD_HEADER_HDR)
18    message(FATAL_ERROR "'add_header' rules requires the HDR argument specifying a headef file.")
19  endif()
20
21  if(ADD_HEADER_DEST_HDR)
22    set(dest_leaf_filename ${ADD_HEADER_DEST_HDR})
23  else()
24    set(dest_leaf_filename ${ADD_HEADER_HDR})
25  endif()
26  set(absolute_path ${CMAKE_CURRENT_SOURCE_DIR}/${dest_leaf_filename})
27  file(RELATIVE_PATH relative_path ${LIBC_INCLUDE_SOURCE_DIR} ${absolute_path})
28  set(dest_file ${LIBC_INCLUDE_DIR}/${relative_path})
29  set(src_file ${CMAKE_CURRENT_SOURCE_DIR}/${ADD_HEADER_HDR})
30
31  add_custom_command(
32    OUTPUT ${dest_file}
33    COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src_file} ${dest_file}
34    DEPENDS ${src_file}
35  )
36
37  get_fq_target_name(${target_name} fq_target_name)
38  set(copied_hdr_target ${fq_target_name}.__copied_hdr__)
39  add_custom_target(
40    ${copied_hdr_target}
41    DEPENDS ${dest_file}
42  )
43
44  if(ADD_HEADER_DEPENDS)
45    get_fq_deps_list(fq_deps_list ${ADD_HEADER_DEPENDS})
46    # Dependencies of a add_header target can only be another add_header target
47    # or an add_gen_header target.
48    foreach(dep IN LISTS fq_deps_list)
49      get_target_property(header_file ${dep} HEADER_FILE_PATH)
50      if(NOT header_file)
51        message(FATAL_ERROR "Invalid dependency '${dep}' for '${fq_target_name}'.")
52      endif()
53    endforeach()
54    add_dependencies(
55      ${copied_hdr_target} ${fq_deps_list}
56    )
57  endif()
58
59  add_header_library(
60    ${target_name}
61    HDRS
62      ${dest_file}
63    DEPENDS
64      ${copied_hdr_target}
65  )
66  set_target_properties(
67    ${fq_target_name}
68    PROPERTIES
69      HEADER_NAME ${dest_leaf_filename}
70      HEADER_FILE_PATH ${dest_file}
71      DEPS "${fq_deps_list}"
72  )
73endfunction(add_header)
74
75function(add_gen_header target_name)
76  cmake_parse_arguments(
77    "ADD_GEN_HDR"
78    "PUBLIC" # No optional arguments
79    "YAML_FILE;GEN_HDR" # Single value arguments
80    "DEPENDS"     # Multi value arguments
81    ${ARGN}
82  )
83  get_fq_target_name(${target_name} fq_target_name)
84  if(NOT LLVM_LIBC_FULL_BUILD)
85    add_library(${fq_target_name} INTERFACE)
86    return()
87  endif()
88  if(NOT ADD_GEN_HDR_GEN_HDR)
89    message(FATAL_ERROR "`add_gen_hdr` rule requires GEN_HDR to be specified.")
90  endif()
91  if(NOT ADD_GEN_HDR_YAML_FILE)
92    message(FATAL_ERROR "`add_gen_hdr` rule requires YAML_FILE to be specified.")
93  endif()
94
95  set(absolute_path ${CMAKE_CURRENT_SOURCE_DIR}/${ADD_GEN_HDR_GEN_HDR})
96  file(RELATIVE_PATH relative_path ${LIBC_INCLUDE_SOURCE_DIR} ${absolute_path})
97  set(out_file ${LIBC_INCLUDE_DIR}/${relative_path})
98  set(dep_file "${out_file}.d")
99  set(yaml_file ${CMAKE_SOURCE_DIR}/${ADD_GEN_HDR_YAML_FILE})
100
101  set(fq_data_files "")
102  if(ADD_GEN_HDR_DATA_FILES)
103    foreach(data_file IN LISTS ADD_GEN_HDR_DATA_FILES)
104      list(APPEND fq_data_files "${CMAKE_CURRENT_SOURCE_DIR}/${data_file}")
105    endforeach(data_file)
106  endif()
107
108  set(entry_points "${TARGET_ENTRYPOINT_NAME_LIST}")
109  list(TRANSFORM entry_points PREPEND "--entry-point=")
110
111  add_custom_command(
112    OUTPUT ${out_file}
113    WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
114    COMMAND ${Python3_EXECUTABLE} "${LIBC_SOURCE_DIR}/utils/hdrgen/main.py"
115            --output ${out_file}
116            --depfile ${dep_file}
117            --write-if-changed
118            ${entry_points}
119            ${yaml_file}
120    DEPENDS ${yaml_file} ${fq_data_files}
121    DEPFILE ${dep_file}
122    COMMENT "Generating header ${ADD_GEN_HDR_GEN_HDR} from ${yaml_file}"
123  )
124  if(LIBC_TARGET_OS_IS_GPU)
125    file(MAKE_DIRECTORY ${LIBC_INCLUDE_DIR}/llvm-libc-decls)
126    file(MAKE_DIRECTORY ${LIBC_INCLUDE_DIR}/llvm-libc-decls/gpu)
127    set(decl_out_file ${LIBC_INCLUDE_DIR}/llvm-libc-decls/${relative_path})
128    add_custom_command(
129      OUTPUT ${decl_out_file}
130      COMMAND ${Python3_EXECUTABLE} "${LIBC_SOURCE_DIR}/utils/hdrgen/yaml_to_classes.py"
131              ${yaml_file}
132              --export-decls
133              ${entry_points}
134              --output_dir ${decl_out_file}
135      WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
136      DEPENDS ${yaml_file} ${fq_data_files}
137    )
138  endif()
139
140  if(ADD_GEN_HDR_DEPENDS)
141    get_fq_deps_list(fq_deps_list ${ADD_GEN_HDR_DEPENDS})
142    # Dependencies of a add_header target can only be another add_gen_header target
143    # or an add_header target.
144    foreach(dep IN LISTS fq_deps_list)
145      get_target_property(header_file ${dep} HEADER_FILE_PATH)
146      if(NOT header_file)
147        message(FATAL_ERROR "Invalid dependency '${dep}' for '${fq_target_name}'.")
148      endif()
149    endforeach()
150  endif()
151  set(generated_hdr_target ${fq_target_name}.__generated_hdr__)
152  add_custom_target(
153    ${generated_hdr_target}
154    DEPENDS ${out_file} ${fq_deps_list} ${decl_out_file}
155  )
156
157  add_header_library(
158    ${target_name}
159    HDRS
160      ${out_file}
161  )
162
163  add_dependencies(${fq_target_name} ${generated_hdr_target})
164
165  set_target_properties(
166    ${fq_target_name}
167    PROPERTIES
168      HEADER_NAME ${ADD_GEN_HDR_GEN_HDR}
169      HEADER_FILE_PATH ${out_file}
170      DECLS_FILE_PATH "${decl_out_file}"
171      DEPS "${fq_deps_list}"
172  )
173
174
175endfunction(add_gen_header)
176