在MacOSM1机器上为java构建通用的Appbunder构建



多年来,我一直在英特尔MacMini上构建MacOs Java应用程序,主要是

  • 使用maven编译/构建
  • 使用jlink制作嵌入式jre
  • 使用TheInfiniteKind AppBundler分叉生成Appbundle
  • 签字并公证
  • 使用DmgCanvas打包为dmg

现在让它在MacOS M1上构建,并且构建良好。当我在Mac M1上运行时,它可以工作,但当我尝试在Intel Macmini上运行时失败,原因是无法加载JRE环境

这是有道理的,因为当我构建它时,我只是在Adoptium Terium 17的M1版本的基础上提供一个jre。但我不明白如果这是我需要做的,我如何提供两个JRE

下面我展示了主要的构建脚本

#!/bin/bash
#set -x
cd $HOME/code/jthink/songkong/src/main/scripts
hiutil -C  -fapplehelpbook/SongKongHelp/SongKongHelp.helpindex applehelpbook/SongKongHelp/
cd $HOME/code/jthink/songkong
sudo rm -fr /Applications/SongKong.app
mvn -f pommacos.xml clean
mvn -f pommacos.xml -DskipTests=true install
rm -fr target/songkong-8.2
unzip target/songkong-8.2-distribution.zip -d target
ant
while read line; do
echo "$line"
if [[ "$line" = "<string>1.0</string>" ]]; then
cat mergefile.txt    # or echo or printf your extra lines
fi
done < /Applications/SongKong.app/Contents/Info.plist > Info.new
while read line; do
echo "$line"
if [[ "$line" = "<false/></dict>" ]]; then
cat mergefile2.txt
fi
done < Info.new > Info.new2
rm /Applications/SongKong.app/Contents/Info.plist
rm Info.new
mv Info.new2 /Applications/SongKong.app/Contents/Info.plist
sudo cp -r target/songkong-8.2/applehelpbook/SongKongHelp /Applications/SongKong.app/Contents/Resources
export CODESIGN_ALLOCATE="/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/codesign_allocate"
/usr/bin/codesign --timestamp --options runtime 
--entitlements $HOME/code/jthink/songkong/songkong.entitlements 
--sign "Developer ID Application: P Taylor" 
--force --deep --verbose /Applications/SongKong.app
/usr/bin/codesign -vvv --deep --strict /Applications/SongKong.app
spctl -a -t exec -vv /Applications/SongKong.app
cd $HOME/code/jthink/SongKong
/usr/local/bin/dmgcanvas $HOME/code/jthink/SongKong/dmgCanvas_songkong.dmgCanvas $HOME/songkong-osx.dmg -v SongKong -identity "Developer ID Application: P Taylor" -notarizationAppleID paultaylor@jthink.net -notarizationPassword xxxxxxxxxxxxxxxxxxxxxx -notarizationPrimaryBundleID songkong

以及appbundler任务使用的ant文件

<?xml version="1.0" encoding="iso-8859-1"?>
<project name="songkong">
<property environment="env"/>
<property name="songkongsrc"        value="/Users/paultaylor/code/jthink/SongKong/target/songkong-8.2"/>
<property name="resources"      value="/Users/paultaylor/code/jthink/SongKong/src/main/resources"/>
<property name="songkonglib"        value="${songkongsrc}/lib"/>
<property name="songkongtargetroot"     value="/Applications"/>
<property name="songkongtarget"     value="${songkongtargetroot}/SongKong.app"/>
<property name="songkongcontentstarget"     value="${songkongtarget}/Contents"/>
<!-- Obtain path to the selected JRE -->
<exec executable="/usr/libexec/java_home"
failonerror="true"
outputproperty="runtime">
<arg value="-v"/>
<arg value="17"/>
</exec>
<taskdef name="bundleapp" classname="com.oracle.appbundler.AppBundlerTask"/>
<bundleapp outputdirectory="${songkongtargetroot}"
name="SongKong"
displayname="SongKong"
executableName="SongKong"
identifier="com.jthink.songkong"
shortversion="8.2"
mainclassname="com.jthink.songkong.cmdline.SongKong"
signature="sgkg"
applicationCategory="public.app-category.music"
icon="${songkongsrc}/songkong.icns"
>
<classpath dir="${songkonglib}">
<include name="**/*.jar"/>
</classpath>
<classpath dir="${songkongsrc}">
<include name="songkong.properties"/>
</classpath>
<librarypath dir="${songkongsrc}">
<include name="fpcalc_osx"/>
<include name="libAppleScriptEngine.dylib"/>
</librarypath>
<option value="-Dcom.mchange.v2.log.MLog=com.mchange.v2.log.jdk14logging.Jdk14MLog"/>
<option value="-Dorg.jboss.logging.provider=jdk"/>
<option value="-Djava.util.logging.config.class=com.jthink.songkong.logging.StandardLogging"/>
<option value="-Dapple.laf.useScreenMenuBar=true"/>
<option value="-Dapple.awt.brushMetalLook=true"/>
<option value="-Dsun.java2d.metal=true"/>
<option value="-XX:+HeapDumpOnOutOfMemoryError"/>
<plistentry key="NSRequiresAquaSystemAppearance" type="boolean" value="false"/>
<plistentry key="AppleWindowTabbingMode" value="manual"/>
<bundledocument extensions="mp3,wma,ogg,flac,wav,aif,aiff,aifc"
name="Music Files"
role="editor"
isPackage="false">
</bundledocument>
<jlink runtime="${runtime}">
<jmod name="java.desktop"/>
<jmod name="java.datatransfer"/>
<jmod name="java.logging"/>
<jmod name="java.management"/>
<jmod name="java.naming"/>
<jmod name="java.net.http"/>
<jmod name="java.prefs"/>
<jmod name="java.scripting"/>
<jmod name="java.sql"/>
<jmod name="jdk.management"/>
<jmod name="jdk.unsupported"/>
<jmod name="jdk.jcmd"/>
<jmod name="jdk.crypto.ec"/>
<jmod name="jdk.dynalink"/>
<argument value="--compress=2"/>
<argument value="--release-info=${runtime}/release"/>
</jlink>
</bundleapp>
<copy file="${resources}/create_itunes_model.scpt"      tofile="${songkongcontentstarget}/Java/create_itunes_model.scpt"/>
<copy file="${resources}/create_music_model.scpt"      tofile="${songkongcontentstarget}/Java/create_music_model.scpt"/>
<copy file="${resources}/get_playlist_folder.scpt"      tofile="${songkongcontentstarget}/Java/get_playlist_folder.scpt"/>
<copy file="${resources}/get_music_playlist_folder.scpt"      tofile="${songkongcontentstarget}/Java/get_music_playlist_folder.scpt"/>
<copy file="${songkongsrc}/songkong.properties" tofile="${songkongcontentstarget}/songkong.properties"/>
<copy file="${songkongsrc}/songkong1.properties" tofile="${songkongcontentstarget}/songkong1.properties"/>
<copy file="${songkongsrc}/songkong2.properties" tofile="${songkongcontentstarget}/songkong2.properties"/>
<copy file="${songkongsrc}/songkong2.properties" tofile="${songkongcontentstarget}/songkong3.properties"/>
<copy file="${songkongsrc}/songkong2.properties" tofile="${songkongcontentstarget}/songkong4.properties"/>
<copy file="${songkongsrc}/songkong5.properties" tofile="${songkongcontentstarget}/songkong5.properties"/>
<copy file="${songkongsrc}/renamemask.properties" tofile="${songkongcontentstarget}/renamemask.properties"/>
<copy file="${songkongsrc}/general.properties" tofile="${songkongcontentstarget}/general.properties"/>
<copy file="${songkongsrc}/license.properties" tofile="${songkongcontentstarget}/license.properties"/>
<copy file="${songkongsrc}/genrelist.txt" tofile="${songkongcontentstarget}/genrelist.txt"/>
<copy file="${songkongsrc}/classical_composers.txt" tofile="${songkongcontentstarget}/classical_composers.txt"/>
<copy file="${songkongsrc}/classical_conductors.txt" tofile="${songkongcontentstarget}/classical_conductors.txt"/>
<copy file="${songkongsrc}/classical_people.txt" tofile="${songkongcontentstarget}/classical_people.txt"/>
<copy file="${songkongsrc}/not_classical_release.txt" tofile="${songkongcontentstarget}/not_classical_release.txt"/>
<copy file="${songkongsrc}/license.txt" tofile="${songkongcontentstarget}/license.txt"/>
<copy file="${songkongsrc}/index.html" tofile="${songkongcontentstarget}/index.html"/>
<copy file="${songkongsrc}/pdfOSX/help.pdf"        tofile="${songkongcontentstarget}/help.pdf"/>
<copy file="${songkongsrc}/osx/bin/songkong.sh"    tofile="${songkongcontentstarget}/bin/songkong.sh"/>
<copy file="${songkongsrc}/osx/bin/songkongremote.sh"    tofile="${songkongcontentstarget}/bin/songkongremote.sh"/>
<copy todir="${songkongcontentstarget}/style"><fileset dir="${songkongsrc}/style"/></copy>
<copy todir="${songkongcontentstarget}/lang"><fileset dir="${songkongsrc}/lang"/></copy>
<chmod file="${songkongcontentstarget}/bin/songkong.sh" perm="777"/>
<chmod file="${songkongcontentstarget}/bin/songkongremote.sh" perm="777"/>
</project>

编辑1:

所以当你说,你想创建一个通用的应用程序,正如我所理解的:

  1. 您希望有一个可以在两个平台上运行的jar
  2. 您希望将两个jre捆绑在同一个构建中,因为您希望在两个独立的平台上运行
  3. 您将在绑定应用程序的主机系统上同时拥有两个jre
  4. 你想要在两个mac平台上都包含两个jre的单个应用程序

如果你想取得1-4的成绩,前面的路很艰难:

您还可以通过分叉这个存储库来定制appbundler

你需要首先关注这门课:https://github.com/TheInfiniteKind/appbundler/blob/master/appbundler/src/com/oracle/appbundler/AppBundlerTask.java

工作原理:我们需要解决的挑战是Appbundler在任何给定时间只需要1个运行时。

https://github.com/TheInfiniteKind/appbundler/blob/master/appbundler/src/com/oracle/appbundler/AppBundlerTask.java#L235

稍后,它将运行时内容复制到名为PlugIns的目录中

https://github.com/TheInfiniteKind/appbundler/blob/master/appbundler/src/com/oracle/appbundler/AppBundlerTask.java#L467

您可以扩展AppBundlerTask并覆盖public void execute()方法。

在这里,您可以提供List<Runtime>而不是单个Runtime

现在,这个execute方法创建了一个Info.plist文件,您可以创建两个具有不同运行时元素的文件。https://stackoverflow.com/a/54569519/1811348

我非常怀疑这是否能解决我心目中的以下三个问题:a.插件目录是如何在应用程序中加载的,以及它是如何使用的,我不知道,所以在同一个目录中有两个运行时,不知道是否可以。b.如果我们在同一个应用程序中有两个plist文件,我不知道如何从应用程序端用设备环境变量切换它们。这个env变量将决定选择哪个plist文件。c.在单个应用程序中捆绑两个jre的应用程序大小帖子。

另外请注意,相应地,您将不得不更新您的ant任务,以便为2jre提供两个目录。


如果只有1,2,3是正确的,您可以将两个jre捆绑在两个不同的应用程序中:

我认为答案仍然是一样的,因为exec标记本身只是设置您的java运行时。不过你们也可以试试下面的方法。

只需为这个exec 添加条件

<!-- Obtain path to the selected JRE -->
<exec executable="/usr/libexec/java_home"
failonerror="true"
outputproperty="runtime">
<arg value="-v"/>
<arg value="17"/>
</exec>

请注意:这个exec标记所做的事情和<runtime dir="${env.JAVA_HOME}" />在本文中所做的相同。

https://docs.oracle.com/javase/7/docs/technotes/guides/jweb/packagingAppsForMac.html

例如:

<?xml version="1.0" encoding="UTF-8"?>
<target name="set-runtime">
<echo level="info">setting-runtime</echo>
<if>
<equals arg1="${os.family}" arg2="mac" />
<then>
<echo message="setting to mac desktop jre" />
<!-- Obtain path to the selected JRE -->
<exec executable="/usr/libexec/java_home" failonerror="true" outputproperty="runtime">
<arg value="-v" />
<arg value="17" />
</exec>
</then>
<else>
<echo message="setting to mac mini jre" />
<!-- Obtain path to the selected JRE -->
<exec executable="path to java home for mac mini on my system" failonerror="true" outputproperty="runtime">
<arg value="-v" />
<arg value="17" />
</exec>
</else>
</if>
</target>

根据我的猜测,您正在加载ant xml的exec标记中的jre。

如果你想根据一些标准进行谈判,你可以使用Ant条件,例如:设备、操作系统、操作系统版本等等

<condition property="isMacOsButNotMacOsX">
<and>
<os family="mac"/>
<not>
<os family="unix"/>
</not>
</and>
</condition>

另请参考:https://stackoverflow.com/a/19272061/1811348

此外,如果你想做任何特别的事情例如:用不同的jdk版本为两个不同平台打包jar,您可以:https://www.zghurskyi.com/maven-package-to-multiple-java-versions/

最新更新