<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

  <modelVersion>4.0.0</modelVersion>

  <parent>
    <groupId>org.tensorflow</groupId>
    <artifactId>tensorflow-core</artifactId>
    <version>0.5.0</version>
  </parent>
  <artifactId>tensorflow-core-api</artifactId>
  <packaging>jar</packaging>

  <name>TensorFlow Core API Library</name>
  <description>Platform-dependent native code and pure-Java code for the TensorFlow machine intelligence library.</description>

  <properties>
    <native.build.skip>false</native.build.skip>
    <javacpp.build.skip>${native.build.skip}</javacpp.build.skip>
    <javacpp.parser.skip>${native.build.skip}</javacpp.parser.skip>
    <javacpp.compiler.skip>${native.build.skip}</javacpp.compiler.skip>
    <java.module.name>org.tensorflow.core.api</java.module.name>
    <ndarray.version>0.4.0</ndarray.version>
    <truth.version>1.0.1</truth.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.bytedeco</groupId>
      <artifactId>javacpp</artifactId>
      <version>${javacpp.version}</version>
    </dependency>
    <dependency>
      <groupId>org.bytedeco</groupId>
      <artifactId>javacpp</artifactId>
      <version>${javacpp.version}</version>
      <classifier>${javacpp.platform}</classifier>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.google.protobuf</groupId>
      <artifactId>protobuf-java</artifactId>
      <version>${protobuf.version}</version>
    </dependency>
    <dependency>
      <groupId>org.tensorflow</groupId>
      <artifactId>ndarray</artifactId>
      <version>${ndarray.version}</version>
    </dependency>
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-api</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-engine</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.openjdk.jmh</groupId>
      <artifactId>jmh-core</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.google.truth</groupId>
      <artifactId>truth</artifactId>
      <version>${truth.version}</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.openjdk.jmh</groupId>
      <artifactId>jmh-generator-annprocess</artifactId>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <profiles>
    <!--
    Developing Profile
      This profile skips the tedious native build for local development, fetching and unpacking
      the native artifact from the Maven repositories instead. If no artifact matching the current
      version have been deployed previously, building with this profile active will fail.

      Note that any changes to the code that may impact low-level bindings with the TensorFlow
      runtime library will require a complete build, in which case this profile cannot be used.
    -->
    <profile>
      <id>dev</id>
      <properties>
        <native.build.skip>true</native.build.skip>
      </properties>
      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <executions>
              <execution>
                <id>dev-unpack-native</id>
                <phase>initialize</phase>
                <goals>
                  <goal>unpack</goal>
                </goals>
                <configuration>
                  <artifact>${project.groupId}:${project.artifactId}:${project.version}:jar:${native.classifier}</artifact>
                  <outputDirectory>${project.build.directory}/native</outputDirectory>
                </configuration>
              </execution>
            </executions>
          </plugin>
        </plugins>
      </build>
    </profile>
    <!--
    Deploying Profile
      When deploying, native libraries are not rebuilt but fetched from the Maven repository
      where the external builders have uploaded them. All artifacts are then bundled together to be
      deploy at once using the `deploy:deploy-file` or `gpg:sign-and-deploy-file` goal (this is
      done by the `deploy.sh` script).
      This is also important for snapshots since all artifacts must have the same timestamp to avoid
      issues when using Gradle. So the default deploy goal is skipped.
    -->
    <profile>
      <id>deploying</id>
      <properties>
        <native.build.skip>true</native.build.skip>
        <maven.deploy.skip>true</maven.deploy.skip>
      </properties>
    </profile>
  </profiles>

  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>build-helper-maven-plugin</artifactId>
        <version>3.0.0</version>
        <executions>
          <!--
          Add generated classes to the source path
            These are classes generated by the javacpp-plugin, including TensorFlow operations
            wrappers and C API Java bindings
          -->
          <execution>
            <id>add-gen-sources</id>
            <phase>generate-sources</phase>
            <goals>
              <goal>add-source</goal>
            </goals>
            <configuration>
              <sources>
                <source>${project.basedir}/src/gen/java</source>
              </sources>
            </configuration>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <artifactId>maven-resources-plugin</artifactId>
        <version>3.1.0</version>
        <executions>
          <!--
            Important: Use a phase before "generate-sources" like "initialize" or Maven may move
            its execution after JavaCPP when profiles override its configuration
          -->
          <execution>
            <id>javacpp-parser</id>
            <phase>initialize</phase>
            <goals>
              <goal>resources</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.0</version>
        <executions>
          <!--
          Generate Ops classes
            All classes found in the source path that are annotated with `@Operator` are processed
            to be added as an endpoint to one of the generated Ops class
          -->
          <execution>
            <id>default-compile</id>
            <configuration>
              <annotationProcessors>
                <annotationProcessor>org.tensorflow.processor.operator.OperatorProcessor</annotationProcessor>
              </annotationProcessors>
              <annotationProcessorPaths>
                <annotationProcessorPath>
                  <groupId>org.tensorflow</groupId>
                  <artifactId>tensorflow-core-generator</artifactId>
                  <version>${project.version}</version>
                </annotationProcessorPath>
              </annotationProcessorPaths>
              <!-- Important: Cannot be ${project.basedir}/src/gen/java or wherever the ops are -->
              <generatedSourcesDirectory>${project.basedir}/src/gen/annotations</generatedSourcesDirectory>
            </configuration>
          </execution>
          <!--
          Compile JavaCPP presets
            This must be done prematurely, before the generate-sources phase, since the javacpp-plugin
            will parse the compiled presets for generating Java bindings to the native APIs
            Important: Use a phase before "generate-sources" like "initialize" or Maven may move
            its execution after JavaCPP when profiles override its configuration
          -->
          <execution>
            <id>javacpp-parser</id>
            <phase>initialize</phase>
            <goals>
              <goal>compile</goal>
            </goals>
            <configuration>
              <includes>
                <include>org/tensorflow/internal/c_api/presets/*.java</include>
              </includes>
              <!-- Build on Java8 to prevent the plugin to automatically include module-info.java (excluding it won't work) -->
              <release>8</release>
              <compilerArgs combine.self="override"></compilerArgs>
            </configuration>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <groupId>org.bytedeco</groupId>
        <artifactId>javacpp</artifactId>
        <version>${javacpp.version}</version>
        <configuration>
          <properties>${javacpp.platform.properties}</properties>
          <propertyKeysAndValues>
            <property>
              <name>platform.root</name>
              <value>${javacpp.platform.root}</value>
            </property>
            <property>
              <name>platform.compiler</name>
              <value>${javacpp.platform.compiler}</value>
            </property>
            <property>
              <name>platform.extension</name>
              <value>${javacpp.platform.extension}</value>
            </property>
          </propertyKeysAndValues>
          <classPath>${project.build.outputDirectory}</classPath>
          <includePaths>
            <includePath>${project.basedir}/</includePath>
            <includePath>${project.basedir}/bazel-${project.artifactId}/external/org_tensorflow/</includePath>
            <includePath>${project.basedir}/bazel-bin/external/org_tensorflow/</includePath>
            <includePath>${project.basedir}/bazel-${project.artifactId}/external/com_google_absl/</includePath>
            <includePath>${project.basedir}/bazel-${project.artifactId}/external/eigen_archive/</includePath>
            <includePath>${project.basedir}/bazel-${project.artifactId}/external/com_google_protobuf/src/</includePath>
            <includePath>${project.basedir}/target/classes/org/tensorflow/internal/c_api/include/</includePath>
          </includePaths>
          <linkPaths>
            <linkPath>${project.basedir}/bazel-bin/external/llvm_openmp/</linkPath>
            <linkPath>${project.basedir}/bazel-bin/external/org_tensorflow/tensorflow/</linkPath>
          </linkPaths>
          <resourcePaths>
            <resourcePath>${project.basedir}/../../</resourcePath>
            <resourcePath>${project.basedir}/bazel-bin/external/org_tensorflow/tensorflow/tools/lib_package/</resourcePath>
          </resourcePaths>
          <preloadPaths>
            <preloadPath>${project.basedir}/bazel-${project.artifactId}/external/mkl_linux/lib/</preloadPath>
            <preloadPath>${project.basedir}/bazel-${project.artifactId}/external/mkl_darwin/lib/</preloadPath>
            <preloadPath>${project.basedir}/bazel-${project.artifactId}/external/mkl_windows/lib/</preloadPath>
          </preloadPaths>
        </configuration>
        <executions>
          <execution>
            <!--
            Validates the configuration of this plugin
            -->
            <id>javacpp-validate</id>
            <phase>validate</phase>
            <goals>
              <goal>build</goal>
            </goals>
          </execution>
          <execution>
            <!--
            Build TensorFlow core libraries
              This launch a script (build.sh) that will execute Bazel for uploading archives and
              executing the build, which may take many hours on a normal desktop. Libraries are then
              cached so only the first execution will actually trigger a full build.
              This task also trigger the generation of the operation wrappers issued from the code
              found in /src/bazel/op_generator.
            -->
            <id>javacpp-build</id>
            <phase>initialize</phase>
            <goals>
              <goal>build</goal>
            </goals>
            <configuration>
              <skip>${javacpp.build.skip}</skip>
              <buildCommand>
                <program>bash</program>
                <argument>${project.basedir}/build.sh</argument>
              </buildCommand>
              <environmentVariables>
                <PLATFORM>${javacpp.platform}</PLATFORM>
                <EXTENSION>${javacpp.platform.extension}</EXTENSION>
                <BUILD_USER_FLAGS>${native.build.flags}</BUILD_USER_FLAGS>
              </environmentVariables>
              <workingDirectory>${project.basedir}</workingDirectory>
            </configuration>
          </execution>
          <execution>
            <!--
            Clean TensorFlow native libraries
              When this gets executed, all libraries build and cached by Bazel will be deleted and
              will be rebuild on the next execution.
            -->
            <id>javacpp-clean</id>
            <phase>clean</phase>
            <goals>
              <goal>build</goal>
            </goals>
            <configuration>
              <skip>${javacpp.build.skip}</skip>
              <buildCommand>
                <program>bazel</program>
                <argument>clean</argument>
              </buildCommand>
              <workingDirectory>${project.basedir}</workingDirectory>
            </configuration>
          </execution>
          <execution>
            <!--
            Generate TensorFlow C API binding sources
              The plugin will parse the pre-compiled TensorFlow C API presets and generate
              source classes for calling this API directly in Java.
            -->
            <id>javacpp-parser</id>
            <phase>generate-sources</phase>
            <goals>
              <goal>parse</goal>
            </goals>
            <configuration>
              <skip>${javacpp.parser.skip}</skip>
              <outputDirectory>${project.basedir}/src/gen/java</outputDirectory>
              <classOrPackageName>org.tensorflow.internal.c_api.presets.*</classOrPackageName>
            </configuration>
          </execution>
          <execution>
            <!--
            Compile JNI native code from this project
              This code is used to call the TensorFlow C API right now but should be eventually
              replaced by the usage of JavaCPP generated bindings
            -->
            <id>javacpp-compiler</id>
            <phase>process-classes</phase>
            <goals>
              <goal>build</goal>
            </goals>
            <configuration>
              <outputDirectory>${project.build.directory}/native/org/tensorflow/internal/c_api/${native.classifier}/</outputDirectory>
              <skip>${javacpp.compiler.skip}</skip>
              <classOrPackageName>org.tensorflow.internal.c_api.**</classOrPackageName>
              <copyLibs>true</copyLibs>
              <copyResources>true</copyResources>
            </configuration>
          </execution>
        </executions>
        <dependencies>
          <dependency>
            <groupId>com.google.protobuf</groupId>
            <artifactId>protobuf-java</artifactId>
            <version>${protobuf.version}</version>
          </dependency>
        </dependencies>
      </plugin>
      <plugin>
        <!--
        An execution to execute the op class generator (which lives in tensorflow-core-generator).
        Must be ran after build.sh, which generates the ops.pb file it reads.
        Will be ran during the generate-sources phase.
        -->
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>exec-maven-plugin</artifactId>
        <version>3.0.0</version>
        <executions>
          <execution>
            <id>generate-ops</id>
            <goals>
              <goal>java</goal>
            </goals>
            <phase>generate-sources</phase>
          </execution>
        </executions>
        <dependencies>
          <dependency>
            <groupId>org.tensorflow</groupId>
            <artifactId>tensorflow-core-generator</artifactId>
            <version>${project.version}</version>
          </dependency>
        </dependencies>
        <configuration>
          <includeProjectDependencies>false</includeProjectDependencies>
          <includePluginDependencies>true</includePluginDependencies>
          <mainClass>org.tensorflow.op.generator.OpGenerator</mainClass>
          <arguments>
            <argument>${project.basedir}/src/gen/java</argument>
            <argument>${project.basedir}/src/gen/resources/ops.pb</argument>
          </arguments>
        </configuration>
      </plugin>
      <plugin>
        <artifactId>maven-jar-plugin</artifactId>
        <version>3.1.0</version>
        <configuration>
          <archive>
            <manifestEntries>
              <Automatic-Module-Name>${java.module.name}</Automatic-Module-Name>
            </manifestEntries>
          </archive>
        </configuration>
        <executions>
          <execution>
            <!--
            Create the native artifact
              This artifact will contain only native libraries compiled by the javacpp-plugin,
              and will be classified under the active platform (OS, arch, extension...)
            -->
            <id>native-jar</id>
            <phase>package</phase>
            <goals>
              <goal>jar</goal>
            </goals>
            <configuration>
              <classifier>${native.classifier}</classifier>
              <skipIfEmpty>true</skipIfEmpty>
              <includes>
                <!-- In case of successive builds for multiple platforms without cleaning, ensures
                     we only include files for this platform. -->
                <include>org/tensorflow/internal/c_api/${native.classifier}/</include>
              </includes>
              <classesDirectory>${project.build.directory}/native</classesDirectory>
              <excludes>
                <exclude>org/tensorflow/internal/c_api/${native.classifier}/*.exp</exclude>
                <exclude>org/tensorflow/internal/c_api/${native.classifier}/*.lib</exclude>
                <exclude>org/tensorflow/internal/c_api/${native.classifier}/*.obj</exclude>
                <exclude>org/tensorflow/internal/c_api/${native.classifier}/*mklml*</exclude>
                <exclude>org/tensorflow/internal/c_api/${native.classifier}/*msvcr120*</exclude>
              </excludes>
            </configuration>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <artifactId>maven-surefire-plugin</artifactId>
        <executions>
          <execution>
            <!--
            Run the tests after packaging the artifacts
              This is required as most of our unit tests are in fact integration tests that should
              be executed in a TensorFlow runtime environment.
            -->
            <id>default-test</id>
            <phase>integration-test</phase>
            <goals>
              <goal>test</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <!-- Activate the use of TCP to transmit events to the plugin -->
          <!-- disabled as it appears to cause intermittent test failures in GitHub Actions
          <forkNode implementation="org.apache.maven.plugin.surefire.extensions.SurefireForkNodeFactory"/>
          -->
          <additionalClasspathElements>
            <additionalClasspathElement>${project.build.directory}/${project.artifactId}-${project.version}-${native.classifier}.jar</additionalClasspathElement>
            <!-- Note: the following path is not accessible in deploying profile, so other libraries like
                       OpenMP must be installed manually when running the tests -->
            <additionalClasspathElement>${project.build.directory}/native/</additionalClasspathElement>
          </additionalClasspathElements>
        </configuration>
      </plugin>
      <plugin>
        <artifactId>maven-source-plugin</artifactId>
        <version>3.2.1</version>
        <executions>
          <execution>
            <id>attach-sources</id>
            <phase>leave-disabled-to-not-generate-sources-twice-on-release</phase>
          </execution>
          <execution>
            <id>attach-source</id>
            <goals>
              <goal>jar-no-fork</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <artifactId>maven-javadoc-plugin</artifactId>
        <version>3.2.0</version>
        <executions>
          <execution>
            <id>attach-javadocs</id>
            <goals>
              <goal>jar</goal>
            </goals>
            <configuration>
              <failOnError>false</failOnError>
              <minmemory>256m</minmemory>
              <maxmemory>2048m</maxmemory>
              <links>
                <link>http://bytedeco.org/javacpp/apidocs</link>
              </links>
            </configuration>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>3.2.0</version>
        <configuration>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>
