Skip to content

Commit

Permalink
Support static native images
Browse files Browse the repository at this point in the history
  • Loading branch information
Glavo committed Oct 9, 2023
1 parent 9d60bc5 commit 43767fc
Show file tree
Hide file tree
Showing 12 changed files with 301 additions and 48 deletions.
23 changes: 19 additions & 4 deletions src/main/java/org/fusesource/jansi/AnsiConsole.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@
import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;

import org.fusesource.jansi.internal.MingwSupport;
import org.fusesource.jansi.internal.OSInfo;
import org.fusesource.jansi.internal.stty.Stty;
import org.fusesource.jansi.io.AnsiOutputStream;
import org.fusesource.jansi.io.AnsiProcessor;
import org.fusesource.jansi.io.FastBufferedOutputStream;
Expand Down Expand Up @@ -173,6 +173,22 @@ public class AnsiConsole {
* The name of the {@code ffm} provider.
*/
public static final String JANSI_PROVIDER_FFM = "ffm";
/**
* The name of the {@code stty} provider.
*/
public static final String JANSI_PROVIDER_STTY = "stty";

/**
* The name of the {@code native-image} provider.
* <p>This provider uses the
* <a href="https://www.graalvm.org/latest/reference-manual/native-image/native-code-interoperability/C-API/">Native Image C API</a>
* to call native functions, so it is only available when building to native image.
* Additionally, this provider currently does not support Windows.
* <p>Note: This is not the only provider available on Native Image,
* and it is usually recommended to use ffm or jni provider.
* This provider is mainly used when building static native images linked to musl libc.
*/
public static final String JANSI_PROVIDER_NATIVE_IMAGE = "native-image";

/**
* @deprecated this field will be made private in a future release, use {@link #sysOut()} instead
Expand Down Expand Up @@ -306,10 +322,9 @@ private static AnsiPrintStream ansiStream(boolean stdout) {
processor = null;
type = AnsiType.Native;
installer = uninstaller = null;
MingwSupport mingw = new MingwSupport();
String name = mingw.getConsoleName(stdout);
String name = Stty.getConsoleName(stdout);
if (name != null && !name.isEmpty()) {
width = () -> mingw.getTerminalWidth(name);
width = () -> Stty.getTerminalWidth(name);
} else {
width = () -> -1;
}
Expand Down
7 changes: 3 additions & 4 deletions src/main/java/org/fusesource/jansi/AnsiMain.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
import org.fusesource.jansi.internal.AnsiConsoleSupport;
import org.fusesource.jansi.internal.AnsiConsoleSupportHolder;
import org.fusesource.jansi.internal.JansiLoader;
import org.fusesource.jansi.internal.MingwSupport;
import org.fusesource.jansi.internal.stty.Stty;

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.fusesource.jansi.Ansi.ansi;
Expand Down Expand Up @@ -208,11 +208,10 @@ private static void diagnoseTty(boolean stderr) {
long console = AnsiConsoleSupportHolder.getKernel32().getStdHandle(!stderr);
isatty = AnsiConsoleSupportHolder.getKernel32().isTty(console);
if ((AnsiConsole.IS_CONEMU || AnsiConsole.IS_CYGWIN || AnsiConsole.IS_MSYSTEM) && isatty == 0) {
MingwSupport mingw = new MingwSupport();
String name = mingw.getConsoleName(!stderr);
String name = Stty.getConsoleName(!stderr);
if (name != null && !name.isEmpty()) {
isatty = 1;
width = mingw.getTerminalWidth(name);
width = Stty.getTerminalWidth(name);
} else {
isatty = 0;
width = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,10 @@ private static AnsiConsoleSupport findProvider(String providerList) {
RuntimeException error = null;

for (String provider : providers) {
String className = "org.fusesource.jansi.internal." + provider.replace("-", "") + ".AnsiConsoleSupportImpl";
try {
return (AnsiConsoleSupport)
Class.forName("org.fusesource.jansi.internal." + provider + ".AnsiConsoleSupportImpl")
.getConstructor()
.newInstance();
Class.forName(className).getConstructor().newInstance();
} catch (Throwable t) {
if (error == null) {
error = new RuntimeException("Unable to create AnsiConsoleSupport provider");
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/org/fusesource/jansi/internal/OSInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,10 @@ public static boolean isWindows() {
return System.getProperty("os.name").toLowerCase(Locale.ROOT).contains("win");
}

public static boolean isMacOS() {
return System.getProperty("os.name").toLowerCase(Locale.ROOT).contains("mac");
}

public static boolean isAndroid() {
return System.getProperty("java.runtime.name", "")
.toLowerCase(Locale.ROOT)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.lang.foreign.MemorySegment;
import java.lang.foreign.ValueLayout;

import org.fusesource.jansi.AnsiConsole;
import org.fusesource.jansi.internal.AnsiConsoleSupport;
import org.fusesource.jansi.internal.OSInfo;
import org.fusesource.jansi.io.AnsiProcessor;
Expand All @@ -30,7 +31,7 @@
public final class AnsiConsoleSupportImpl extends AnsiConsoleSupport {

public AnsiConsoleSupportImpl() {
super("ffm");
super(AnsiConsole.JANSI_PROVIDER_FFM);
}

public AnsiConsoleSupportImpl(boolean checkNativeAccess) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;

import org.fusesource.jansi.AnsiConsole;
import org.fusesource.jansi.internal.AnsiConsoleSupport;
import org.fusesource.jansi.io.AnsiProcessor;
import org.fusesource.jansi.io.WindowsAnsiProcessor;
Expand All @@ -36,7 +37,7 @@
public final class AnsiConsoleSupportImpl extends AnsiConsoleSupport {

public AnsiConsoleSupportImpl() {
super("jni");
super(AnsiConsole.JANSI_PROVIDER_JNI);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright (C) 2009-2023 the original author(s).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fusesource.jansi.internal.nativeimage;

import org.fusesource.jansi.AnsiConsole;
import org.fusesource.jansi.internal.AnsiConsoleSupport;
import org.fusesource.jansi.internal.OSInfo;
import org.fusesource.jansi.internal.stty.SttyCLibrary;
import org.graalvm.nativeimage.c.type.CTypeConversion;

public final class AnsiConsoleSupportImpl extends AnsiConsoleSupport {

public AnsiConsoleSupportImpl() {
super(AnsiConsole.JANSI_PROVIDER_NATIVE_IMAGE);

if (!OSInfo.isInImageCode()) {
throw new UnsupportedOperationException("This provider is only available in native images");
}

if (OSInfo.isWindows()) {
throw new UnsupportedOperationException("This provider is currently unavailable on Windows");
}
}

@Override
protected CLibrary createCLibrary() {
String stdoutTty = CTypeConversion.toJavaString(PosixCLibrary.ttyname(CLibrary.STDOUT_FILENO));
String stderrTty = CTypeConversion.toJavaString(PosixCLibrary.ttyname(CLibrary.STDERR_FILENO));

return new SttyCLibrary(stdoutTty, stderrTty) {
@Override
public int isTty(int fd) {
return PosixCLibrary.isatty(fd);
}
};
}

@Override
protected Kernel32 createKernel32() {
throw new UnsupportedOperationException();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright (C) 2009-2023 the original author(s).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fusesource.jansi.internal.nativeimage;

import org.graalvm.nativeimage.c.CContext;
import org.graalvm.nativeimage.c.function.CFunction;
import org.graalvm.nativeimage.c.type.CCharPointer;

@CContext(PosixDirectives.class)
final class PosixCLibrary {
@CFunction(transition = CFunction.Transition.NO_TRANSITION)
public static native int isatty(int fd);

@CFunction(transition = CFunction.Transition.NO_TRANSITION)
public static native CCharPointer ttyname(int fd);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright (C) 2009-2023 the original author(s).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fusesource.jansi.internal.nativeimage;

import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.c.CContext;

public class PosixDirectives implements CContext.Directives {
@Override
public boolean isInConfiguration() {
return Platform.includedIn(Platform.LINUX.class) || Platform.includedIn(Platform.MACOS.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright (C) 2009-2023 the original author(s).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fusesource.jansi.internal.stty;

import org.fusesource.jansi.AnsiConsole;
import org.fusesource.jansi.internal.AnsiConsoleSupport;

public final class AnsiConsoleSupportImpl extends AnsiConsoleSupport {
public AnsiConsoleSupportImpl() {
super(AnsiConsole.JANSI_PROVIDER_STTY);
}

@Override
protected CLibrary createCLibrary() {
return new SttyCLibrary(Stty.getConsoleName(true), Stty.getConsoleName(false));
}

@Override
protected Kernel32 createKernel32() {
throw new UnsupportedOperationException();
}
}
Loading

0 comments on commit 43767fc

Please sign in to comment.