blob: 668160aeadbe962f006ad5b24c8ff3fe53a073ac [file] [log] [blame] [view]
estevensonc0b135ff2016-11-17 16:03:511# Accessing C++ Enums In Java
2
3[TOC]
4
5## Introduction
6
7Accessing C++ enums in Java is implemented via a Python script which analyzes
8the C++ enum and spits out the corresponding Java class. The enum needs to be
9annotated in a particular way. By default, the generated class name will be the
10same as the name of the enum. If all the names of the enum values are prefixed
11with the MACRO\_CASED\_ name of the enum those prefixes will be stripped from
12the Java version.
13
14## Features
15* Customize the package name of the generated class using the
16`GENERATED_JAVA_ENUM_PACKAGE` directive (required)
17* Customize the class name using the `GENERATED_JAVA_CLASS_NAME_OVERRIDE`
18directive (optional)
19* Strip enum entry prefixes to make the generated classes less verbose using
20the `GENERATED_JAVA_PREFIX_TO_STRIP` directive (optional)
Nate Fischerbce817152021-07-14 02:14:1521* Follows best practices by using
22[IntDef Instead of Enum](/styleguide/java/java.md#IntDef-Instead-of-Enum)
Keigo Okac5174602024-11-19 15:55:1923* Generate the `flag` attribute using the `GENERATED_JAVA_IS_FLAG` directive (optional)
qyearsleyc0dc6f42016-12-02 22:13:3924* Copies comments that directly precede enum entries into the generated Java
estevensonc0b135ff2016-11-17 16:03:5125class
26
27## Usage
28
Nate Fischerbce817152021-07-14 02:14:15291. Add directives to your C++ enum. Only the `GENERATED_JAVA_ENUM_PACKAGE`
30 directive is required:
estevensonc0b135ff2016-11-17 16:03:5131
32 ```cpp
33 // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome
34 // GENERATED_JAVA_CLASS_NAME_OVERRIDE: FooBar
35 // GENERATED_JAVA_PREFIX_TO_STRIP: BAR_
Keigo Okac5174602024-11-19 15:55:1936 // GENERATED_JAVA_IS_FLAG: true
estevensonc0b135ff2016-11-17 16:03:5137 enum SomeEnum {
Keigo Okac5174602024-11-19 15:55:1938 BAR_A = 1 << 0,
39 BAR_B = 1 << 1,
estevensonc0b135ff2016-11-17 16:03:5140 BAR_C = BAR_B,
41 };
42 ```
43
Nate Fischerbce817152021-07-14 02:14:15442. Add a new build target and add it to the `srcjar_deps` of an
45 `android_library` target:
estevensonc0b135ff2016-11-17 16:03:5146
Nate Fischer93c59152019-02-05 01:25:0847 ```gn
Nate Fischerbce817152021-07-14 02:14:1548 if (is_android) {
49 import("//build/config/android/rules.gni")
50 }
estevensonc0b135ff2016-11-17 16:03:5151
Nate Fischerbce817152021-07-14 02:14:1552 if (is_android) {
53 java_cpp_enum("java_enum_srcjar") {
54 # External code should depend on ":foo_java" instead.
55 visibility = [ ":*" ]
56 sources = [
57 # Include the .h or .cc file(s) which defines the enum(s).
58 "base/android/native_foo_header.h",
59 ]
60 }
61
62 # If there's already an android_library target, you can add
63 # java_enum_srcjar to that target's srcjar_deps. Otherwise, the best
64 # practice is to create a new android_library just for this target.
65 android_library("foo_java") {
66 srcjar_deps = [ ":java_enum_srcjar" ]
67
68 # Important: the generated enum uses the @IntDef annotation provided by
69 # this dependency.
70 deps = [ "//third_party/androidx:androidx_annotation_annotation_java" ]
71 }
estevensonc0b135ff2016-11-17 16:03:5172 }
73 ```
74
Nate Fischerbce817152021-07-14 02:14:15753. The generated file `org/chromium/chrome/FooBar.java` would contain:
estevensonc0b135ff2016-11-17 16:03:5176
77 ```java
78 package org.chromium.chrome;
79
Nate Fischerbce817152021-07-14 02:14:1580 import androidx.annotation.IntDef;
estevensonc0b135ff2016-11-17 16:03:5181
82 import java.lang.annotation.Retention;
83 import java.lang.annotation.RetentionPolicy;
84
Keigo Okac5174602024-11-19 15:55:1985 @IntDef(flag = true, value = {
dgn2b5c5e822017-05-12 20:33:3986 FooBar.A, FooBar.B, FooBar.C
87 })
88 @Retention(RetentionPolicy.SOURCE)
89 public @interface FooBar {
Keigo Okac5174602024-11-19 15:55:1990 int A = 1 << 0;
91 int B = 1 << 1;
92 int C = 1 << 1;
estevensonc0b135ff2016-11-17 16:03:5193 }
94 ```
95
96## Formatting Notes
97
98* Handling long package names:
99
Nate Fischer93c59152019-02-05 01:25:08100 ```cpp
estevensonc0b135ff2016-11-17 16:03:51101 // GENERATED_JAVA_ENUM_PACKAGE: (
102 // org.chromium.chrome.this.package.is.too.long.to.fit.on.a.single.line)
103 ```
104
105* Enum entries
106 * Single line enums should look like this:
107
Nate Fischer93c59152019-02-05 01:25:08108 ```cpp
109 // GENERATED_JAVA_ENUM_PACKAGE: org.foo
110 enum NotificationActionType { BUTTON, TEXT };
111 ```
estevensonc0b135ff2016-11-17 16:03:51112
113 * Multi-line enums should have one enum entry per line, like this:
114
Nate Fischer93c59152019-02-05 01:25:08115 ```cpp
116 // GENERATED_JAVA_ENUM_PACKAGE: org.foo
117 enum NotificationActionType {
118 BUTTON,
119 TEXT
120 };
121 ```
estevensonc0b135ff2016-11-17 16:03:51122
123 * Multi-line enum entries are allowed but should be formatted like this:
124
Nate Fischer93c59152019-02-05 01:25:08125 ```cpp
126 // GENERATED_JAVA_ENUM_PACKAGE: org.foo
127 enum NotificationActionType {
128 LongKeyNumberOne,
129 LongKeyNumberTwo,
130 ...
131 LongKeyNumberThree =
132 LongKeyNumberOne | LongKeyNumberTwo | ...
133 };
134 ```
estevensonc0b135ff2016-11-17 16:03:51135
136* Preserving comments
137
138 ```cpp
139 // GENERATED_JAVA_ENUM_PACKAGE: org.chromium
140 enum CommentEnum {
141 // This comment will be preserved.
142 ONE,
143 TWO, // This comment will NOT be preserved.
144 THREE
145 }
146 ```
147
148 ```java
149 ...
dgn2b5c5e822017-05-12 20:33:39150 public @interface CommentEnum {
estevensonc0b135ff2016-11-17 16:03:51151 ...
152 /**
153 * This comment will be preserved.
154 */
dgn2b5c5e822017-05-12 20:33:39155 int ONE = 0;
156 int TWO = 1;
157 int THREE = 2;
estevensonc0b135ff2016-11-17 16:03:51158 }
159 ```
160
Nate Fischerbce817152021-07-14 02:14:15161## Troubleshooting
162
163### Symbol not found/could not resolve IntDef
164
165You may see an error like this when compiling:
166
167```shell
168$ autoninja -C out/Default base/foo_java
169util.build_utils.CalledProcessError: Command failed: ...
170org/chromium/chrome/FooBar.java:13: error: symbol not found androidx.annotation.IntDef
Andrew Grieve048ea392022-02-14 17:58:54171Hint: Add "//third_party/androidx:androidx_annotation_annotation_java" to deps of //base/foo_java
Nate Fischerbce817152021-07-14 02:14:15172import androidx.annotation.IntDef;
173 ^
174org/chromium/chrome/FooBar.java:18: error: could not resolve IntDef
175@IntDef({
176^
177```
178
179The fix is to add
180`"//third_party/androidx:androidx_annotation_annotation_java"` to the `deps` of
181the `android_library`. Note: **do not** add this to the `java_cpp_enum` target
182by mistake, otherwise you'll see a new error:
183
184```shell
185$ autoninja -C out/Default base/foo_java
186[0/1] Regenerating ninja files
187ERROR at //base/BUILD.gn:194:12: Assignment had no effect.
188 deps = [ "//third_party/androidx:androidx_annotation_annotation_java" ]
189 ^--------------------------------------------------------------
190You set the variable "deps" here and it was unused before it went
191out of scope.
192...
193```
194
Nate Fischerac07b2622020-10-01 20:20:14195## See also
196* [Accessing C++ Switches In Java](android_accessing_cpp_switches_in_java.md)
197* [Accessing C++ Features In Java](android_accessing_cpp_features_in_java.md)
198
estevensonc0b135ff2016-11-17 16:03:51199## Code
200* [Generator
201code](https://cs.chromium.org/chromium/src/build/android/gyp/java_cpp_enum.py?dr=C&sq=package:chromium)
202and
203[Tests](https://cs.chromium.org/chromium/src/build/android/gyp/java_cpp_enum_tests.py?dr=C&q=java_cpp_enum_tests&sq=package:chromium&l=1)
204* [GN
205template](https://cs.chromium.org/chromium/src/build/config/android/rules.gni?q=java_cpp_enum.py&sq=package:chromium&dr=C&l=458)