Skip to content

Commit 4383a3b

Browse files
authored
updated OS versions in ci/cd (#7)
* updated OS versions in ci/cd * fixed msvc c11 requirements * fixed gradle * fixed work with arch
1 parent 46da6f1 commit 4383a3b

File tree

14 files changed

+187
-1517
lines changed

14 files changed

+187
-1517
lines changed

.github/workflows/publish.yml

Lines changed: 47 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,26 @@ jobs:
1111
runs-on: ${{ matrix.os }}
1212
strategy:
1313
matrix:
14+
# https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners#standard-github-hosted-runners-for-public-repositories
1415
include:
15-
- os: ubuntu-22.04
16-
arch: x86_64
16+
- os: ubuntu-24.04
17+
arch: x64
1718
OUT_OS_NAME: linux
18-
- os: ubuntu-22.04
19-
arch: aarch64
19+
- os: ubuntu-24.04-arm
20+
arch: arm64
2021
OUT_OS_NAME: linux
21-
- os: macos-12
22-
arch: x86_64
22+
- os: macos-13
23+
arch: x64
2324
OUT_OS_NAME: darwin
24-
- os: macos-12
25+
- os: macos-15
2526
arch: arm64
2627
OUT_OS_NAME: darwin
27-
- os: windows-2022
28-
arch: x86_64
28+
- os: windows-2025
29+
arch: x64
2930
OUT_OS_NAME: windows
31+
# - os: windows-11-arm
32+
# arch: arm64
33+
# OUT_OS_NAME: windows
3034
fail-fast: false
3135

3236
steps:
@@ -45,47 +49,65 @@ jobs:
4549
- name: Setup Julia
4650
uses: julia-actions/setup-julia@v2
4751
with:
48-
version: '1.10'
52+
version: '1.11'
4953

5054
- name: Setup JDK
5155
uses: actions/setup-java@v4
5256
with:
5357
distribution: 'temurin'
5458
java-version: '21'
5559

60+
# Install cross toolchain for aarch64 on Ubuntu
61+
- name: Install cross toolchain (aarch64)
62+
if: ${{ startsWith(matrix.os, 'ubuntu-') && matrix.arch == 'aarch64' }}
63+
run: |
64+
sudo apt-get update
65+
sudo apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
66+
5667
- name: Install dependencies
5768
shell: bash
5869
run: |
5970
if [[ "$RUNNER_OS" == "Linux" ]]; then
6071
sudo apt-get update
61-
sudo apt-get install -y cmake make swig gcc g++
72+
sudo apt-get install -y cmake swig gcc g++
6273
elif [[ "$RUNNER_OS" == "macOS" ]]; then
6374
brew update
64-
brew install cmake make swig
75+
brew install cmake swig
6576
elif [[ "$RUNNER_OS" == "Windows" ]]; then
66-
choco install cmake make swig
77+
choco install cmake swig
6778
fi
6879
6980
- name: Build native library
7081
shell: bash
7182
run: |
7283
cd swig
7384
cmake .
74-
make install
85+
cmake --build . --config Release
86+
cmake --install . --config Release
7587
cd ..
76-
echo "Library built at: $(pwd)/src/main/resources/native/64/${{ matrix.OUT_OS_NAME }}"
88+
echo "Library built at: $(pwd)/src/main/resources/native/${{ matrix.OUT_OS_NAME }}/${{ matrix.arch }}"
89+
90+
- name: Local test of native library
91+
shell: bash
92+
run: |
93+
if [[ "$RUNNER_OS" == "Windows" ]]; then
94+
./gradlew.bat test
95+
else
96+
./gradlew test
97+
fi
98+
echo "Native library tests passed."
7799
78100
# Add artifact retention period based on release type
79101
- name: Upload artifact
80102
uses: actions/upload-artifact@v4
81103
with:
82104
name: native-${{ matrix.OUT_OS_NAME }}-${{ matrix.arch }}
83-
path: src/main/resources/native/64/${{ matrix.OUT_OS_NAME }}/
105+
path: src/main/resources/native/${{ matrix.OUT_OS_NAME }}/${{ matrix.arch }}/
84106
retention-days: ${{ github.event.release.draft && 7 || 1 }}
85107

86108
build-java:
87109
name: Build Java Library
88-
runs-on: ubuntu-22.04
110+
runs-on: ubuntu-24.04
89111
needs: build-native
90112
if: ${{ !cancelled() }} # Run unless previous jobs were cancelled
91113

@@ -110,8 +132,9 @@ jobs:
110132
for artifact in native-artifacts/*; do
111133
os_arch=$(basename $artifact)
112134
os=$(echo $os_arch | cut -d'-' -f2)
113-
mkdir -p "src/main/resources/native/64/$os"
114-
cp -R "$artifact"/* "src/main/resources/native/64/$os/"
135+
arch=$(echo $os_arch | cut -d'-' -f3)
136+
mkdir -p "src/main/resources/native/$os/$arch"
137+
cp -R "$artifact"/* "src/main/resources/native/$os/$arch/"
115138
done
116139
echo "Assembled native libraries:"
117140
find src/main/resources/native -type f
@@ -120,17 +143,18 @@ jobs:
120143
run: ./gradlew build
121144

122145
# Test artifact before final upload
123-
- name: Test JAR (Example)
146+
- name: Test presence of JAR
124147
run: |
125-
java -jar build/libs/*.jar --version
126-
# Add your real validation commands here
148+
# java -jar build/libs/*.jar --version
149+
jar xf build/libs/*.jar META-INF/MANIFEST.MF
150+
grep 'Implementation-Version' META-INF/MANIFEST.MF | awk -F ': ' '{print $2}'
127151
128152
# Conditional artifact upload
129153
- name: Upload Java artifact
130154
if: ${{ github.event.release.draft || github.event_name == 'workflow_dispatch' }}
131155
uses: actions/upload-artifact@v4
132156
with:
133-
name: java-library
157+
name: julia4j-crossplatform-jar
134158
path: build/libs/*.jar
135159
retention-days: 7
136160

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,6 @@ gradle-app.setting
6262
.gradletasknamecache
6363

6464
# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
65-
# gradle/wrapper/gradle-wrapper.properties
65+
# gradle/wrapper/gradle-wrapper.properties
66+
67+
tmp/

build.gradle

Lines changed: 40 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
plugins {
2-
id 'java'
2+
id 'java-library'
33
id 'maven-publish'
44
}
55

66
group = 'org.julia'
7-
version = '0.0.3.SNAPSHOT'
7+
version = '0.0.3-SNAPSHOT'
88

99
java {
1010
sourceCompatibility = JavaVersion.VERSION_21
@@ -28,12 +28,12 @@ publishing {
2828
}
2929
}
3030

31-
// Helper function to get Julia's lib directory
31+
// Helper function to get Julia's lib directory (cross-platform)
3232
def getJuliaLibPath() {
3333
def juliaCmd = [
34-
'julia',
35-
'-e',
36-
'print(abspath(joinpath(Sys.BINDIR, "..", "lib")))'
34+
'julia',
35+
'-e',
36+
'print(abspath(joinpath(dirname(Sys.BINDIR), string(:lib))))'
3737
]
3838
def process = juliaCmd.execute()
3939
process.waitFor()
@@ -43,33 +43,45 @@ def getJuliaLibPath() {
4343
return process.text.trim()
4444
}
4545

46-
test {
46+
// Helper to detect OS in a stable way
47+
def getOsName() {
48+
def os = System.getProperty('os.name').toLowerCase()
49+
if (os.contains('mac')) return 'mac'
50+
if (os.contains('win')) return 'windows'
51+
if (os.contains('nux')) return 'linux'
52+
return 'other'
53+
}
54+
55+
tasks.test {
4756
useJUnitPlatform()
4857

49-
// Set library paths for all platforms
50-
def juliaLibPath = getJuliaLibPath()
51-
52-
// macOS specific configuration
53-
if (org.gradle.nativeplatform.platform.internal.DefaultNativePlatform.currentOperatingSystem.isMacOsX()) {
54-
environment "DYLD_LIBRARY_PATH", juliaLibPath + (
55-
System.getenv('DYLD_LIBRARY_PATH')
56-
? ":" + System.getenv('DYLD_LIBRARY_PATH')
57-
: ""
58-
)
58+
testClassesDirs = testing.suites.test.sources.output.classesDirs
59+
classpath = testing.suites.test.sources.runtimeClasspath
60+
61+
doFirst {
62+
def juliaLibPath = getJuliaLibPath()
63+
def osName = getOsName()
64+
65+
if (osName == 'mac') {
66+
def current = System.getenv('DYLD_LIBRARY_PATH')
67+
environment "DYLD_LIBRARY_PATH", juliaLibPath + (current ? ":" + current : "")
68+
} else if (osName == 'linux') {
69+
def current = System.getenv('LD_LIBRARY_PATH')
70+
environment "LD_LIBRARY_PATH", juliaLibPath + (current ? ":" + current : "")
71+
} else if (osName == 'windows') {
72+
def current = System.getenv('PATH') ?: ""
73+
environment "PATH", juliaLibPath + File.pathSeparator + current
74+
}
5975
}
60-
// Linux specific configuration
61-
else if (org.gradle.nativeplatform.platform.internal.DefaultNativePlatform.currentOperatingSystem.isLinux()) {
62-
environment "LD_LIBRARY_PATH", juliaLibPath + (
63-
System.getenv('LD_LIBRARY_PATH')
64-
? ":" + System.getenv('LD_LIBRARY_PATH')
65-
: ""
76+
}
77+
78+
tasks.named('jar') {
79+
manifest {
80+
attributes(
81+
'Automatic-Module-Name': 'JuliaEngine',
82+
'Implementation-Version': project.version
6683
)
6784
}
68-
// Windows specific configuration
69-
else if (org.gradle.nativeplatform.platform.internal.DefaultNativePlatform.currentOperatingSystem.isWindows()) {
70-
def currentPath = System.getenv('PATH') ?: ""
71-
environment "PATH", juliaLibPath + File.pathSeparator + currentPath
72-
}
7385
}
7486

7587
dependencies {

src/main/java/org/julia/jni/NativeUtils.java

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -154,26 +154,53 @@ private static File createTempDirectory(String prefix) throws IOException {
154154
return generatedDir;
155155
}
156156

157+
/**
158+
* Returns the resource path for a native library based on the current OS and architecture.
159+
* Example: /native/linux/x86_64/libfoo.so
160+
*/
157161
public static String libnameToPlatform(String libname) {
162+
String osName = System.getProperty("os.name").toLowerCase();
163+
String arch = System.getProperty("os.arch").toLowerCase();
164+
165+
String osFolder;
166+
if (osName.contains("mac")) {
167+
osFolder = "darwin";
168+
} else if (osName.contains("linux")) {
169+
osFolder = "linux";
170+
} else if (osName.contains("windows")) {
171+
osFolder = "windows";
172+
} else {
173+
throw new IllegalArgumentException("Unsupported OS: " + osName);
174+
}
158175

159-
String path = "/native/";
160-
if (System.getProperty("os.arch").toLowerCase().endsWith("64")) {
161-
path += "64/";
176+
String archFolder;
177+
if (arch.contains("aarch64") || arch.contains("arm64")) {
178+
archFolder = "arm64";
179+
} else if (arch.contains("arm")) {
180+
archFolder = "arm";
181+
} else if (arch.contains("x86_64") || arch.contains("amd64") || arch.contains("x64")) {
182+
archFolder = "x64";
183+
} else if (arch.matches("^(x86|i[3-6]86)$") || arch.contains("x86")) {
184+
archFolder = "x86";
162185
} else {
163-
throw new IllegalArgumentException("Not support this arch");
186+
throw new IllegalArgumentException("Unsupported architecture: " + arch);
164187
}
165-
String osName = System.getProperty("os.name").toLowerCase();
166-
if (osName.startsWith("mac os")) {
167-
path += "darwin/" + libname + ".jnilib";
168-
} else if (osName.startsWith("linux")) {
169-
path += "linux/" + libname + ".so";
170-
} else if (osName.startsWith("windows")) {
171-
path += "windows/" + libname + ".dll";
188+
189+
String extension;
190+
if (osFolder.equals("darwin")) {
191+
extension = ".jnilib";
192+
} else if (osFolder.equals("linux")) {
193+
extension = ".so";
194+
} else if (osFolder.equals("windows")) {
195+
extension = ".dll";
172196
} else {
173-
throw new IllegalArgumentException("Not support this OS");
197+
throw new IllegalArgumentException("Unknown extension for OS: " + osFolder);
174198
}
175199

176-
return path;
200+
// On Windows, libraries are usually named without "lib" prefix
201+
String fileName = (osFolder.equals("windows") ? "" : "lib") + libname + extension;
202+
203+
return "/native/" + osFolder + "/" + archFolder + "/" + fileName;
177204
}
178205

179206
/**

src/main/java/org/julia/scripting/JuliaEngine.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
public class JuliaEngine extends AbstractScriptEngine {
1717
static {
1818
try {
19-
NativeUtils.loadLibraryFromJar(NativeUtils.libnameToPlatform("libjulia4j"));
19+
NativeUtils.loadLibraryFromJar(NativeUtils.libnameToPlatform("julia4j"));
2020
} catch (IOException e) {
2121
e.printStackTrace();
2222
}

src/main/resources/native/64/darwin/.gitkeep

Whitespace-only changes.

src/main/resources/native/64/linux/.gitkeep

Whitespace-only changes.

src/main/resources/native/64/windows/.gitkeep

Whitespace-only changes.

src/test/java/Julia4JJNITest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
public class Julia4JJNITest {
1414
static {
1515
try {
16-
NativeUtils.loadLibraryFromJar(NativeUtils.libnameToPlatform("libjulia4j"));
16+
NativeUtils.loadLibraryFromJar(NativeUtils.libnameToPlatform("julia4j"));
1717
} catch (IOException e) {
1818
e.printStackTrace();
1919
}

swig/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
CMakeCache.txt
22
CMakeFiles/
3+
cmake_install.cmake
4+
install_manifest.txt
35
Makefile
46
*.jnilib
57
*.dll

0 commit comments

Comments
 (0)