<?xml version="1.0" encoding="UTF-8"?>
<project name="jffi" default="jar" basedir=".">
  <description>Builds, tests, and runs the project jffi.</description>
  <path id="classpath.test">
    <pathelement location="lib/junit_4/junit-4.11.jar"/>
    <pathelement location="lib/junit_4/hamcrest-core-1.3.jar"/>
  </path>

  <target name="clean-java" depends="-init">
    <delete dir="${build.dir}/classes"/>
    <delete dir="${build.dir}/java"/>
    <delete dir="${build.test.dir}"/>
    <delete dir="${dist.dir}"/>
  </target>

  <target name="clean" depends="-init">
    <delete dir="${build.dir}"/>
    <delete dir="${dist.dir}"/>
  </target>

  <target name="jar" depends="-init,-pre-jar,-do-jar,-post-jar"/>

  <target name="build-native" depends="-init, -build-platform-jar, -assemble-final-jar"/>

  <target name="-pre-init">
    <property name="run.jvmargs" value="-Djffi.library.path=build/jni -Djffi.boot.library.path=build/jni"/>
  </target>

  <target name="-init-vars">
    <property name="src.dir" location="src/main/java"/>
    <property name="src.test.dir" location="src/test/java"/>
    <property name="build.dir" location="build"/>
    <property name="dist.dir"  location="dist"/>

    <property name="build.classes.dir" location="${build.dir}/classes"/>
    <property name="build.test.dir" location="${build.dir}/test"/>
    <property name="dist.jar"  value="${dist.dir}/jffi.jar"/>
    <property name="complete.jar" value="${dist.dir}/jffi-complete.jar"/>
    <property name="build.native.dir" location="${build.dir}/jni"/>
    <property name="src.native.dir" location="jni"/>
    <property name="ant.build.javac.target" value="8"/>
    <property name="ant.build.javac.source" value="8"/>
    <property name="ant.build.javac.includeantruntime" value="false"/>
    <property name="test.fork" value="yes"/>
    <property name="test.fork.mode" value="once"/>

    <mkdir dir="${build.native.dir}"/>


    <!-- normalize the various os.arch naming conventions -->
    <condition property="platform.cpu" value="i386">
      <or>
        <os arch="i386"/>
        <os arch="x86"/>
      </or>
    </condition>
    <condition property="platform.cpu" value="x86_64">
      <or>
        <os arch="amd64"/>
        <os arch="x86_64"/>
      </or>
    </condition>
    <condition property="platform.cpu" value="ppc">
      <or>
        <os arch="ppc"/>
        <os arch="powerpc"/>
      </or>
    </condition>
    <condition property="platform.cpu" value="ppc64">
      <or>
        <os arch="ppc64"/>
        <os arch="powerpc64"/>
      </or>
    </condition>
    <condition property="platform.cpu" value="aarch64">
      <or>
        <os arch="aarch64"/>
      </or>
    </condition>

    <condition property="platform.cpu" value="loongarch64">
      <or>
        <os arch="loongarch64"/>
      </or>
    </condition>
    <condition property="platform.cpu" value="mipsel">
      <or>
        <os arch="mipsel"/>
      </or>
    </condition>
    <condition property="platform.cpu" value="mips64">
      <or>
        <os arch="mips64"/>
      </or>
    </condition>
    <condition property="platform.cpu" value="mips64el">
      <or>
        <os arch="mips64el"/>
      </or>
    </condition>

    <condition property="platform.os" value="Windows">
      <os family="Windows"/>
    </condition>
    <!-- default to os.arch for the cpu -->
    <condition property="platform.cpu" value="${os.arch}">
      <not><isset property="platform.cpu"/></not>
    </condition>
    <condition property="platform.os" value="${os.name}">
      <not><isset property="platform.os"/></not>
    </condition>
    <condition property="platform" value="Darwin">
      <os family="Mac"/>
    </condition>
    <condition property="platform" value="${platform.cpu}-${platform.os}">
      <not><isset property="platform"/></not>
    </condition>

    <condition property="native.jar" value="${build.dir}/native.jar">
      <not><isset property="native.jar"/></not>
    </condition>
    <condition property="make.exe" value="gmake">
      <or>
        <os name="FreeBSD"/>
        <os name="OpenBSD"/>
        <os name="DragonFlyBSD"/>
        <os name="AIX"/>
        <os name="HP-UX"/>
      </or>
    </condition>
    <condition property="make.exe" value="/usr/sfw/bin/gmake">
      <os name="SunOS"/>
    </condition>
    <condition property="make.exe" value="make">
      <not><isset property="make.exe"/></not>
    </condition>
  </target>

  <target name="-init" depends="-pre-init,-init-vars,-post-init">
    <!-- Create the time stamp -->
    <tstamp/>
    <!-- Create the build directory structure used by compile -->
    <mkdir dir="${build.dir}"/>
  </target>

  <import file="version.xml"/>


  <target name="-pre-jar"/>
  <target name="-post-init" depends="-init-vars"/>
  <target name="-pre-compile" depends="-init"/>
  <target name="-post-compile" depends="-build-native-library"/>
  <target name="-pre-compile-test" depends="-init"/>
  <target name="-post-compile-test" depends="-build-native-testlib"/>
  <target name="-post-jar" depends="-assemble-final-jar"/>

  <target name="-do-compile" depends="-init">
    <mkdir dir="${build.classes.dir}"/>
    <!-- Compile the java code from ${src} into ${build} -->
    <javac srcdir="${src.dir}" destdir="${build.classes.dir}" includeantruntime="false"/>
  </target>

  <target name="-compile-java" depends="-do-compile"/>
  <target name="compile" depends="-init,-pre-compile,-do-compile,-post-compile">
  </target>

  <target name="-do-jar" depends="-init,compile">
    <mkdir dir="${dist.dir}"/>
    <jar destfile="${dist.jar}" basedir="${build.classes.dir}" compress="true"/>
  </target>

  <target name="test" depends="compile,-compile-test">
    <mkdir dir="${build.test.dir}/results"/>

    <echo>test with jni libraries from sources</echo>
    <junit fork="${test.fork}" forkMode="${test.fork.mode}" printsummary="withOutAndErr" haltonfailure="true">
      <env key="LC_ALL" value="C"/>
      <classpath>
        <pathelement location="${build.classes.dir}"/>
        <pathelement location="${build.test.dir}/classes"/>
        <pathelement location="lib/junit_4/junit-4.11.jar"/>
        <pathelement location="lib/junit_4/hamcrest-core-1.3.jar"/>
      </classpath>
      <sysproperty key="java.library.path" value="${build.native.dir}"/>

      <formatter type="plain" /> <!-- to file -->
      <batchtest todir="${build.test.dir}/results">
        <fileset dir="${src.test.dir}">
          <include name="**/*Test*.java"/>
        </fileset>
      </batchtest>
    </junit>

    <echo>test with unpack of jni library</echo>
    <junit fork="${test.fork}" forkMode="${test.fork.mode}" printsummary="withOutAndErr" haltonfailure="true">
      <env key="LC_ALL" value="C"/>
      <classpath>
        <pathelement location="${build.classes.dir}"/>
        <pathelement location="${build.test.dir}/classes"/>
        <fileset dir="archive" includes="*.jar"/>
        <pathelement location="lib/junit_4/junit-4.11.jar"/>
        <pathelement location="lib/junit_4/hamcrest-core-1.3.jar"/>
      </classpath>

      <formatter type="plain" /> <!-- to file -->
      <batchtest todir="${build.test.dir}/results">
        <fileset dir="${src.test.dir}">
          <include name="**/*Test*.java"/>
        </fileset>
      </batchtest>
    </junit>

    <echo>test with unpack of jni library to specific locatiohn</echo>
    <junit fork="${test.fork}" forkMode="${test.fork.mode}" printsummary="withOutAndErr" haltonfailure="true">
      <env key="LC_ALL" value="C"/>
      <classpath>
        <pathelement location="${build.classes.dir}"/>
        <pathelement location="${build.test.dir}/classes"/>
        <fileset dir="archive" includes="*.jar"/>
        <pathelement location="lib/junit_4/junit-4.11.jar"/>
        <pathelement location="lib/junit_4/hamcrest-core-1.3.jar"/>
      </classpath>
      <sysproperty key="jffi.extract.name" value=""/>

      <formatter type="plain" /> <!-- to file -->
      <batchtest todir="${build.test.dir}/results">
        <fileset dir="${src.test.dir}">
          <include name="**/*Test*.java"/>
        </fileset>
      </batchtest>
    </junit>
  </target>

  <target name="ensure-test-name" unless="test">
    <fail message="You must run this target with -Dtest=TestName"/>
  </target>

  <target name="runtest" description="Runs the test you specify on the command
    line with -Dtest=" depends="compile, -compile-test, ensure-test-name">
    <junit printsummary="withOutAndErr" fork="${test.fork}" forkMode="${test.fork.mode}">
      <classpath>
        <pathelement location="${build.classes.dir}"/>
        <pathelement location="${build.test.dir}/classes"/>
        <pathelement location="lib/junit_4/junit-4.11.jar"/>
        <pathelement location="lib/junit_4/hamcrest-core-1.3.jar"/>
      </classpath>
      <sysproperty key="java.library.path" value="${build.native.dir}"/>
      <formatter type="plain" usefile="false"/>
      <batchtest>
        <fileset dir="${src.test.dir}">
          <include name="**/${test}.java"/>
        </fileset>
      </batchtest>
    </junit>
  </target>

  <target name="-compile-test" depends="-pre-compile-test,-do-compile-test,-post-compile-test"/>


  <target name="-do-compile-test" depends="-init">
    <mkdir dir="${build.test.dir}/classes"/>
    <!-- Compile the java code from ${src} into ${build} -->
    <javac srcdir="${src.test.dir}" destdir="${build.test.dir}/classes" includeantruntime="false" classpathref="classpath.test">
      <classpath>
        <pathelement location="${build.classes.dir}"/>
        <pathelement location="lib/junit_4/junit-4.11.jar"/>
        <pathelement location="lib/junit_4/hamcrest-core-1.3.jar"/>
      </classpath>
    </javac>
  </target>


  <target name="cross-win32" depends="-init, -generate-native-headers">
    <mkdir dir="${build.native.dir}"/>

    <exec executable="${make.exe}" failonerror="true">
      <arg value="JAVA_HOME=${java.home}"/>
      <arg value="OS=cross-mingw32"/>
      <arg value="SRC_DIR=${src.native.dir}"/>
      <arg value="JNI_DIR=${src.native.dir}"/>
      <arg value="BUILD_DIR=${build.native.dir}"/>
      <arg value="VERSION=${jffi.version.major}.${jffi.version.minor}"/>
      <arg value="CPU=i386"/>
      <arg value="-f"/>
      <arg value="jni/GNUmakefile"/>
    </exec>
    <exec executable="i686-w64-mingw32-strip" failonerror="true">
      <arg value="--strip-debug"/> <!-- Strip debug symbols only -->
      <arg value="${build.native.dir}/jffi-${jffi.version.major}.${jffi.version.minor}.dll"/>
    </exec>
    <mkdir dir="${dist.dir}"/>
    <zip destfile="${dist.dir}/jffi-i386-Windows.jar" level="9">
      <zipfileset prefix="jni/i386-Windows" dir="${build.native.dir}">
        <include name="jffi*.dll"/>
      </zipfileset>
    </zip>
  </target>

  <target name="cross-win64" depends="-init, -generate-native-headers">
    <mkdir dir="${build.native.dir}"/>

    <exec executable="${make.exe}" failonerror="true">
      <arg value="JAVA_HOME=${java.home}"/>
      <arg value="OS=cross-win64"/>
      <arg value="SRC_DIR=${src.native.dir}"/>
      <arg value="JNI_DIR=${src.native.dir}"/>
      <arg value="BUILD_DIR=${build.native.dir}"/>
      <arg value="VERSION=${jffi.version.major}.${jffi.version.minor}"/>
      <arg value="CPU=x86_64"/>
      <arg value="-f"/>
      <arg value="jni/GNUmakefile"/>
    </exec>
    <exec executable="x86_64-w64-mingw32-strip" failonerror="true">
      <arg value="--strip-debug"/> <!-- Strip debug symbols only -->
      <arg value="${build.native.dir}/jffi-${jffi.version.major}.${jffi.version.minor}.dll"/>
    </exec>
    <mkdir dir="${dist.dir}"/>
    <zip destfile="${dist.dir}/jffi-x86_64-Windows.jar" level="9">
      <zipfileset prefix="jni/x86_64-Windows" dir="${build.native.dir}">
        <include name="jffi*.dll"/>
      </zipfileset>
    </zip>
  </target>



  <target name="-generate-version" depends="-init,-init-vars,-generate-version-source">
    <javac target="${ant.build.javac.target}" destdir="${build.classes.dir}" srcdir="${build.dir}/java" includeantruntime="false"/>
  </target>

  <target name="-generate-native-headers" depends="-init-vars,-generate-version,-compile-java">
    <mkdir dir="${build.native.dir}"/>
    <mkdir dir="${build.classes.dir}"/>
    <javac destdir="${build.native.dir}" nativeheaderdir="${build.native.dir}">
      <src path="${src.dir}"/>
      <src path="${build.dir}/java"/>
      <include name="com/kenai/jffi/Foreign.java"/>
      <include name="com/kenai/jffi/ObjectBuffer.java"/>
      <include name="com/kenai/jffi/Version.java"/>
    </javac>
    <!--
    <exec executable="javah" failonerror="true">
      <arg line="-d ${build.native.dir}"/>
      <arg line="-classpath ${build.classes.dir}"/>
      <arg line="com.kenai.jffi.Foreign"/>
      <arg line="com.kenai.jffi.ObjectBuffer"/>
    </exec>
    -->
  </target>

  <target name="-build-native-library" depends="-init-vars, -generate-native-headers, -generate-version">
    <mkdir dir="${build.native.dir}"/>

    <exec executable="cygpath" outputproperty="jni.GNUmakefile" osfamily="Windows">
      <arg value="-u"/>
      <arg value="${src.native.dir}/GNUmakefile"/>
    </exec>
    <exec executable="cygpath" outputproperty="jni.src.dir" osfamily="Windows">
      <arg value="-u"/>
      <arg value="${src.native.dir}"/>
    </exec>
    <exec executable="cygpath" outputproperty="jni.build.dir" osfamily="Windows">
      <arg value="-u"/>
      <arg value="${build.native.dir}"/>
    </exec>
    <exec executable="cygpath" outputproperty="jni.java.home" osfamily="Windows">
      <arg value="-u"/>
      <arg value="${java.home}"/>
    </exec>
    <condition property="jni.GNUmakefile" value="${src.native.dir}/GNUmakefile">
      <not><isset property="jni.GNUmakefile"/></not>
    </condition>
    <condition property="jni.src.dir" value="${src.native.dir}">
      <not><isset property="jni.src.dir"/></not>
    </condition>
    <condition property="jni.build.dir" value="${build.native.dir}">
      <not><isset property="jni.build.dir"/></not>
    </condition>
    <condition property="jni.java.home" value="${java.home}">
      <not><isset property="jni.java.home"/></not>
    </condition>
    <exec executable="${make.exe}" failonerror="true">
      <arg value="JAVA_HOME=${jni.java.home}"/>
      <arg value="SRC_DIR=${jni.src.dir}"/>
      <arg value="JNI_DIR=${jni.src.dir}"/>
      <arg value="BUILD_DIR=${jni.build.dir}"/>
      <arg value="CPU=${platform.cpu}"/>
      <arg value="VERSION=${jffi.version.major}.${jffi.version.minor}"/>
      <arg value="USE_SYSTEM_LIBFFI=${use.system.libffi}"/>
      <!-- <arg value="USE_SYSTEM_LIBFFI=0"/> -->
      <arg value="-f"/>
      <arg value="${jni.GNUmakefile}"/>
    </exec>

  </target>


  <target name="-build-native-testlib" depends="-init-vars">
    <mkdir dir="${build.native.dir}"/>

    <exec executable="${make.exe}" failonerror="true">
      <arg value="JAVA_HOME=${java.home}"/>
      <arg value="BUILD_DIR=${build.dir}"/>
      <arg value="CPU=${platform.cpu}"/>
      <arg value="-f"/>
      <arg value="libtest/GNUmakefile"/>
    </exec>
  </target>

  <target name="-build-platform-jar" depends="-init-vars, -build-native-library">
    <echo message="platform=${platform}"/>
    <zip destfile="${dist.dir}/jffi-${platform}.jar" level="9">
      <zipfileset prefix="jni/${platform}" dir="${build.native.dir}">
        <include name="jffi*.dll"/>
        <include name="libjffi*.so"/>
        <include name="libjffi*.jnilib"/>
        <include name="libjffi*.dylib"/>
        <include name="libjffi*.a"/>
      </zipfileset>
    </zip>
  </target>

  <target name="-assemble-final-jar" depends="-init-vars, -assemble-native-jar">
    <jar jarfile="${complete.jar}" index="true" update="true" duplicate="preserve"
         filesetmanifest="skip">
      <zipfileset src="${dist.jar}"/>
      <zipfileset src="${native.jar}"/>
      <manifest>
        <attribute name="Main-Class" value="com.kenai.jffi.Main"/>
      </manifest>
    </jar>
  </target>

  <target name="-assemble-native-jar" depends="-init-vars, -build-platform-jar">
    <jar jarfile="${native.jar}" index="true" update="true" duplicate="preserve"
         filesetmanifest="skip">
      <zipgroupfileset dir="archive" includes="jffi-*.jar"/>
      <zipfileset src="${dist.dir}/jffi-${platform}.jar"/>
    </jar>
  </target>

  <target name="archive-platform-jar" depends="-build-platform-jar">
    <copy file="${dist.dir}/jffi-${platform}.jar" todir="archive" flatten="true"/>
  </target>
</project>
