Moved to modular java build system.
[panamaz] / README
1
2 Introduction
3 ------------
4
5 This is various experiments with the panama-foreign abi JEP for
6 invoking native C functions from Java directly and without JNI.
7
8 The main goal is to experiment with creating a "java friendly" and
9 mostly type-safe api directly in one step, without requiring
10 additional wrapping.
11
12 It uses a gcc plugin to compile c headers to obtain most of the api
13 information, but requires cpp and perl to extract the values of
14 #define constants as they are not available to the gcc plugin.
15
16 This api information is then converted to Java code using a
17 config-directed perl script `export-api'.  The config file can be used
18 to create static (all-in-one) or object oriented output.  It includes
19 templated strings as well as perl fragments to generate various source
20 parts.
21
22 The vulkan api is officially defined by a registry in xml, so there's
23 a separate generator for that.
24
25 Compile
26 -------
27
28 Requirements are gcc and GNU cpp, perl, GNU make, and of course a
29 compatible jdk-foreign jdk.  The various modules require headers or
30 sdks for their corresponding libraries, e.g. ffmpeg-5.x,
31 vulkan-tools-1.2.x.
32
33 Copy config.make.in to config.make and modify any variables required.
34
35 Parallel make should work.
36
37 Build all:
38
39 $ make -j
40
41 Build one module:
42
43 $ make notzed.nativez
44
45 Run a demo (see next section):
46
47 $ make run-notzed.vkregistry/vulkan.test.TestVulkan
48
49 A non-recursive make setup is used although make file fragments are
50 included from various locations across the modules.  All java is
51 compiled as modules.
52
53 JAVA_HOME must point to a compatible panama-enabled jdk.
54
55 The latest at the time of writing was:
56
57  branch: foreign-jextract
58  commit: 2e1291680024f12fbf2f0f02b0f79d7b4348b369
59  date: Fri Feb 4 11:01:21 2022 +0000
60
61 All output and intermediate files are in bin/
62
63 bin/modules/<module>/classes - compiled java modules
64 bin/gen/<module>/classes - generated java
65 bin/gen/<module>/gen - generated intermediate non-java
66
67 These are more or less an exploded view of all jmod files:
68
69 bin/<target>/bin - commands for all modules
70 bin/<target>/lib - libraries/config and modular jar files for all modules
71 bin/<target>/include - header files for all modules
72
73 Finally:
74
75 bin/<target>/jmods - .jmod modules
76
77
78 Demos
79 -----
80
81 Most examples have a demo, see the <module>_JMAIN variables in the
82 Makefile for the targets.  They are executed using:
83
84 $ make run-<module>/<main-class>
85
86 Modules
87 --------
88
89 notzed.nativez contains some support classes and the code generator.
90 The gcc plugin source is in src/notzed.nativez/native/ the code
91 generator is in src/notzed.nativez/{bin,lib}.
92
93 notzed.api is a pseudo-module containing a simple test c api for
94 experiments, it just builds into a library.
95
96 notzed.apistatic is a 'all in one class' static wrapper for
97 notzed.api.
98
99 notzed.apiobject is an object-oriented wrapper for notzed.api.
100
101 notzed.clstatic is an 'all in one class' static wrapper for OpenCL
102 (2.1).  The api closesly matches the C api except it converts error
103 codes into exceptins and can infer certain arguments from others such
104 as length parameters.  This is probably the most complete api.
105
106 notzed.ffmpeg is a partial object-oriented mapping for ffmpeg-5.0 that
107 closely follows the jjmpeg design.  It's enough to read video frames.
108 The demo requires a file 'movie.api' in the root directory to run.
109
110 notzed.vkheader uses the header-based generator on the vulkan
111 installed headers.  This is still very incomplete work in progress.
112 Much meta-data is lost such as which functions are extensions during
113 the generation of the headers.
114
115 notzed.vkregistry uses a completely different generator which directly
116 parses the official xml registry specification for vulkan
117 (/usr/share/vulkan/registry/vk.xml).  This is directly converted to
118 about-as-java-friendly a vulkan api as one can hope for, particularly
119 the constructors for all the config objects.
120
121 Export process
122 --------------
123
124 The main generator is written in perl and lives in
125 src/notzed.nativez/{bin,lib}.
126
127 The process:
128
129 * run the gcc plugin to extract all of the available c structures from
130   gcc and save them to a perl hash.
131
132   gcc plugins aren't very well documented so it was a lot of trial and
133   error to get it to output all the type information even starting
134   with a partial example.  The names of parameters for function calls
135   were particularly problematic.
136
137 * optionally run export-defines to extract #define constants.  They
138   can be grouped/excluded by name or by the filename they belong to.
139   The the first rule to match will complete the processing for a given
140   type.
141
142   This is also a surprisingly difficult process because the c
143   pre-processor can just generate arbitrary c expressions so the only
144   way to find their correct value is to execute the c.  So the export
145   script generates a c file which is compiled and executed to generate
146   the perl definitions.
147
148   Currently the types are mapped to a 'compatible' native type by
149   using the gcc operators __builtin_choose_expr,
150   __builtin_types_compatible_p, and typeof to implement a
151   pseudo-function overloading in c - possiblly using c++ is a better
152   choice here.  For now inclusions or exclusions are required to
153   avoid problematic definitions that confuse these operators.
154
155 These files are then fed to generate-api.  It proceeds in multiple
156 stages.
157
158 First stages are handled by lib/api.pm.
159
160 * Load and preprocess the api definition.
161
162  - Perform a bunch of 'fix up' processing on the data structures such
163    as inserting anonymous types which are not generated by the plugin.
164
165  - Create a full dependency tree for the objects
166    specificallyreferenced by the api definition so only objects and
167    functions of interest are included.
168
169  - Resolve all the various export options using some rules and store
170    the information about the selected options onto target objects.
171
172 Then generate-api produces the java files from a combination of the
173 processed data definitions and the api definition.
174
175 * Export 'libraries'.  These are static classes of functions and/or
176   constants.
177
178  - Can include static methods.  Methods can have per-method template
179    overrides.
180
181  - Can include constants.
182
183 * Export 'structures'.  These represent C pointers.
184
185  - struct/union have a MemorySegment, a layout, and potentially
186    accessors for fields.
187
188  - anonymous structures just have a MemoryAddress and no accessors.
189
190  - Can include static and member methods.  Methods can have per-method
191    template overrides.
192
193  - Can include constants.
194
195 * Export 'calls'.  These are function interfaces for function pointers.
196
197  - The interface is the java form of the call.
198
199  - If available a typedef name is used, otherwise the names are mapped
200    to a mangled name of the form Call_<args>_<return>.
201
202  - An upcall factory creates an upcall to an instance of a hidden
203    trampline interface which performs the mapping of arguments to java
204    and returns to c.
205
206  - A downcall factory creates a downcall which maps the java call to
207    native and back.
208
209  - Both factories return a record of type FunctionPointer<type> which
210    contains both a NativeSymbol and the java interface instance so they
211    can be used from either environment.
212
213 * Export 'constants'.  These are referenced enums or any defines which
214   haven't been included in any other library or struct.
215
216  - enums are mapped to an interface with fields of:
217      'static final int FOO = xx'
218    of
219      'static final long FOO = xx'
220
221  - defines are mapped to a matching native type which includes
222    floating point types and strings in addition to all the integral
223    types.
224
225 lib/code.pm is used to generate some of the code and handle
226 templating. Common code templates are defined in lib/code.api but can
227 be extended or replaced by a given api file.
228
229 lib/method.pm is used to generate per-field (struct) and per-argument
230 (function) sub-templates for mapping c to and from java.  The
231 sub-templates it uses are defined in lib/types.api but again they can
232 be extended or replaced by a given api file.
233
234 Status
235 ------
236
237 It's all very much work in progress and due to the constant changes in
238 panama will be in flux for some time.
239
240 * bitfields are implemented.
241 * varargs is not implemented.
242 * the generator for notzed.vkregistry uses a lot of miserable
243   write-once perl.
244 * the scope and object lifecycle stuff is not really sorted out yet.
245 * the config format and features are still being fiddled with.
246 * the config file isn't really documented.
247 * the build system is still being fiddled with, some of the output
248   directories are mixed up.
249 * linux-amd64 only at this point in time.
250
251 License
252 -------
253
254 GNU General Public License, version 3 or later, but see individual
255 file headers for specifics.
256
257 Links
258 -----
259
260  * https://www.zedzone/software/panamaz.html - project page.
261  * https://openjdk.java.net/projects/panama - openjdk panama page.
262  * https://github.com/openjdk/panama-foreign - openjdk panama source.