xref: /aosp_15_r20/external/federated-compute/fcp/tensorflow/BUILD (revision 14675a029014e728ec732f129a32e299b2da0601)
1# Copyright 2019 Google LLC
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#      http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15load("@system_provided_tf//:system_provided_tf.bzl", "tf_custom_op_library")
16load("@rules_python//python:defs.bzl", "py_binary", "py_test")
17load("//fcp:config.bzl", "FCP_COPTS")
18load("//fcp/tracing:build_defs.bzl", "tracing_schema_cc_library")
19load("@org_tensorflow//tensorflow:tensorflow.bzl", "tf_cc_test", "tf_gen_op_wrapper_py")
20load("@org_tensorflow//tensorflow:tensorflow.bzl", "tf_custom_op_py_library")
21load("@com_github_grpc_grpc//bazel:python_rules.bzl", "py_proto_library")
22
23default_visibility = ["//fcp:internal"]
24
25package(
26    default_visibility = default_visibility,
27    licenses = ["notice"],  # Apache 2.0
28)
29
30tf_cc_test(
31    name = "tf_smoke_test",
32    srcs = ["tf_smoke_test.cc"],
33    extra_copts = FCP_COPTS,
34    deps = [
35        "@com_google_googletest//:gtest_main",
36        "@org_tensorflow//tensorflow/cc:cc_ops",
37        "@org_tensorflow//tensorflow/cc:client_session",
38        "@org_tensorflow//tensorflow/core:framework",
39        "@org_tensorflow//tensorflow/core:tensorflow_opensource",
40        "@org_tensorflow//tensorflow/core:testlib",
41    ],
42)
43
44py_test(
45    name = "tf_py_smoke_test",
46    srcs = ["tf_py_smoke_test.py"],
47    python_version = "PY3",
48)
49
50# Library for converting between the FCP and TensorFlow versions of a Status.
51# Note that this library is intended to be usable in an op .so, thus it depends
52# on TF headers but *not* an implementation (the final binary needs to link it
53# in). We must also use the right copy of headers, depending on whether the
54# build is targeting a system-provided TF library or a bazel-built one.
55cc_library(
56    name = "status",
57    srcs = [
58        "status.cc",
59    ],
60    hdrs = [
61        "status.h",
62    ],
63    copts = FCP_COPTS,
64    deps = [
65        "//fcp/base",
66    ] + select({
67        "@system_provided_tf//:system_provided_tf_build": ["@system_provided_tf//:tf_headers"],
68        "//conditions:default": ["@org_tensorflow//tensorflow/core:framework_headers_lib"],
69    }),
70)
71
72cc_test(
73    name = "status_test",
74    srcs = [
75        "status_test.cc",
76    ],
77    copts = FCP_COPTS,
78    deps = [
79        ":status",
80        "@com_google_googletest//:gtest_main",
81        # See remarks on :status about the TF framework dependency
82        "@org_tensorflow//tensorflow/core:framework",
83    ],
84)
85
86cc_library(
87    name = "host_object",
88    srcs = [
89        "host_object.cc",
90    ],
91    hdrs = [
92        "host_object.h",
93    ],
94    copts = FCP_COPTS,
95    visibility = default_visibility + [
96    ],
97    deps = [
98        "//fcp/base",
99        "//fcp/base:random_token",
100        "//fcp/base:unique_value",
101        "@com_google_absl//absl/base:core_headers",
102        "@com_google_absl//absl/container:flat_hash_map",
103        "@com_google_absl//absl/synchronization",
104    ],
105)
106
107cc_test(
108    name = "host_object_test",
109    srcs = [
110        "host_object_test.cc",
111    ],
112    copts = FCP_COPTS,
113    deps = [
114        ":host_object",
115        "@com_google_googletest//:gtest_main",
116    ],
117)
118
119tracing_schema_cc_library(
120    name = "tracing_schema",
121    srcs = ["tracing_schema.fbs"],
122)
123
124cc_library(
125    name = "tf_session",
126    srcs = ["tf_session.cc"],
127    hdrs = ["tf_session.h"],
128    copts = FCP_COPTS,
129    deps = [
130        ":status",
131        ":tracing_schema",
132        "//fcp/base",
133        "//fcp/base:process_unique_id",
134        "//fcp/base:result",
135        "//fcp/protos:plan_cc_proto",
136        "//fcp/tracing",
137        "@com_google_absl//absl/container:flat_hash_map",
138        "@com_google_absl//absl/strings",
139        "@com_google_absl//absl/strings:cord",
140        "@org_tensorflow//tensorflow/core:core_cpu",
141        "@org_tensorflow//tensorflow/core:protos_all_cc",
142        "@org_tensorflow//tensorflow/core:tensorflow",
143    ],
144)
145
146cc_test(
147    name = "tf_session_test",
148    srcs = ["tf_session_test.cc"],
149    copts = FCP_COPTS,
150    deps = [
151        ":tf_session",
152        ":tracing_schema",
153        "//fcp/base:tracing_schema",
154        "//fcp/protos:plan_cc_proto",
155        "//fcp/tensorflow/testing:tf_helper",
156        "//fcp/testing:result_matchers",
157        "//fcp/tracing:test_tracing_recorder",
158        "@com_google_googletest//:gtest_main",
159        "@org_tensorflow//tensorflow/cc:cc_ops",
160        "@org_tensorflow//tensorflow/cc:scope",
161        "@org_tensorflow//tensorflow/core:protos_all_cc",
162        "@org_tensorflow//tensorflow/core:tensorflow",
163        "@org_tensorflow//tensorflow/core:testlib",
164    ],
165)
166
167# C++ interfaces for implementing an 'external dataset' (a kind of host object).
168# Note this does *not* depend on TensorFlow.
169cc_library(
170    name = "external_dataset",
171    srcs = [
172    ],
173    hdrs = [
174        "external_dataset.h",
175    ],
176    copts = FCP_COPTS,
177    visibility = default_visibility + [
178    ],
179    deps = [
180        ":host_object",
181        "//fcp/base:bounds",
182        "@com_google_absl//absl/status",
183        "@com_google_absl//absl/status:statusor",
184        "@com_google_absl//absl/strings",
185    ],
186)
187
188# The targets below produce a custom op, which involves a native library as
189# well as Python wrappers. There is some significant complexity arising from
190# the various ways that an op / kernel might be linked in, which we'll try to
191# explain here:
192#
193#   - Ops / kernels are meant to be buildable as DSOs (dynamic shared objects,
194#     i.e. .so files). Yet, all ops and kernels must agree on the same
195#     'framework' for registration etc. When building a DSO, ops and kernels
196#     can include TensorFlow framework *headers*, with implementations provided
197#     by libtensorflow_framework.so at runtime.
198#
199#   - When using ops / kernels (and TensorFlow) from a standard Python
200#     interpreter, they *must* be loaded as DSOs.
201#
202#   - When using ops / kernels (and TensorFlow) from C++, we have the option of
203#     linking a monolithic binary, with Bazel's usual handling of deps. This is
204#     in fact necessary to generate Python wrapper code (the generator links in
205#     cc_library deps).
206#
207# Below, we generate *both* a DSO and cc_library variant of the ExternalDataset
208# op and kernel:
209#   cc_library: :external_dataset_op_lib
210#   DSO: _external_dataset_op.so
211#
212# The ExternalDataset op is a peculiar case, since it is specifically intended
213# to use objects provided by the program hosting TensorFlow (beyond the usual
214# TensorFlow APIs). This is problematic, since separate host and DSO binaries
215# each end up with their own definitions of symbols from common libraries (and
216# likely export them!). Though this might appear to work sometimes, it must be
217# avoided.
218# See e.g. https://github.com/abseil/abseil-cpp/issues/125
219#
220#                    ---------------------------
221#                    | _external_dataset_op.so |
222#  -------------  -> |  absl                   |
223#  | Host      | /   |  fcp/base               |
224#  |  absl     |     ---------------------------
225#  |  fcp/base | \           |
226#  -------------  \          v
227#                  \   ------------------------------
228#                   -> | libtensorflow_framework.so |
229#                      ------------------------------
230#
231# When using the cc_library version and Bazel's usual handling of the deps
232# graph, this is of course not a problem.
233#
234# As such, the DSO version is specifically useful for *building graphs in
235# Python* and therefore targets the system-provided Python TensorFlow package.
236# (C++) host programs must use the cc_library version.
237
238EXTERNAL_DATASET_OP_SRCS = ["external_dataset_op.cc"]
239
240EXTERNAL_DATASET_OP_DEPS = [
241    ":external_dataset",
242    ":status",
243    "@com_google_absl//absl/strings:str_format",
244    "//fcp/base:random_token",
245]
246
247# Public: TensorFlow op and op-kernel, that delegates to an ExternalDatasetStub
248# host object. This is the cc_library version. See explanation above.
249cc_library(
250    name = "external_dataset_op_lib",
251    srcs = EXTERNAL_DATASET_OP_SRCS,
252    copts = FCP_COPTS,
253    visibility = ["//visibility:public"],
254    deps = EXTERNAL_DATASET_OP_DEPS + [
255        "@org_tensorflow//tensorflow/core:framework",
256        "@org_tensorflow//tensorflow/core:lib",
257    ],
258    # Uses TensorFlow's registration macros
259    alwayslink = 1,
260)
261
262# DSO version of :external_dataset_op_lib, intended to be loaded by Python
263# wrappers. See explanation above.
264tf_custom_op_library(
265    name = "_external_dataset_op.so",
266    srcs = EXTERNAL_DATASET_OP_SRCS,
267    copts = FCP_COPTS,
268    deps = EXTERNAL_DATASET_OP_DEPS,
269)
270
271# Generates the basic op wrapper for use in Python. As this is a dataset op,
272# it's not useful directly; see :external_dataset_py.
273tf_gen_op_wrapper_py(
274    name = "gen_external_dataset_py",
275    out = "gen_external_dataset_py.py",
276    deps = [
277        ":external_dataset_op_lib",
278    ],
279)
280
281# Public: Python library for ExternalDataset.
282tf_custom_op_py_library(
283    name = "external_dataset_py",
284    srcs = ["external_dataset.py"],
285    dso = [":_external_dataset_op.so"],
286    kernels = [
287        ":external_dataset_op_lib",
288    ],
289    visibility = ["//visibility:public"],
290    deps = [":gen_external_dataset_py"],
291)
292
293# The dataset API isn't really usable from C++, so we generate a GraphDef for
294# testing using Python.
295py_binary(
296    name = "make_external_dataset_test_graph",
297    testonly = True,
298    srcs = ["make_external_dataset_test_graph.py"],
299    python_version = "PY3",
300    deps = [":external_dataset_py"],
301)
302
303genrule(
304    name = "external_dataset_test_graph",
305    testonly = True,
306    srcs = [],
307    outs = ["external_dataset_test.pbtxt"],
308    cmd = "$(location :make_external_dataset_test_graph) --output \"$@\"",
309    tools = [":make_external_dataset_test_graph"],
310)
311
312# Selector proto used in test dataset stubs and example selector fuser op.
313proto_library(
314    name = "test_selector_proto",
315    testonly = True,
316    srcs = [
317        "test_selector.proto",
318    ],
319)
320
321cc_proto_library(
322    name = "test_selector_cc_proto",
323    testonly = True,
324    deps = [":test_selector_proto"],
325)
326
327tf_cc_test(
328    name = "external_dataset_op_test",
329    srcs = ["external_dataset_op_test.cc"],
330    data = [
331        "external_dataset_test.pbtxt",
332    ],
333    extra_copts = FCP_COPTS,
334    deps = [
335        ":external_dataset",
336        ":external_dataset_op_lib",
337        ":test_selector_cc_proto",
338        "@com_google_googletest//:gtest_main",
339        "@com_google_protobuf//:protobuf",
340        "@org_tensorflow//tensorflow/core:core_cpu",
341        "@org_tensorflow//tensorflow/core:direct_session",
342        "@org_tensorflow//tensorflow/core:framework",
343        "@org_tensorflow//tensorflow/core:protos_all_cc",
344        "@org_tensorflow//tensorflow/core:tensorflow_opensource",
345        "@org_tensorflow//tensorflow/core:testlib",
346    ],
347)
348
349CRC32_OP_SRCS = [
350    "crc32_op.cc",
351    "tensor_crc32.cc",
352]
353
354# Custom op to compute the CRC32 checksum of a tensor.
355cc_library(
356    name = "crc32_op_lib",
357    srcs = [
358        "crc32_op.cc",
359        "tensor_crc32.cc",
360    ],
361    hdrs = ["tensor_crc32.h"],
362    copts = FCP_COPTS,
363    visibility = ["//visibility:public"],
364    deps = [
365        "@org_tensorflow//tensorflow/core:framework",
366        "@org_tensorflow//tensorflow/core:lib",
367    ],
368    # Uses TensorFlow's registration macros
369    alwayslink = 1,
370)
371
372tf_custom_op_library(
373    name = "_crc32_op.so",
374    srcs = CRC32_OP_SRCS + ["tensor_crc32.h"],
375    copts = FCP_COPTS,
376)
377
378# Generates the basic op wrapper for use in Python.
379tf_gen_op_wrapper_py(
380    name = "gen_crc32_py",
381    out = "gen_crc32_py.py",
382    deps = [
383        ":crc32_op_lib",
384    ],
385)
386
387tf_custom_op_py_library(
388    name = "crc32_py",
389    srcs = ["crc32.py"],
390    dso = [":_crc32_op.so"],
391    kernels = [
392        ":crc32_op_lib",
393    ],
394    deps = [":gen_crc32_py"],
395)
396
397py_test(
398    name = "crc32_test",
399    srcs = ["crc32_test.py"],
400    python_version = "PY3",
401    deps = [":crc32_py"],
402)
403
404EXAMPLE_SELECTOR_FUSER_OP_SRCS = ["example_selector_fuser_op.cc"]
405
406EXAMPLE_SELECTOR_FUSER_OP_DEPS = [
407    "@com_google_protobuf//:protobuf",
408    "//fcp/protos:plan_cc_proto",
409]
410
411# Custom op to add resumption token to example selector.
412cc_library(
413    name = "example_selector_fuser_op_lib",
414    srcs = EXAMPLE_SELECTOR_FUSER_OP_SRCS,
415    copts = FCP_COPTS,
416    visibility = ["//visibility:public"],
417    deps = EXAMPLE_SELECTOR_FUSER_OP_DEPS + [
418        "@org_tensorflow//tensorflow/core:framework",
419        "@org_tensorflow//tensorflow/core:lib",
420    ],
421    # Uses TensorFlow's registration macros
422    alwayslink = 1,
423)
424
425tf_custom_op_library(
426    name = "_example_selector_fuser_op.so",
427    srcs = EXAMPLE_SELECTOR_FUSER_OP_SRCS,
428    copts = FCP_COPTS,
429    deps = EXAMPLE_SELECTOR_FUSER_OP_DEPS,
430)
431
432# Generates the basic op wrapper for use in Python.
433tf_gen_op_wrapper_py(
434    name = "gen_example_selector_fuser_op",
435    out = "gen_example_selector_fuser_op.py",
436    deps = [
437        ":example_selector_fuser_op_lib",
438    ],
439)
440
441tf_custom_op_py_library(
442    name = "example_selector_fuser_py",
443    srcs = ["example_selector_fuser.py"],
444    dso = [":_example_selector_fuser_op.so"],
445    kernels = [
446        ":example_selector_fuser_op_lib",
447    ],
448    visibility = ["//visibility:public"],
449    deps = [":gen_example_selector_fuser_op"],
450)
451
452py_proto_library(
453    name = "test_selector_py_pb2",
454    testonly = True,
455    deps = [
456        ":test_selector_proto",
457    ],
458)
459
460py_test(
461    name = "example_selector_fuser_test",
462    srcs = ["example_selector_fuser_test.py"],
463    python_version = "PY3",
464    deps = [
465        ":example_selector_fuser_py",
466        ":test_selector_py_pb2",
467        "//fcp/protos:plan_py_pb2",
468    ],
469)
470
471# C++ library to set and access callbacks for slice serving requests.
472# Used by the `ServeSlices` custom op below.
473cc_library(
474    name = "serve_slices_registry",
475    hdrs = [
476        "serve_slices_registry.h",
477    ],
478    copts = FCP_COPTS,
479    visibility = ["//visibility:public"],
480    deps = [
481        ":host_object",
482    ],
483)
484
485cc_test(
486    name = "serve_slices_registry_test",
487    srcs = ["serve_slices_registry_test.cc"],
488    deps = [
489        ":host_object",
490        ":serve_slices_registry",
491        "//fcp/base:random_token",
492        "@com_google_googletest//:gtest_main",
493        "@org_tensorflow//tensorflow/core:framework",
494    ],
495)
496
497SERVE_SLICES_OP_SRCS = ["serve_slices_op.cc"]
498
499SERVE_SLICES_OP_DEPS = [
500    ":serve_slices_registry",
501    "@com_google_absl//absl/strings",
502    "@com_google_absl//absl/strings:str_format",
503]
504
505# Custom op to register slices to serve for a `federated_select`.
506cc_library(
507    name = "serve_slices_op_lib",
508    srcs = SERVE_SLICES_OP_SRCS,
509    copts = FCP_COPTS,
510    visibility = ["//visibility:public"],
511    deps = SERVE_SLICES_OP_DEPS + [
512        "@org_tensorflow//tensorflow/core:framework",
513        "@org_tensorflow//tensorflow/core:lib",
514    ],
515    # Uses TensorFlow's registration macros
516    alwayslink = 1,
517)
518
519# DSO version of `:serve_slices_op_lib`, intended to be loaded by Python
520# wrappers. See explanation above starting with "The targets below...".
521tf_custom_op_library(
522    name = "_serve_slices_op.so",
523    srcs = SERVE_SLICES_OP_SRCS + [
524        # Bundling the registry and op ensures that the same HostObjectRegistry is used by both.
525        "//fcp/tensorflow/python:serve_slices_registry.cc",
526    ],
527    copts = FCP_COPTS,
528    deps = SERVE_SLICES_OP_DEPS + [
529        "@pybind11",
530        "@pybind11_abseil//pybind11_abseil:absl_casters",
531    ],
532)
533
534# Generates the basic op wrapper for use in Python.
535# Don't use this directly: use `:serve_slices_py` to ensure that the
536# appropriate shared libraries are loaded.
537tf_gen_op_wrapper_py(
538    name = "gen_serve_slices_py",
539    out = "gen_serve_slices_py.py",
540    deps = [
541        ":serve_slices_op_lib",
542    ],
543)
544
545# Public: Python library for ServeSlices.
546tf_custom_op_py_library(
547    name = "serve_slices_py",
548    srcs = ["serve_slices.py"],
549    dso = [":_serve_slices_op.so"],
550    kernels = [
551        ":serve_slices_op_lib",
552    ],
553    visibility = ["//visibility:public"],
554    deps = [":gen_serve_slices_py"],
555)
556
557# Generate a GraphDef for testing `ServeSlices` using Python.
558py_binary(
559    name = "make_serve_slices_test_graph",
560    testonly = True,
561    srcs = ["make_serve_slices_test_graph.py"],
562    python_version = "PY3",
563    deps = [":serve_slices_py"],
564)
565
566genrule(
567    name = "serve_slices_test_graph",
568    testonly = True,
569    srcs = [],
570    outs = ["serve_slices_test.pbtxt"],
571    cmd = "$(location :make_serve_slices_test_graph) --output \"$@\"",
572    tools = [":make_serve_slices_test_graph"],
573)
574
575tf_cc_test(
576    name = "serve_slices_op_test",
577    srcs = ["serve_slices_op_test.cc"],
578    data = [
579        "serve_slices_test.pbtxt",
580    ],
581    extra_copts = FCP_COPTS,
582    deps = [
583        ":serve_slices_op_lib",
584        ":serve_slices_registry",
585        "@com_google_absl//absl/strings",
586        "@com_google_googletest//:gtest_main",
587        "@com_google_protobuf//:protobuf",
588        "@org_tensorflow//tensorflow/core:core_cpu",
589        "@org_tensorflow//tensorflow/core:direct_session",
590        "@org_tensorflow//tensorflow/core:framework",
591        "@org_tensorflow//tensorflow/core:protos_all_cc",
592        "@org_tensorflow//tensorflow/core:tensorflow_opensource",
593        "@org_tensorflow//tensorflow/core:testlib",
594        "@org_tensorflow//tensorflow/core/platform:status_matchers",
595    ],
596)
597
598MAKE_SLICES_SELECTOR_EXAMPLE_SELECTOR_OP_SRCS = ["make_slices_selector_example_selector_op.cc"]
599
600MAKE_SLICES_SELECTOR_EXAMPLE_SELECTOR_OP_DEPS = [
601    "@com_google_absl//absl/strings:str_format",
602    "//fcp/protos:plan_cc_proto",
603    "//fcp/client:federated_select",
604]
605
606# Custom op to serialize an ExampleSelector containing a SlicesSelector proto.
607cc_library(
608    name = "make_slices_selector_example_selector_op_lib",
609    srcs = MAKE_SLICES_SELECTOR_EXAMPLE_SELECTOR_OP_SRCS,
610    copts = FCP_COPTS,
611    visibility = ["//visibility:public"],
612    deps = ["@com_google_protobuf//:protobuf"] + MAKE_SLICES_SELECTOR_EXAMPLE_SELECTOR_OP_DEPS + [
613        "@org_tensorflow//tensorflow/core:framework",
614        "@org_tensorflow//tensorflow/core:lib",
615    ],
616    # Uses TensorFlow's registration macros
617    alwayslink = 1,
618)
619
620tf_custom_op_library(
621    name = "_make_slices_selector_example_selector_op.so",
622    srcs = MAKE_SLICES_SELECTOR_EXAMPLE_SELECTOR_OP_SRCS,
623    copts = FCP_COPTS,
624    deps = ["@com_google_protobuf//:protobuf"] + MAKE_SLICES_SELECTOR_EXAMPLE_SELECTOR_OP_DEPS,
625)
626
627# Generates the basic op wrapper for use in Python.
628# Don't use this directly: use `:make_slices_selector_py` to ensure that the
629# appropriate shared libraries are loaded.
630tf_gen_op_wrapper_py(
631    name = "gen_make_slices_selector_example_selector_py",
632    out = "gen_make_slices_selector_example_selector_py.py",
633    deps = [
634        ":make_slices_selector_example_selector_op_lib",
635    ],
636)
637
638# Public: Python library for the `MakeSlicesSelectorExampleSelector` op.
639tf_custom_op_py_library(
640    name = "make_slices_selector_example_selector_py",
641    srcs = ["make_slices_selector_example_selector.py"],
642    dso = [":_make_slices_selector_example_selector_op.so"],
643    kernels = [
644        ":make_slices_selector_example_selector_op_lib",
645    ],
646    visibility = ["//visibility:public"],
647    deps = [":gen_make_slices_selector_example_selector_py"],
648)
649
650# Test `MakeSlicesSelectorExampleSelector` using Python.
651py_test(
652    name = "make_slices_selector_example_selector_test",
653    testonly = True,
654    srcs = ["make_slices_selector_example_selector_test.py"],
655    python_version = "PY3",
656    deps = [
657        ":make_slices_selector_example_selector_py",
658        "//fcp/protos:plan_py_pb2",
659    ],
660)
661
662APPEND_SLICES_OP_SRCS = ["append_slices_op.cc"]
663
664APPEND_SLICES_OP_DEPS = [
665    "@com_google_absl//absl/base:core_headers",
666    "@com_google_absl//absl/synchronization",
667    "@org_tensorflow//tensorflow/core/util:saved_tensor_slice_proto_cc",
668]
669
670# Custom op to serialize an ExampleSelector containing a SlicesSelector proto.
671cc_library(
672    name = "append_slices_op_lib",
673    srcs = APPEND_SLICES_OP_SRCS,
674    copts = FCP_COPTS,
675    visibility = ["//visibility:public"],
676    deps = APPEND_SLICES_OP_DEPS + [
677        "@org_tensorflow//tensorflow/core:framework",
678        "@org_tensorflow//tensorflow/core:lib",
679        "@org_tensorflow//tensorflow/core:protos_all_cc",
680        "@org_tensorflow//tensorflow/core/kernels:save_restore_tensor",
681    ],
682    # Uses TensorFlow's registration macros
683    alwayslink = 1,
684)
685
686tf_custom_op_library(
687    name = "_append_slices_op.so",
688    srcs = APPEND_SLICES_OP_SRCS,
689    copts = FCP_COPTS,
690    deps = APPEND_SLICES_OP_DEPS,
691)
692
693# Generates the basic op wrapper for use in Python.
694# Don't use this directly: use `:append_slices_py` to ensure that the
695# appropriate shared libraries are loaded.
696tf_gen_op_wrapper_py(
697    name = "gen_append_slices_py",
698    out = "gen_append_slices_py.py",
699    deps = [
700        ":append_slices_op_lib",
701    ],
702)
703
704# Public: Python library for the `AppendSlices` and `MergeAppendedSlices` ops.
705tf_custom_op_py_library(
706    name = "append_slices_py",
707    srcs = ["append_slices.py"],
708    dso = [":_append_slices_op.so"],
709    kernels = [
710        ":append_slices_op_lib",
711    ],
712    visibility = ["//visibility:public"],
713    deps = [":gen_append_slices_py"],
714)
715
716# Test `AppendSlices` and `MergeAppendedSlices` using Python.
717py_test(
718    name = "append_slices_test",
719    testonly = True,
720    srcs = ["append_slices_test.py"],
721    python_version = "PY3",
722    deps = [
723        ":append_slices_py",
724        ":delete_file_py",
725    ],
726)
727
728DELETE_FILE_OP_SRCS = ["delete_file_op.cc"]
729
730DELETE_FILE_OP_DEPS = [
731    "@com_google_absl//absl/base:core_headers",
732    "@com_google_absl//absl/synchronization",
733]
734
735# Custom op to serialize an ExampleSelector containing a SlicesSelector proto.
736cc_library(
737    name = "delete_file_op_lib",
738    srcs = DELETE_FILE_OP_SRCS,
739    copts = FCP_COPTS,
740    visibility = ["//visibility:public"],
741    deps = DELETE_FILE_OP_DEPS + [
742        "@org_tensorflow//tensorflow/core:framework",
743        "@org_tensorflow//tensorflow/core:lib",
744        "@org_tensorflow//tensorflow/core:protos_all_cc",
745    ],
746    # Uses TensorFlow's registration macros
747    alwayslink = 1,
748)
749
750tf_custom_op_library(
751    name = "_delete_file_op.so",
752    srcs = DELETE_FILE_OP_SRCS,
753    copts = FCP_COPTS,
754    deps = DELETE_FILE_OP_DEPS,
755)
756
757# Generates the basic op wrapper for use in Python.
758# Don't use this directly: use `:delete_file_py` to ensure that the
759# appropriate shared libraries are loaded.
760tf_gen_op_wrapper_py(
761    name = "gen_delete_file_py",
762    out = "gen_delete_file_py.py",
763    deps = [
764        ":delete_file_op_lib",
765    ],
766)
767
768# Public: Python library for the `DeleteFile` ops.
769tf_custom_op_py_library(
770    name = "delete_file_py",
771    srcs = ["delete_file.py"],
772    dso = [":_delete_file_op.so"],
773    kernels = [
774        ":delete_file_op_lib",
775    ],
776    visibility = ["//visibility:public"],
777    deps = [":gen_delete_file_py"],
778)
779
780# Test `DeleteFile` using Python.
781py_test(
782    name = "delete_file_test",
783    testonly = True,
784    srcs = ["delete_file_test.py"],
785    python_version = "PY3",
786    deps = [":delete_file_py"],
787)
788
789TENSOR_NAME_OP_SRCS = ["tensor_name_op.cc"]
790
791TENSOR_NAME_OP_DEPS = [
792    "@com_google_absl//absl/strings:str_format",
793]
794
795# Custom op to get the name of a tensor in the final graph at runtime.
796cc_library(
797    name = "tensor_name_op_lib",
798    srcs = TENSOR_NAME_OP_SRCS,
799    copts = FCP_COPTS,
800    visibility = ["//visibility:public"],
801    deps = TENSOR_NAME_OP_DEPS + [
802        "@org_tensorflow//tensorflow/core:framework",
803        "@org_tensorflow//tensorflow/core:lib",
804    ],
805    # Uses TensorFlow's registration macros
806    alwayslink = 1,
807)
808
809# DSO version of `:tensor_name_op_lib`, intended to be loaded by Python
810# wrappers. See explanation above starting with "The targets below...".
811tf_custom_op_library(
812    name = "_tensor_name_op.so",
813    srcs = TENSOR_NAME_OP_SRCS,
814    copts = FCP_COPTS,
815    deps = TENSOR_NAME_OP_DEPS,
816)
817
818# Generates the basic op wrapper for use in Python.
819# Don't use this directly: use `:tensor_name_py` to ensure that the
820# appropriate shared libraries are loaded.
821tf_gen_op_wrapper_py(
822    name = "gen_tensor_name_py",
823    out = "gen_tensor_name_py.py",
824    deps = [
825        ":tensor_name_op_lib",
826    ],
827)
828
829# Public: Python library for the `TensorName` op.
830tf_custom_op_py_library(
831    name = "tensor_name_py",
832    srcs = ["tensor_name.py"],
833    dso = [":_tensor_name_op.so"],
834    kernels = [
835        ":tensor_name_op_lib",
836    ],
837    visibility = ["//visibility:public"],
838    deps = [":gen_tensor_name_py"],
839)
840
841# Test `TensorName` using Python.
842py_test(
843    name = "tensor_name_test",
844    testonly = True,
845    srcs = ["tensor_name_test.py"],
846    python_version = "PY3",
847    deps = [":tensor_name_py"],
848)
849
850TASK_ELIGIBILITY_INFO_OPS_SRCS = ["task_eligibility_info_ops.cc"]
851
852TASK_ELIGIBILITY_INFO_OPS_DEPS = [
853    "//fcp/protos:federated_api_cc_proto",
854]
855
856cc_library(
857    name = "task_eligibility_info_ops_lib",
858    srcs = TASK_ELIGIBILITY_INFO_OPS_SRCS,
859    copts = FCP_COPTS,
860    visibility = ["//visibility:public"],
861    deps = TASK_ELIGIBILITY_INFO_OPS_DEPS + [
862        "@org_tensorflow//tensorflow/core:framework",
863        "@org_tensorflow//tensorflow/core:lib",
864    ],
865    # Uses TensorFlow's registration macros
866    alwayslink = 1,
867)
868
869tf_custom_op_library(
870    name = "_task_eligibility_info_ops.so",
871    srcs = TASK_ELIGIBILITY_INFO_OPS_SRCS,
872    copts = FCP_COPTS,
873    deps = TASK_ELIGIBILITY_INFO_OPS_DEPS,
874)
875
876# Generates the basic op wrapper for use in Python. We don't expose this wrapper
877# directly, and rather we create a more user-friendly wrapper below, which uses
878# this auto-generated one.
879tf_gen_op_wrapper_py(
880    name = "gen_task_eligibility_info_ops_py",
881    out = "gen_task_eligibility_info_ops.py",
882    visibility = ["//visibility:private"],
883    deps = [
884        ":task_eligibility_info_ops_lib",
885    ],
886)
887
888# Python library exposing the user-facing task eligibility info ops.
889tf_custom_op_py_library(
890    name = "task_eligibility_info_ops_py",
891    srcs = ["task_eligibility_info_ops.py"],
892    dso = [":_task_eligibility_info_ops.so"],
893    kernels = [
894        ":task_eligibility_info_ops_lib",
895    ],
896    visibility = ["//visibility:public"],
897    deps = [":gen_task_eligibility_info_ops_py"],
898)
899
900py_test(
901    name = "task_eligibility_info_ops_test",
902    srcs = ["task_eligibility_info_ops_test.py"],
903    python_version = "PY3",
904    deps = [
905        ":task_eligibility_info_ops_py",
906        "//fcp/protos:federated_api_py_pb2",
907    ],
908)
909
910DICTIONARY_OPS_SRCS = ["dictionary_ops.cc"]
911
912DICTIONARY_OPS_DEPS = [
913    "//fcp/base",
914    "//fcp/dictionary:dictionary_lib",
915    "//fcp/dictionary:dictionary_cc_proto",
916    "@com_google_absl//absl/status",
917    "@com_google_absl//absl/status:statusor",
918]
919
920cc_library(
921    name = "dictionary_ops_lib",
922    srcs = DICTIONARY_OPS_SRCS,
923    copts = FCP_COPTS,
924    visibility = ["//visibility:public"],
925    deps = DICTIONARY_OPS_DEPS + [
926        "@org_tensorflow//tensorflow/core:framework",
927        "@org_tensorflow//tensorflow/core:lib",
928    ],
929    # Uses TensorFlow's registration macros
930    alwayslink = 1,
931)
932
933tf_custom_op_library(
934    name = "_dictionary_ops.so",
935    srcs = DICTIONARY_OPS_SRCS,
936    copts = FCP_COPTS,
937    deps = DICTIONARY_OPS_DEPS,
938)
939
940tf_gen_op_wrapper_py(
941    name = "gen_dictionary_ops_py",
942    out = "gen_dictionary_ops.py",
943    op_allowlist = [
944        "DictionarySize",
945        "DictionaryLookup",
946        "DictionaryReverseLookup",
947    ],
948    visibility = ["//visibility:private"],
949    deps = [":dictionary_ops_lib"],
950)
951
952tf_custom_op_py_library(
953    name = "dictionary_ops_py",
954    srcs = ["dictionary_ops.py"],
955    dso = [":_dictionary_ops.so"],
956    kernels = [
957        ":dictionary_ops_lib",
958    ],
959    visibility = ["//visibility:public"],
960    deps = [
961        ":gen_dictionary_ops_py",
962        "//fcp/dictionary:dictionary_py_pb2",
963    ],
964)
965
966py_test(
967    name = "dictionary_ops_test",
968    srcs = ["dictionary_ops_test.py"],
969    python_version = "PY3",
970    deps = [
971        ":dictionary_ops_py",
972        "//fcp/dictionary:dictionary_py_pb2",
973    ],
974)
975