Skip to content

Commit 9ef8b02

Browse files
committed
feat : windows compatibility
1 parent 89f46f6 commit 9ef8b02

7 files changed

Lines changed: 176 additions & 39 deletions

File tree

.github/workflows/build-and-publish.yml

Lines changed: 110 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,29 @@ permissions:
99
contents: read
1010

1111
jobs:
12-
build-and-publish:
13-
name: Build and Publish to Maven Central
14-
runs-on: ubuntu-latest
12+
build-natives:
13+
name: Build natives for ${{ matrix.platform }}-${{ matrix.arch }}
14+
strategy:
15+
matrix:
16+
include:
17+
- os: ubuntu-latest
18+
platform: linux
19+
arch: x64
20+
lib: libflecs.so
21+
- os: windows-latest
22+
platform: windows
23+
arch: x64
24+
lib: flecs.dll
25+
- os: macos-13
26+
platform: macos
27+
arch: x64
28+
lib: libflecs.dylib
29+
- os: macos-latest
30+
platform: macos
31+
arch: aarch64
32+
lib: libflecs.dylib
33+
34+
runs-on: ${{ matrix.os }}
1535

1636
steps:
1737
- name: Checkout code
@@ -23,28 +43,109 @@ jobs:
2343
java-version: '25'
2444
distribution: 'temurin'
2545

26-
- name: Install GCC
46+
- name: Install GCC (Linux)
47+
if: runner.os == 'Linux'
2748
run: |
2849
sudo apt-get update
2950
sudo apt-get install -y gcc build-essential
3051
52+
- name: Install GCC (Windows)
53+
if: runner.os == 'Windows'
54+
run: choco install mingw -y
55+
56+
- name: Grant execute permission for gradlew
57+
if: runner.os != 'Windows'
58+
run: chmod +x gradlew
59+
60+
- name: Build natives
61+
run: ./gradlew copyFlecsNative -PNATIVE_ARCH=${{ matrix.platform }}-${{ matrix.arch }}
62+
shell: bash
63+
64+
- name: Verify native library was built
65+
run: |
66+
echo "Checking for native library..."
67+
ls -la build/natives/${{ matrix.platform }}-${{ matrix.arch }}/
68+
shell: bash
69+
70+
- name: Upload natives artifact
71+
uses: actions/upload-artifact@v4
72+
with:
73+
name: natives-${{ matrix.platform }}-${{ matrix.arch }}
74+
path: build/natives/${{ matrix.platform }}-${{ matrix.arch }}/${{ matrix.lib }}
75+
retention-days: 1
76+
77+
publish:
78+
name: Publish to Maven Central
79+
needs: build-natives
80+
runs-on: ubuntu-latest
81+
82+
steps:
83+
- name: Checkout code
84+
uses: actions/checkout@v4
85+
86+
- name: Set up JDK 25
87+
uses: actions/setup-java@v4
88+
with:
89+
java-version: '25'
90+
distribution: 'temurin'
91+
92+
- name: Download all natives
93+
uses: actions/download-artifact@v4
94+
with:
95+
path: downloaded-natives
96+
97+
- name: Debug downloaded artifacts
98+
run: |
99+
echo "Downloaded artifacts structure:"
100+
find downloaded-natives -type f
101+
102+
- name: Organize natives
103+
run: |
104+
mkdir -p build/natives
105+
106+
# Copy each artifact to the correct structure
107+
for artifact_dir in downloaded-natives/natives-*/; do
108+
# Extract platform-arch from folder name (e.g. natives-linux-x64 -> linux-x64)
109+
platform_arch=$(basename "$artifact_dir" | sed 's/^natives-//')
110+
111+
echo "Processing $platform_arch..."
112+
mkdir -p "build/natives/$platform_arch"
113+
114+
# Copy library file from artifact
115+
cp "$artifact_dir"/* "build/natives/$platform_arch/" 2>/dev/null || {
116+
echo "Warning: No files found in $artifact_dir"
117+
}
118+
done
119+
120+
echo ""
121+
echo "Final native libraries structure:"
122+
find build/natives -type f
123+
31124
- name: Grant execute permission for gradlew
32125
run: chmod +x gradlew
33126

34-
- name: Build project with natives
35-
run: ./gradlew build -PNATIVE_ARCH=linux-x64 -x test
127+
- name: Build final JAR with all natives
128+
run: ./gradlew jar -x compileFlecsNative -x copyFlecsNative
36129

37130
- name: Verify JAR contents
38131
run: |
39132
VERSION=${GITHUB_REF_NAME#v}
40133
echo "Verifying JAR for version $VERSION..."
41-
jar tf build/libs/flecs-java-$VERSION.jar | grep "natives/linux-x64/libflecs.so" && echo "✓ Native library found" || echo "✗ Native NOT found"
42-
jar tf build/libs/flecs-java-$VERSION.jar | grep "META-INF/services/javax.annotation.processing.Processor" && echo "✓ Processor found" || echo "✗ Processor NOT found"
134+
echo ""
135+
echo "All natives in JAR:"
136+
jar tf build/libs/flecs-java-$VERSION.jar | grep "natives/" | sort
137+
echo ""
138+
139+
# Check each platform
140+
jar tf build/libs/flecs-java-$VERSION.jar | grep "natives/linux-x64/libflecs.so" && echo "✓ Linux x64" || echo "✗ Linux x64 MISSING"
141+
jar tf build/libs/flecs-java-$VERSION.jar | grep "natives/windows-x64/flecs.dll" && echo "✓ Windows x64" || echo "✗ Windows x64 MISSING"
142+
jar tf build/libs/flecs-java-$VERSION.jar | grep "natives/macos-x64/libflecs.dylib" && echo "✓ macOS x64" || echo "✗ macOS x64 MISSING"
143+
jar tf build/libs/flecs-java-$VERSION.jar | grep "natives/macos-aarch64/libflecs.dylib" && echo "✓ macOS ARM64" || echo "✗ macOS ARM64 MISSING"
43144
44145
- name: Publish to Maven Central
45146
env:
46147
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
47148
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
48149
SIGNING_KEY: ${{ secrets.SIGNING_KEY }}
49150
SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }}
50-
run: ./gradlew publishToSonatype closeAndReleaseSonatypeStagingRepository -PNATIVE_ARCH=linux-x64
151+
run: ./gradlew publishToSonatype closeAndReleaseSonatypeStagingRepository

build.gradle.kts

Lines changed: 51 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,19 @@ val jextractExecutable = when {
4747
else -> "$userHome/.local/jextract/jextract-25/bin/jextract"
4848
}
4949

50-
val nativeLibName = "libflecs.so"
50+
val nativeLibName = when {
51+
os.isWindows -> "flecs.dll"
52+
os.isMacOsX -> "libflecs.dylib"
53+
else -> "libflecs.so"
54+
}
55+
5156
val nativeArch = project.findProperty("NATIVE_ARCH") as String? ?: when {
5257
os.isLinux && System.getProperty("os.arch") in listOf("amd64", "x86_64") -> "linux-x64"
5358
os.isLinux && System.getProperty("os.arch") in listOf("aarch64", "arm64") -> "linux-aarch64"
59+
os.isWindows && System.getProperty("os.arch") in listOf("amd64", "x86_64") -> "windows-x64"
60+
os.isWindows && System.getProperty("os.arch") == "aarch64" -> "windows-aarch64"
61+
os.isMacOsX && System.getProperty("os.arch") == "aarch64" -> "macos-aarch64"
62+
os.isMacOsX && System.getProperty("os.arch") in listOf("amd64", "x86_64") -> "macos-x64"
5463
else -> "unknown"
5564
}
5665

@@ -101,22 +110,47 @@ val compileFlecsNative by tasks.registering(Exec::class) {
101110
val outputNativeFile = File(flecsSourceDir, "distr/$nativeLibName")
102111
outputs.file(outputNativeFile)
103112

104-
val compileCommand = listOf(
105-
"gcc",
106-
"-shared",
107-
"-fPIC",
108-
"-o", outputNativeFile.absolutePath,
109-
flecsCFile.absolutePath,
110-
"-Ofast",
111-
"-std=c99",
112-
"-DFLECS_SHARED",
113-
"-DNDEBUG",
114-
"-D_POSIX_C_SOURCE=200809L",
115-
"-D_DEFAULT_SOURCE",
116-
"-lm",
117-
"-lrt",
118-
"-lpthread"
119-
)
113+
val compileCommand = when {
114+
os.isWindows -> listOf(
115+
"gcc",
116+
"-shared",
117+
"-o", outputNativeFile.absolutePath,
118+
flecsCFile.absolutePath,
119+
"-Ofast",
120+
"-std=c99",
121+
"-DFLECS_SHARED",
122+
"-DNDEBUG",
123+
"-lws2_32",
124+
"-ldbghelp"
125+
)
126+
os.isMacOsX -> listOf(
127+
"gcc",
128+
"-dynamiclib",
129+
"-o", outputNativeFile.absolutePath,
130+
flecsCFile.absolutePath,
131+
"-Ofast",
132+
"-std=c99",
133+
"-DFLECS_SHARED",
134+
"-DNDEBUG",
135+
"-framework", "CoreFoundation"
136+
)
137+
else -> listOf(
138+
"gcc",
139+
"-shared",
140+
"-fPIC",
141+
"-o", outputNativeFile.absolutePath,
142+
flecsCFile.absolutePath,
143+
"-Ofast",
144+
"-std=c99",
145+
"-DFLECS_SHARED",
146+
"-DNDEBUG",
147+
"-D_POSIX_C_SOURCE=200809L",
148+
"-D_DEFAULT_SOURCE",
149+
"-lm",
150+
"-lrt",
151+
"-lpthread"
152+
)
153+
}
120154
commandLine(compileCommand)
121155
}
122156

src/main/generated/com/github/elebras1/flecs/flecs_h$shared.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public class flecs_h$shared {
2727
public static final ValueLayout.OfDouble C_DOUBLE = (ValueLayout.OfDouble) Linker.nativeLinker().canonicalLayouts().get("double");
2828
public static final AddressLayout C_POINTER = ((AddressLayout) Linker.nativeLinker().canonicalLayouts().get("void*"))
2929
.withTargetLayout(MemoryLayout.sequenceLayout(java.lang.Long.MAX_VALUE, C_CHAR));
30-
public static final ValueLayout.OfLong C_LONG = (ValueLayout.OfLong) Linker.nativeLinker().canonicalLayouts().get("long");
30+
public static final ValueLayout.OfLong C_LONG = ValueLayout.JAVA_LONG;
3131

3232
static final boolean TRACE_DOWNCALLS = Boolean.getBoolean("jextract.trace.downcalls");
3333

src/main/java/com/github/elebras1/flecs/ObserverBuilder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ public FlecsObserver each(Query.EntityCallback callback) {
190190
MemorySegment entities = ecs_iter_t.entities(it);
191191

192192
for (int i = 0; i < count; i++) {
193-
long entityId = entities.getAtIndex(flecs_h$shared.C_LONG, i);
193+
long entityId = entities.getAtIndex(ValueLayout.JAVA_LONG, i);
194194
callback.accept(entityId);
195195
}
196196
}, this.world.arena());

src/main/java/com/github/elebras1/flecs/Query.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.github.elebras1.flecs.collection.EcsLongList;
44
import java.lang.foreign.Arena;
55
import java.lang.foreign.MemorySegment;
6+
import java.lang.foreign.ValueLayout;
67

78
public class Query implements AutoCloseable {
89

@@ -46,7 +47,7 @@ public void each(EntityCallback callback) {
4647
MemorySegment entities = ecs_iter_t.entities(iter);
4748

4849
for (int i = 0; i < count; i++) {
49-
long entityId = entities.getAtIndex(flecs_h$shared.C_LONG, i);
50+
long entityId = entities.getAtIndex(ValueLayout.JAVA_LONG, i);
5051
callback.accept(entityId);
5152
}
5253
}

src/main/java/com/github/elebras1/flecs/SystemBuilder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ public FlecsSystem each(Query.EntityCallback callback) {
218218
MemorySegment entities = ecs_iter_t.entities(it);
219219

220220
for (int i = 0; i < count; i++) {
221-
long entityId = entities.getAtIndex(flecs_h$shared.C_LONG, i);
221+
long entityId = entities.getAtIndex(ValueLayout.JAVA_LONG, i);
222222
callback.accept(entityId);
223223
}
224224
}, this.world.arena());

src/main/java/com/github/elebras1/flecs/util/internal/FlecsLoader.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,29 +43,30 @@ private static String getArchitecture() {
4343
return "aarch64";
4444
}
4545

46-
return osArch;
46+
throw new UnsupportedOperationException("Unsupported architecture: " + osArch);
4747
}
4848

4949
private static String getNativeLibraryPath() {
5050
String os = System.getProperty("os.name").toLowerCase();
5151
String arch = getArchitecture();
52+
53+
String osName;
5254
String libName;
5355

5456
if (os.contains("win")) {
57+
osName = "windows";
5558
libName = "flecs.dll";
5659
} else if (os.contains("mac")) {
60+
osName = "macos";
5761
libName = "libflecs.dylib";
58-
} else {
62+
} else if (os.contains("linux") || os.contains("nux")) {
63+
osName = "linux";
5964
libName = "libflecs.so";
65+
} else {
66+
throw new UnsupportedOperationException("Unsupported OS: " + os);
6067
}
6168

62-
// Try architecture-specific path first for Linux
63-
if (os.contains("linux")) {
64-
return "/natives/linux-" + arch + "/" + libName;
65-
}
66-
67-
// Fallback to root for backward compatibility
68-
return "/" + libName;
69+
return String.format("/natives/%s-%s/%s", osName, arch, libName);
6970
}
7071

7172
private static boolean loadFromResources(String libPath) {

0 commit comments

Comments
 (0)