From d9231afa29c1f09e5b558ea23c10085a8a1fa88b Mon Sep 17 00:00:00 2001 From: Kerry Billingham Date: Sun, 5 Mar 2017 19:06:00 +0000 Subject: [PATCH] Changes made to the Maven build process: * Introduced OSGi Blueprint XML file and Bean class too automatically load the native library. * Introduced integration testing module to deploy to Karaf OSGi implementation. * Clears library executable stack flag during build. * Updated README document. --- .../generator/src/java/osgi+OpenCVInterface.java | 8 + .../src/java/osgi+OpenCVNativeLoader.java | 18 ++ platforms/maven/README.md | 35 +-- platforms/maven/opencv-it/pom.xml | 98 ++++++++ .../java/org/opencv/osgi/DeployOpenCVTest.java | 97 +++++++ platforms/maven/opencv/pom.xml | 279 +++++++++++++++++++++ .../resources/OSGI-INF/blueprint/blueprint.xml | 11 + .../maven/{ => opencv}/scripts/deb_package_check | 0 platforms/maven/opencv/scripts/execstack_check | 30 +++ platforms/maven/{ => opencv}/scripts/properties | 0 platforms/maven/pom.xml | 245 ++---------------- 11 files changed, 576 insertions(+), 245 deletions(-) create mode 100644 modules/java/generator/src/java/osgi+OpenCVInterface.java create mode 100644 modules/java/generator/src/java/osgi+OpenCVNativeLoader.java create mode 100644 platforms/maven/opencv-it/pom.xml create mode 100644 platforms/maven/opencv-it/src/test/java/org/opencv/osgi/DeployOpenCVTest.java create mode 100644 platforms/maven/opencv/pom.xml create mode 100644 platforms/maven/opencv/resources/OSGI-INF/blueprint/blueprint.xml rename platforms/maven/{ => opencv}/scripts/deb_package_check (100%) create mode 100755 platforms/maven/opencv/scripts/execstack_check rename platforms/maven/{ => opencv}/scripts/properties (100%) diff --git a/modules/java/generator/src/java/osgi+OpenCVInterface.java b/modules/java/generator/src/java/osgi+OpenCVInterface.java new file mode 100644 index 0000000..83ffee1 --- /dev/null +++ b/modules/java/generator/src/java/osgi+OpenCVInterface.java @@ -0,0 +1,8 @@ +package org.opencv.osgi; + +/** + * Dummy interface to allow some integration testing within OSGi implementation. + */ +public interface OpenCVInterface +{ +} diff --git a/modules/java/generator/src/java/osgi+OpenCVNativeLoader.java b/modules/java/generator/src/java/osgi+OpenCVNativeLoader.java new file mode 100644 index 0000000..5ab9847 --- /dev/null +++ b/modules/java/generator/src/java/osgi+OpenCVNativeLoader.java @@ -0,0 +1,18 @@ +package org.opencv.osgi; + +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * This class is intended to provide a convenient way to load OpenCV's native + * library from the Java bundle. If Blueprint is enabled in the OSGi container + * this class will be instantiated automatically and the init() method called + * loading the native library. + */ +public class OpenCVNativeLoader implements OpenCVInterface { + + public void init() { + System.loadLibrary("opencv_java320"); + Logger.getLogger("org.opencv.osgi").log(Level.INFO, "Successfully loaded OpenCV native library."); + } +} diff --git a/platforms/maven/README.md b/platforms/maven/README.md index 54f151a..30a6c6a 100644 --- a/platforms/maven/README.md +++ b/platforms/maven/README.md @@ -4,16 +4,24 @@ This page describes the how to build OpenCV using [Apache Maven](http://maven.ap The following assumes building on Debian-based Linux platform. -## Overview +## 1 - Overview The Maven build process aims to: 1. Provide a simpler route to build OpenCV and Java bundles. 2. Automatically check the required native dependencies. 3. Make the Java libraries OSGi compatible. 4. Include the native OpenCV native library inside the Java bundle. - 5. Allow the build to function on x86, x86_64 or amd architectures, Debian-based Linux platform. + 5. Integration testing of the bundle within an OSGi environment. + 6. Allow the build to function on x86, x86_64 or amd architectures, Debian-based Linux platform. -### Starting the build -#### Environment variables +### 2 - Preparing The Build environment +To build using the Maven build process both `Maven` and and up-to-date `JDK` (Java Development Kit) need to be installed. If you know you already have these installed then continue to `Environment Variable` otherwise the easiest solution is to install them using the aptitude package manager: + +`sudo aptitude install maven default-jdk` + +Note that installing via `aptitude` you are unlikely to get the latest version of Maven or JDK although if you are not developing Java code this shouldn't matter for this build process. + +### 3 - Starting the build +#### 3.1 - Environment variables **Applicability:** All processors. The following environment variables must be set otherwise the build will fail and halt: @@ -28,37 +36,36 @@ It is recommended that advantage is taken of multiple processor cores to reduce However if this flag is not set the build will NOT fail. On a RaspberryPi 2 typical build times are 5 hours with `-j1` (which is the default if `$MAKEFLAGS` is not specified) and a little over 2 hours with `-j4`. All of the above environment variables can be set on an ad-hoc basis using 'export'. -#### Build Directory +#### 3.2 - Build Directory **Applicability:** All processors By default the following build directories are created. `/build` -`/build/target` +`/build/maven/opencv/target` -Under `build` are the standard OpenCV artifacts. Under `build/target` can be found the OSGi compatible Java bundle. When deploying the bundle into an OSGi framework e.g. [Apache Karaf](http://karaf.apache.org/), loading of the native library is automatically taken care of. The standard Java library as created by the CMake process is also available as specified in the existing OpenCV documentation. +`/build/maven/opencv-it/target` + +Under `build` are the standard OpenCV artifacts. Under `build/maven/opencv/target` can be found the OSGi compatible Java bundle. When deploying the bundle into an OSGi framework e.g. [Apache Karaf](http://karaf.apache.org/), loading of the native library is automatically taken care of. An integration testing module is created under the `open-cv` directory and is only of use during the build. The standard Java library as created by the CMake process is also available as specified in the existing OpenCV documentation. The Maven build is initiated from the directory contain the `pom.xml` file. -#### x86 or x86_64 Architecture: +#### 3.3 - x86 or x86_64 Architecture: Generally all that is required is the standard Maven command: -`mvn clean install` +`mvn clean install -Ddownload.cmake=false` One of the first things the build will do is check the required native dependencies. The Maven build indicates the status of the required dependencies and will fail at this point if any are missing. Install using the package manager e.g. aptitude or apt-get, and restart the build with the above command. Once the build succesfully completes the OSGi compatible artifacts are available as described above in 'Build Directory'. -#### ARM 32-bit Architecture - Raspbian Distribution +#### 3.4 - ARM 32-bit Architecture - Raspbian Distribution Similar to the x86 architecture the native dependencies are first checked so install any that are missing, however at the time of writing there are no official `libtbb2` and `libtbb-dev` packages in Raspbian. Version 4.4.3 of Intel's Thread Building Blocks library are available [here](http://www.javatechnics.com/thread-building-blocks-tbb-4-4-3-for-raspbian) as a Raspbian-compatible Debian packages. **PLEASE NOTE THESE ARE NOT OFFICIAL RASPBIAN PACKAGES. INSTALL AT YOUR OWN RISK.** OpenCV is built using CMake and the Maven build process uses the the [cmake-maven plugin](https://github.com/cmake-maven-project/cmake-maven-project). The cmake-maven plugin by default downloads CMake at build time but unfortunately there is no binary for ARM architecture currently available. As a work around it is possible to use the native CMake (which is checked for availability in the above dependency checks). Assuming all native dependencies are available the build can be started with the following command: -`mvn clean install -Duse.native.cmake=true` +`mvn clean install -Ddownload.cmake=false` Upon a successful build the libraries will be available as described above in 'Build Directory'. - -#### cmake-mave-plugin 3.4.1-b2-SNAPSHOT -Should this plugin not be available in Maven central, the source can be found at my GitHub page [here](https://github.com/jtkb/cmake-maven-project), checkout the `raspberrypi` branch and install. On x86 it is a standard Maven build and install command. If building on Raspbian you also need to supply the `-Duse.native.cmake=true` command-line option. diff --git a/platforms/maven/opencv-it/pom.xml b/platforms/maven/opencv-it/pom.xml new file mode 100644 index 0000000..caeaa7b --- /dev/null +++ b/platforms/maven/opencv-it/pom.xml @@ -0,0 +1,98 @@ + + 4.0.0 + + org.opencv + opencv-parent + 3.2.0 + + org.opencv + opencv-it + OpenCV Integration Test + + + org.ops4j.pax.exam + pax-exam-container-karaf + ${pax.exam.version} + test + + + org.ops4j.pax.exam + pax-exam-junit4 + ${pax.exam.version} + test + + + org.apache.geronimo.specs + geronimo-atinject_1.0_spec + 1.0 + test + + + org.ops4j.pax.url + pax-url-aether + 1.6.0 + test + + + org.osgi + org.osgi.core + 4.3.1 + test + + + org.osgi + org.osgi.compendium + 4.3.0 + test + + + org.slf4j + slf4j-api + 1.7.24 + test + + + org.slf4j + slf4j-simple + 1.7.24 + test + + + org.apache.karaf.log.core + org.apache.karaf.log + 4.0.6 + test + + + org.ops4j.pax.logging + pax-logging-api + 1.8.0 + test + + + junit + junit + 4.8.1 + test + + + ${project.groupId} + opencv + ${project.version} + test + + + + ../../../build/maven/opencv-it/target + src/test/java + ../../../build/maven/opencv-it/target + + + org.apache.maven.plugins + maven-surefire-plugin + 2.15 + + + + diff --git a/platforms/maven/opencv-it/src/test/java/org/opencv/osgi/DeployOpenCVTest.java b/platforms/maven/opencv-it/src/test/java/org/opencv/osgi/DeployOpenCVTest.java new file mode 100644 index 0000000..71c1f3b --- /dev/null +++ b/platforms/maven/opencv-it/src/test/java/org/opencv/osgi/DeployOpenCVTest.java @@ -0,0 +1,97 @@ +package org.opencv.osgi; + +import java.io.File; +import javax.inject.Inject; +import junit.framework.TestCase; +import org.apache.karaf.log.core.LogService; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.ops4j.pax.exam.Configuration; +import static org.ops4j.pax.exam.CoreOptions.maven; +import static org.ops4j.pax.exam.CoreOptions.mavenBundle; +import org.ops4j.pax.exam.Option; +import org.ops4j.pax.exam.junit.PaxExam; +import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.karafDistributionConfiguration; +import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.keepRuntimeFolder; +import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.logLevel; +import org.ops4j.pax.exam.karaf.options.LogLevelOption; +import org.ops4j.pax.exam.options.MavenArtifactUrlReference; +import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; +import org.ops4j.pax.exam.spi.reactors.PerClass; +import org.ops4j.pax.logging.spi.PaxLoggingEvent; +import org.osgi.framework.BundleContext; + +/** + * + * @author Kerry Billingham + */ +@ExamReactorStrategy(PerClass.class) +@RunWith(PaxExam.class) +public class DeployOpenCVTest { + + /* + The expected string in Karaf logs when the bundle has deployed and native library loaded. + */ + private static final String OPEN_CV_SUCCESSFUL_LOAD_STRING = "Successfully loaded OpenCV native library."; + + private static final String KARAF_VERSION = "4.0.6"; + + @Inject + protected BundleContext bundleContext; + + @Inject + private LogService logService; + + /* + This service is required to ensure that the native library has been loaded + before any test is carried out. + */ + @Inject + private OpenCVInterface openCVInterface; + + @Configuration + public static Option[] configuration() throws Exception { + MavenArtifactUrlReference karafUrl = maven() + .groupId("org.apache.karaf") + .artifactId("apache-karaf") + .version(KARAF_VERSION) + .type("tar.gz"); + return new Option[]{ + karafDistributionConfiguration() + .frameworkUrl(karafUrl) + .unpackDirectory(new File("../../../build/target/exam")) + .useDeployFolder(false), + keepRuntimeFolder(), + mavenBundle() + .groupId("org.opencv") + .artifactId("opencv") + .version("3.2.0"), + logLevel(LogLevelOption.LogLevel.INFO) + }; + } + + /** + * Tests that the OpenCV bundle has been successfully deployed and that the + * native library has been loaded. + */ + @Test + public void testOpenCVNativeLibraryLoadSuccess() { + + Iterable loggingEvents = logService.getEvents(); + boolean loadSuccessful = logsContainsMessage(loggingEvents, OPEN_CV_SUCCESSFUL_LOAD_STRING); + + TestCase.assertTrue("Could not determine if OpenCV library successfully loaded from the logs.", loadSuccessful); + + } + + private boolean logsContainsMessage(Iterable logEnumeration, final String logMessageString) { + boolean contains = false; + for (PaxLoggingEvent logEntry : logEnumeration) { + if (logEntry.getMessage().contains(logMessageString)) { + contains = true; + break; + } + } + return contains; + } +} diff --git a/platforms/maven/opencv/pom.xml b/platforms/maven/opencv/pom.xml new file mode 100644 index 0000000..23b65c2 --- /dev/null +++ b/platforms/maven/opencv/pom.xml @@ -0,0 +1,279 @@ + + 4.0.0 + + org.opencv + opencv-parent + 3.2.0 + + org.opencv + opencv + bundle + OpenCV + + + ../../.. + ${source.path}/build + libopencv_java${lib.version.string}.so + ${build.directory}/src + + + ../../../build/maven/opencv/target + ../../../build/src + ../../../build/src + + + org.apache.maven.plugins + maven-clean-plugin + 3.0.0 + + + + ${build.directory} + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.4.0 + + + get-opencv-version + generate-resources + + exec + + + bash + ${project.basedir}/scripts + + properties + ../../../../modules/core/include/opencv2/core/version.hpp + ${build.directory} + build.properties + + + + + setup-environment + validate + + exec + + + bash + ${project.basedir}/scripts + + deb_package_check + build-essential + cmake + git + libgtk2.0-dev + pkg-config + libavcodec-dev + libavformat-dev + libswscale-dev + python-dev + python-numpy + libtbb2 + libtbb-dev + libjpeg-dev + libpng12-dev + libtiff5-dev + libjasper-dev + libdc1394-22-dev + execstack + ant + + + + + execstack + process-classes + + exec + + + ${build.directory}/lib + execstack + + -c + libopencv_java320.so + + + + + check-execstack + process-classes + + exec + + + ${project.basedir}/scripts + bash + + execstack_check + ${build.directory}/lib/libopencv_java320.so + + + + + + + maven-resources-plugin + 3.0.2 + + + copy-resources + generate-resources + + copy-resources + + + ${resources.directory} + + + resources + + + + + + + + org.codehaus.mojo + properties-maven-plugin + 1.0.0 + + + set-arch-properties + process-resources + + read-project-properties + + + + ${build.directory}/build.properties + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 1.4.1 + + + validate + enforce-os + + enforce + + + + + unix + This POM is written to function on UNIX family of OS. + More specifically it should be a Debian flavour of Linux. + + + + + + enforce-environment + + enforce + + + + + ANT_HOME + $ANT_HOME is not set. Build may fail. + + + JAVA_HOME + $JAVA_HOME is not set. Build WILL fail. + + + WARN + MAKEFLAGS + No MAKEFLAGS environment variable. Build may be slow. + To speed up the build you can try exporting MAKEFLAGS=-jX where X equals the number of parallel builds. + + + + + + process-resources + check-versions-match + + enforce + + + + + project.version + ${opencv.version} + The Maven POM version ${project.version} does not match the extracted OpenCV version ${opencv.version}. + + + + + + + + org.apache.felix + maven-bundle-plugin + 2.3.7 + true + + + * + ${nativelibrary.name};osname=linux;processor=${osgi.processor} + ${build.directory}/lib/${nativelibrary.name} + + ${build.directory}/manifest + true + + + + com.googlecode.cmake-maven-project + cmake-maven-plugin + 3.4.1-b2 + + + cmake-generate + + generate + + + ../../.. + ../../../build + Unix Makefiles + + + + + + + cmake-compile + + compile + + + ../../../build + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.15 + + + + diff --git a/platforms/maven/opencv/resources/OSGI-INF/blueprint/blueprint.xml b/platforms/maven/opencv/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 0000000..cdd9978 --- /dev/null +++ b/platforms/maven/opencv/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/platforms/maven/scripts/deb_package_check b/platforms/maven/opencv/scripts/deb_package_check similarity index 100% rename from platforms/maven/scripts/deb_package_check rename to platforms/maven/opencv/scripts/deb_package_check diff --git a/platforms/maven/opencv/scripts/execstack_check b/platforms/maven/opencv/scripts/execstack_check new file mode 100755 index 0000000..f40db09 --- /dev/null +++ b/platforms/maven/opencv/scripts/execstack_check @@ -0,0 +1,30 @@ +#!/bin/bash + +################################################################## +# +# This script will clear the executable flag on +# the specified library and then check it has +# been cleared as a separate operation. +# +# $1 - The absolute path to the OpenCV native library. +# +# Returns: +# 0 - The executable flag has been cleared +# 1 - The executable flag could NOT be cleared (failure). +# +# Kerry Billingham +# 11 March 2017 +# +################################################################## +red=$'\e[1;31m' +green=$'\e[1;32m' +end=$'\e[0m' +echo "${green}[INFO] Checking that the native library executable stack flag is NOT set.${end}" +execstack -c $1 +execstack -q $1 | grep -o ^- +if [ $? -ne 0 ]; then + echo + echo "${red}[ERROR] The Executable Flag could not be cleared on the library $1.${end}" + exit 1 +fi +exit 0 diff --git a/platforms/maven/scripts/properties b/platforms/maven/opencv/scripts/properties similarity index 100% rename from platforms/maven/scripts/properties rename to platforms/maven/opencv/scripts/properties diff --git a/platforms/maven/pom.xml b/platforms/maven/pom.xml index d070acf..15aba5f 100644 --- a/platforms/maven/pom.xml +++ b/platforms/maven/pom.xml @@ -1,11 +1,11 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - opencv.org - opencv - bundle + org.opencv + opencv-parent 3.2.0 - OpenCV + pom + OpenCV Parent POM License Agreement For Open Source Computer Vision Library (3-clause BSD License) @@ -25,17 +25,12 @@ www.javatechnics.com - - - junit - junit - 3.8.1 - test - - + - ../../build libopencv_java${lib.version.string}.so + 4.8.0 + 1.8 + 1.8 @@ -43,221 +38,9 @@ ${repo.url} - - ../../build/target - ../../build/src - ../../build/src - - - org.apache.maven.plugins - maven-clean-plugin - 3.0.0 - - - - ${build.directory} - - - - - - com.github.maven-nar - nar-maven-plugin - 3.3.0 - true - - - nar-initiliase - validate - - nar-validate - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.4.0 - - - get-opencv-version - generate-resources - - exec - - - bash - ${project.basedir}/scripts - - properties - ../../../modules/core/include/opencv2/core/version.hpp - ${build.directory} - build.properties - - - - - setup-environment - validate - - exec - - - bash - ${project.basedir}/scripts - - deb_package_check - build-essential - cmake - git - libgtk2.0-dev - pkg-config - libavcodec-dev - libavformat-dev - libswscale-dev - python-dev - python-numpy - libtbb2 - libtbb-dev - libjpeg-dev - libpng12-dev - libtiff5-dev - libjasper-dev - libdc1394-22-dev - ant - - - - - - - org.codehaus.mojo - properties-maven-plugin - 1.0.0 - - - set-arch-properties - process-resources - - read-project-properties - - - - ${build.directory}/build.properties - - - - - - - org.apache.maven.plugins - maven-enforcer-plugin - 1.4.1 - - - validate - enforce-os - - enforce - - - - - unix - This POM is written to function on UNIX family of OS. - More specifically it should be a Debian flavour of Linux. - - - - - - enforce-environment - - enforce - - - - - ANT_HOME - $ANT_HOME is not set. Build may fail. - - - JAVA_HOME - $JAVA_HOME is not set. Build WILL fail. - - - WARN - MAKEFLAGS - No MAKEFLAGS environment variable. Build may be slow. -To speed up the build you can try exporting MAKEFLAGS=-jX where X equals the number of parallel builds. - - - - - - process-resources - check-versions-match - - enforce - - - - - project.version - ${opencv.version} - The Maven POM version ${project.version} does not match the extracted OpenCV version ${opencv.version}. - - - - - - - - org.apache.felix - maven-bundle-plugin - 2.3.7 - true - - - * - ${nativelibrary.name};osname=linux;processor=${osgi.processor} - ${build.directory}/lib/${nativelibrary.name} - - ${build.directory}/manifest - true - - - - com.googlecode.cmake-maven-project - cmake-maven-plugin - 3.4.1-b2-SNAPSHOT - - - cmake-generate - - generate - - - ../.. - ../../build - Unix Makefiles - - - - - - - cmake-compile - - compile - - - ../../build - - - - - - + + + opencv + opencv-it + -- 2.7.4