Skip to content

Commit 592efc4

Browse files
committed
Make spikes into maven projects
1 parent fa789a3 commit 592efc4

11 files changed

Lines changed: 498 additions & 9 deletions

File tree

1917-java-embed-rust-cli-runtime-remove-before-merge/20260723-prompts.md

Lines changed: 91 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@ It must be a standalone Java program that produces an executable jar I can invok
3838

3939
### 18:22 Prompt
4040

41-
42-
4341
In this session, we are reducing the ignorance in the `copilot-sdk/1917-java-embed-rust-cli-runtime-remove-before-merge/1917-embed-cli-runtime-ignorance-reduction-plan.md` by working through the items in Section 3 for which we do not yet have a **Resolution:**. For starters, read and understand that whole document.
4442

4543
Today we start with ### 3.6 — Platform detection implementation
@@ -153,3 +151,94 @@ Running it with:
153151
`java -jar spike-3-6-platform-detection-darwin-arm64.jar`
154152

155153
prints detected platform details by default; on this machine it logs `arch=arm64` and `classifier=darwin-arm64`.
154+
155+
### 18:37 Prompt
156+
157+
In this session, we are reducing the ignorance in the `copilot-sdk/1917-java-embed-rust-cli-runtime-remove-before-merge/1917-embed-cli-runtime-ignorance-reduction-plan.md` by working through the items in Section 3 for which we do not yet have a **Resolution:**. For starters, read and understand that whole document.
158+
159+
Today we start with ### 3.6 — Platform detection implementation
160+
161+
> **Question:** What is the exact implementation of platform detection, particularly the ELF PT_INTERP parsing for musl vs. glibc on Linux?
162+
>
163+
> ADR-007 specifies reading the first 2 KB of `/proc/self/exe` and parsing the ELF PT_INTERP segment. This is the same approach as the `detect-libc` npm package.
164+
>
165+
> **Open questions:**
166+
>
167+
> 1. Can we read `/proc/self/exe` from Java? (`/proc/self/exe` is a symlink to the JVM binary — on glibc Linux it will contain the glibc dynamic linker path, on Alpine/musl it will contain the musl path.)
168+
> 2. Should the detector be in a standalone utility class (reusable) or inline in the loader?
169+
> 3. Edge case: What about container environments where `/proc` is mounted but the JVM binary is from a different libc than the container's userspace? (This shouldn't happen in practice — the JVM must match the libc.)
170+
>
171+
> **Spike needed:** Write a Java snippet that parses ELF PT_INTERP from `/proc/self/exe` on a glibc Linux system and on Alpine. Verify the dynamic linker paths match expectations (`/lib64/ld-linux-x86-64.so.2` vs. `/lib/ld-musl-x86_64.so.1`).
172+
>
173+
> **Recommendation:** Standalone `PlatformDetector` class in `com.github.copilot.ffi` with methods `detectOs()`, `detectArch()`, `detectLinuxLibc()`, `detectClassifier()`. Pure Java, no dependencies. Unit-testable with mocked system properties and test ELF binaries.
174+
175+
Platform detection needs to work on all supported tuples specified in the Platform dimensions section of `copilot-sdk/java/docs/adr/adr-007-native-bundling-strategy.md`.
176+
177+
Now, we happening to be running now on.
178+
179+
180+
| Platform label | Rust triple | Constraint |
181+
| ----------------- | ---------------------------- | ---------------------------------------------------------------- |
182+
| `linux-x64` | `x86_64-unknown-linux-gnu` | [glibc](#references) ≥ 2.28 (Debian 10+, Ubuntu 20.04+, RHEL 8+) |
183+
184+
Let's start spiking with this one. Create the spike in `copilot-sdk/1917-java-embed-rust-cli-runtime-remove-before-merge/spike-3-6-platform-detection-linux-x64`.
185+
186+
It must be a standalone Java program that produces an executable jar I can invoke with `java -jar spike-3-6-platform-detection-linux-x64.jar` and when it runs it shows the detected arch. We need to detect enough information so that we can select the corresponding binary content contained in the classifier jar as shown in section 3.1 of `copilot-sdk/1917-java-embed-rust-cli-runtime-remove-before-merge/1917-embed-cli-runtime-ignorance-reduction-plan.md`. The spike program must use java.util.logging such that the output is printed by default.
187+
188+
Note that `copilot-sdk/1917-java-embed-rust-cli-runtime-remove-before-merge/spike-3-6-platform-detection-darwin-arm64` already exists and is the spike for `darwin-arm64`. That was built when running on that hardware.
189+
190+
You are now running on linux-x64 hardware.
191+
192+
Now, here is where all that ELF and `/proc/self/exe` stuff comes into play. Consider that for inclusion in your spike.
193+
194+
### 18:45 Response
195+
196+
Good, I have a clear picture of the darwin-arm64 spike. Now I'll create the linux-x64 version. The code is identical (it's the same `PlatformDetector` logic), just packaged for running on linux-x64. I'll create the directory structure, copy the source, build it, and run it.
197+
198+
Shell Create spike directory structure 1 line…
199+
mkdir -p /home/edburns/workareas/copilot-sdk/1917-java-embed-rust-cli-runtime-remove-before-merge/spike-3-6-platfo…
200+
201+
Create PlatformDetector.java +242
202+
Create PlatformDetectionSpikeMain.java +55
203+
Create README.md +43
204+
205+
Now let me build and run the spike:
206+
207+
Shell Check Java availability 4 lines…
208+
export JAVA_HOME="/Library/Java/JavaVirtualMachines/microsoft-25.jdk/Contents/Home" && export PATH="${JAVA_HOME}/b…
209+
Shell Build the spike jar 2 lines…
210+
export JAVA_HOME="/Library/Java/JavaVirtualMachines/microsoft-25.jdk/Contents/Home" && export PATH="${JAVA_HOME}/b…
211+
Shell Run the spike jar 19 lines…
212+
export JAVA_HOME="/Library/Java/JavaVirtualMachines/microsoft-25.jdk/Contents/Home" && export PATH="${JAVA_HOME}/b…
213+
214+
The spike is working perfectly. All key findings confirmed:
215+
216+
Spike 3.6 results on linux-x64:
217+
218+
┌───────────────┬─────────────────────────────┐
219+
│ Detection │ Result │
220+
├───────────────┼─────────────────────────────┤
221+
│ os │ linux │
222+
├───────────────┼─────────────────────────────┤
223+
│ arch │ x64 │
224+
├───────────────┼─────────────────────────────┤
225+
│ linuxLibc │ GLIBC │
226+
├───────────────┼─────────────────────────────┤
227+
│ classifier │ linux-x64 │
228+
├───────────────┼─────────────────────────────┤
229+
│ ELF PT_INTERP │ /lib64/ld-linux-x86-64.so.2 │
230+
└───────────────┴─────────────────────────────┘
231+
232+
Key answers to the open questions from section 3.6:
233+
234+
1. Can we read `/proc/self/exe` from Java? — ✅ Yes. `Files.newInputStream(Path.of("/proc/self/exe"))` works fine. The JVM binary is an ELF64 executable linked against glibc, and `PT_INTERP` is at offset within the first 2 KB.
235+
2. Does the ELF parsing correctly identify glibc? — ✅ Yes. The dynamic linker path `/lib64/ld-linux-x86-64.so.2` is correctly extracted and matched as glibc.
236+
3. Classifier maps to correct resource path — `native/linux-x64/runtime.node` matches the expected layout from section 3.1.
237+
238+
The spike is at:
239+
240+
1917-java-embed-rust-cli-runtime-remove-before-merge/spike-3-6-platform-detection-linux-x64/
241+
242+
Run it with:
243+
244+
java -jar spike-3-6-platform-detection-linux-x64.jar

1917-java-embed-rust-cli-runtime-remove-before-merge/spike-3-6-platform-detection-darwin-arm64/README.md

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,11 @@ It includes ELF `PT_INTERP` parsing from `/proc/self/exe` for Linux musl/glibc d
1212
## Build
1313

1414
```sh
15-
mkdir -p out/classes
16-
javac -d out/classes $(find src/main/java -name '*.java')
17-
jar --create \
18-
--file spike-3-6-platform-detection-darwin-arm64.jar \
19-
--main-class com.github.copilot.spike.platform.PlatformDetectionSpikeMain \
20-
-C out/classes .
15+
mvn clean package
2116
```
2217

2318
## Run
2419

2520
```sh
26-
java -jar spike-3-6-platform-detection-darwin-arm64.jar
21+
java -jar target/spike-3-6-platform-detection-darwin-arm64.jar
2722
```
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<groupId>com.github.copilot.spike</groupId>
8+
<artifactId>spike-3-6-platform-detection-darwin-arm64</artifactId>
9+
<version>1.0-SNAPSHOT</version>
10+
<packaging>jar</packaging>
11+
12+
<properties>
13+
<maven.compiler.source>17</maven.compiler.source>
14+
<maven.compiler.target>17</maven.compiler.target>
15+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
16+
</properties>
17+
18+
<build>
19+
<plugins>
20+
<plugin>
21+
<groupId>org.apache.maven.plugins</groupId>
22+
<artifactId>maven-jar-plugin</artifactId>
23+
<version>3.3.0</version>
24+
<configuration>
25+
<archive>
26+
<manifest>
27+
<mainClass>com.github.copilot.spike.platform.PlatformDetectionSpikeMain</mainClass>
28+
</manifest>
29+
</archive>
30+
<finalName>spike-3-6-platform-detection-darwin-arm64</finalName>
31+
</configuration>
32+
</plugin>
33+
</plugins>
34+
</build>
35+
</project>
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Spike 3.6 — Platform detection (linux-x64)
2+
3+
This spike is a standalone Java program that detects:
4+
5+
- OS (`darwin`, `linux`, `win32`)
6+
- arch (`x64`, `arm64`)
7+
- Linux libc (`GLIBC`, `MUSL`, `UNKNOWN`) via ELF `PT_INTERP` parsing of `/proc/self/exe`
8+
- final runtime classifier (for `native/<classifier>/runtime.node`)
9+
10+
On this platform (linux-x64 glibc), it exercises the ELF parsing path and verifies
11+
that `/proc/self/exe` resolves to the JVM binary, whose `PT_INTERP` segment contains
12+
the glibc dynamic linker path `/lib64/ld-linux-x86-64.so.2`.
13+
14+
## Build
15+
16+
```sh
17+
mvn clean package
18+
```
19+
20+
## Run
21+
22+
```sh
23+
java -jar target/spike-3-6-platform-detection-linux-x64.jar
24+
```
25+
26+
## Expected output (glibc linux-x64)
27+
28+
```
29+
INFO: Detected os=linux
30+
INFO: Detected arch=x64
31+
INFO: Detected linuxLibc=GLIBC
32+
INFO: Detected classifier=linux-x64
33+
INFO: ELF PT_INTERP=/lib64/ld-linux-x86-64.so.2
34+
INFO: PASS: PT_INTERP matches expected glibc x86_64 dynamic linker
35+
INFO: --- Spike result ---
36+
INFO: Classifier for native binary selection: linux-x64
37+
INFO: Resource path would be: native/linux-x64/runtime.node
38+
```
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<groupId>com.github.copilot.spike</groupId>
8+
<artifactId>spike-3-6-platform-detection-linux-x64</artifactId>
9+
<version>1.0-SNAPSHOT</version>
10+
<packaging>jar</packaging>
11+
12+
<properties>
13+
<maven.compiler.source>17</maven.compiler.source>
14+
<maven.compiler.target>17</maven.compiler.target>
15+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
16+
</properties>
17+
18+
<build>
19+
<plugins>
20+
<plugin>
21+
<groupId>org.apache.maven.plugins</groupId>
22+
<artifactId>maven-jar-plugin</artifactId>
23+
<version>3.3.0</version>
24+
<configuration>
25+
<archive>
26+
<manifest>
27+
<mainClass>com.github.copilot.spike.platform.PlatformDetectionSpikeMain</mainClass>
28+
</manifest>
29+
</archive>
30+
<finalName>spike-3-6-platform-detection-linux-x64</finalName>
31+
</configuration>
32+
</plugin>
33+
</plugins>
34+
</build>
35+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package com.github.copilot.spike.platform;
2+
3+
import java.io.IOException;
4+
import java.nio.file.Path;
5+
import java.util.logging.Level;
6+
import java.util.logging.Logger;
7+
8+
/**
9+
* Entry point for platform detection spike on linux-x64.
10+
*
11+
* Demonstrates that we can read /proc/self/exe, parse the ELF PT_INTERP
12+
* segment, and determine whether the JVM is linked against glibc or musl.
13+
*/
14+
public final class PlatformDetectionSpikeMain {
15+
private static final Logger LOGGER = Logger.getLogger(PlatformDetectionSpikeMain.class.getName());
16+
17+
private PlatformDetectionSpikeMain() {
18+
}
19+
20+
public static void main(String[] args) {
21+
String os = PlatformDetector.detectOs();
22+
String arch = PlatformDetector.detectArch();
23+
PlatformDetector.LinuxLibc libc = PlatformDetector.detectLinuxLibc();
24+
String classifier = PlatformDetector.detectClassifier();
25+
26+
LOGGER.log(Level.INFO, "Detected os={0}", os);
27+
LOGGER.log(Level.INFO, "Detected arch={0}", arch);
28+
LOGGER.log(Level.INFO, "Detected linuxLibc={0}", libc);
29+
LOGGER.log(Level.INFO, "Detected classifier={0}", classifier);
30+
31+
if ("linux".equals(os)) {
32+
try {
33+
String interp = PlatformDetector.readElfPtInterp(Path.of("/proc/self/exe"));
34+
LOGGER.log(Level.INFO, "ELF PT_INTERP={0}", interp);
35+
36+
// Verify expectations for linux-x64 glibc
37+
if (interp.contains("/ld-linux-x86-64.so.2")) {
38+
LOGGER.log(Level.INFO, "PASS: PT_INTERP matches expected glibc x86_64 dynamic linker");
39+
} else if (interp.contains("/ld-musl-x86_64.so.1")) {
40+
LOGGER.log(Level.INFO, "PASS: PT_INTERP matches expected musl x86_64 dynamic linker");
41+
} else {
42+
LOGGER.log(Level.WARNING, "UNEXPECTED: PT_INTERP does not match known linker paths: {0}", interp);
43+
}
44+
} catch (IOException ex) {
45+
LOGGER.log(Level.WARNING, "Unable to parse PT_INTERP from /proc/self/exe: " + ex.getMessage(), ex);
46+
}
47+
} else {
48+
LOGGER.log(Level.INFO, "Not on Linux — skipping ELF PT_INTERP parsing");
49+
}
50+
51+
LOGGER.log(Level.INFO, "--- Spike result ---");
52+
LOGGER.log(Level.INFO, "Classifier for native binary selection: {0}", classifier);
53+
LOGGER.log(Level.INFO, "Resource path would be: native/{0}/runtime.node", classifier);
54+
}
55+
}

0 commit comments

Comments
 (0)