Gradle 'maven-publish' 插件失败并出现 "unmappable character for encoding" 错误

Gradle 'maven-publish' plugin fails with "unmappable character for encoding" error

我最近将一个项目从 Maven 迁移到 Gradle(IE:用 build.gradle 文件替换了 pom.xml 文件)。由于我的公司仍然有几个依赖于它的下游 Maven 项目,我们必须继续将 pom 文件连同 class、源代码和 javadoc JAR 发布到我们的 Nexus 存储库,以便下游项目仍然可以使用该项目作为Maven 依赖。这就是 Gradle 的 'maven-publish' 插件的用途。这是我的 build.gradle 文件的样子,其中包含 maven-publish 插件的配置:

apply plugin: 'java'
apply plugin: 'maven-publish'

group = 'com.my.company'
version = 'myProduct-SNAPSHOT'

repositories {
    mavenLocal()
    maven { url 'http://nexus.my.company.net/nexus/content/repositories/build-test-release' }
    maven { url 'http://nexus.my.company.net/nexus/content/repositories/build-test-snapshot' }
    maven { url 'http://nexus.my.company.net/nexus/content/repositories/central' }
    maven { url 'http://nexus.my.company.net/nexus/content/repositories/thirdparty' }
}

dependencies {
    // Stuff
}

sourceSets {
    main {
        // Stuff
    }
}

task sourcesJar (type: Jar) {
    classifier = 'sources'
    from sourceSets.main.allJava
}

task javadocJar (type: Jar, dependsOn: javadoc) {
    classifier = 'javadoc'
    from javadoc.destinationDir
}

publishing {
    publications {
        mavenJars(MavenPublication) {

            // Classes
            from components.java

            // Sources
            artifact(sourcesJar) {
                classifier = 'sources'
            }

            // Javadoc
            artifact(javadocJar) {
                classifier = 'javadoc'
            }
        }
    }
    repositories {
        maven {
            url 'http://nexus.my.company.net/nexus/content/repositories/build-test-snapshot'
            credentials {
                username 'user'
                password 'password'
            }
        }
    }
}

这会生成一个 Gradle 'publish' 任务,该任务将生成所需的 pom.xml 文件以及 class、源代码和 javadoc JAR。完成后,它会将 jars 发布到 'build-test-snapshot' Nexus 存储库。

这在我的机器以及我们的构建服务器和我的大多数同事的机器上都运行良好。然而,一些同事一直在抱怨,因为 'gradlew publish' 命令(请注意,项目中包含 Gradle 2.4 包装器)在他们身上失败并出现如下错误:

C:\Users\user\Perforce\WORKSPACE\project\src\main\java\com\my\company\test\randomizati
on\RandomHelper.java:18: error: unmappable character for encoding Cp1252
    private static final String NON_ENGLISH_CHARACTERS = "1234567890─Ç─?─é─â─ä─à─å─ç─ê─ë─è─ï─î─?─Ä─?─?─æ─Æ─ô─ö─ò─û─ù─ÿ─Ö
─Ü─¢─£─?─₧─ƒ─á─í─ó─ú─ñ─Ñ─ª─º─¿─⌐─¬─½─¼─¡─«─»─░─▒─▓─│─┤─╡─╢─╖─╕─╣─║─╗─╝─╜─╛─┐┼Ç┼?┼é┼â┼ä┼à┼å┼ç┼ê┼ë┼è┼ï┼î┼?┼Ä┼?┼?┼æ┼Æ┼ô┼ö┼ò
┼û┼ù┼ÿ┼Ö┼Ü┼¢┼£┼?┼₧┼ƒ┼á┼í┼ó┼ú┼ñ┼Ñ┼ª┼º┼¿┼⌐┼¬┼½┼¼┼¡┼«┼»┼░┼▒┼▓┼│┼┤┼╡┼╢┼╖┼╕┼╣┼║┼╗┼╝┼╜┼╛┼┐╞Ç╞?╞é╞â╞ä╞à╞å╞ç╞ê╞ë╞è╞ï╞î╞?╞Ä╞?╞Æ╞á
╞í╞»╟?╟Ä╟?╟?╟æ╟Æ╟ô╟ö╟ò╟û╟ù╟ÿ╟Ö╟Ü╟¢╟£╟║╟╗╟╝╟╜╟╛╟┐├Ç├?├é├â├ä├à├å├ç├ê├ë├è├ï├î├?├Ä├?├?├æ├Æ├ô├ö├ò├û├ù├ÿ├Ö├Ü├¢├£├?├₧├ƒ├á├í├ó├ú
äåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ&-.*$";

有趣的是,'gradlew build' 命令(使用 javac 编译项目)在每个人的机器上执行得很好。 'gradlew publish' 命令在某些机器上有问题(在 Mac 和 Windows 上都通过或失败)。

我不知道这里的关键区别是什么,但我怀疑受影响的用户错误配置了他们的 Perforce 客户端(未指定 P4CHARSET)并且所有项目文件都使用默认编码同步到他们的机器。我不清楚如何检查同步时 Perforce 使用的编码,所以这只是一个理论。据我了解,即使他们修复了他们的配置,他们仍然需要清除他们的征兵并再次从 Perforce 服务器下载所有内容,以获取所有具有正确编码 (utf16le-bom) 的文件。

不管任何 Perforce 问题,责任都落在我身上,因为我是第一个将我们切换到 Gradle 的人。如果有某种方法可以配置 maven-publish 插件来解决这个问题,那么我更愿意这样做。如果 javac 可以将这些文件中的非标准字符编译成 classes 那么插件就没有理由不能读取它们并为它们生成 javadoc,对吗?也许需要明确告诉它使用什么编码?

我已经尝试在 JAVA_OPTS 和 GRADLE_OPTS 中使用 -Dfile.encoding=x-UTF-16LE-BOM 选项(这没有任何区别)。我还发现以下代码片段用于指定 Gradle 中 'Compile' 任务的编码:

tasks.withType(Compile) {
    options.encoding = 'x-UTF-16LE-BOM'
}

不幸的是,这是针对 'Compile' 任务的,项目已经编译成功。我不确定 maven-publish 插件生成什么类型​​的任务,所以我不知道如何将这种方法应用于这些任务(这可能吗?)。

还有什么我可以尝试让 Gradle maven-publish 插件停止因文件编码而绊倒?

在深入研究 Gradle API 之后,我想到了这个:

// Force character encoding in case the workspace was not set up correctly
tasks.withType(Javadoc) {
    options.encoding = 'x-UTF-16LE-BOM'
}

这解决了以前在 运行 'gradlew publish' 时因编码错误而失败的机器上的问题。

注意:对于大多数用例,options.encoding 应设置为 UTF8 而不是 x-UTF-16LE-BOM。