[libc-commits] [libc] [libc] cmake configruation for newhdrgen (PR #98257)

via libc-commits libc-commits at lists.llvm.org
Tue Jul 9 17:48:10 PDT 2024


https://github.com/aaryanshukla created https://github.com/llvm/llvm-project/pull/98257

- this is a draft to get more input/reviews
- tests have been done on dirent and ctype to see matching results as
  old headergen
- added entrypoints filtering within the script


>From 8502b463b718f7f75faa73b848bd48214525d3e2 Mon Sep 17 00:00:00 2001
From: Aaryan Shukla <aaryanshukla at google.com>
Date: Wed, 10 Jul 2024 00:46:38 +0000
Subject: [PATCH] [libc] cmake configruation for newhdrgen

- this is a draft to get more input/reviews
- tests have been done on dirent and ctype to see matching results as
  old headergen
- added entrypoints filtering within the script
---
 libc/cmake/modules/LLVMLibCHeaderRules.cmake | 87 +++++++++++++++++++-
 libc/include/CMakeLists.txt                  |  7 +-
 libc/newhdrgen/yaml_to_classes.py            | 32 +++++--
 3 files changed, 114 insertions(+), 12 deletions(-)

diff --git a/libc/cmake/modules/LLVMLibCHeaderRules.cmake b/libc/cmake/modules/LLVMLibCHeaderRules.cmake
index 7fc6860f23eb2..51e546b687098 100644
--- a/libc/cmake/modules/LLVMLibCHeaderRules.cmake
+++ b/libc/cmake/modules/LLVMLibCHeaderRules.cmake
@@ -6,6 +6,7 @@
 #       <target name>
 #       HDR <header file>
 #     )
+
 function(add_header target_name)
   cmake_parse_arguments(
     "ADD_HEADER"
@@ -15,7 +16,7 @@ function(add_header target_name)
     ${ARGN}
   )
   if(NOT ADD_HEADER_HDR)
-    message(FATAL_ERROR "'add_header' rules requires the HDR argument specifying a headef file.")
+    message(FATAL_ERROR "'add_header' rules requires the HDR argument specifying a header file.")
   endif()
 
   set(absolute_path ${CMAKE_CURRENT_SOURCE_DIR}/${ADD_HEADER_HDR})
@@ -66,6 +67,90 @@ function(add_header target_name)
   )
 endfunction(add_header)
 
+function(add_yaml_header target_name)
+  cmake_parse_arguments(
+    "ADD_YAML_HDR"
+    "PUBLIC" # No optional arguments
+    "YAML_FILE;DEF_FILE;GEN_HDR" # Single value arguments
+    "DEPENDS"     # Multi value arguments
+    ${ARGN}
+  )
+  get_fq_target_name(${target_name} fq_target_name)
+  if(NOT LLVM_LIBC_FULL_BUILD)
+    # We don't want to use generated headers if we are doing a non-full-build.
+    add_library(${fq_target_name} INTERFACE)
+    return()
+  endif()
+  if(NOT ADD_YAML_HDR_DEF_FILE)
+    message(FATAL_ERROR "`add_yaml_hdr` rule requires DEF_FILE to be specified.")
+  endif()
+  if(NOT ADD_YAML_HDR_GEN_HDR)
+    message(FATAL_ERROR "`add_yaml_hdr` rule requires GEN_HDR to be specified.")
+  endif()
+  if(NOT ADD_YAML_HDR_YAML_FILE)
+    message(FATAL_ERROR "`add_yaml_hdr` rule requires YAML_FILE to be specified.")
+  endif()
+
+  set(absolute_path ${CMAKE_CURRENT_SOURCE_DIR}/${ADD_YAML_HDR_GEN_HDR})
+  file(RELATIVE_PATH relative_path ${LIBC_INCLUDE_SOURCE_DIR} ${absolute_path})
+  set(out_file ${LIBC_INCLUDE_DIR}/${relative_path})
+  set(yaml_file ${CMAKE_SOURCE_DIR}/${ADD_YAML_HDR_YAML_FILE})
+  set(def_file ${CMAKE_CURRENT_SOURCE_DIR}/${ADD_YAML_HDR_DEF_FILE})
+
+  set(fq_data_files "")
+  if(ADD_YAML_HDR_DATA_FILES)
+    foreach(data_file IN LISTS ADD_YAML_HDR_DATA_FILES)
+      list(APPEND fq_data_files "${CMAKE_CURRENT_SOURCE_DIR}/${data_file}")
+    endforeach(data_file)
+  endif()
+
+  set(entry_points "${TARGET_ENTRYPOINT_NAME_LIST}")
+  list(TRANSFORM entry_points PREPEND "--e=")
+
+  add_custom_command(
+    OUTPUT ${out_file}
+    COMMAND ${Python3_EXECUTABLE} ${LIBC_SOURCE_DIR}/newhdrgen/yaml_to_classes.py
+            ${yaml_file}
+            ${def_file}
+            ${entry_points}
+            --output_dir ${CMAKE_CURRENT_BINARY_DIR}
+    DEPENDS ${yaml_file} ${def_file} ${fq_data_files}
+    COMMENT "Generating header ${ADD_YAML_HDR_GEN_HDR} from ${yaml_file} and ${def_file}"
+  )
+
+  if(ADD_YAML_HDR_DEPENDS)
+    get_fq_deps_list(fq_deps_list ${ADD_YAML_HDR_DEPENDS})
+    # Dependencies of a add_header target can only be another add_gen_header target
+    # or an add_header target.
+    foreach(dep IN LISTS fq_deps_list)
+      get_target_property(header_file ${dep} HEADER_FILE_PATH)
+      if(NOT header_file)
+        message(FATAL_ERROR "Invalid dependency '${dep}' for '${fq_target_name}'.")
+      endif()
+    endforeach()
+  endif()
+  set(generated_hdr_target ${fq_target_name}.__generated_hdr__)
+  add_custom_target(
+    ${generated_hdr_target}
+    DEPENDS ${out_file} ${fq_deps_list}
+  )
+
+  add_header_library(
+    ${target_name}
+    HDRS
+      ${out_file}
+  )
+
+  add_dependencies(${fq_target_name} ${generated_hdr_target})
+
+  set_target_properties(
+    ${fq_target_name}
+    PROPERTIES
+      HEADER_FILE_PATH ${out_file}
+      DEPS "${fq_deps_list}"
+  )
+endfunction(add_yaml_header)
+
 # A rule for generated header file targets.
 # Usage:
 #     add_gen_header(
diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index f8ef35078a8c4..6f4cb9e1ba1d5 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -3,6 +3,7 @@ set(LIBC_INCLUDE_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
 
 include(LLVMLibCHeaderRules)
 
+
 # The GPU build wants to install files in the compiler's resource directory.
 if(LIBC_TARGET_OS_IS_GPU)
   include(GetClangResourceDir)
@@ -17,16 +18,18 @@ add_header(
     __llvm-libc-common.h
 )
 
-add_gen_header(
+add_yaml_header(
   ctype
+  YAML_FILE ../libc/newhdrgen/yaml/ctype.yaml
   DEF_FILE ctype.h.def
   GEN_HDR ctype.h
   DEPENDS
     .llvm_libc_common_h
 )
 
-add_gen_header(
+add_yaml_header(
   dirent
+  YAML_FILE ../libc/newhdrgen/yaml/dirent.yaml
   DEF_FILE dirent.h.def
   GEN_HDR dirent.h
   DEPENDS
diff --git a/libc/newhdrgen/yaml_to_classes.py b/libc/newhdrgen/yaml_to_classes.py
index 9e0337f4a308e..ee2abec4fdc11 100644
--- a/libc/newhdrgen/yaml_to_classes.py
+++ b/libc/newhdrgen/yaml_to_classes.py
@@ -11,7 +11,6 @@
 
 import yaml
 import argparse
-
 from pathlib import Path
 from header import HeaderFile
 from class_implementation.classes.macro import Macro
@@ -22,12 +21,13 @@
 from class_implementation.classes.object import Object
 
 
-def yaml_to_classes(yaml_data):
+def yaml_to_classes(yaml_data, entry_points=None):
     """
-    Convert YAML data to header classes.
+    Convert YAML data to header classes, filtering functions by entry points.
 
     Args:
         yaml_data: The YAML data containing header specifications.
+        entry_points: A list of entry points to filter functions.
 
     Returns:
         HeaderFile: An instance of HeaderFile populated with the data.
@@ -47,6 +47,9 @@ def yaml_to_classes(yaml_data):
         )
 
     functions = yaml_data.get("functions", [])
+    if entry_points:
+        entry_points_set = set(entry_points)
+        functions = [f for f in functions if f["name"] in entry_points_set]
     sorted_functions = sorted(functions, key=lambda x: x["name"])
     for function_data in sorted_functions:
         arguments = [arg["type"] for arg in function_data["arguments"]]
@@ -75,19 +78,20 @@ def yaml_to_classes(yaml_data):
     return header
 
 
-def load_yaml_file(yaml_file):
+def load_yaml_file(yaml_file, entry_points):
     """
-    Load YAML file and convert it to header classes.
+    Load YAML file and convert it to header classes, filtering by entry points.
 
     Args:
         yaml_file: The path to the YAML file.
+        entry_points: A list of entry points to filter functions.
 
     Returns:
         HeaderFile: An instance of HeaderFile populated with the data from the YAML file.
     """
     with open(yaml_file, "r") as f:
         yaml_data = yaml.safe_load(f)
-    return yaml_to_classes(yaml_data)
+    return yaml_to_classes(yaml_data, entry_points)
 
 
 def fill_public_api(header_str, h_def_content):
@@ -177,7 +181,7 @@ def increase_indent(self, flow=False, indentless=False):
     print(f"Added function {new_function.name} to {yaml_file}")
 
 
-def main(yaml_file, h_def_file, output_dir, add_function=None):
+def main(yaml_file, h_def_file, output_dir, add_function=None, entry_points=None):
     """
     Main function to generate header files from YAML and .h.def templates.
 
@@ -186,12 +190,13 @@ def main(yaml_file, h_def_file, output_dir, add_function=None):
         h_def_file: Path to the .h.def template file.
         output_dir: Directory to output the generated header file.
         add_function: Details of the function to be added to the YAML file (if any).
+        entry_points: A list of entry points to filter functions.
     """
 
     if add_function:
         add_function_to_yaml(yaml_file, add_function)
 
-    header = load_yaml_file(yaml_file)
+    header = load_yaml_file(yaml_file, entry_points)
 
     with open(h_def_file, "r") as f:
         h_def_content = f.read()
@@ -234,6 +239,15 @@ def main(yaml_file, h_def_file, output_dir, add_function=None):
         ),
         help="Add a function to the YAML file",
     )
+    parser.add_argument(
+        "--e", action="append", help="Entry point to include", dest="entry_points"
+    )
     args = parser.parse_args()
 
-    main(args.yaml_file, args.h_def_file, args.output_dir, args.add_function)
+    main(
+        args.yaml_file,
+        args.h_def_file,
+        args.output_dir,
+        args.add_function,
+        args.entry_points,
+    )



More information about the libc-commits mailing list