fusesource / jansi

Jansi is a small java library that allows you to use ANSI escape sequences to format your console output which works even on windows.
http://fusesource.github.io/jansi/
Apache License 2.0
1.1k stars 139 forks source link

Support static native images (fix #246) #270

Open Glavo opened 9 months ago

Glavo commented 9 months ago

This PR provides a new implementation of AnsiConsoleSupport. It uses the native image C interface to implement isatty and uses the stty size command to implement getTerminalWidth.

I'm temporarily naming the provider musl, but that's not an appropriate name and I'll change it later.

Glavo commented 9 months ago

@rsenden It's working!

glavo@glavo-desktop /m/d/P/j/s/target (stty)> native-image --static --libc=musl -Djansi.providers=musl -jar ./jansi-2.4.1-SNAPSHOT.jar
========================================================================================================================
GraalVM Native Image: Generating 'jansi-2.4.1-SNAPSHOT' (static executable)...
========================================================================================================================
[1/8] Initializing...                                                                                    (2.6s @ 0.14GB)
 Java version: 21+35, vendor version: Oracle GraalVM 21+35.1
 Graal compiler: optimization level: 2, target machine: x86-64-v3, PGO: ML-inferred
 C compiler: x86_64-linux-musl-gcc (linux, x86_64, 10.2.1)
 Garbage collector: Serial GC (max heap size: 80% of RAM)
 2 user-specific feature(s):
 - com.oracle.svm.thirdparty.gson.GsonFeature
 - org.fusesource.jansi.internal.NativeImageFeature
------------------------------------------------------------------------------------------------------------------------
Build resources:
 - 26.49GB of memory (41.5% of 63.78GB system memory, determined at start)
 - 16 thread(s) (100.0% of 16 available processor(s), determined at start)
[2/8] Performing analysis...  [****]                                                                     (4.0s @ 0.32GB)
    3,476 reachable types   (72.6% of    4,785 total)
    4,239 reachable fields  (50.8% of    8,343 total)
   18,030 reachable methods (47.4% of   38,027 total)
    1,076 types,   112 fields, and   678 methods registered for reflection
       72 types,   174 fields, and   134 methods registered for JNI access
        4 native libraries: dl, pthread, rt, z
[3/8] Building universe...                                                                               (0.8s @ 0.50GB)
[4/8] Parsing methods...      [*]                                                                        (1.5s @ 0.70GB)
[5/8] Inlining methods...     [***]                                                                      (0.3s @ 0.54GB)
[6/8] Compiling methods...    [***]                                                                      (8.1s @ 0.47GB)
[7/8] Layouting methods...    [*]                                                                        (1.3s @ 0.39GB)
[8/8] Creating image...       [*]                                                                        (1.3s @ 0.47GB)
   7.38MB (47.54%) for code area:     9,327 compilation units
   7.75MB (49.95%) for image heap:  123,075 objects and 35 resources
 399.45kB ( 2.51%) for other data
  15.52MB in total
------------------------------------------------------------------------------------------------------------------------
Top 10 origins of code area:                                Top 10 object types in image heap:
   5.13MB java.base                                            1.93MB byte[] for code metadata
   1.55MB svm.jar (Native Image)                               1.49MB byte[] for java.lang.String
 175.72kB jansi-2.4.1-SNAPSHOT.jar                           925.41kB java.lang.String
 145.67kB java.logging                                       690.28kB java.lang.Class
 132.50kB com.oracle.svm.svm_enterprise                      415.92kB heap alignment
  42.09kB jdk.proxy1                                         299.72kB java.util.HashMap$Node
  41.55kB jdk.proxy3                                         250.95kB byte[] for general heap data
  29.36kB org.graalvm.nativeimage.base                       178.65kB byte[] for reflection metadata
  28.88kB org.graalvm.collections                            162.94kB com.oracle.svm.core.hub.DynamicHubCompanion
  21.54kB jdk.internal.vm.ci                                 155.34kB byte[] for embedded resources
  31.12kB for 4 more packages                                  1.33MB for 952 more object types
                              Use '-H:+BuildReport' to create a report with more details.
------------------------------------------------------------------------------------------------------------------------
Security report:
 - Binary includes Java deserialization.
 - Use '--enable-sbom' to embed a Software Bill of Materials (SBOM) in the binary.
------------------------------------------------------------------------------------------------------------------------
Recommendations:
 G1GC: Use the G1 GC ('--gc=G1') for improved latency and throughput.
 PGO:  Use Profile-Guided Optimizations ('--pgo') for improved throughput.
 INIT: Adopt '-H:+StrictImageHeap' to prepare for the next GraalVM release.
 HEAP: Set max heap for improved and more predictable memory usage.
 CPU:  Enable more CPU features with '-march=native' for improved performance.
------------------------------------------------------------------------------------------------------------------------
                        1.3s (6.0% of total time) in 179 GCs | Peak RSS: 1.34GB | CPU load: 9.81
------------------------------------------------------------------------------------------------------------------------
Produced artifacts:
 /mnt/d/Projects/jansi/stty/target/jansi-2.4.1-SNAPSHOT (executable)
========================================================================================================================
Finished generating 'jansi-2.4.1-SNAPSHOT' in 20.5s.
glavo@glavo-desktop /m/d/P/j/s/target (stty)> ./jansi-2.4.1-SNAPSHOT
Jansi 2.4.1-SNAPSHOT

jansi.providers= musl
Selected provider: musl

os.name= Linux, os.version= 4.4.0-22621-Microsoft, os.arch= amd64
file.encoding= UTF-8
sun.stdout.encoding= null, sun.stderr.encoding= null
stdout.encoding= UTF-8, stderr.encoding= UTF-8
java.version= 21, java.vendor= Oracle Corporation, java.home= null

jansi.graceful=
jansi.mode=
jansi.out.mode=
jansi.err.mode=
jansi.colors=
jansi.out.colors=
jansi.err.colors=
jansi.passthrough= false
jansi.strip= false
jansi.force= false
jansi.noreset= false
org.fusesource.jansi.Ansi.disable= false

IS_WINDOWS: false

isatty(STDOUT_FILENO): 1, System.out is a terminal
width(STDOUT_FILENO): 229
isatty(STDERR_FILENO): 1, System.err is a terminal
width(STDERR_FILENO): 229

Resulting Jansi modes for stout/stderr streams:
  - System.out: AnsiPrintStream{type=Native, colors=Colors256, mode=Default, resetAtUninstall=true}
  - System.err: AnsiPrintStream{type=Native, colors=Colors256, mode=Default, resetAtUninstall=true}
Processor types description:
  - Native: Supports ansi sequences natively
  - Unsupported: Ansi sequences are stripped out
  - VirtualTerminal: Supported through windows virtual terminal
  - Emulation: Emulated through using windows API console commands
  - Redirected: The stream is redirected to a file or a pipe
Colors support description:
  - Colors16: 16 colors
  - Colors256: 256 colors
  - TrueColor: 24-bit colors
Modes description:
  - Strip: Strip all ansi sequences
  - Default: Print ansi sequences if the stream is a terminal
  - Force: Always print ansi sequences, even if the stream is redirected

image

Glavo commented 9 months ago

I have updated this PR and hope to have it reviewed again.

However, before it is merged, I would like to rename the provider. musl is not an appropriate name as it also works with glibc or macOS.

Glavo commented 9 months ago

I finally decided to rename the provider to native-image.

rsenden commented 9 months ago

@Glavo Many thanks for working on this, looking forward to see this included in an upcoming Jansi release.