Skip to content

Commit b036e86

Browse files
committed
Implement architecture auto detection once again
closes #47
1 parent 5c28887 commit b036e86

9 files changed

Lines changed: 341 additions & 6 deletions

File tree

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,18 @@ dynamically configuring the `javacan.native.javacan-<module>.path` properties in
9696

9797
The value for the `<module>` placeholder used throughout this section is `core` and if the EPoll support is used, an additional option with `epoll` for `<module>` is necessary.
9898

99+
##### Architecture Detection
100+
101+
While JavaCAN 2.x bundled the native components in its main artifacts, starting with the 3.x release series the native components are instead provided as
102+
separate jar files (classified by their architecture). This provides full control over which library is loaded, especially on architectures on which the JVM doesn't provide enough
103+
information for a reliable architecture detection. Programs using JavaCAN usually depend on specific architectures and thus can pull just the relevant components and nothing more.
104+
105+
For applications like test tools that don't really care about program size and don't need to support every possible architecture, starting with JavaCAN 3.3 `*-arch-detect` modules are provided.
106+
These modules bundle all prebuilt architectures and provide a function to automatically load the correct variant based on the `os.arch` system property.
107+
108+
For example for the `javacan-core` module you would instead depend on the `javacan-core-arch-detect` module and then, somewhere early in your program, invoke `JavaCANAutoDetect.initialize()`.
109+
This will configure the necessary system property based on the architecture detection and eagerly initialize JavaCAN.
110+
99111
## Troubleshooting
100112

101113
In case you have issues, have a look at the [troubleshooting document](TROUBLESHOOTING.md).

core-arch-detect/pom.xml

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
5+
<parent>
6+
<groupId>tel.schich</groupId>
7+
<artifactId>javacan</artifactId>
8+
<version>3.2.6-SNAPSHOT</version>
9+
</parent>
10+
11+
<artifactId>javacan-core-arch-detect</artifactId>
12+
13+
<dependencies>
14+
<dependency>
15+
<groupId>tel.schich</groupId>
16+
<artifactId>javacan-core</artifactId>
17+
<version>${project.version}</version>
18+
</dependency>
19+
</dependencies>
20+
21+
<build>
22+
<plugins>
23+
<plugin>
24+
<groupId>org.apache.maven.plugins</groupId>
25+
<artifactId>maven-dependency-plugin</artifactId>
26+
<version>3.6.1</version>
27+
<executions>
28+
<execution>
29+
<id>resource-dependencies</id>
30+
<phase>compile</phase>
31+
<goals>
32+
<goal>unpack</goal>
33+
</goals>
34+
<configuration>
35+
<artifactItems>
36+
<artifactItem>
37+
<groupId>tel.schich</groupId>
38+
<artifactId>javacan-core</artifactId>
39+
<version>${project.version}</version>
40+
<classifier>x86_64</classifier>
41+
<type>jar</type>
42+
<outputDirectory>${project.build.outputDirectory}/x86_64</outputDirectory>
43+
</artifactItem>
44+
<artifactItem>
45+
<groupId>tel.schich</groupId>
46+
<artifactId>javacan-core</artifactId>
47+
<version>${project.version}</version>
48+
<classifier>x86_32</classifier>
49+
<type>jar</type>
50+
<outputDirectory>${project.build.outputDirectory}/x86_32</outputDirectory>
51+
</artifactItem>
52+
<artifactItem>
53+
<groupId>tel.schich</groupId>
54+
<artifactId>javacan-core</artifactId>
55+
<version>${project.version}</version>
56+
<classifier>armv6</classifier>
57+
<type>jar</type>
58+
<outputDirectory>${project.build.outputDirectory}/armv6</outputDirectory>
59+
</artifactItem>
60+
<artifactItem>
61+
<groupId>tel.schich</groupId>
62+
<artifactId>javacan-core</artifactId>
63+
<version>${project.version}</version>
64+
<classifier>armv7</classifier>
65+
<type>jar</type>
66+
<outputDirectory>${project.build.outputDirectory}/armv7</outputDirectory>
67+
</artifactItem>
68+
<artifactItem>
69+
<groupId>tel.schich</groupId>
70+
<artifactId>javacan-core</artifactId>
71+
<version>${project.version}</version>
72+
<classifier>armv7a</classifier>
73+
<type>jar</type>
74+
<outputDirectory>${project.build.outputDirectory}/armv7a</outputDirectory>
75+
</artifactItem>
76+
<artifactItem>
77+
<groupId>tel.schich</groupId>
78+
<artifactId>javacan-core</artifactId>
79+
<version>${project.version}</version>
80+
<classifier>armv7l</classifier>
81+
<type>jar</type>
82+
<outputDirectory>${project.build.outputDirectory}/armv7l</outputDirectory>
83+
</artifactItem>
84+
<artifactItem>
85+
<groupId>tel.schich</groupId>
86+
<artifactId>javacan-core</artifactId>
87+
<version>${project.version}</version>
88+
<classifier>aarch64</classifier>
89+
<type>jar</type>
90+
<outputDirectory>${project.build.outputDirectory}/aarch64</outputDirectory>
91+
</artifactItem>
92+
<artifactItem>
93+
<groupId>tel.schich</groupId>
94+
<artifactId>javacan-core</artifactId>
95+
<version>${project.version}</version>
96+
<classifier>riscv32</classifier>
97+
<type>jar</type>
98+
<outputDirectory>${project.build.outputDirectory}/riscv32</outputDirectory>
99+
</artifactItem>
100+
<artifactItem>
101+
<groupId>tel.schich</groupId>
102+
<artifactId>javacan-core</artifactId>
103+
<version>${project.version}</version>
104+
<classifier>riscv64</classifier>
105+
<type>jar</type>
106+
<outputDirectory>${project.build.outputDirectory}/riscv64</outputDirectory>
107+
</artifactItem>
108+
</artifactItems>
109+
<includes>native/**</includes>
110+
</configuration>
111+
</execution>
112+
</executions>
113+
</plugin>
114+
</plugins>
115+
</build>
116+
</project>
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* The MIT License
3+
* Copyright © 2018 Phillip Schichtel
4+
*
5+
* Permission is hereby granted, free of charge, to any person obtaining a copy
6+
* of this software and associated documentation files (the "Software"), to deal
7+
* in the Software without restriction, including without limitation the rights
8+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be included in
13+
* all copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
* THE SOFTWARE.
22+
*/
23+
package tel.schich.javacan;
24+
25+
import tel.schich.javacan.platform.Platform;
26+
27+
public class JavaCANAutoDetect {
28+
public static void initialize() {
29+
System.setProperty(Platform.classPathPropertyNameForLibrary(JavaCAN.LIB_NAME), "/" + Platform.detectCpuArch() + "/native/" + Platform.LINUX_LIBRARY_PREFIX + JavaCAN.LIB_NAME + ".so");
30+
JavaCAN.initialize();
31+
}
32+
}

core/src/main/java/tel/schich/javacan/JavaCAN.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public class JavaCAN {
3131

3232
private static volatile boolean initialized = false;
3333

34-
private static final String LIB_NAME = "javacan-core";
34+
public static final String LIB_NAME = "javacan-core";
3535

3636
/**
3737
* Initializes the library by loading the native library.

core/src/main/java/tel/schich/javacan/platform/Platform.java

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
public class Platform {
3939
private static final Logger LOGGER = LoggerFactory.getLogger(Platform.class);
4040

41+
public static final String LINUX_LIBRARY_PREFIX = "lib";
4142
private static final String LIB_PREFIX = "/native";
4243
private static final String PATH_PROP_PREFIX = "javacan.native.";
4344
private static final String PATH_PROP_FS_PATH = ".path";
@@ -70,6 +71,30 @@ public static void loadNativeLibrary(String name, Class<?> base) {
7071
}
7172
}
7273

74+
public static String classPathPropertyNameForLibrary(String name) {
75+
return PATH_PROP_PREFIX + name.toLowerCase() + PATH_PROP_CLASS_PATH;
76+
}
77+
78+
public static String detectCpuArch() {
79+
String arch = System.getProperty("os.arch").toLowerCase();
80+
if (arch.contains("arm")) {
81+
return "armv7";
82+
} else if (arch.contains("86") || arch.contains("amd")) {
83+
if (arch.contains("64")) {
84+
return "x86_64";
85+
}
86+
return "x86_32";
87+
} else if (arch.contains("riscv")) {
88+
if (arch.contains("64")) {
89+
return "riscv64";
90+
}
91+
return "riscv32";
92+
} else if (arch.contains("aarch64") || arch.contains("arm64")) {
93+
return "aarch64";
94+
}
95+
return arch;
96+
}
97+
7398
private static void loadExplicitLibrary(String name, Class<?> base) {
7499
String explicitLibraryPath = System.getProperty(PATH_PROP_PREFIX + name.toLowerCase() + PATH_PROP_FS_PATH);
75100
if (explicitLibraryPath != null) {
@@ -78,25 +103,25 @@ private static void loadExplicitLibrary(String name, Class<?> base) {
78103
return;
79104
}
80105

81-
String explicitLibraryClassPath = System.getProperty(PATH_PROP_PREFIX + name.toLowerCase() + PATH_PROP_CLASS_PATH);
106+
String explicitLibraryClassPath = System.getProperty(classPathPropertyNameForLibrary(name));
82107
if (explicitLibraryClassPath != null) {
83108
LOGGER.trace("Loading native library {} from explicit classpath at {}", name, explicitLibraryClassPath);
84109
try {
85110
final Path tempDirectory = Files.createTempDirectory(name + "-");
86-
final Path libPath = tempDirectory.resolve("lib" + name + ".so");
111+
final Path libPath = tempDirectory.resolve(LINUX_LIBRARY_PREFIX + name + ".so");
87112
loadFromClassPath(name, base, explicitLibraryClassPath, libPath);
88113
return;
89114
} catch (IOException e) {
90115
throw new LinkageError("Unable to load native library " + name + "!", e);
91116
}
92117
}
93118

94-
final String sourceLibPath = LIB_PREFIX + "/lib" + name + ".so";
119+
final String sourceLibPath = LIB_PREFIX + "/" + LINUX_LIBRARY_PREFIX + name + ".so";
95120
LOGGER.trace("Loading native library {} from {}", name, sourceLibPath);
96121

97122
try {
98123
final Path tempDirectory = Files.createTempDirectory(name + "-");
99-
final Path libPath = tempDirectory.resolve("lib" + name + ".so");
124+
final Path libPath = tempDirectory.resolve(LINUX_LIBRARY_PREFIX + name + ".so");
100125
loadFromClassPath(name, base, sourceLibPath, libPath);
101126
} catch (IOException e) {
102127
throw new LinkageError("Unable to load native library " + name + "!", e);

epoll-arch-detect/pom.xml

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
5+
<parent>
6+
<groupId>tel.schich</groupId>
7+
<artifactId>javacan</artifactId>
8+
<version>3.2.6-SNAPSHOT</version>
9+
</parent>
10+
11+
<artifactId>javacan-epoll-arch-detect</artifactId>
12+
13+
<dependencies>
14+
<dependency>
15+
<groupId>tel.schich</groupId>
16+
<artifactId>javacan-epoll</artifactId>
17+
<version>${project.version}</version>
18+
</dependency>
19+
</dependencies>
20+
21+
<build>
22+
<plugins>
23+
<plugin>
24+
<groupId>org.apache.maven.plugins</groupId>
25+
<artifactId>maven-dependency-plugin</artifactId>
26+
<version>3.6.1</version>
27+
<executions>
28+
<execution>
29+
<id>resource-dependencies</id>
30+
<phase>compile</phase>
31+
<goals>
32+
<goal>unpack</goal>
33+
</goals>
34+
<configuration>
35+
<artifactItems>
36+
<artifactItem>
37+
<groupId>tel.schich</groupId>
38+
<artifactId>javacan-epoll</artifactId>
39+
<version>${project.version}</version>
40+
<classifier>x86_64</classifier>
41+
<type>jar</type>
42+
<outputDirectory>${project.build.outputDirectory}/x86_64</outputDirectory>
43+
</artifactItem>
44+
<artifactItem>
45+
<groupId>tel.schich</groupId>
46+
<artifactId>javacan-epoll</artifactId>
47+
<version>${project.version}</version>
48+
<classifier>x86_32</classifier>
49+
<type>jar</type>
50+
<outputDirectory>${project.build.outputDirectory}/x86_32</outputDirectory>
51+
</artifactItem>
52+
<artifactItem>
53+
<groupId>tel.schich</groupId>
54+
<artifactId>javacan-epoll</artifactId>
55+
<version>${project.version}</version>
56+
<classifier>armv6</classifier>
57+
<type>jar</type>
58+
<outputDirectory>${project.build.outputDirectory}/armv6</outputDirectory>
59+
</artifactItem>
60+
<artifactItem>
61+
<groupId>tel.schich</groupId>
62+
<artifactId>javacan-epoll</artifactId>
63+
<version>${project.version}</version>
64+
<classifier>armv7</classifier>
65+
<type>jar</type>
66+
<outputDirectory>${project.build.outputDirectory}/armv7</outputDirectory>
67+
</artifactItem>
68+
<artifactItem>
69+
<groupId>tel.schich</groupId>
70+
<artifactId>javacan-epoll</artifactId>
71+
<version>${project.version}</version>
72+
<classifier>armv7a</classifier>
73+
<type>jar</type>
74+
<outputDirectory>${project.build.outputDirectory}/armv7a</outputDirectory>
75+
</artifactItem>
76+
<artifactItem>
77+
<groupId>tel.schich</groupId>
78+
<artifactId>javacan-epoll</artifactId>
79+
<version>${project.version}</version>
80+
<classifier>armv7l</classifier>
81+
<type>jar</type>
82+
<outputDirectory>${project.build.outputDirectory}/armv7l</outputDirectory>
83+
</artifactItem>
84+
<artifactItem>
85+
<groupId>tel.schich</groupId>
86+
<artifactId>javacan-epoll</artifactId>
87+
<version>${project.version}</version>
88+
<classifier>aarch64</classifier>
89+
<type>jar</type>
90+
<outputDirectory>${project.build.outputDirectory}/aarch64</outputDirectory>
91+
</artifactItem>
92+
<artifactItem>
93+
<groupId>tel.schich</groupId>
94+
<artifactId>javacan-epoll</artifactId>
95+
<version>${project.version}</version>
96+
<classifier>riscv32</classifier>
97+
<type>jar</type>
98+
<outputDirectory>${project.build.outputDirectory}/riscv32</outputDirectory>
99+
</artifactItem>
100+
<artifactItem>
101+
<groupId>tel.schich</groupId>
102+
<artifactId>javacan-epoll</artifactId>
103+
<version>${project.version}</version>
104+
<classifier>riscv64</classifier>
105+
<type>jar</type>
106+
<outputDirectory>${project.build.outputDirectory}/riscv64</outputDirectory>
107+
</artifactItem>
108+
</artifactItems>
109+
<includes>native/**</includes>
110+
</configuration>
111+
</execution>
112+
</executions>
113+
</plugin>
114+
</plugins>
115+
</build>
116+
</project>

0 commit comments

Comments
 (0)