在 MacOS M1 机器上为 java 构建通用 Appbunder 版本

Pau*_*lor 12 java macos app-bundle apple-m1

多年来我一直在 Intel MacMini 上构建 MacOs Java 应用程序,本质上是

现在在 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
Run Code Online (Sandbox Code Playgroud)

以及 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>
Run Code Online (Sandbox Code Playgroud)

swa*_*ntu 5

编辑1: .

因此,当您说您想创建一个通用应用程序时,据我了解:

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

如果你想达到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.

现在,此执行方法创建一个 Info.plist 文件,您可以创建两个具有不同运行时元素的文件。 /sf/answers/3819866361/

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

另请注意,相应地,您必须更新 ant 任务才能为 2 个 jre 提供两个目录。


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

我认为答案仍然相同,因为 exec 标签本身只是设置你的 java 运行时。不过你也可以尝试下面的方法。

只需为此执行添加条件

<!-- Obtain path to the selected JRE -->
<exec executable="/usr/libexec/java_home"
      failonerror="true"
      outputproperty="runtime">
    <arg value="-v"/>
    <arg value="17"/>
</exec>
Run Code Online (Sandbox Code Playgroud)

请注意:此 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>
Run Code Online (Sandbox Code Playgroud)

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

如果您想根据某些条件进行协商,例如:设备、操作系统、操作系统版本等,您可以使用 Ant 条件。

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

Run Code Online (Sandbox Code Playgroud)

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

另外,如果你想做一些特殊的事情,例如:为两个不同的平台和不同的 jdk 版本打包 jar,你可以: https ://www.zghurskyi.com/maven-package-to-multiple-java-versions/