diff --git a/build.gradle b/build.gradle index 85880b1..9bac741 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,6 @@ plugins { id 'jacoco' id 'maven-publish' - alias catalog.plugins.multi.release.jar alias catalog.plugins.envelope apply false alias catalog.plugins.lombok apply false } @@ -17,8 +16,8 @@ allprojects { java { modularity.inferModulePath = true toolchain { - languageVersion = JavaLanguageVersion.of(21) - vendor = JvmVendorSpec.ORACLE + languageVersion = JavaLanguageVersion.of(25) + vendor = JvmVendorSpec.GRAAL_VM } } @@ -48,10 +47,12 @@ allprojects { dependencies { implementation catalog.xz + compileOnly catalog.lombok testImplementation catalog.junit.jupiter.api testImplementation catalog.junit.jupiter.params testRuntimeOnly catalog.junit.jupiter.engine + testRuntimeOnly catalog.junit.platform.launcher } test { diff --git a/gradle.properties b/gradle.properties index 084b881..dd6ffaa 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ org.gradle.caching=true -wson.version = 2025.01.21 -lys.version = 2025.01.17 +wson.version = 2026.03.12 +lys.version = 2026.02.19 gitea.maven.url = https://gitea.woggioni.net/api/packages/woggioni/maven diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index cea7a79..dbc3ce4 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.0-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index 1aa94a4..adff685 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -84,7 +86,7 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -112,7 +114,6 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -170,7 +171,6 @@ fi # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) @@ -203,15 +203,14 @@ fi DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # and any embedded shellness will be escaped. # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. diff --git a/gradlew.bat b/gradlew.bat index 7101f8e..e509b2d 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @@ -68,11 +70,10 @@ goto fail :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell diff --git a/settings.gradle b/settings.gradle index a5f683d..a351cfb 100644 --- a/settings.gradle +++ b/settings.gradle @@ -6,7 +6,6 @@ pluginManagement { includeGroup 'net.woggioni.gradle' includeGroup 'net.woggioni.gradle.lombok' includeGroup 'net.woggioni.gradle.envelope' - includeGroup 'net.woggioni.gradle.multi-release-jar' includeGroup 'net.woggioni.gradle.graalvm.native-image' includeGroup 'net.woggioni.gradle.graalvm.jlink' includeGroup 'net.woggioni.gradle.sambal' @@ -28,6 +27,7 @@ dependencyResolutionManagement { versionCatalogs { catalog { from group: 'com.lys', name: 'lys-catalog', version: getProperty('lys.version') + version('my-gradle-plugins', '2026.02.23') } } } diff --git a/src/main/java9/module-info.java b/src/main/java/module-info.java similarity index 100% rename from src/main/java9/module-info.java rename to src/main/java/module-info.java diff --git a/wcfg/build.gradle b/wcfg/build.gradle index 7618aef..05d31f5 100644 --- a/wcfg/build.gradle +++ b/wcfg/build.gradle @@ -1,7 +1,6 @@ plugins { id 'antlr' id 'jacoco' - alias catalog.plugins.multi.release.jar } configurations { diff --git a/wcfg/src/main/java9/module-info.java b/wcfg/src/main/java/module-info.java similarity index 100% rename from wcfg/src/main/java9/module-info.java rename to wcfg/src/main/java/module-info.java diff --git a/wson-cli/build.gradle b/wson-cli/build.gradle index 21b8ab8..5c37876 100644 --- a/wson-cli/build.gradle +++ b/wson-cli/build.gradle @@ -1,14 +1,13 @@ plugins { id 'maven-publish' id 'jacoco' - alias catalog.plugins.multi.release.jar alias catalog.plugins.envelope alias catalog.plugins.graalvm.native.image alias catalog.plugins.sambal } - -import net.woggioni.gradle.graalvm.NativeImageTask import net.woggioni.gradle.envelope.EnvelopeJarTask +import net.woggioni.gradle.envelope.EnvelopePlugin +import net.woggioni.gradle.graalvm.* import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform dependencies { @@ -19,9 +18,12 @@ dependencies { implementation project(':wcfg') } -application { - mainClass = 'net.woggioni.wson.cli.WsonCli' - mainModule = 'net.woggioni.wson.cli' +Property mainClassName = objects.property(String.class).convention('net.woggioni.wson.cli.WsonCli') +Property mainModuleName = objects.property(String.class).convention('net.woggioni.wson.cli') + +envelopeJar { + mainClass = mainClassName + mainModule = mainModuleName } compileJava { @@ -33,17 +35,16 @@ compileJava { options.javaModuleVersion = project.version } -configureNativeImage { -// args = [ -// 'wson', -// '-f', -// '../test-utils/src/main/resources/wordpress.json', -// '-t', -// 'jbon', -// '-o', -// '/dev/null' -// ] - +tasks.named(NativeImagePlugin.CONFIGURE_NATIVE_IMAGE_TASK_NAME, NativeImageConfigurationTask) { + toolchain { + languageVersion = JavaLanguageVersion.of(25) + vendor = JvmVendorSpec.GRAAL_VM + } + mainClass = mainClassName + mainModule = mainModuleName + mergeConfiguration = true + modularity.inferModulePath = true + enabled = true args = [ 'wcfg', '-f', @@ -53,24 +54,34 @@ configureNativeImage { '-o', '/dev/null' ] - - mergeConfiguration = true } -Provider envelopeJarTaskProvider = tasks.named('envelopeJar') - -Provider nativeImageTaskProvider = tasks.named("nativeImage") { +nativeImage { + toolchain { + languageVersion = JavaLanguageVersion.of(25) + vendor = JvmVendorSpec.GRAAL_VM + } + mainClass = mainClassName + mainModule = mainModuleName useMusl = true buildStaticImage = true + linkAtBuildTime = false + compressExecutable = true + compressionLevel = 6 + useLZMA = false } -tasks.named(BasePlugin.ASSEMBLE_TASK_NAME, Task) { - inputs.files(nativeImageTaskProvider) +Provider upxTaskProvider = tasks.named(NativeImagePlugin.UPX_TASK_NAME, UpxTask) { +} + +Provider envelopeJarTaskProvider = tasks.named(EnvelopePlugin.ENVELOPE_JAR_TASK_NAME, EnvelopeJarTask.class) { + mainModule = mainModuleName + mainClass = mainClassName } artifacts { - archives nativeImageTaskProvider.map(NativeImageTask.&getOutputFile) - archives envelopeJarTaskProvider.map(EnvelopeJarTask.&getArchiveFile) + add('archives', upxTaskProvider) + add('archives', envelopeJarTaskProvider) } publishing { @@ -78,10 +89,10 @@ publishing { maven(MavenPublication) { artifact envelopeJar def host = DefaultNativePlatform.host() - artifact( - source: nativeImageTaskProvider, - classifier: host.operatingSystem.name + '-' + host.architecture.name - ) + artifact(upxTaskProvider) { + extension = "exe" + classifier = host.operatingSystem.name + '-' + host.architecture.name + } } } } diff --git a/wson-cli/native-image/reachability-metadata.json b/wson-cli/native-image/reachability-metadata.json new file mode 100644 index 0000000..ea25f01 --- /dev/null +++ b/wson-cli/native-image/reachability-metadata.json @@ -0,0 +1,635 @@ +{ + "reflection": [ + { + "type": "com.sun.crypto.provider.AESCipher$General", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "type": "com.sun.crypto.provider.ARCFOURCipher", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "type": "com.sun.crypto.provider.ChaCha20Cipher$ChaCha20Poly1305", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "type": "com.sun.crypto.provider.DESCipher", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "type": "com.sun.crypto.provider.DESedeCipher", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "type": "com.sun.crypto.provider.GaloisCounterMode$AESGCM", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "type": "groovy.lang.Closure" + }, + { + "type": "java.lang.Boolean", + "jniAccessible": true, + "methods": [ + { + "name": "getBoolean", + "parameterTypes": [ + "java.lang.String" + ] + } + ] + }, + { + "type": "java.lang.Object", + "allDeclaredFields": true + }, + { + "type": "java.nio.file.Path" + }, + { + "type": "java.nio.file.Paths", + "methods": [ + { + "name": "get", + "parameterTypes": [ + "java.lang.String", + "java.lang.String[]" + ] + } + ] + }, + { + "type": "java.security.AlgorithmParametersSpi" + }, + { + "type": "java.security.KeyStoreSpi" + }, + { + "type": "java.security.SecureRandomParameters" + }, + { + "type": "java.sql.Connection" + }, + { + "type": "java.sql.Driver" + }, + { + "type": "java.sql.DriverManager", + "methods": [ + { + "name": "getConnection", + "parameterTypes": [ + "java.lang.String" + ] + }, + { + "name": "getDriver", + "parameterTypes": [ + "java.lang.String" + ] + } + ] + }, + { + "type": "java.sql.Time", + "methods": [ + { + "name": "", + "parameterTypes": [ + "long" + ] + } + ] + }, + { + "type": "java.sql.Timestamp", + "methods": [ + { + "name": "valueOf", + "parameterTypes": [ + "java.lang.String" + ] + } + ] + }, + { + "type": "java.time.Duration", + "methods": [ + { + "name": "parse", + "parameterTypes": [ + "java.lang.CharSequence" + ] + } + ] + }, + { + "type": "java.time.Instant", + "methods": [ + { + "name": "parse", + "parameterTypes": [ + "java.lang.CharSequence" + ] + } + ] + }, + { + "type": "java.time.LocalDate", + "methods": [ + { + "name": "parse", + "parameterTypes": [ + "java.lang.CharSequence" + ] + } + ] + }, + { + "type": "java.time.LocalDateTime", + "methods": [ + { + "name": "parse", + "parameterTypes": [ + "java.lang.CharSequence" + ] + } + ] + }, + { + "type": "java.time.LocalTime", + "methods": [ + { + "name": "parse", + "parameterTypes": [ + "java.lang.CharSequence" + ] + } + ] + }, + { + "type": "java.time.MonthDay", + "methods": [ + { + "name": "parse", + "parameterTypes": [ + "java.lang.CharSequence" + ] + } + ] + }, + { + "type": "java.time.OffsetDateTime", + "methods": [ + { + "name": "parse", + "parameterTypes": [ + "java.lang.CharSequence" + ] + } + ] + }, + { + "type": "java.time.OffsetTime", + "methods": [ + { + "name": "parse", + "parameterTypes": [ + "java.lang.CharSequence" + ] + } + ] + }, + { + "type": "java.time.Period", + "methods": [ + { + "name": "parse", + "parameterTypes": [ + "java.lang.CharSequence" + ] + } + ] + }, + { + "type": "java.time.Year", + "methods": [ + { + "name": "parse", + "parameterTypes": [ + "java.lang.CharSequence" + ] + } + ] + }, + { + "type": "java.time.YearMonth", + "methods": [ + { + "name": "parse", + "parameterTypes": [ + "java.lang.CharSequence" + ] + } + ] + }, + { + "type": "java.time.ZoneId", + "methods": [ + { + "name": "of", + "parameterTypes": [ + "java.lang.String" + ] + } + ] + }, + { + "type": "java.time.ZoneOffset", + "methods": [ + { + "name": "of", + "parameterTypes": [ + "java.lang.String" + ] + } + ] + }, + { + "type": "java.time.ZonedDateTime", + "methods": [ + { + "name": "parse", + "parameterTypes": [ + "java.lang.CharSequence" + ] + } + ] + }, + { + "type": "javax.security.auth.x500.X500Principal", + "fields": [ + { + "name": "thisX500Name" + } + ], + "methods": [ + { + "name": "", + "parameterTypes": [ + "sun.security.x509.X500Name" + ] + } + ] + }, + { + "type": "net.woggioni.wson.cli.OutputTypeConverter", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "type": "net.woggioni.wson.cli.SerializationTypeConverter", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "type": "net.woggioni.wson.cli.VersionProvider", + "allDeclaredFields": true, + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "type": "net.woggioni.wson.cli.WcfgCommand", + "allDeclaredFields": true, + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "type": "net.woggioni.wson.cli.WsonCli", + "allDeclaredFields": true + }, + { + "type": "net.woggioni.wson.cli.WsonCommand", + "allDeclaredFields": true, + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "type": "org.slf4j.simple.SimpleServiceProvider" + }, + { + "type": "sun.security.pkcs12.PKCS12KeyStore", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "type": "sun.security.pkcs12.PKCS12KeyStore$DualFormatPKCS12", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "type": "sun.security.provider.JavaKeyStore$JKS", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "type": "sun.security.provider.NativePRNG", + "methods": [ + { + "name": "", + "parameterTypes": [] + }, + { + "name": "", + "parameterTypes": [ + "java.security.SecureRandomParameters" + ] + } + ] + }, + { + "type": "sun.security.provider.SHA", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "type": "sun.security.provider.X509Factory", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "type": "sun.security.rsa.RSAKeyFactory$Legacy", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "type": "sun.security.ssl.KeyManagerFactoryImpl$SunX509", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "type": "sun.security.ssl.SSLContextImpl$DefaultSSLContext", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "type": "sun.security.ssl.TrustManagerFactoryImpl$PKIXFactory", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "type": "sun.security.x509.AuthorityInfoAccessExtension", + "methods": [ + { + "name": "", + "parameterTypes": [ + "java.lang.Boolean", + "java.lang.Object" + ] + } + ] + }, + { + "type": "sun.security.x509.AuthorityKeyIdentifierExtension", + "methods": [ + { + "name": "", + "parameterTypes": [ + "java.lang.Boolean", + "java.lang.Object" + ] + } + ] + }, + { + "type": "sun.security.x509.BasicConstraintsExtension", + "methods": [ + { + "name": "", + "parameterTypes": [ + "java.lang.Boolean", + "java.lang.Object" + ] + } + ] + }, + { + "type": "sun.security.x509.CRLDistributionPointsExtension", + "methods": [ + { + "name": "", + "parameterTypes": [ + "java.lang.Boolean", + "java.lang.Object" + ] + } + ] + }, + { + "type": "sun.security.x509.CertificatePoliciesExtension", + "methods": [ + { + "name": "", + "parameterTypes": [ + "java.lang.Boolean", + "java.lang.Object" + ] + } + ] + }, + { + "type": "sun.security.x509.ExtendedKeyUsageExtension", + "methods": [ + { + "name": "", + "parameterTypes": [ + "java.lang.Boolean", + "java.lang.Object" + ] + } + ] + }, + { + "type": "sun.security.x509.IssuerAlternativeNameExtension", + "methods": [ + { + "name": "", + "parameterTypes": [ + "java.lang.Boolean", + "java.lang.Object" + ] + } + ] + }, + { + "type": "sun.security.x509.KeyUsageExtension", + "methods": [ + { + "name": "", + "parameterTypes": [ + "java.lang.Boolean", + "java.lang.Object" + ] + } + ] + }, + { + "type": "sun.security.x509.NetscapeCertTypeExtension", + "methods": [ + { + "name": "", + "parameterTypes": [ + "java.lang.Boolean", + "java.lang.Object" + ] + } + ] + }, + { + "type": "sun.security.x509.PrivateKeyUsageExtension", + "methods": [ + { + "name": "", + "parameterTypes": [ + "java.lang.Boolean", + "java.lang.Object" + ] + } + ] + }, + { + "type": "sun.security.x509.SubjectAlternativeNameExtension", + "methods": [ + { + "name": "", + "parameterTypes": [ + "java.lang.Boolean", + "java.lang.Object" + ] + } + ] + }, + { + "type": "sun.security.x509.SubjectKeyIdentifierExtension", + "methods": [ + { + "name": "", + "parameterTypes": [ + "java.lang.Boolean", + "java.lang.Object" + ] + } + ] + } + ], + "resources": [ + { + "glob": "META-INF/MANIFEST.MF" + }, + { + "glob": "META-INF/services/java.lang.System$LoggerFinder" + }, + { + "glob": "META-INF/services/java.net.spi.URLStreamHandlerProvider" + }, + { + "glob": "META-INF/services/java.time.zone.ZoneRulesProvider" + }, + { + "glob": "META-INF/services/org.slf4j.spi.SLF4JServiceProvider" + }, + { + "glob": "simplelogger.properties" + }, + { + "module": "net.woggioni.wson.cli", + "glob": "META-INF/MANIFEST.MF" + } + ] +} \ No newline at end of file diff --git a/wson-cli/src/main/java9/module-info.java b/wson-cli/src/main/java/module-info.java similarity index 100% rename from wson-cli/src/main/java9/module-info.java rename to wson-cli/src/main/java/module-info.java diff --git a/wson-cli/src/main/java/net/woggioni/wson/cli/AbstractVersionProvider.java b/wson-cli/src/main/java/net/woggioni/wson/cli/AbstractVersionProvider.java index ed598c2..879b549 100644 --- a/wson-cli/src/main/java/net/woggioni/wson/cli/AbstractVersionProvider.java +++ b/wson-cli/src/main/java/net/woggioni/wson/cli/AbstractVersionProvider.java @@ -20,18 +20,14 @@ abstract class AbstractVersionProvider implements CommandLine.IVersionProvider { protected AbstractVersionProvider(String specificationTitle) { String version = null; String vcsHash = null; - Enumeration it = getClass().getClassLoader().getResources(JarFile.MANIFEST_NAME); - while (it.hasMoreElements()) { - URL manifestURL = it.nextElement(); - Manifest mf = new Manifest(); - try (InputStream inputStream = manifestURL.openStream()) { - mf.read(inputStream); - } - Attributes mainAttributes = mf.getMainAttributes(); - if (Objects.equals(specificationTitle, mainAttributes.getValue(Attributes.Name.SPECIFICATION_TITLE))) { - version = mainAttributes.getValue(Attributes.Name.SPECIFICATION_VERSION); - vcsHash = mainAttributes.getValue(Attributes.Name.IMPLEMENTATION_VERSION); - } + final Manifest mf = new Manifest(); + try(InputStream is = getClass().getModule().getResourceAsStream(JarFile.MANIFEST_NAME)) { + mf.read(is); + } + Attributes mainAttributes = mf.getMainAttributes(); + if (Objects.equals(specificationTitle, mainAttributes.getValue(Attributes.Name.SPECIFICATION_TITLE))) { + version = mainAttributes.getValue(Attributes.Name.SPECIFICATION_VERSION); + vcsHash = mainAttributes.getValue(Attributes.Name.IMPLEMENTATION_VERSION); } if (version == null || vcsHash == null) { throw new RuntimeException("Version information not found in manifest");