2
0

Move native implementation build into masterpassword-core

This commit is contained in:
Maarten Billemont 2018-05-25 13:08:05 -04:00
parent cc82e52c33
commit 3b24e1d1b8
28 changed files with 115 additions and 89 deletions

44
core/c/build.gradle Normal file
View File

@ -0,0 +1,44 @@
import org.gradle.internal.jvm.Jvm
plugins {
id 'cpp-library'
id 'xcode'
id 'visual-studio'
}
description = 'Master Password Algorithm Implementation'
library {
linkage.set( [Linkage.STATIC, Linkage.SHARED] )
binaries.configureEach {
// Reconfigure the toolchain from C++ to C.
compileTask.get().source.setFrom( fileTree( dir: "src", include: "**/*.c" ) )
if (toolChain instanceof VisualCpp) {
compileTask.get().compilerArgs = ["/TC"]
} else if (toolChain instanceof GccCompatibleToolChain) {
compileTask.get().compilerArgs = ["-x", "c", "-std=c11"]
//linkTask.get().linkerArgs = ["-nodefaultlibs", "-lc"]
}
// Resolve our standard naming for OS platforms.
def platform = System.getProperty( "os.name" ).toLowerCase( Locale.ROOT )
if (platform.startsWith( "mac" ))
platform = "macos"
project.dependencies {
// Depend on JDK for JNI support.
add( includePathConfiguration.name,
files( new File( Jvm.current().javaHome, "include" ) ) { first().eachDir { from it } } )
// Depend on libsodium from `lib`; run `lib/bin/build_libsodium-${os}` first.
add( includePathConfiguration.name,
files( "../../lib/libsodium/build-${platform}~/out/include" ) )
add( linkLibraries.name,
fileTree( "../../lib/libsodium/build-${platform}~/out/lib" ) )
}
compileTask.get().compilerArgs.add "-DMPW_SODIUM=1"
}
}

View File

@ -1,4 +1,4 @@
#include "jni_mpw.h" #include "mpw-jni.h"
/** native int _scrypt(byte[] passwd, int passwdlen, byte[] salt, int saltlen, int N, int r, int p, byte[] buf, int buflen); */ /** native int _scrypt(byte[] passwd, int passwdlen, byte[] salt, int saltlen, int N, int r, int p, byte[] buf, int buflen); */
JNIEXPORT jint JNICALL Java_com_lyndir_masterpassword_impl_MPAlgorithmV0__1scrypt(JNIEnv *env, jobject obj, JNIEXPORT jint JNICALL Java_com_lyndir_masterpassword_impl_MPAlgorithmV0__1scrypt(JNIEnv *env, jobject obj,

View File

@ -1,78 +1,27 @@
plugins { plugins {
id 'java' id 'java-library'
id 'c'
} }
description = 'Master Password Algorithm Implementation' description = 'Master Password Algorithm Implementation'
configurations {
resource
}
dependencies { dependencies {
compile( group: 'com.lyndir.lhunath.opal', name: 'opal-system', version: '1.7-p1' ) { implementation group: 'com.lyndir.lhunath.opal', name: 'opal-system', version: '1.7-p1'
exclude( module: 'joda-time' )
}
compile 'com.fasterxml.jackson.core:jackson-annotations:2.9.5' api( group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: '2.9.5' )
compile group: 'org.jetbrains', name: 'annotations', version: '13.0' api group: 'org.jetbrains', name: 'annotations', version: '13.0'
compile group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.1' api group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.1'
resource project( path: ':masterpassword-core', configuration: 'releaseSharedRuntimeElements' )
} }
processResources { jar {
dependsOn 'mpwSharedLibrary' dependsOn task( type: Sync, 'copyResources' ) {
} from files( configurations.resource )
into processResources.outputs.files.singleFile
// TODO: nativeGenHeaders should run prior to mpwSharedLibrary
// TODO: but that creates a cyclic dependency since processResources runs before compileJava which nativeGenHeaders depends on.
//task mpwSharedLibrary {
// dependsOn processResources
//}
build {
// dependsOn 'mpwSharedLibrary'
dependsOn 'nativeGenHeaders'
}
task nativeGenHeaders {
description "Uses javah to regenerate the JNI header files"
inputs.file sourceSets.main.output.asFileTree.matching {
include 'com/lyndir/masterpassword/impl/MPAlgorithmV0.class'
}
outputs.file 'src/mpw/c/jni_mpw.h'
def classpath = files( sourceSets.main.compileClasspath, sourceSets.main.output )
doLast {
ant.javah( class: 'com.lyndir.masterpassword.impl.MPAlgorithmV0',
outputFile: 'src/mpw/c/jni_mpw.h',
classpath: classpath.asPath )
}
}
model {
components {
mpw( NativeLibrarySpec ) {
binaries.all {
if (targetPlatform.operatingSystem.macOsX) {
cCompiler.args '-I', "${org.gradle.internal.jvm.Jvm.current().javaHome}/include"
cCompiler.args '-I', "${org.gradle.internal.jvm.Jvm.current().javaHome}/include/darwin"
cCompiler.args '-mmacosx-version-min=10.4'
linker.args '-mmacosx-version-min=10.4'
} else if (targetPlatform.operatingSystem.linux) {
cCompiler.args '-I', "${org.gradle.internal.jvm.Jvm.current().javaHome}/include"
cCompiler.args '-I', "${org.gradle.internal.jvm.Jvm.current().javaHome}/include/linux"
cCompiler.args '-D_FILE_OFFSET_BITS=64'
} else if (targetPlatform.operatingSystem.windows) {
cCompiler.args "-I${org.gradle.internal.jvm.Jvm.current().javaHome}/include"
cCompiler.args "-I${org.gradle.internal.jvm.Jvm.current().javaHome}/include/win32"
linker.args "Shlwapi.lib", "Advapi32.lib"
} else if (targetPlatform.operatingSystem.freeBSD) {
cCompiler.args '-I', "${org.gradle.internal.jvm.Jvm.current().javaHome}/include"
cCompiler.args '-I', "${org.gradle.internal.jvm.Jvm.current().javaHome}/include/freebsd"
}
}
// TODO: Can't we add the sharedLibraryFile to the resources through some kind of task dependency instead?
binaries.withType( SharedLibraryBinarySpec ) {
sourceSets.main.resources.srcDirs it.sharedLibraryFile.parent
// copy {
// from sharedLibraryFile
// to sourceSets.main.resources.outputDir
// }
}
}
} }
} }

View File

@ -18,42 +18,67 @@
package com.lyndir.masterpassword.impl; package com.lyndir.masterpassword.impl;
import com.google.common.base.Joiner;
import com.google.common.io.ByteStreams; import com.google.common.io.ByteStreams;
import com.lyndir.lhunath.opal.system.logging.Logger; import com.lyndir.lhunath.opal.system.logging.Logger;
import java.io.*; import java.io.*;
import java.util.Locale;
import javax.annotation.Nonnull;
/** /**
* @author lhunath, 2018-05-22 * @author lhunath, 2018-05-22
*/ */
public final class Native { public final class Native {
private static final Logger logger = Logger.get( Native.class ); private static final Logger logger = Logger.get( Native.class );
private static final char FILE_DOT = '.'; @SuppressWarnings("HardcodedFileSeparator")
private static final String NATIVES_PATH = ""; private static final char RESOURCE_SEPARATOR = '/';
private static final char EXTENSION_SEPARATOR = '.';
private static final String NATIVES_PATH = "lib";
@SuppressWarnings({ "HardcodedFileSeparator", "LoadLibraryWithNonConstantString" }) @SuppressWarnings({ "HardcodedFileSeparator", "LoadLibraryWithNonConstantString" })
public static void load(final Class<?> context, final String name) { public static void load(final Class<?> context, final String name) {
try { try {
// Find and open a stream to the packaged library resource.
String library = System.mapLibraryName( name ); String library = System.mapLibraryName( name );
int libraryDot = library.lastIndexOf( FILE_DOT ); int libraryDot = library.lastIndexOf( EXTENSION_SEPARATOR );
String libraryName = (libraryDot > 0)? library.substring( 0, libraryDot ): library; String libraryName = (libraryDot > 0)? library.substring( 0, libraryDot ): library;
String libraryExtension = (libraryDot > 0)? library.substring( libraryDot ): "lib"; String libraryExtension = (libraryDot > 0)? library.substring( libraryDot ): ".lib";
String libraryResource = String.format( "%s/%s", NATIVES_PATH, library ); String libraryResource = getLibraryResource( library );
InputStream libraryStream = context.getResourceAsStream( libraryResource ); InputStream libraryStream = context.getResourceAsStream( libraryResource );
if (libraryStream == null) if (libraryStream == null)
throw new IllegalStateException( throw new IllegalStateException(
"Library: " + name + " (" + libraryResource + "), not found in class loader for: " + context ); "Library: " + name + " (" + libraryResource + "), not found in class loader for: " + context );
File libraryFile = File.createTempFile( "libmpw", ".dylib" ); // Write the library resource to a temporary file.
ByteStreams.copy( libraryStream, new FileOutputStream( libraryFile ) ); File libraryFile = File.createTempFile( libraryName, libraryExtension );
FileOutputStream libraryFileStream = new FileOutputStream( libraryFile );
try {
libraryFile.deleteOnExit();
ByteStreams.copy( libraryStream, libraryFileStream );
}
finally {
libraryFileStream.close();
libraryStream.close();
}
// Load the library from the temporary file.
System.load( libraryFile.getAbsolutePath() ); System.load( libraryFile.getAbsolutePath() );
libraryFile.deleteOnExit();
if (!libraryFile.delete())
logger.wrn( "Couldn't clean up library after loading: " + libraryFile );
} }
catch (final IOException e) { catch (final IOException e) {
throw new IllegalStateException( "Couldn't load library: " + name, e ); throw new IllegalStateException( "Couldn't extract library: " + name, e );
} }
} }
@Nonnull
private static String getLibraryResource(final String library) {
String system = System.getProperty( "os.name" ).toLowerCase( Locale.ROOT );
String architecture = System.getProperty( "os.arch" ).toLowerCase( Locale.ROOT );
if ("Mac OS X".equalsIgnoreCase( system ))
system = "macos";
return Joiner.on( RESOURCE_SEPARATOR ).join( NATIVES_PATH, system, architecture, library );
}
} }

View File

@ -1,19 +1,22 @@
plugins { plugins {
id 'java' id 'java-library'
id 'net.ltgt.apt' version '0.9' id 'net.ltgt.apt' version '0.9'
} }
description = 'Master Password Site Model' description = 'Master Password Site Model'
dependencies { dependencies {
compile project( ':masterpassword-algorithm' ) implementation group: 'com.lyndir.lhunath.opal', name: 'opal-system', version: '1.7-p1'
compile 'joda-time:joda-time:2.4' implementation 'com.fasterxml.jackson.core:jackson-core:2.9.5'
compile 'com.fasterxml.jackson.core:jackson-core:2.9.5'
compile 'com.fasterxml.jackson.core:jackson-annotations:2.9.5' api project( ':masterpassword-algorithm' )
compile 'com.fasterxml.jackson.core:jackson-databind:2.9.5' api 'joda-time:joda-time:2.4'
//compile group: 'com.google.code.gson', name: 'gson', version: '2.8.2' api 'com.fasterxml.jackson.core:jackson-annotations:2.9.5'
api 'com.fasterxml.jackson.core:jackson-databind:2.9.5'
compileOnly 'com.google.auto.value:auto-value:1.2' compileOnly 'com.google.auto.value:auto-value:1.2'
apt group: 'com.google.auto.value', name: 'auto-value', version: '1.2' apt group: 'com.google.auto.value', name: 'auto-value', version: '1.2'
testCompile 'org.testng:testng:6.8.5' testCompile 'org.testng:testng:6.8.5'
testCompile 'ch.qos.logback:logback-classic:1.1.2' testCompile 'ch.qos.logback:logback-classic:1.1.2'
} }

View File

@ -5,6 +5,8 @@ plugins {
description = 'Master Password Test Suite' description = 'Master Password Test Suite'
dependencies { dependencies {
implementation group: 'com.lyndir.lhunath.opal', name: 'opal-system', version: '1.7-p1'
compile project( ':masterpassword-algorithm' ) compile project( ':masterpassword-algorithm' )
compile project( ':masterpassword-model' ) compile project( ':masterpassword-model' )

Binary file not shown.

View File

@ -1,6 +1,5 @@
#Thu Apr 26 12:52:02 EDT 2018
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.7-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.3-all.zip

View File

@ -6,6 +6,9 @@ try {
} catch (FileNotFoundException ignored) { } catch (FileNotFoundException ignored) {
} }
include 'masterpassword-core'
project(':masterpassword-core').projectDir = new File( '../core/c' )
include 'masterpassword-algorithm' include 'masterpassword-algorithm'
project(':masterpassword-algorithm').projectDir = new File( '../core/java/algorithm' ) project(':masterpassword-algorithm').projectDir = new File( '../core/java/algorithm' )
@ -18,9 +21,10 @@ project(':masterpassword-tests').projectDir = new File( '../core/java/tests' )
include 'masterpassword-gui' include 'masterpassword-gui'
project(':masterpassword-gui').projectDir = new File( '../platform-independent/gui-java' ) project(':masterpassword-gui').projectDir = new File( '../platform-independent/gui-java' )
/*
if (local.containsKey('sdk.dir')) { if (local.containsKey('sdk.dir')) {
include 'masterpassword-android' include 'masterpassword-android'
project(':masterpassword-android').projectDir = new File( '../platform-android' ) project(':masterpassword-android').projectDir = new File( '../platform-android' )
} else { } else {
logger.warn( "Skipping masterpassword-android since sdk.dir is not defined in local.properties." ) logger.warn( "Skipping masterpassword-android since sdk.dir is not defined in local.properties." )
} }*/