|
| 1 | +.. role:: raw-html(raw) |
| 2 | + :format: html |
| 3 | + |
1 | 4 | Generating Public and Internal headers
|
2 | 5 | ======================================
|
3 | 6 |
|
4 |
| -.. warning:: |
5 |
| - This page is severely out of date. Much of the information it contains may be |
6 |
| - incorrect. Please only remove this warning once the page has been updated. |
7 |
| - |
8 |
| -Other libc implementations make use of preprocessor macro tricks to make header |
9 |
| -files platform agnostic. When macros aren't suitable, they rely on build |
10 |
| -system tricks to pick the right set of files to compile and export. While these |
11 |
| -approaches have served them well, parts of their systems have become extremely |
12 |
| -complicated making it hard to modify, extend or maintain. To avoid these |
13 |
| -problems in llvm-libc, we use a header generation mechanism. The mechanism is |
14 |
| -driven by a *header configuration language*. |
15 |
| - |
16 |
| -Header Configuration Language |
17 |
| ------------------------------ |
18 |
| - |
19 |
| -Header configuration language consists of few special *commands*. The header |
20 |
| -generation mechanism takes an input file, which has an extension of |
21 |
| -``.h.def``, and produces a header file with ``.h`` extension. The header |
22 |
| -configuration language commands are listed in the input ``.h.def`` file. While |
23 |
| -reading a ``.h.def`` file, the header generation tool does two things: |
24 |
| - |
25 |
| -1. Copy the lines not containing commands as is into the output ``.h`` file. |
26 |
| -2. Replace the line on which a command occurs with some other text as directed |
27 |
| - by the command. The replacement text can span multiple lines. |
28 |
| - |
29 |
| -Command syntax |
30 |
| -~~~~~~~~~~~~~~ |
31 |
| - |
32 |
| -A command should be listed on a line by itself, and should not span more than |
33 |
| -one line. The first token to appear on the line is the command name prefixed |
34 |
| -with ``%%``. For example, a line with the ``include_file`` command should start |
35 |
| -with ``%%include_file``. There can be indentation spaces before the ``%%`` |
36 |
| -prefix. |
| 7 | +This is a new implementation of the previous libc header generator. The old |
| 8 | +header generator (libc-hdrgen aka “headergen”) is based on tablegen, which |
| 9 | +creates an awkward dependency on the rest of LLVM for our build system. By |
| 10 | +creating a new standalone headergen we can eliminate these dependencies for |
| 11 | +easier cross compatibility. |
37 | 12 |
|
38 |
| -Most commands typically take arguments. They are listed as a comma separated |
39 |
| -list of named identifiers within parenthesis, similar to the C function call |
40 |
| -syntax. Before performing the action corresponding to the command, the header |
41 |
| -generator replaces the arguments with concrete values. |
| 13 | +There are 3 main components of the new Headergen. The first component are the |
| 14 | +yaml files that contain all the function header information and are separated by |
| 15 | +header specification and standard. The second component are the classes that are |
| 16 | +created for each component of the function header: macros, enumerations, types, |
| 17 | +function, arguments, and objects. The third component is the python script that |
| 18 | +uses the class representation to deserialize yaml files into its specific |
| 19 | +components and then reserializes the components into the function header. The |
| 20 | +python script also combines the generated header content with header definitions |
| 21 | +and extra macro and type inclusions from the .h.def file. |
42 | 22 |
|
43 |
| -Argument Syntax |
44 |
| -~~~~~~~~~~~~~~~ |
45 | 23 |
|
46 |
| -Arguments are named indentifiers but prefixed with ``$`` and enclosed in ``{`` |
47 |
| -and ``}``. For example, ``${path_to_constants}``. |
48 |
| - |
49 |
| -Comments |
50 |
| -~~~~~~~~ |
51 |
| - |
52 |
| -There can be cases wherein one wants to add comments in the .h.def file but |
53 |
| -does not want them to be copied into the generated header file. Such comments |
54 |
| -can be added by beginning the comment lines with the ``<!>`` prefix. Currently, |
55 |
| -comments have to be on lines of their own. That is, they cannot be suffixes like |
56 |
| -this: |
57 |
| - |
58 |
| -``` |
59 |
| -%%include_file(a/b/c) <!> Path to c in b of a. !!! WRONG SYNTAX |
60 |
| -``` |
61 |
| - |
62 |
| -Available Commands |
63 |
| ------------------- |
64 |
| - |
65 |
| -Sub-sections below describe the commands currently available. Under each command |
66 |
| -is the description of the arguments to the command, and the action taken by the |
67 |
| -header generation tool when processing a command. |
| 24 | +Instructions |
| 25 | +----------------------------- |
68 | 26 |
|
69 |
| -``include_file`` |
70 |
| -~~~~~~~~~~~~~~~~ |
| 27 | +Required Versions: |
71 | 28 |
|
72 |
| -This is a replacement command which should be listed in an input ``.h.def`` |
73 |
| -file. |
| 29 | +- Python Version: 3.11.8 [subject to be lower] |
| 30 | +- CMake Version: 3.20.0 |
74 | 31 |
|
75 |
| -Arguments |
| 32 | +1. Make sure to have `LLVM <https://llvm.org/docs/GettingStarted.html>`_ on your |
| 33 | + system. |
| 34 | +2. Make sure you have created a build directory within your LLVM directory. |
| 35 | +3. When generating the necessary files by your build make sure to include: |
| 36 | + ``-DLLVM_LIBC_FULL_BUILD=ON`` within the CMake command since new headergen |
| 37 | + only runs on full-build. |
| 38 | +4. Once the build is complete, enter in the command line within the build |
| 39 | + directory ``ninja check-newhdrgen`` to ensure that the integration tests are |
| 40 | + passing. |
| 41 | +5. Then enter in the command line ``ninja libc`` to generate headers. Headers |
| 42 | + will be in “build/projects/libc/include” or “build/libc/include” in a runtime |
| 43 | + build. Sys spec headers will be located in |
| 44 | + ``build/projects/libc/include/sys``. |
76 | 45 |
|
77 |
| - * **path argument** - An argument representing a path to a file. The file |
78 |
| - should have an extension of ``.h.inc``. |
79 | 46 |
|
80 |
| -Action |
| 47 | +New Headergen is turned on by default, but if you wanted to use old headergen, |
| 48 | +you can include this statement when building: ``-DLIBC_USE_NEW_HEADER_GEN=OFF`` |
81 | 49 |
|
82 |
| - This command instructs that the line on which the command appears should be |
83 |
| - replaced by the contents of the file whose path is passed as argument to the |
84 |
| - command. |
| 50 | +To add a function to the yaml files, you can either manually enter it in the |
| 51 | +yaml file depending on the header spec or enter it through the command line. |
85 | 52 |
|
86 |
| -``begin`` |
87 |
| -~~~~~~~~~ |
| 53 | +To enter through the command line: |
88 | 54 |
|
89 |
| -This is not a replacement command. It is an error to list it in the input |
90 |
| -``.h.def`` file. It is normally listed in the files included by the |
91 |
| -``include_file`` command (the ``.h.inc`` files). A common use of this command it |
92 |
| -mark the beginning of what is to be included. This prevents copying items like |
93 |
| -license headers into the generated header file. |
| 55 | +1. Make sure you are in the llvm-project directory. |
94 | 56 |
|
95 |
| -Arguments |
| 57 | +2. Enter in the command line: |
| 58 | + ``python3 libc/newhdrgen/yaml_to_classes.py |
| 59 | + libc/newhdrgen/yaml/[yaml_file.yaml] --add_function “<return_type>” |
| 60 | + <function_name> “<function_arg1, function_arg2>” <standard> <guard> |
| 61 | + <attribute>`` |
96 | 62 |
|
97 |
| - None. |
| 63 | + Example: |
| 64 | + ``python3 libc/newhdrgen/yaml_to_classes.py |
| 65 | + libc/newhdrgen/yaml/ctype.yaml --add_function “char” example_funtion “int, |
| 66 | + void, const void” stdc example_float example_attribute`` |
| 67 | + |
| 68 | + Keep in mind only the return_type and arguments have quotes around them. If |
| 69 | + you do not have any guards or attributes you may enter “null” for both. |
98 | 70 |
|
99 |
| -Action |
| 71 | +3. Check the yaml file that the added function is present. You will also get a |
| 72 | + generated header file with the new addition in the newhdrgen directory to |
| 73 | + examine. |
100 | 74 |
|
101 |
| - The header generator will only include content starting from the line after the |
102 |
| - line on which this command is listed. |
103 | 75 |
|
104 |
| -``public_api`` |
105 |
| -~~~~~~~~~~~~~~ |
| 76 | +Testing |
| 77 | +----------------------------- |
106 | 78 |
|
107 |
| -This is a replacement command which should be listed in an input ``.h.def`` |
108 |
| -file. The header file generator will replace this command with the public API of |
109 |
| -the target platform. See the build system document for more information on the |
110 |
| -relevant build rules. Also, see "Mechanics of public_api" to learn the mechanics |
111 |
| -of how the header generator replaces this command with the public API. |
| 79 | +New Headergen has an integration test that you may run once you have configured |
| 80 | +your CMake within the build directory. In the command line, enter the following: |
| 81 | +“ninja check -newhdrgen”. The integration test is one test that ensures the |
| 82 | +process of yaml to classes to generate headers works properly. If there are any |
| 83 | +new additions on formatting headers, make sure the test is updated with the |
| 84 | +specific addition. |
112 | 85 |
|
113 |
| -Arguments |
| 86 | +Integration Test can be found in: ``libc/newhdrgen/tests/test_integration.py`` |
114 | 87 |
|
115 |
| - None. |
| 88 | +File to modify if adding something to formatting: |
| 89 | +``libc/newhdrgen/tests/expected_output/test_header.h`` |
116 | 90 |
|
117 |
| -Action |
118 | 91 |
|
119 |
| - The header generator will replace this command with the public API to be exposed |
120 |
| - from the generated header file. |
| 92 | +Common Errors |
| 93 | +----------------------------- |
| 94 | +1. ``"/llvm-project/libc/newhdrgen/yaml_to_classes.py", line 67, in yaml_to_classes function_data["return_type"]`` |
| 95 | + |
| 96 | + If you receive this error or any error pertaining to |
| 97 | + ``function_data[function_specific_component]`` while building the headers that |
| 98 | + means the function specific component is missing within the yaml files. |
| 99 | + Through the call stack, you will be able to find the header file which has the |
| 100 | + issue. Ensure there is no missing function specific component for that yaml |
| 101 | + header file. |
| 102 | + |
| 103 | +2. ``CMake Error at: |
| 104 | + /llvm-project/libc/cmake/modules/LLVMLibCHeaderRules.cmake:86 (message): |
| 105 | + 'add_gen_hdr2' rule requires GEN_HDR to be specified. |
| 106 | + Call Stack (most recent call first): |
| 107 | + /llvm-project/libc/include/CMakeLists.txt:22 (add_gen_header2) |
| 108 | + /llvm-project/libc/include/CMakeLists.txt:62 (add_header_macro)`` |
| 109 | + |
| 110 | + If you receive this error, there is a missing yaml_file, h_def file, or |
| 111 | + header name within the ``libc/include/CMakeLists.txt``. The last line in the |
| 112 | + error call stack will point to the header where there is a specific |
| 113 | + component missing. Ensure the correct style and required files are present: |
| 114 | + |
| 115 | + | ``[header_name]`` |
| 116 | + | ``[../libc/newhdrgen/yaml/[yaml_file.yaml]`` |
| 117 | + | ``[header_name.h.def]`` |
| 118 | + | ``[header_name.h]`` |
| 119 | + | ``DEPENDS`` |
| 120 | + | ``{Necessary Depend Files}`` |
| 121 | +
|
| 122 | +3. ``usage: yaml_to_classes.py [-h] [--output_dir OUTPUT_DIR] |
| 123 | + [--h_def_file H_DEF_FILE] [--add_function RETURN_TYPE NAME ARGUMENTS |
| 124 | + STANDARDS GUARD ATTRIBUTES][--e ENTRY_POINTS] [--export-decls] yaml_file |
| 125 | + yaml_to_classes.py: error: argument --add_function: expected 6 arguments`` |
| 126 | + |
| 127 | + In the process of adding a function, you may run into an issue where the |
| 128 | + command line is requiring more arguments than what you currently have.Ensure that all components of the new function are filled. Even if you do |
| 129 | + not have a guard or attribute, make sure to put null in those two areas. |
| 130 | + |
| 131 | +4. ``File "/llvm-project/libc/newhdrgen/header.py", line 60, in __str__ for function in self.functions: AttributeError: 'HeaderFile' object has no attribute 'functions'`` |
| 132 | + |
| 133 | + When running ninja libc in the build directory to generate headers you may |
| 134 | + receive the error above. Essentially this means that in |
| 135 | + ``libc/newhdrgen/header.py`` there is a missing attribute named functions. |
| 136 | + Make sure all function components are defined within this file and there are |
| 137 | + no missing functions to add these components. |
| 138 | + |
| 139 | +5. ``/llvm-project/build/projects/libc/include/sched.h:20:25: error: unknown type name 'size_t'; did you mean 'time_t'?`` |
| 140 | + :raw-html:`<br />` ``20 | int_sched_getcpucount(size_t, const cpu_set_t*) __NOEXCEPT`` |
| 141 | + :raw-html:`<br />` ``/llvm-project/build/projects/libc/include/llvm-libc-types/time_t.h:15:24: note: 'time_t' declared here`` |
| 142 | + :raw-html:`<br />` ``15 | typedef __INT64_TYPE__ time_t;`` |
| 143 | + |
| 144 | + During the header generation process errors like the one above may occur |
| 145 | + because there are missing types for a specific header file. Check the yaml |
| 146 | + file corresponding to the header file and make sure all the necessary types |
| 147 | + that are being used are input into the types as well. Delete the specific |
| 148 | + header file from the build folder and re-run ninja libc to ensure the types |
| 149 | + are being recognized. |
| 150 | + |
| 151 | +6. Test Integration Errors: Sometimes the integration test will fail but that |
| 152 | + still means the process is working unless the comparison between the output |
| 153 | + and expected_output is not showing. If that is the case make sure in |
| 154 | + ``libc/newhdrgen/tests/test_integration.py`` there are no missing arguments |
| 155 | + that run through the script. |
| 156 | + If the integration tests are failing due to mismatching of lines or small |
| 157 | + errors in spacing that is nothing to worry about. If this is happening |
| 158 | + while you are making a new change to the formatting of the headers, then |
| 159 | + ensure the expected output file ``libc/newhdrgen/tests/expected_output/test_header.h`` |
| 160 | + has the changes you are applying. |
0 commit comments