Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .github/workflows/pr-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,25 @@ jobs:
echo "::error title=Inconsistent JavaDoc::JavaDoc-Basher discovered JavaDoc inconsistencies between implementations, which must be resolved."
exit 1
fi

check-jni-generator-consistency:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493 # v5.0.0
- uses: actions/setup-java@de5a937a1dc73fbc1a67d7d1aa4bebc1082f3190 # v5.0.0
with:
java-version: 25
distribution: 'temurin'
cache: maven
- name: Run JNI generator
run: >
mvn --non-recursive --batch-mode --no-transfer-progress
-Pjni-generator exec:exec@run-jni-generator
- name: Verify no changes
run: |
if ! git diff --exit-code ; then
echo "::error title=Outdated JNI glue code::The generated native sources (os.c, *_stats.*, *_structs.* ...) do not match the Java native declarations. Regenerate them with 'mvn --non-recursive -Pjni-generator exec:exec@run-jni-generator' and commit the result."
exit 1
fi
9 changes: 7 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,12 @@ mvn clean verify -DskipTests
See `bundles/org.eclipse.swt/Readme.md#building-native-binaries` for instructions how to build the SWT native binaries.

**CRITICAL**: Files like `os.c`, `os_stats.c`, `os_stats.h` are **auto-generated**. Never edit them directly!
Instead: modify Java source (e.g., `OS.java`), clean/rebuild the project, then run the native build command above.
Instead: modify Java source (e.g., `OS.java`), regenerate the C files, then run the native build command above.
To regenerate without the Eclipse IDE, run at the repository root:
```bash
mvn --non-recursive -Pjni-generator exec:exec@run-jni-generator
```
The pull-request checks run this command and fail if the committed generated files are outdated.

**CRITICAL**: Never commit any built native binary files to git. These are built and committed by the CI. This includes:
- Linux: `libswt-*.so`
Expand Down Expand Up @@ -198,7 +203,7 @@ display.asyncExec(() -> button.setText("Updated"));

### Adding GTK Functions
1. Add native method declaration to `OS.java` with JavaDoc annotations (`@param cast=`, `@method flags=dynamic`)
2. Clean and rebuild `org.eclipse.swt` project (regenerates `os.c`)
2. Regenerate `os.c` and friends: `mvn --non-recursive -Pjni-generator exec:exec@run-jni-generator` (or clean and rebuild the `org.eclipse.swt` project in the IDE)
3. Rebuild natives: `cd bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library && export GTK_VERSION=3.0 && ./build.sh install`

## Tips for AI Tools
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,19 +79,18 @@ public ASTClass(String sourcePath, MetaData metaData) {
packageName = unit.getPackage().getName().getFullyQualifiedName();
name = packageName + "." + simpleName;
superclassName = type.getSuperclassType() != null ? type.getSuperclassType().toString() : null;
List<ImportDeclaration> imports = unit.imports();
List<?> imports = unit.imports();
this.imports = new String[imports.size()];
int count = 0;
for (ImportDeclaration imp : imports) {
this.imports[count++] = imp.getName().getFullyQualifiedName();
for (Object imp : imports) {
this.imports[count++] = ((ImportDeclaration) imp).getName().getFullyQualifiedName();
}
start = type.getStartPosition();

Javadoc doc = type.getJavadoc();
List<TagElement> tags = null;
if (doc != null) {
tags = doc.tags();
for (TagElement tag : tags) {
for (Object element : doc.tags()) {
TagElement tag = (TagElement) element;
if ("@jniclass".equals(tag.getTagName())) {
String data = tag.fragments().get(0).toString();
setMetaData(data);
Expand All @@ -102,9 +101,8 @@ public ASTClass(String sourcePath, MetaData metaData) {

List<ASTField> fid = new ArrayList<>();
for (FieldDeclaration field : type.getFields()) {
List<VariableDeclarationFragment> fragments = field.fragments();
for (VariableDeclarationFragment fragment : fragments) {
fid.add(new ASTField(this, field, fragment));
for (Object fragment : field.fragments()) {
fid.add(new ASTField(this, field, (VariableDeclarationFragment) fragment));
}
}
this.fields = fid.toArray(new ASTField[fid.size()]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,9 @@ public ASTField(ASTClass declaringClass, FieldDeclaration field, VariableDeclara
start = field.getStartPosition();

Javadoc doc = field.getJavadoc();
List<TagElement> tags = null;
if (doc != null) {
tags = doc.tags();
for (TagElement tag : tags) {
for (Object element : doc.tags()) {
TagElement tag = (TagElement) element;
if ("@field".equals(tag.getTagName())) {
String data = tag.fragments().get(0).toString();
setMetaData(data);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,11 @@ public ASTMethod(ASTClass declaringClass, MethodDeclaration method) {
start = method.getStartPosition();

Javadoc doc = method.getJavadoc();
List<TagElement> tags = null;
List<?> tags = null;
if (doc != null) {
tags = doc.tags();
for (TagElement tag : tags) {
for (Object element : tags) {
TagElement tag = (TagElement) element;
if ("@method".equals(tag.getTagName())) {
String data = tag.fragments().get(0).toString();
setMetaData(data);
Expand All @@ -49,19 +50,20 @@ public ASTMethod(ASTClass declaringClass, MethodDeclaration method) {
}
}
returnType = new ASTType(declaringClass.resolver, method.getReturnType2(), method.getExtraDimensions());
List<SingleVariableDeclaration> parameters = method.parameters();

List<?> parameters = method.parameters();
paramTypes = new ASTType[parameters.size()];
this.parameters = new ASTParameter[paramTypes.length];
int i = 0;
for (Iterator<SingleVariableDeclaration> iterator = parameters.iterator(); iterator.hasNext(); i++) {
SingleVariableDeclaration param = iterator.next();
for (Iterator<?> iterator = parameters.iterator(); iterator.hasNext(); i++) {
SingleVariableDeclaration param = (SingleVariableDeclaration) iterator.next();
paramTypes[i] = new ASTType(declaringClass.resolver, param.getType(), param.getExtraDimensions());
this.parameters[i] = new ASTParameter(this, i, param.getName().getIdentifier());

if (tags != null) {
String name = param.getName().getIdentifier();
for (TagElement tag : tags) {
for (Object element : tags) {
TagElement tag = (TagElement) element;
if ("@param".equals(tag.getTagName())) {
List<?> fragments = tag.fragments();
if (fragments.size() >= 2 && name.equals(fragments.get(0).toString())) {
Expand Down
15 changes: 15 additions & 0 deletions bundles/org.eclipse.swt/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,21 @@ Running the snippets:
* (Optionally) install CDT from marketplace if you want to work on C/Native parts of SWT.
* You should be able to run snippets now. (_e.g._ `Snippet1`).

## Regenerating the JNI glue code

The C files `os.c`, `*_stats.c/h` and `*_structs.c/h` next to `build.sh` in the `library` folders are generated
from the `native` method declarations (and their `@method`/`@param` JavaDoc annotations) in the Java sources.
Never edit them by hand. After changing a native declaration, regenerate them for all platforms from the CLI
(at the repository root):
```bash
mvn --non-recursive -Pjni-generator exec:exec@run-jni-generator
```
and commit the changed C files together with the Java change. The pull-request checks run the same command and
fail when the committed C files are outdated.

In the Eclipse IDE the same happens automatically when the **SWT Tools** feature is installed:
its `JNI Builder` regenerates the files on every build of the `org.eclipse.swt` project.

## Building native binaries

To build only SWT's native binaries, run from the CLI (at the repository root):
Expand Down
80 changes: 63 additions & 17 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>run-javadoc-basher</id>
Expand All @@ -118,37 +117,84 @@
</goals>
<phase>validate</phase>
<configuration>
<forceJava>true</forceJava>
<workingDirectory>bundles/org.eclipse.swt.tools</workingDirectory>
<executable>java</executable>
<arguments>
<argument>-classpath</argument>
<classpath/>
<argument>JavadocBasher/org/eclipse/swt/tools/internal/JavadocBasher.java</argument>
</arguments>
<includePluginDependencies>true</includePluginDependencies>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.eclipse.jdt</groupId>
<artifactId>org.eclipse.jdt.core</artifactId>
<version>[3.44.0,)</version>
</dependency>
<dependency>
<groupId>org.eclipse.platform</groupId>
<artifactId>org.eclipse.jface</artifactId>
<version>[3.38.0,)</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</profile>
<profile>
<!--
Regenerates the JNI glue code (os.c, *_stats.*, *_structs.* ...) of all platforms from the
native method declarations in the Java sources, without the Eclipse IDE builder. Run it with
"mvn -N -Pjni-generator exec:exec@run-jni-generator" (see bundles/org.eclipse.swt/Readme.md).
The pr-checks workflow runs this and fails when the committed generated files are out of date.
-->
<id>jni-generator</id>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<id>run-jni-generator</id>
<goals>
<goal>exec</goal>
</goals>
<phase>validate</phase>
<configuration>
<arguments>
<argument>-classpath</argument>
<classpath/>
<argument>JNI Generation/org/eclipse/swt/tools/internal/JNIGeneratorApp.java</argument>
<argument>all</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>

<build>
<pluginManagement>
<plugins>
<plugin>
<!-- Used by the javadoc-basher and jni-generator profiles to run tools from
bundles/org.eclipse.swt.tools with the java source-file launcher. -->
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.6.3</version>
<configuration>
<forceJava>true</forceJava>
<executable>java</executable>
<workingDirectory>bundles/org.eclipse.swt.tools</workingDirectory>
<includePluginDependencies>true</includePluginDependencies>
</configuration>
<dependencies>
<dependency>
<groupId>org.eclipse.jdt</groupId>
<artifactId>org.eclipse.jdt.core</artifactId>
<version>[3.46.0,)</version>
</dependency>
<dependency>
<groupId>org.eclipse.platform</groupId>
<artifactId>org.eclipse.jface</artifactId>
<version>[3.39.100.0,)</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.eclipse.tycho</groupId>
Expand Down
Loading