Building a universal Appbunder build for java on MacOS M1 machine - java

I have been building MacOs Java application on Intel MacMini for number of years, essentially
Compile/Build with maven
Make cutdown embedded jre using jlink
Make Appbundle using TheInfiniteKind AppBundler fork
Sign and notarize
Package up as a dmg using DmgCanvas
Now have it building on MacOS M1 and it builds okay. When I run on Mac M1 it works but when I try to run on Intel Macmini it fails with Unable to load JRE Environment
This kind of makes sense because when I build it I am just providing a single jre based on the M1 version of Adoptium Terium 17. But I dont understand how I provide two JRE's if this is what I need to do
Below I show the main build script
#!/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
and the ant file used by the appbundler task
<?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>

Edit 1:.
So when you say, you want to create a universal app, as I understand:
you want to have a single jar that will run on both platforms
you want to bundle both jre's in same build as you want to run on two separate platforms.
You will have both jre's present on your host system from which you are bundling app.
You want single app with both jre's included for both mac platforms.
If you want to achieve 1-4, there is a hard road ahead:
You can also customize an appbundler by forking this repository
You need to focus on this class first:
https://github.com/TheInfiniteKind/appbundler/blob/master/appbundler/src/com/oracle/appbundler/AppBundlerTask.java
How it works:
Challenge we need to solve is Appbundler takes only 1 runtime at any given time.
https://github.com/TheInfiniteKind/appbundler/blob/master/appbundler/src/com/oracle/appbundler/AppBundlerTask.java#L235
Later it copies the runtime contents to a directory called PlugIns
https://github.com/TheInfiniteKind/appbundler/blob/master/appbundler/src/com/oracle/appbundler/AppBundlerTask.java#L467
You can extend AppBundlerTask and override public void execute() method.
Here you can provide List<Runtime> instead of single Runtime.
now, this execute method creates a Info.plist file, you can create two instead with different runtime elements.
https://stackoverflow.com/a/54569519/1811348
I am highly in doubt if this will work for following three issues in my mind:
a. How Plugins directory is loaded in the app and how its used is not known to me, so two runtimes in same dir, no idea if its okay.
b. If at all we can have two plist file in same app how to toggle them with device environment variable from app side is not known to me. This env variable will decide what plist file to select.
c. app size post bundling two jre's in single app.
Also note, accordingly you will have to update your ant task to provide two directories for 2 jre's.
If only 1,2,3 are correct, you can bundle two jre's in two different applications:
I think answer still remains the same as the exec tag itself is just setting your java runtime. However you can try following way as well.
Just add condition for this exec
<!-- Obtain path to the selected JRE -->
<exec executable="/usr/libexec/java_home"
failonerror="true"
outputproperty="runtime">
<arg value="-v"/>
<arg value="17"/>
</exec>
kindly note that: this exec tag is doing same thing that <runtime dir="${env.JAVA_HOME}" /> is doing in provided article.
https://docs.oracle.com/javase/7/docs/technotes/guides/jweb/packagingAppsForMac.html
eg:
<?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>
From what I am guessing you are loading the jre in exec tag of ant xml.
You can use Ant conditionals if you want to negotiate based on some criteria eg: device, os, os version and so on.
<condition property="isMacOsButNotMacOsX">
<and>
<os family="mac"/>
<not>
<os family="unix"/>
</not>
</and>
</condition>
also ref:
https://stackoverflow.com/a/19272061/1811348
Additionally, if you want to do anything special
eg: package jar for two different platforms altogether with different jdk versions you can:
https://www.zghurskyi.com/maven-package-to-multiple-java-versions/

Related

Ant: Class not found: javac1.8

I am trying to build a project using Ant in eclipse. I right-clicked on build.xml > Run As > Ant Build. However, I am getting the following error:
BUILD FAILED
C:\Users\David\eclipse\test-project\build.xml:26: Class not found: javac1.8
and also a warning:
compile:
[javac] C:\Users\David\eclipse\test-project\build.xml:26: warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last; set to false for repeatable builds
As I read in other posts that this might be due to having an ant version that is too old or not having set the environment variables correctly here is all the info:
C:\>java -version
java version "1.8.0_05"
Java(TM) SE Runtime Environment (build 1.8.0_05-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.5-b02, mixed mode)
C:\>ant -version
Apache Ant(TM) version 1.9.3 compiled on December 23 2013
C:\>echo %JAVA_HOME%
C:\Program Files\Java\jdk1.8.0_05
C:\>echo %JRE_HOME%
C:\Program Files\Java\jre8
EDIT:
Here is the whole build.xml, line 26 is the javac tag:
<?xml version="1.0"?>
<project name="test-project" default="main" basedir=".">
<!-- Sets variables which can later be used. -->
<!-- The value of a property is accessed via ${} -->
<property name="src.dir" location="src" />
<property name="build.dir" location="bin" />
<property name="dist.dir" location="dist" />
<property name="docs.dir" location="docs" />
<!-- Deletes the existing build, docs and dist directory-->
<target name="clean">
<delete dir="${build.dir}" />
<delete dir="${docs.dir}" />
<delete dir="${dist.dir}" />
</target>
<!-- Creates the build, docs and dist directory-->
<target name="makedir">
<mkdir dir="${build.dir}" />
<mkdir dir="${docs.dir}" />
<mkdir dir="${dist.dir}" />
</target>
<!-- Compiles the java code (including the usage of library for JUnit -->
<target name="compile" depends="clean, makedir">
<javac srcdir="${src.dir}" destdir="${build.dir}">
</javac>
</target>
<!-- Creates Javadoc -->
<target name="docs" depends="compile">
<javadoc packagenames="src" sourcepath="${src.dir}" destdir="${docs.dir}">
<!-- Define which files / directory should get included, we include all -->
<fileset dir="${src.dir}">
<include name="**" />
</fileset>
</javadoc>
</target>
<!--Creates the deployable jar file -->
<target name="jar" depends="compile">
<jar destfile="${dist.dir}\test-project1.jar" basedir="${build.dir}">
<manifest>
<attribute name="Main-Class" value="test.Main" />
</manifest>
</jar>
</target>
<target name="main" depends="compile, jar, docs">
<description>Main target</description>
</target>
</project>
The version of Ant bundled with your version of Eclipse is not compatible with Java 1.8.
Go to the Ant download page, and extract the latest version somewhere appropriate onto your filesystem.
In Eclipse, go to Window > Preferences > Ant > Runtime, click the Ant Home... button, and select the location that you extracted the newly downloaded Ant to.
To make it still more clear.
1>Set JAVA_HOME,JRE_HOME and Update Ant to 1.9
2>Over build.xml right click => run as (this takes into configuration)==>Now in this Edit Configuration and launch pop-up window
select Main tab then the third form field called "Arguments"
add:
-Dbuild.compiler=javac1.7
3> In build.xml add includeantruntime="false"
<javac srcdir="${src}" destdir="${bin}" debug="true" encoding="ISO-8859-1" includeantruntime="false">
<classpath refid="my.classpath"/>
</javac>
It should compile without any message
Mr. studro is right. I just confirmed an example on Ubuntu 14.04
sudo apt-get install ant
ant -version
Apache Ant (TM) Version 1.9.3 compiled on April August 2014
works perfectly in eclipse, just follow the steps described by Mr studro to configure the 'Ant Home' in eclipse with "/usr/share/ant".Regards, Stéphane.
I think, what you are seeing is Ant Bug 53347 (see https://issues.apache.org/bugzilla/show_bug.cgi?id=53347).
If so, try either pf the following workarounds:
Set the property "build.compiler" to a meaningful value like "javac1.7", or "javac1.3".
Set the "compiler" attribute of the "javac" element of your build script to either of the above values.
For all possible values, and their meaning, see http://ant.apache.org/manual/Tasks/javac.html
Make sure your source files are in "ProjectDirectory/src".
I already did some extensive googling before asking this question but continuing that I found a solution here:
This issue seems to only appear when using JDK 1.8 so using JDK 1.7 instead solves the problem. The following line needs to be added to eclipse.ini:
-vm "path-to-jdk-1.7\bin\javaw.exe"

Eclipse Equinox, how to configure auto load the bundles in plugin folder

I've followed http://www.eclipse.org/equinox/documents/quickstart-framework.php but it seems to be old and not valid.
There is no such bundles as described org.eclipse.update.configurator_3.2.100.jar
I tried with the org.eclipse.equinox.simpleconfigurator_1.0.200.v20100503, but doesn't work.
Anyone can tell me how to make Equinox auto load the bundles inside plugins folder?
Simplest approach would be to use Apache Felix File Install. It works just fine with Equinox, you only need to put File Install configuration parameters into the configuration/config.ini. Note though that if you launch Equinox via launcher JAR or via binary, the working directory would be parent of configuration/ or plugins/ directory.
Excerpt from our project config.ini:
# Start File Install itself
osgi.bundles=reference\:file\:org.apache.felix.fileinstall_3.1.0.jar#1\:start
# The name of the directory to watch
felix.fileinstall.dir=./plugins
# A regular expression to be used to filter file names
# We have all bundles in plugins/ directory, this regexp
# forbids monitoring bundles that are started via osgi.bundles property
felix.fileinstall.filter=^(?!org.apache.felix.fileinstall|org.eclipse.osgi).*
# Determines if File Install waits felix.fileinstall.poll milliseconds before doing an initial scan or not.
felix.fileinstall.noInitialDelay=true
# Not sure why we have this...
felix.fileinstall.start.level=2
Other possible solution would be to use Eclipse P2. It is much more advanced and powerful, though I find it quite difficult to use.
Good thing is that if your application is agnostic to the way bundles are provisioned (and it should be this way), you can always change your mind later.
Here is the fragment from my automated eclipse installer written in ant.
This installs all features from the custom update site. The code is 'as is', but I sure would have liked to have something like this to guide me when I wrote it.
This script also uses antcontrib extension to ant. Antcontrib tasks are have 'ac:' namespace prefix
Hope this helps.
<property name="real.eclipse.home" location="${eclipse.home}/eclipse"/>
<property file="${real.eclipse.home}/configuration/config.ini" prefix="ECLIPSE_CONFIG"/>
<property name="eclipse-plugins.dir" location="${real.eclipse.home}/plugins"/>
<path id="newest.equinox.launcher-library.path.id">
<dirset dir="${eclipse-plugins.dir}">
<include name="org.eclipse.equinox.launcher.*"/>
</dirset>
</path>
<property name="equinox.launcher-library.full-path" refid="newest.equinox.launcher-library.path.id"/>
<basename property="equinox.launcher-library.dir" file="${equinox.launcher-library.full-path}"/>
<echo message="equinox.launcher-library.dir='${equinox.launcher-library.dir}'"/>
<path id="newest.equinox.launcher.path.id">
<fileset dir="${eclipse-plugins.dir}">
<include name="org.eclipse.equinox.launcher_*.jar"/>
</fileset>
</path>
<property name="equinox.launcher.jar" refid="newest.equinox.launcher.path.id"/>
<basename property="equinox.launcher.jar.basename" file="${equinox.launcher.jar}"/>
<echo message="equinox.launcher.jar='${equinox.launcher.jar}'"/>
<java jar="${equinox.launcher.jar}"
fork="true"
failonerror="true"
>
<arg value="-consolelog"/>
<arg value="-application"/>
<arg value="org.eclipse.equinox.p2.director"/>
<arg value="-repository"/>
<arg value="http://${repository.server}/custom-update-site"/>
<arg value="-list"/>
<redirector
logError="true"
outputproperty="features.list"
>
<outputfilterchain>
<linecontains>
<contains value="feature.group="/>
</linecontains>
<replaceregex pattern="(.*feature\.group)=.*$" replace="\1"/>
</outputfilterchain>
</redirector>
</java>
<ac:for list="${features.list}" delimiter="${line.separator}" trim="true" param="feature">
<sequential>
<ac:if>
<isset property="feature.comma.list"/>
<then>
<ac:var name="feature.comma.list" value="${feature.comma.list},#{feature}"/>
</then>
<else>
<property name="feature.comma.list" value="#{feature}"/>
</else>
</ac:if>
</sequential>
</ac:for>
<echo message="Found following features to install"/>
<echo message="${features.list}"/>
<java jar="${equinox.launcher.jar}"
fork="true"
failonerror="true"
>
<arg value="-consolelog"/>
<arg value="-application"/>
<arg value="org.eclipse.equinox.p2.director"/>
<arg value="-repository"/>
<arg value="http://${repository.server}/custom-update-site"/>
<arg value="-destination"/>
<arg file="${real.eclipse.home}"/>
<arg value="-installIU"/>
<arg value="${feature.comma.list}"/>
<arg value="-profile"/>
<arg value="${ECLIPSE_CONFIG.eclipse.p2.profile}"/>
</java>
P.S. For its usefulness and complexity Eclipse P2 is surely one of the most underdocumented features.
In your eclipse installation folder you have the file bundles.info, for example:
eclipse-3.6.1/configuration/org.eclipse.equinox.simpleconfigurator/bundles.info
You can modify the file to add any bundle you want, and also the start level. But the simplest method of adding bundles to an eclipse installation is to add them to the "dropins" folder. This will lead to an automatic modification of the bundle.info file.

Ant, NetBeans Platform project - how to pass command line arguments and access via System.getProperties?

All,
I have a NetBeans Platform project (not just a project I wrote in NetBeans, but one using the rich client framework provided by NetBeans). I can run the project via an ant run command. Now, I want to pass in an argument that will work its way through ant to be accessible via the System.getProperty method.
I understand that I need to use a <sysproperty> node to actually inject the key/value pair into the runtime environment, but for the life of me I cannot figure out how to get this to work with the convoluted build tree that NetBeans creates for you (build.xml depends on build-impl.xml, which in turn depends on ${harness.dir}/suite.xml, which in turn depends on ${harness.dir}/run.xml)
The simplest example I've found is
<target name="run" depends="compile">
<java classname="prop"
fork="true">
<sysproperty key="test.property"
value="blue"
/>
</java>
</target>
but the problem is that none of my xml files have an easily accessible <java> node like that. I think I've managed to trace the execution flow to where something is actually invoked (in ${harness.dir}/run.xml)
<target name="run" depends="-prepare-as-app,-prepare-as-platform">
<touch file="${cluster}/.lastModified"/> <!-- #138427 -->
<property name="run.args" value=""/>
<property name="run.args.ide" value=""/>
<property name="run.args.extra" value=""/>
<condition property="run.args.mac" value="-J-Xdock:name=${app.name}" else="">
<os family="mac"/>
</condition>
<exec osfamily="windows" executable="${run.exe}" failonerror="no" resultproperty="result.prop">
<arg value="--jdkhome"/>
<arg file="${run.jdkhome}"/>
<arg line="${run.args.common}"/>
<arg line="${run.args.prepared}"/>
<arg line="${run.args}"/>
<arg line="${run.args.ide}"/>
<arg line="${run.args.extra}"/>
</exec>
<exec osfamily="unix" dir="." executable="sh"
failonerror="no" resultproperty="result.prop">
<arg value="${run.sh}"/>
<arg value="--jdkhome"/>
<arg file="${run.jdkhome}"/>
<arg line="${run.args.common}"/>
<arg line="${run.args.prepared}"/>
<arg line="${run.args}"/>
<arg line="${run.args.ide}"/>
<arg line="${run.args.extra}"/>
<arg line="${run.args.mac}"/>
</exec>
<fail>
The application is already running within the test user directory.
You must shut it down before trying to run it again.
<condition>
<and>
<isset property="result.prop" />
<or>
<!-- unknown option exit code as returned from IDE by org.netbeans.api.sendopts.CommandLine -->
<equals arg1="${result.prop}" arg2="50346" />
<!-- unknown option exit code as returned from platform app by org.netbeans.CLIHandler -->
<equals arg1="${result.prop}" arg2="2" />
</or>
</and>
</condition>
</fail>
</target>
As you can see, there is no <java> node underneath which I can put my custom sysproperty. Furthermore, it seems like a very wrong thing to do to have to muck around with harness xml files to inject a property that only affects one of my projects, not all of them. So what's the correct way to ensure that a command line property I pass to ant run ends up within a NetBeans Platform project?
There is a folder etc in the distribution of your RCP app and in that folder is file yourapp.conf i think there is an answer you seek. For example from one of mine NB RCP app:
# ${HOME} will be replaced by user home directory according to platform
default_userdir="${HOME}/.${APPNAME}/dev"
default_mac_userdir="${HOME}/Library/Application Support/${APPNAME}/dev"
# options used by the launcher by default, can be overridden by explicit
# command line switches
default_options="--laf Metal --branding xmled -J-Xms24m -J-Xmx64m"
# for development purposes you may wish to append: -J-Dnetbeans.logger.console=true -J-ea
# default location of JDK/JRE, can be overridden by using --jdkhome <dir> switch
#jdkhome="/path/to/jdk"
# clusters' paths separated by path.separator (semicolon on Windows, colon on Unices)
#extra_clusters=

ant deploy problem

I am working on a spring project. I use ant to deploy application and STS (eclipse based) IDE to develop. I set the CATALINA_HOME environment variable
echo $CATALINA_HOME
/home/username/springsource/apache-tomcat
When I run the deploy ant task from IDE it deploys to a folder under
/home/username/workspace/myproject/${env.CATALINA_HOME}/webapp
but not
/home/username/springsource/apache-tomcat/webapp
Do you know any fix?
My build.properties file
src.dir=src
web.dir=web
build.dir=${web.dir}/WEB-INF/classes
name=myproject
appserver.home=${env.CATALINA_HOME}
deploy.path=${appserver.home}/webapps
appserver.lib=${appserver.home}/lib
and build.xml file
<?xml version="1.0" encoding="UTF-8"?>
<project name="kervan" basedir="." default="usage">
<property environment="env"/>
<property file="build.properties"/>
<path id="cp">
<fileset dir="${web.dir}/WEB-INF/lib">
<include name="*.jar"/>
</fileset>
<fileset dir="${appserver.lib}">
<include name="servlet-api.jar"/>
</fileset>
<pathelement path="${build.dir}"/>
</path>
<target name="usage">
<echo message=""/>
<echo message="${name} build file"/>
<echo message="-----------------------------------"/>
<echo message=""/>
<echo message="Available targets are:"/>
<echo message=""/>
<echo message="build --> Build the application"/>
<echo message="deploy --> Deploy application as a WAR file"/>
<echo message=""/>
</target>
<target name="build" description="Compile main source tree java files">
<mkdir dir="${build.dir}"/>
<javac destdir="${build.dir}" source="1.6" target="1.6"
debug="true" deprecation="false" optimize="false"
failonerror="true">
<src path="${src.dir}"/>
<classpath refid="cp"/>
</javac>
</target>
<target name="deploy" depends="build" description="Deploy application as a WAR file">
<war destfile="${name}.war"
webxml="${web.dir}/WEB-INF/web.xml">
<fileset dir="${web.dir}">
<include name="**/*.*"/>
</fileset>
</war>
<copy todir="${deploy.path}" overwrite="true">
<fileset dir=".">
<include name="*.war"/>
</fileset>
</copy>
</target>
</project>
Try putting the following after the two <property> lines:
<echo message="CATALINA_HOME=${env.CATALINA_HOME}" />
and see what it outputs. If it in fact outputs the correct value, then something strange may be happening. If it outputs the literal string
CATALINA_HOME=${env.CATALINA_HOME}
then somehow your ant script hasn't picked up the environment variable.
Note that when you set an environment variable for your system, only applications launched AFTER the variable is set will recognize the new variable. And variables set from the command line will only be recognized if the application being launched is being launched from that same command line session.
If you're running from within Eclipse or an Eclipse-like environment, Eclipse can be kind of weird in that depending on how you launch it, it's startup scripts won't make your environment natively available to your in-IDE Ant build process.
With my Eclipse-based Ant build, I had to manually set the environment. So for me, I right click on my project & go to "Properties". Then I click on the "Builders" section. I select my "Ant Builder" and click "Edit...". Under this section there's an "Environment" tab where you can specify environment variables and their corresponding values.
Even if you're not using Eclipse exactly like I was, poke around in the build properties and you should be able to find a way to specify environment variables and make them available to the build process.
Is CATALINA_HOME set in your environment?
e.g. Windows
echo %CATALINA_HOME%
Linux
echo $CATALINA_HOME
You could always hardcode the value in your properties file if it's not getting resolved correctly but provided it's in your environment then it should work.
The forum here discusses the same problem:
http://www.nabble.com/%3Cproperty-environment%3D%E2%80%9Denv%E2%80%9D%3E-doesn%27t-pick-up-an-environment-variable-td21481164.html
When run from eclipse, I don't believe the environment is passed to ant. You will have to specify each of the environment variables (and the values) that you want passed to ant in the configuration of the build file within eclipse.
if you are set your environmental variable in global
/etc/environment
thats the problem in Ubuntu. Ant does not pick the environment variable from here.
But the echo $CATALINA_HOME works fine in terminal. I am facing the same problem.
set your environment in .bashrc may fix your problem.
I recently suffered a similar issue.
The problem was in the CATALINA_HOME environment variable: I needed to close the path with a backslash ("/"):
$ export CATALINA_HOME=/home/username/springsource/apache-tomcat/
After fixing that I could deploy the application with ant.
Please make sure you end your path with a / and it shall solve your problem.
example: export JAVA_HOME=/opt/java/
instead of: export JAVA_HOME=/opt/java

How to determine build architecture (32bit / 64bit) with ant?

We have inherited an ant build file but now need to deploy to both 32bit and 64bit systems.
The non-Java bits are done with GNUMakefiles where we just call "uname" to get the info. Is there a similar or even easier way to mimic this with ant?
Late to the party, but what the heck...
${os.arch} only tells you if the JVM is 32/64bit. You may be running the 32bit JVM on a 64bit OS. Try this:
<var name ="os.bitness" value ="unknown"/>
<if>
<os family="windows"/>
<then>
<exec dir="." executable="cmd" outputproperty="command.ouput">
<arg line="/c SET ProgramFiles(x86)"/>
</exec>
<if>
<contains string="${command.ouput}" substring="Program Files (x86)"/>
<then>
<var name ="os.bitness" value ="64"/>
</then>
<else>
<var name ="os.bitness" value ="32"/>
</else>
</if>
</then>
<elseif>
<os family="unix"/>
<then>
<exec dir="." executable="/bin/sh" outputproperty="command.ouput">
<arg line="/c uname -m"/>
</exec>
<if>
<contains string="${command.ouput}" substring="_64"/>
<then>
<var name ="os.bitness" value ="64"/>
</then>
<else>
<var name ="os.bitness" value ="32"/>
</else>
</if>
</then>
</elseif>
</if>
<echo>OS bitness: ${os.bitness}</echo>
EDIT:
As #GreenieMeanie pointed out, this requires the ant-contrib library from ant-contrib.sourceforge.net
you can get at the java system properties (http://java.sun.com/javase/6/docs/api/java/lang/System.html#getProperties()) from ant with ${os.arch}. other properties of interest might be os.name, os.version, sun.cpu.endian, and sun.arch.data.model.
Here is an answer that works (I tested on Kubuntu 64, Debian 32, Windows 2000 and Windows XP) without the need of external or optional ANT dependencies. It was based on #phatypus's answer.
<project name="FindArchitecture" default="check-architecture" basedir=".">
<!-- Properties set: unix-like (if it is unix or linux), x64 (if it is 64-bits),
register- size (32 or 64) -->
<target name="check-architecture" depends="check-family,check-register" >
<echo>Register size: ${register-size}</echo>
<echo>OS Family: ${os-family}</echo>
</target>
<target name="check-family" >
<condition property="os-family" value="unix" else="windows">
<os family="unix" />
</condition>
<condition property="unix">
<os family="unix" />
</condition>
</target>
<target name="check-register" depends="reg-unix,reg-windows">
</target>
<!-- Test under GNU/Linux -->
<target name="reg-unix" if="unix">
<exec dir="." executable="uname" outputproperty="result">
<arg line="-m"/>
</exec>
<!-- String ends in 64 -->
<condition property="x64">
<matches string="${result}" pattern="^.*64$"/>
</condition>
<condition property="register-size" value="64" else="32">
<isset property="x64"/>
</condition>
</target>
<!-- Test under MS/Windows-->
<target name="reg-windows" unless="unix">
<!-- 64 bit Windows versions have the variable "ProgramFiles(x86)" -->
<exec dir="." executable="cmd" outputproperty="result">
<arg line="/c SET ProgramFiles(x86)"/>
</exec>
<!-- String ends in "Program Files (x86)" -->
<condition property="x64">
<matches string="${result}" pattern="^.*=.*Program Files \(x86\)"/>
</condition>
<condition property="register-size" value="64" else="32">
<isset property="x64"/>
</condition>
</target>
</project>
You can just pass a parameter into the build file with the value you want. For example, if your target is dist:
ant -Dbuild.target=32 dist
or
ant -Dbuild.target=64 dist
and then in your Ant build script, take different actions depending on the value of the ${build.target} property (you can also use conditions to set a default value for the property if it is not set).
Or, you can check the value of the built-in system properties, such as ${os.arch}.
os.arch does not work very well, another approach is asking the JVM, for example:
~$ java -d32 test
Mon Jun 04 07:05:00 CEST 2007
~$ echo $?
0
~$ java -d64 test
Running a 64-bit JVM is not supported on this platform.
~$ echo $?
1
That'd have to be in a script or a wrapper.
BTW, the os.arch (arch property of the os tag) I got for 64-bit Linux was amd64.
Assuming you are using ANT for building Java Application, Why would you need to know if it is a 32 bit arch or 64-bit? We can always pass parameters to ant tasks. A cleaner way would be to programmaticaly emit the system properties file used by Ant before calling the actual build. There is this interesting post http://forums.sun.com/thread.jspa?threadID=5306174.

Categories

Resources