如何正确配置Maven项目生成带Classifier的JAR且兼容Javadoc插件
问题场景
我有一个包含Java源码和JNI C++代码的Maven项目,为适配不同平台,需要生成带平台标识Classifier的JAR文件(将编译后的共享库打包进JAR)。但执行mvn install时触发MINSTALL-151错误:
Failed to execute goal org.apache.maven.plugins:maven-install-plugin:3.1.1:install (default-install) on project <project_name>: NoFileAssignedException: The packaging plugin for this project did not assign a main file to the project but it has attachments. Change packaging to 'pom'. -> [Help 1]
尝试过两种解决思路,但均存在问题:
使用
allowIncompleteProjects配置:根据Bug评论指引,在maven-install-plugin中开启该参数可绕过错误,但官方文档指出这是“逃生舱”,推荐改用pom打包类型,让我担心这种方式不符合Maven规范。默认情况下,此类项目是被禁止的,Mojo将无法处理它们。……大多数情况下,用户真正需要的是一个打包类型为"pom"的项目,并附加一些带分类器的构件(典型示例是打包并附加带分类器的程序集)。
切换为
pom打包类型:按官方建议修改后,需手动配置resources、compiler和surefire插件的执行逻辑,但Javadoc和Source插件完全失效:- 生成Javadoc JAR时提示:
Not executing Javadoc as the project is not a Java classpath-capable package - 执行
mvn site时,Javadoc报告看似配置正常,但实际无任何内容生成(对比正常jar打包项目,缺少Javadoc生成的日志步骤)
- 生成Javadoc JAR时提示:
当前项目提交哈希为f53ab7a8的版本采用pom打包,无法生成Javadoc或Source JAR,可能需暂时切回jar打包以保证基础功能可用。
关于Classifier的说明
项目中JNI C++代码编译生成的共享库依赖特定平台,因此需为每个平台生成带专属Classifier的JAR文件,后续计划构建一个名为uber(或类似)的Classifier JAR,整合多平台共享库内容。
推荐解决方案
方案1:保持Jar打包+优化插件配置(推荐)
核心思路是保留jar打包类型,禁用默认的无Classifier主JAR生成,显式配置带平台Classifier的JAR构建,同时通过allowIncompleteProjects允许安装无主构件的项目。这种方式既能解决MINSTALL-151错误,又能让Javadoc和Source插件正常工作。
示例配置:
<build> <plugins> <!-- 禁用默认的无Classifier主JAR生成 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.3.0</version> <executions> <execution> <id>default-jar</id> <phase>none</phase> </execution> <!-- 构建带平台Classifier的JAR,包含Java类和JNI共享库 --> <execution> <id>platform-specific-jar</id> <phase>package</phase> <goals> <goal>jar</goal> </goals> <configuration> <classifier>${platform.classifier}</classifier> <includes> <include>**/*.class</include> <include>**/*.so</include> <include>**/*.dll</include> <include>**/*.dylib</include> </includes> </configuration> </execution> </executions> </plugin> <!-- 允许安装无主构件的项目,绕过MINSTALL-151错误 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-install-plugin</artifactId> <version>3.1.1</version> <configuration> <allowIncompleteProjects>true</allowIncompleteProjects> </configuration> </plugin> <!-- 正常配置Source插件,生成带sources Classifier的JAR --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-source-plugin</artifactId> <version>3.3.0</version> <executions> <execution> <id>attach-sources</id> <goals> <goal>jar-no-fork</goal> </goals> <configuration> <classifier>sources</classifier> </configuration> </execution> </executions> </plugin> <!-- 正常配置Javadoc插件,生成带javadoc Classifier的JAR --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-javadoc-plugin</artifactId> <version>3.6.0</version> <executions> <execution> <id>attach-javadocs</id> <goals> <goal>jar</goal> </goals> <configuration> <classifier>javadoc</classifier> </configuration> </execution> </executions> </plugin> </plugins> </build>
方案2:拆分多模块项目(更规范)
若追求严格符合Maven项目结构规范,可拆分为三个模块:
- 父模块(pom打包):统一管理依赖版本、插件配置和子模块聚合
- 核心Java模块(jar打包):仅包含Java源码,生成不带JNI库的普通JAR
- 平台专属模块(每个平台一个子模块,pom打包):编译对应平台的JNI库,将核心JAR和JNI库打包成带平台Classifier的构件
这种方式结构更清晰,但会增加项目复杂度,适合大型多平台JNI项目。
为什么Pom打包不可行?
Maven的pom打包类型设计初衷是用于父项目或聚合项目,Java相关插件(compiler、javadoc、source)默认会跳过pom类型项目的执行逻辑,即使手动强制配置插件执行,也会因打包类型限制导致功能失效(比如Javadoc插件会判断项目是否为Java类路径兼容包,直接跳过生成),因此不适合用于需要编译Java源码、生成Javadoc和Source JAR的项目。
内容的提问来源于stack exchange,提问作者Nick Williams

