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