jsadler
jsadler

Reputation: 619

How to include contrib op in Tensorflow bazel build

I'm building for Android using selective registration and the //tensorflow/contrib/android:libtensorflow_inference.so target:

bazel build -c opt --copt="-DSELECTIVE_REGISTRATION" --copt="-DSUPPORT_SELECTIVE_REGISTRATION" //tensorflow/contrib/android:libtensorflow_inference.so --crosstool_top=//external:android/crosstool --host_crosstool_top=@bazel_tools//tools/cpp:toolchain --cpu=x86_64

Which works fine until I need to use an op that lives in contrib. Specifically I need access to ImageProjectiveTransform, which is part of the //tensorflow/contrib/image:image_ops_cc target. I tried modifying the //tensorflow/core:android_tensorflow_lib target to add it as a dependency:

# Full TensorFlow library with operator support. Use this unless reducing
# binary size (by packaging a reduced operator set) is a concern.
cc_library(
    name = "android_tensorflow_lib",
    srcs = if_android([":android_op_registrations_and_gradients"]),
    copts = tf_copts(),
    tags = [
        "manual",
        "notap",
    ],
    visibility = ["//visibility:public"],
    deps = [
        ":android_tensorflow_lib_lite",
        ":protos_all_cc_impl",
        "//tensorflow/core/kernels:android_tensorflow_kernels",
        "//tensorflow/contrib/image:image_ops_cc",
        "//third_party/eigen3",
        "@protobuf_archive//:protobuf",
    ],
    alwayslink = 1,
)

But now the compile fails:

In file included from external/com_googlesource_code_re2/re2/bitstate.cc:25:
In file included from external/com_googlesource_code_re2/re2/prog.h:14:
In file included from external/androidndk/ndk/sources/cxx-stl/gnu-libstdc++/4.9/include/mutex:35:
external/androidndk/ndk/sources/cxx-stl/gnu-libstdc++/4.9/include/bits/c++0x_warning.h:32:2: error: This file requires compiler and library support for the ISO C++ 2011 standard. This support is currently experimental, and must be enabled with the -std=c++11 or -std=gnu++11 compiler options.

But if I specify C++11 in the bazel build call:

bazel build -c opt --copt="-std=c++11" --copt="-DSELECTIVE_REGISTRATION" --copt="-DSUPPORT_SELECTIVE_REGISTRATION" //tensorflow/contrib/android:libtensorflow_inference.so --crosstool_top=//external:android/crosstool --host_crosstool_top=@bazel_tools//tools/cpp:toolchain --cpu=x86_64

Then I get a different error:

ERROR: /private/var/tmp/_bazel_json/e38619818ff94aae50ac5b3bdbbe0f32/external/png_archive/BUILD:8:1: C++ compilation of rule '@png_archive//:png' failed (Exit 1)
error: invalid argument '-std=c++11' not allowed with 'C/ObjC'
Target //tensorflow/contrib/android:libtensorflow_inference.so failed to build

(I have no idea why anything in the Android build would be using Objective-C)

Upvotes: 1

Views: 880

Answers (1)

nmatter
nmatter

Reputation: 81

I also wanted to include ImageProjectiveTransform and encountered the same errors. I was able to successfully include it via the following steps, which are a modification of the procedure suggested here.

git clone https://github.com/tensorflow/tensorflow.git
git checkout r1.10
python tensorflow/tensorflow/python/tools/print_selective_registration_header.py --graphs PATH_TO_MODEL/model.pb > ops_to_register.h
cp ops_to_register.h tensorflow/tensorflow/core/framework/
cd tensorflow
bazel build -c opt --cxxopt="-DSELECTIVE_REGISTRATION" //tensorflow/contrib/android:libtensorflow_inference.so --host_crosstool_top=@bazel_tools//tools/cpp:toolchain --crosstool_top=//external:android/crosstool --cpu=armeabi-v7a --jobs 10 --cxxopt=-std=c++11
cp bazel-bin/tensorflow/contrib/android/libtensorflow_inference.so ANDROID_PROJECT/libs/armeabi-v7a/

However, before running this, the following modifications were necessary.

These changes resolved compiling errors:

diff --git a/tensorflow/contrib/image/kernels/image_ops.h b/tensorflow/contrib/image/kernels/image_ops.h
index 209aa24..b8ec643 100644
--- a/tensorflow/contrib/image/kernels/image_ops.h
+++ b/tensorflow/contrib/image/kernels/image_ops.h
@@ -97,8 +97,8 @@ class ProjectiveGenerator {
   EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T
   nearest_interpolation(const DenseIndex batch, const float y, const float x,
                         const DenseIndex channel, const T fill_value) const {
-    return read_with_fill_value(batch, DenseIndex(std::round(y)),
-                                DenseIndex(std::round(x)), channel, fill_value);
+    return read_with_fill_value(batch, DenseIndex(::round(y)),
+                                DenseIndex(::round(x)), channel, fill_value);
   }

   EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T
diff --git a/tensorflow/core/common_runtime/eager/BUILD b/tensorflow/core/common_runtime/eager/BUILD
index 7f28f3b..aa64220 100644
--- a/tensorflow/core/common_runtime/eager/BUILD
+++ b/tensorflow/core/common_runtime/eager/BUILD
@@ -150,7 +150,7 @@ tf_cuda_library(
     deps = select({
         "//tensorflow:android": [
             "//tensorflow/core:android_tensorflow_lib_lite",
-            "//util/hash:farmhash_fingerprint",
+            #"//util/hash:farmhash_fingerprint",
         ],
         "//conditions:default": [
             "//tensorflow/core:core_cpu_lib",
@@ -223,7 +223,7 @@ tf_cuda_library(
     ] + select({
         "//tensorflow:android": [
             "//tensorflow/core:android_tensorflow_lib_lite",
-            "//util/hash:farmhash_fingerprint",
+            #"//util/hash:farmhash_fingerprint",
         ],
         "//conditions:default": [
             "//tensorflow/core:core_cpu",

This adds the files for missing ops and kernels to the build. For me, this included Asin, Sin, Cos, and ResizeArea in addition to ImageProjectiveTransform.

diff --git a/tensorflow/core/kernels/BUILD b/tensorflow/core/kernels/BUILD
index 7599cf7..8ebb77e 100644
--- a/tensorflow/core/kernels/BUILD
+++ b/tensorflow/core/kernels/BUILD
@@ -4936,6 +4936,7 @@ filegroup(
 filegroup(
     name = "android_extended_ops_headers",
     srcs = [
+       "//tensorflow/contrib/image:image_ops_op_lib",
         "argmax_op.h",
         "avgpooling_op.h",
         "batch_matmul_op_impl.h",
@@ -4995,6 +4996,11 @@ filegroup(
 filegroup(
     name = "android_extended_ops_group1",
     srcs = [
+       "//tensorflow/contrib/image:image_ops_kernels",
+       "resize_area_op.cc",
+       "cwise_op_asin.cc",
+       "cwise_op_cos.cc",
+       "cwise_op_sin.cc",
         "argmax_op.cc",
         "avgpooling_op.cc",
         "batch_matmul_op_real.cc",

This causes tf.contrib to be registered before loading the frozen graph:

diff --git a/tensorflow/python/tools/print_selective_registration_header.py b/tensorflow/python/tools/print_selective_registration_header.py
index 21d7de0..923ad76 100644
--- a/tensorflow/python/tools/print_selective_registration_header.py
+++ b/tensorflow/python/tools/print_selective_registration_header.py
@@ -40,6 +40,8 @@ import sys

 from tensorflow.python.platform import app
 from tensorflow.python.tools import selective_registration_header_lib
+from tensorflow import contrib
+contrib.resampler

 FLAGS = None

This shows how to find the *.cc files with missing ops so they can be added to BUILD.

cd <tensorflow_repo>/tensorflow/core/kernels
for i in <op_list>
do 
    echo ====
    echo $i
    echo ====
    grep -Rl \”$i\” .
done

Upvotes: 1

Related Questions