Native libraries: (issue #624)

- publish to maven central
- load from same location as flatlaf.jar (if available, otherwise extract from jar to temporary directory)
This commit is contained in:
Karl Tauber
2023-01-21 18:29:05 +01:00
parent 9b62b8395f
commit 35e23574cf
3 changed files with 93 additions and 7 deletions

View File

@@ -15,10 +15,13 @@
*/ */
open class NativeArtifact( val fileName: String, val classifier: String, val type: String ) {}
open class PublishExtension { open class PublishExtension {
var artifactId: String? = null var artifactId: String? = null
var name: String? = null var name: String? = null
var description: String? = null var description: String? = null
var nativeArtifacts: List<NativeArtifact>? = null
} }
val extension = project.extensions.create<PublishExtension>( "flatlafPublish" ) val extension = project.extensions.create<PublishExtension>( "flatlafPublish" )
@@ -71,6 +74,15 @@ publishing {
url.set( "https://github.com/JFormDesigner/FlatLaf/issues" ) url.set( "https://github.com/JFormDesigner/FlatLaf/issues" )
} }
} }
afterEvaluate {
extension.nativeArtifacts?.forEach {
artifact( artifacts.add( "archives", file( it.fileName ) ) {
classifier = it.classifier
type = it.type
} )
}
}
} }
} }

View File

@@ -14,6 +14,8 @@
* limitations under the License. * limitations under the License.
*/ */
import Flatlaf_publish_gradle.NativeArtifact
plugins { plugins {
`java-library` `java-library`
`flatlaf-toolchain` `flatlaf-toolchain`
@@ -123,4 +125,11 @@ flatlafPublish {
artifactId = "flatlaf" artifactId = "flatlaf"
name = "FlatLaf" name = "FlatLaf"
description = "Flat Look and Feel" description = "Flat Look and Feel"
val natives = "src/main/resources/com/formdev/flatlaf/natives"
nativeArtifacts = listOf(
NativeArtifact( "${natives}/flatlaf-windows-x86.dll", "windows-x86", "dll" ),
NativeArtifact( "${natives}/flatlaf-windows-x86_64.dll", "windows-x86_64", "dll" ),
NativeArtifact( "${natives}/libflatlaf-linux-x86_64.so", "linux-x86_64", "so" ),
)
} }

View File

@@ -17,6 +17,7 @@
package com.formdev.flatlaf.ui; package com.formdev.flatlaf.ui;
import java.io.File; import java.io.File;
import java.net.URL;
import com.formdev.flatlaf.FlatSystemProperties; import com.formdev.flatlaf.FlatSystemProperties;
import com.formdev.flatlaf.util.LoggingFacade; import com.formdev.flatlaf.util.LoggingFacade;
import com.formdev.flatlaf.util.NativeLibrary; import com.formdev.flatlaf.util.NativeLibrary;
@@ -46,13 +47,13 @@ class FlatNativeLibrary
if( nativeLibrary != null ) if( nativeLibrary != null )
return; return;
String libraryName; String classifier;
String ext;
if( SystemInfo.isWindows_10_orLater && (SystemInfo.isX86 || SystemInfo.isX86_64) ) { if( SystemInfo.isWindows_10_orLater && (SystemInfo.isX86 || SystemInfo.isX86_64) ) {
// Windows: requires Windows 10/11 (x86 or x86_64) // Windows: requires Windows 10/11 (x86 or x86_64)
libraryName = "flatlaf-windows-x86"; classifier = SystemInfo.isX86_64 ? "windows-x86_64" : "windows-x86";
if( SystemInfo.isX86_64 ) ext = "dll";
libraryName += "_64";
// In Java 8, load jawt.dll (part of JRE) explicitly because it // In Java 8, load jawt.dll (part of JRE) explicitly because it
// is not found when running application with <jdk>/bin/java.exe. // is not found when running application with <jdk>/bin/java.exe.
@@ -64,7 +65,8 @@ class FlatNativeLibrary
} else if( SystemInfo.isLinux && SystemInfo.isX86_64 ) { } else if( SystemInfo.isLinux && SystemInfo.isX86_64 ) {
// Linux: requires x86_64 // Linux: requires x86_64
libraryName = "flatlaf-linux-x86_64"; classifier = "linux-x86_64";
ext = "so";
// Load libjawt.so (part of JRE) explicitly because it is not found // Load libjawt.so (part of JRE) explicitly because it is not found
// in all Java versions/distributions. // in all Java versions/distributions.
@@ -76,10 +78,13 @@ class FlatNativeLibrary
return; // no native library available for current OS or CPU architecture return; // no native library available for current OS or CPU architecture
// load native library // load native library
nativeLibrary = createNativeLibrary( libraryName ); nativeLibrary = createNativeLibrary( classifier, ext );
} }
private static NativeLibrary createNativeLibrary( String libraryName ) { private static NativeLibrary createNativeLibrary( String classifier, String ext ) {
String libraryName = "flatlaf-" + classifier;
// load from "java.library.path" or from path specified in system property "flatlaf.nativeLibraryPath"
String libraryPath = System.getProperty( FlatSystemProperties.NATIVE_LIBRARY_PATH ); String libraryPath = System.getProperty( FlatSystemProperties.NATIVE_LIBRARY_PATH );
if( libraryPath != null ) { if( libraryPath != null ) {
if( "system".equals( libraryPath ) ) { if( "system".equals( libraryPath ) ) {
@@ -97,9 +102,69 @@ class FlatNativeLibrary
} }
} }
// load from beside the FlatLaf jar
// e.g. for flatlaf-3.1.jar, load flatlaf-3.1-windows-x86_64.dll (from same directory)
File libraryFile = findLibraryBesideJar( classifier, ext );
if( libraryFile != null )
return new NativeLibrary( libraryFile, true );
// load from FlatLaf jar (extract native library to temp folder)
return new NativeLibrary( "com/formdev/flatlaf/natives/" + libraryName, null, true ); return new NativeLibrary( "com/formdev/flatlaf/natives/" + libraryName, null, true );
} }
/**
* Search for a native library beside the jar that contains this class
* (usually the FlatLaf jar).
* The native library must be in the same directory (or in "../bin" if jar is in "lib")
* as the jar and have the same basename as the jar.
* If FlatLaf jar is repackaged into fat/uber application jar, "-flatlaf" is appended to jar basename.
* The classifier and the extension are appended to the jar basename.
*
* E.g.
* flatlaf-3.1.jar
* flatlaf-3.1-windows-x86_64.dll
* flatlaf-3.1-linux-x86_64.so
*/
private static File findLibraryBesideJar( String classifier, String ext ) {
try {
// get location of FlatLaf jar
URL jarUrl = FlatNativeLibrary.class.getProtectionDomain().getCodeSource().getLocation();
if( jarUrl == null )
return null;
File jarFile = new File( jarUrl.toURI() );
// if jarFile is a directory, then we're in a development environment
if( !jarFile.isFile() )
return null;
// build library file
String jarName = jarFile.getName();
String jarBasename = jarName.substring( 0, jarName.lastIndexOf( '.' ) );
File parent = jarFile.getParentFile();
String libraryName = jarBasename
+ (jarBasename.contains( "flatlaf" ) ? "" : "-flatlaf")
+ '-' + classifier + '.' + ext;
// check whether native library exists in same directory as jar
File libraryFile = new File( parent, libraryName );
if( libraryFile.isFile() )
return libraryFile;
// if jar is in "lib" directory, then also check whether library exists
// in "../bin" directory
if( parent.getName().equalsIgnoreCase( "lib" ) ) {
libraryFile = new File( parent.getParentFile(), "bin/" + libraryName );
if( libraryFile.isFile() )
return libraryFile;
}
} catch( Exception ex ) {
LoggingFacade.INSTANCE.logSevere( ex.getMessage(), ex );
}
return null;
}
private static void loadJAWT() { private static void loadJAWT() {
try { try {
System.loadLibrary( "jawt" ); System.loadLibrary( "jawt" );