• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
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# ==============================================================================
15# CMake rules for generating the TensorFlow Python bindings.
16#
17# Known limitations:
18# * Generates output in a hard-coded path ${CMAKE_CURRENT_BINARY_DIR}/tf_python.
19# * No support for dynamic library loading.
20# * Limited support for tf.contrib.
21#
22# The _pywrap_tensorflow_internal target builds everything.
23
24########################################################
25# Resolve installed dependencies
26########################################################
27
28# 1. Resolve the installed version of Python (for Python.h and python).
29# TODO(mrry): Parameterize the build script to enable Python 3 building.
30if(NOT PYTHON_INCLUDE_DIR)
31  set(PYTHON_NOT_FOUND false)
32  exec_program("${PYTHON_EXECUTABLE}"
33    ARGS "-c \"import distutils.sysconfig; print(distutils.sysconfig.get_python_inc())\""
34    OUTPUT_VARIABLE PYTHON_INCLUDE_DIR
35    RETURN_VALUE PYTHON_NOT_FOUND)
36  if(${PYTHON_NOT_FOUND})
37    message(FATAL_ERROR
38            "Cannot get Python include directory. Is distutils installed?")
39  endif(${PYTHON_NOT_FOUND})
40endif(NOT PYTHON_INCLUDE_DIR)
41FIND_PACKAGE(PythonLibs)
42
43# 2. Resolve the installed version of NumPy (for numpy/arrayobject.h).
44if(NOT NUMPY_INCLUDE_DIR)
45  set(NUMPY_NOT_FOUND false)
46  exec_program("${PYTHON_EXECUTABLE}"
47    ARGS "-c \"import numpy; print(numpy.get_include())\""
48    OUTPUT_VARIABLE NUMPY_INCLUDE_DIR
49    RETURN_VALUE NUMPY_NOT_FOUND)
50  if(${NUMPY_NOT_FOUND})
51    message(FATAL_ERROR
52            "Cannot get NumPy include directory: Is NumPy installed?")
53  endif(${NUMPY_NOT_FOUND})
54endif(NOT NUMPY_INCLUDE_DIR)
55
56
57########################################################
58# Build the Python directory structure.
59########################################################
60
61# TODO(mrry): Configure this to build in a directory other than tf_python/
62
63# Generates the Python protobuf wrappers.
64# ROOT_DIR must be absolute; subsequent arguments are interpreted as
65# paths of .proto files, and must be relative to ROOT_DIR.
66function(RELATIVE_PROTOBUF_GENERATE_PYTHON ROOT_DIR SRCS)
67  if(NOT ARGN)
68    message(SEND_ERROR "Error: RELATIVE_PROTOBUF_GENERATE_PYTHON() called without any proto files")
69    return()
70  endif()
71
72  set(${SRCS})
73  foreach(FIL ${ARGN})
74    set(ABS_FIL ${ROOT_DIR}/${FIL})
75    get_filename_component(FIL_WE ${FIL} NAME_WE)
76    get_filename_component(FIL_DIR ${ABS_FIL} PATH)
77    file(RELATIVE_PATH REL_DIR ${ROOT_DIR} ${FIL_DIR})
78
79    list(APPEND ${SRCS} "${CMAKE_CURRENT_BINARY_DIR}/tf_python/${REL_DIR}/${FIL_WE}_pb2.py")
80    add_custom_command(
81      OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/tf_python/${REL_DIR}/${FIL_WE}_pb2.py"
82      COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
83      ARGS --python_out  ${CMAKE_CURRENT_BINARY_DIR}/tf_python/ -I ${ROOT_DIR} -I ${PROTOBUF_INCLUDE_DIRS} ${ABS_FIL}
84      DEPENDS ${PROTOBUF_PROTOC_EXECUTABLE} protobuf
85      COMMENT "Running Python protocol buffer compiler on ${FIL}"
86      VERBATIM )
87  endforeach()
88  set(${SRCS} ${${SRCS}} PARENT_SCOPE)
89endfunction()
90
91function(RELATIVE_PROTOBUF_GENERATE_CPP SRCS HDRS ROOT_DIR)
92  if(NOT ARGN)
93    message(SEND_ERROR "Error: RELATIVE_PROTOBUF_GENERATE_CPP() called without any proto files")
94    return()
95  endif()
96
97  set(${SRCS})
98  set(${HDRS})
99  foreach(FIL ${ARGN})
100    set(ABS_FIL ${ROOT_DIR}/${FIL})
101    get_filename_component(FIL_WE ${FIL} NAME_WE)
102    get_filename_component(FIL_DIR ${ABS_FIL} PATH)
103    file(RELATIVE_PATH REL_DIR ${ROOT_DIR} ${FIL_DIR})
104
105    list(APPEND ${SRCS} "${CMAKE_CURRENT_BINARY_DIR}/${REL_DIR}/${FIL_WE}.pb.cc")
106    list(APPEND ${HDRS} "${CMAKE_CURRENT_BINARY_DIR}/${REL_DIR}/${FIL_WE}.pb.h")
107
108    add_custom_command(
109      OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${REL_DIR}/${FIL_WE}.pb.cc"
110             "${CMAKE_CURRENT_BINARY_DIR}/${REL_DIR}/${FIL_WE}.pb.h"
111      COMMAND  ${PROTOBUF_PROTOC_EXECUTABLE}
112      ARGS --cpp_out  ${CMAKE_CURRENT_BINARY_DIR} -I ${ROOT_DIR} ${ABS_FIL} -I ${PROTOBUF_INCLUDE_DIRS}
113      DEPENDS ${ABS_FIL} protobuf
114      COMMENT "Running C++ protocol buffer compiler on ${FIL}"
115      VERBATIM )
116  endforeach()
117
118  set_source_files_properties(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE)
119  set(${SRCS} ${${SRCS}} PARENT_SCOPE)
120  set(${HDRS} ${${HDRS}} PARENT_SCOPE)
121endfunction()
122
123FILE(READ python_protos.txt python_protos)
124# Convert file contents into a CMake list (where each element in the list is one line of the file)
125STRING(REGEX REPLACE ";" "\\\\;" python_protos "${python_protos}")
126STRING(REGEX REPLACE "\n" ";" python_protos "${python_protos}")
127
128foreach(python_proto ${python_protos})
129  if(NOT python_proto MATCHES "^\#")
130    STRING(REGEX REPLACE " *\#.*" "" python_proto "${python_proto}")
131    if(NOT EXISTS "${tensorflow_source_dir}/${python_proto}")
132      message(SEND_ERROR "Python proto directory not found: ${python_proto}")
133    endif()
134    file(GLOB_RECURSE tf_python_protos_src RELATIVE ${tensorflow_source_dir}
135        "${tensorflow_source_dir}/${python_proto}/*.proto"
136    )
137    list(APPEND tf_python_protos_srcs ${tf_python_protos_src})
138  endif()
139endforeach(python_proto)
140
141RELATIVE_PROTOBUF_GENERATE_PYTHON(
142    ${tensorflow_source_dir} PYTHON_PROTO_GENFILES ${tf_python_protos_srcs}
143)
144
145FILE(READ python_protos_cc.txt python_protos_cc)
146# Convert file contents into a CMake list (where each element in the list is one line of the file)
147STRING(REGEX REPLACE ";" "\\\\;" python_protos_cc "${python_protos_cc}")
148STRING(REGEX REPLACE "\n" ";" python_protos_cc "${python_protos_cc}")
149
150foreach(python_proto_cc ${python_protos_cc})
151  if(NOT python_proto_cc MATCHES "^\#")
152    STRING(REGEX REPLACE " *\#.*" "" python_proto_cc "${python_proto_cc}")
153    if(NOT EXISTS "${tensorflow_source_dir}/${python_proto_cc}")
154      message(SEND_ERROR "Python proto CC directory not found: ${python_proto_cc}")
155    endif()
156    file(GLOB_RECURSE tf_python_protos_cc_src RELATIVE ${tensorflow_source_dir}
157        "${tensorflow_source_dir}/${python_proto_cc}/*.proto"
158    )
159    list(APPEND tf_python_protos_cc_srcs ${tf_python_protos_cc_src})
160  endif()
161endforeach(python_proto_cc)
162
163RELATIVE_PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS
164    ${tensorflow_source_dir} ${tf_python_protos_cc_srcs}
165)
166
167add_library(tf_python_protos_cc ${PROTO_SRCS} ${PROTO_HDRS})
168add_dependencies(tf_python_protos_cc tf_protos_cc)
169
170# tf_python_touchup_modules adds empty __init__.py files to all
171# directories containing Python code, so that Python will recognize
172# them as modules.
173add_custom_target(tf_python_touchup_modules)
174
175# tf_python_copy_scripts_to_destination copies all Python files
176# (including static source and generated protobuf wrappers, but *not*
177# generated TensorFlow op wrappers) into tf_python/.
178add_custom_target(tf_python_copy_scripts_to_destination DEPENDS tf_python_touchup_modules)
179
180
181# tf_python_srcs contains all static .py files
182function(add_python_module MODULE_NAME)
183    set(options DONTCOPY)
184    cmake_parse_arguments(ADD_PYTHON_MODULE "${options}" "" "" ${ARGN})
185    add_custom_command(TARGET tf_python_touchup_modules PRE_BUILD
186        COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}/tf_python/${MODULE_NAME}")
187    add_custom_command(TARGET tf_python_touchup_modules PRE_BUILD
188        COMMAND ${CMAKE_COMMAND} -E touch "${CMAKE_CURRENT_BINARY_DIR}/tf_python/${MODULE_NAME}/__init__.py")
189    file(GLOB module_python_srcs RELATIVE ${tensorflow_source_dir}
190        "${tensorflow_source_dir}/${MODULE_NAME}/*.py"
191    )
192    if(NOT ${ADD_PYTHON_MODULE_DONTCOPY})
193        foreach(script ${module_python_srcs})
194            get_filename_component(REL_DIR ${script} DIRECTORY)
195            # NOTE(mrry): This rule may exclude modules that should be part of
196            # the distributed PIP package
197            # (e.g. tensorflow/contrib/testing/python/framework/util_test.py),
198            # so we currently add explicit commands to include those files
199            # later on in this script.
200            if (NOT "${script}" MATCHES "_test\.py$")
201            add_custom_command(TARGET tf_python_copy_scripts_to_destination PRE_BUILD
202                  COMMAND ${CMAKE_COMMAND} -E copy ${tensorflow_source_dir}/${script} ${CMAKE_CURRENT_BINARY_DIR}/tf_python/${script})
203            endif()
204        endforeach()
205    endif()
206endfunction()
207
208FILE(READ python_modules.txt python_modules)
209# Convert file contents into a CMake list (where each element in the list is one line of the file)
210STRING(REGEX REPLACE ";" "\\\\;" python_modules "${python_modules}")
211STRING(REGEX REPLACE "\n" ";" python_modules "${python_modules}")
212
213foreach(python_module ${python_modules})
214  if(NOT python_module MATCHES "^\#")
215    STRING(REGEX REPLACE " *\#.*" "" python_module "${python_module}")
216    if(NOT EXISTS "${tensorflow_source_dir}/${python_module}")
217      message(SEND_ERROR "Python module not found: ${python_module}")
218    endif()
219    add_python_module(${python_module})
220  endif()
221endforeach(python_module)
222
223add_custom_command(TARGET tf_python_touchup_modules PRE_BUILD
224    COMMAND ${CMAKE_COMMAND} -E make_directory
225    "${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/lite")
226add_custom_command(TARGET tf_python_touchup_modules PRE_BUILD
227    COMMAND ${CMAKE_COMMAND} -E make_directory
228    "${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/lite/python")
229add_custom_command(TARGET tf_python_touchup_modules PRE_BUILD
230    COMMAND ${CMAKE_COMMAND} -E touch
231    "${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/lite/python/__init__.py")
232add_custom_command(
233    TARGET tf_python_copy_scripts_to_destination PRE_BUILD
234    COMMAND ${CMAKE_COMMAND} -E touch
235    ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/lite/python/lite.py)
236
237# Generate the tensorflow.python.platform.build_info module.
238set(BUILD_INFO_PY "${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/python/platform/build_info.py")
239add_custom_command(TARGET tf_python_copy_scripts_to_destination PRE_BUILD
240  COMMAND ${PYTHON_EXECUTABLE} ${tensorflow_source_dir}/tensorflow/tools/build_info/gen_build_info.py --raw_generate ${BUILD_INFO_PY} ${tensorflow_BUILD_INFO_FLAGS})
241
242
243########################################################
244# tf_python_op_gen_main library
245########################################################
246set(tf_python_op_gen_main_srcs
247    "${tensorflow_source_dir}/tensorflow/python/framework/python_op_gen.cc"
248    "${tensorflow_source_dir}/tensorflow/python/framework/python_op_gen.h"
249    "${tensorflow_source_dir}/tensorflow/python/framework/python_op_gen_internal.cc"
250    "${tensorflow_source_dir}/tensorflow/python/framework/python_op_gen_internal.h"
251    "${tensorflow_source_dir}/tensorflow/python/framework/python_op_gen_main.cc"
252)
253
254add_library(tf_python_op_gen_main OBJECT ${tf_python_op_gen_main_srcs})
255
256add_dependencies(tf_python_op_gen_main tf_core_framework)
257
258# create directory for ops generated files
259set(python_ops_target_dir ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/python/ops)
260
261set(tf_python_ops_generated_files)
262
263set(tf_python_op_lib_names
264    ${tf_op_lib_names}
265    "user_ops"
266)
267
268function(GENERATE_PYTHON_OP_LIB tf_python_op_lib_name)
269    set(options SHAPE_FUNCTIONS_NOT_REQUIRED)
270    set(oneValueArgs DESTINATION)
271    set(multiValueArgs ADDITIONAL_LIBRARIES)
272    cmake_parse_arguments(GENERATE_PYTHON_OP_LIB
273      "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
274    if(NOT DEFINED GENERATE_PYTHON_OP_LIB_DESTINATION)
275      # Default destination is tf_python/tensorflow/python/ops/gen_<...>.py.
276      set(GENERATE_PYTHON_OP_LIB_DESTINATION
277          "${python_ops_target_dir}/gen_${tf_python_op_lib_name}.py")
278    endif()
279    if(GENERATE_PYTHON_OP_LIB_SHAPE_FUNCTIONS_NOT_REQUIRED)
280      set(require_shape_fn 0)
281    else()
282      set(require_shape_fn 1)
283    endif()
284
285    get_filename_component(GENERATE_PYTHON_OP_LIB_MKDIRPATH ${GENERATE_PYTHON_OP_LIB_DESTINATION} PATH)
286    file(MAKE_DIRECTORY ${GENERATE_PYTHON_OP_LIB_MKDIRPATH})
287
288    # Create a C++ executable that links in the appropriate op
289    # registrations and generates Python wrapper code based on the
290    # registered ops.
291    add_executable(${tf_python_op_lib_name}_gen_python
292        $<TARGET_OBJECTS:tf_python_op_gen_main>
293        $<TARGET_OBJECTS:tf_${tf_python_op_lib_name}>
294        $<TARGET_OBJECTS:tf_core_lib>
295        $<TARGET_OBJECTS:tf_core_framework>
296        ${GENERATE_PYTHON_OP_LIB_ADDITIONAL_LIBRARIES}
297    )
298    target_link_libraries(${tf_python_op_lib_name}_gen_python PRIVATE
299        tf_protos_cc
300                tf_python_protos_cc
301        ${tensorflow_EXTERNAL_LIBRARIES}
302    )
303
304    # Use the generated C++ executable to create a Python file
305    # containing the wrappers.
306    add_custom_command(
307      OUTPUT ${GENERATE_PYTHON_OP_LIB_DESTINATION}
308      COMMAND ${tf_python_op_lib_name}_gen_python ${tensorflow_source_dir}/tensorflow/core/api_def/base_api,${tensorflow_source_dir}/tensorflow/core/api_def/python_api ${require_shape_fn} > ${GENERATE_PYTHON_OP_LIB_DESTINATION}
309      DEPENDS ${tf_python_op_lib_name}_gen_python
310    )
311
312    set(tf_python_ops_generated_files ${tf_python_ops_generated_files}
313        ${GENERATE_PYTHON_OP_LIB_DESTINATION} PARENT_SCOPE)
314endfunction()
315
316GENERATE_PYTHON_OP_LIB("array_ops")
317GENERATE_PYTHON_OP_LIB("audio_ops")
318GENERATE_PYTHON_OP_LIB("batch_ops")
319GENERATE_PYTHON_OP_LIB("bitwise_ops")
320GENERATE_PYTHON_OP_LIB("boosted_trees_ops")
321GENERATE_PYTHON_OP_LIB("candidate_sampling_ops")
322GENERATE_PYTHON_OP_LIB("checkpoint_ops")
323GENERATE_PYTHON_OP_LIB("collective_ops")
324GENERATE_PYTHON_OP_LIB("control_flow_ops"
325  ADDITIONAL_LIBRARIES $<TARGET_OBJECTS:tf_no_op>)
326GENERATE_PYTHON_OP_LIB("ctc_ops")
327GENERATE_PYTHON_OP_LIB("cudnn_rnn_ops")
328GENERATE_PYTHON_OP_LIB("data_flow_ops")
329GENERATE_PYTHON_OP_LIB("dataset_ops")
330GENERATE_PYTHON_OP_LIB("decode_proto_ops"
331  DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/proto/python/ops/gen_decode_proto_op.py)
332GENERATE_PYTHON_OP_LIB("encode_proto_ops"
333  DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/proto/python/ops/gen_encode_proto_op.py)
334GENERATE_PYTHON_OP_LIB("function_ops")
335GENERATE_PYTHON_OP_LIB("functional_ops")
336GENERATE_PYTHON_OP_LIB("image_ops")
337GENERATE_PYTHON_OP_LIB("io_ops")
338GENERATE_PYTHON_OP_LIB("linalg_ops")
339GENERATE_PYTHON_OP_LIB("list_ops")
340GENERATE_PYTHON_OP_LIB("logging_ops")
341GENERATE_PYTHON_OP_LIB("lookup_ops")
342GENERATE_PYTHON_OP_LIB("manip_ops")
343GENERATE_PYTHON_OP_LIB("math_ops")
344GENERATE_PYTHON_OP_LIB("nn_ops")
345GENERATE_PYTHON_OP_LIB("no_op")
346GENERATE_PYTHON_OP_LIB("parsing_ops")
347GENERATE_PYTHON_OP_LIB("random_ops")
348GENERATE_PYTHON_OP_LIB("remote_fused_graph_ops"
349  DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/remote_fused_graph/pylib/python/ops/gen_remote_fused_graph_ops.py)
350GENERATE_PYTHON_OP_LIB("resource_variable_ops")
351GENERATE_PYTHON_OP_LIB("rpc_ops"
352  DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/rpc/python/ops/gen_rpc_op.py)
353GENERATE_PYTHON_OP_LIB("scoped_allocator_ops")
354GENERATE_PYTHON_OP_LIB("script_ops")
355GENERATE_PYTHON_OP_LIB("sdca_ops")
356GENERATE_PYTHON_OP_LIB("sendrecv_ops")
357GENERATE_PYTHON_OP_LIB("set_ops")
358GENERATE_PYTHON_OP_LIB("sparse_ops")
359GENERATE_PYTHON_OP_LIB("spectral_ops")
360GENERATE_PYTHON_OP_LIB("state_ops")
361GENERATE_PYTHON_OP_LIB("stateless_random_ops")
362GENERATE_PYTHON_OP_LIB("string_ops")
363GENERATE_PYTHON_OP_LIB("summary_ops")
364GENERATE_PYTHON_OP_LIB("user_ops")
365GENERATE_PYTHON_OP_LIB("training_ops"
366  DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/python/training/gen_training_ops.py)
367GENERATE_PYTHON_OP_LIB("word2vec_ops")
368
369GENERATE_PYTHON_OP_LIB("contrib_boosted_trees_model_ops"
370  DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/boosted_trees/python/ops/gen_model_ops.py)
371GENERATE_PYTHON_OP_LIB("contrib_boosted_trees_split_handler_ops"
372  DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/boosted_trees/python/ops/gen_split_handler_ops.py)
373GENERATE_PYTHON_OP_LIB("contrib_boosted_trees_training_ops"
374  DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/boosted_trees/python/ops/gen_training_ops.py)
375GENERATE_PYTHON_OP_LIB("contrib_boosted_trees_prediction_ops"
376  DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/boosted_trees/python/ops/gen_prediction_ops.py)
377GENERATE_PYTHON_OP_LIB("contrib_boosted_trees_quantiles_ops"
378  DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/boosted_trees/python/ops/gen_quantile_ops.py)
379GENERATE_PYTHON_OP_LIB("contrib_boosted_trees_stats_accumulator_ops"
380  DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/boosted_trees/python/ops/gen_stats_accumulator_ops.py)
381GENERATE_PYTHON_OP_LIB("contrib_coder_ops"
382  DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/coder/python/ops/gen_coder_ops.py)
383GENERATE_PYTHON_OP_LIB("contrib_factorization_clustering_ops"
384  DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/factorization/python/ops/gen_clustering_ops.py)
385GENERATE_PYTHON_OP_LIB("contrib_factorization_factorization_ops"
386  DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/factorization/python/ops/gen_factorization_ops.py)
387GENERATE_PYTHON_OP_LIB("contrib_framework_variable_ops"
388  DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/framework/python/ops/gen_variable_ops.py)
389GENERATE_PYTHON_OP_LIB("contrib_input_pipeline_ops"
390  DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/input_pipeline/ops/gen_input_pipeline_ops.py)
391GENERATE_PYTHON_OP_LIB("contrib_image_ops"
392  DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/image/ops/gen_image_ops.py)
393GENERATE_PYTHON_OP_LIB("contrib_image_distort_image_ops"
394  DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/image/ops/gen_distort_image_ops.py)
395GENERATE_PYTHON_OP_LIB("contrib_image_sirds_ops"
396  DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/image/ops/gen_single_image_random_dot_stereograms_ops.py)
397GENERATE_PYTHON_OP_LIB("contrib_layers_sparse_feature_cross_ops"
398  DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/layers/ops/gen_sparse_feature_cross_op.py)
399GENERATE_PYTHON_OP_LIB("contrib_memory_stats_ops"
400  DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/memory_stats/ops/gen_memory_stats_ops.py)
401GENERATE_PYTHON_OP_LIB("contrib_periodic_resample_ops"
402  DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/periodic_resample/python/ops/gen_periodic_resample_op.py)
403GENERATE_PYTHON_OP_LIB("contrib_nearest_neighbor_ops"
404  DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/nearest_neighbor/ops/gen_nearest_neighbor_ops.py)
405GENERATE_PYTHON_OP_LIB("contrib_resampler_ops"
406  DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/resampler/ops/gen_resampler_ops.py)
407GENERATE_PYTHON_OP_LIB("contrib_rnn_gru_ops"
408  DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/rnn/ops/gen_gru_ops.py)
409GENERATE_PYTHON_OP_LIB("contrib_rnn_lstm_ops"
410  DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/rnn/ops/gen_lstm_ops.py)
411GENERATE_PYTHON_OP_LIB("contrib_seq2seq_beam_search_ops"
412  DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/seq2seq/ops/gen_beam_search_ops.py)
413GENERATE_PYTHON_OP_LIB("contrib_tensor_forest_ops"
414  DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/tensor_forest/python/ops/gen_tensor_forest_ops.py)
415GENERATE_PYTHON_OP_LIB("contrib_tensor_forest_hybrid_ops"
416  DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/tensor_forest/hybrid/ops/gen_training_ops.py)
417GENERATE_PYTHON_OP_LIB("contrib_tensor_forest_model_ops"
418  DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/tensor_forest/python/ops/gen_model_ops.py)
419GENERATE_PYTHON_OP_LIB("contrib_tensor_forest_stats_ops"
420  DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/tensor_forest/python/ops/gen_stats_ops.py)
421GENERATE_PYTHON_OP_LIB("contrib_text_skip_gram_ops"
422  DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/text/python/ops/gen_skip_gram_ops.py)
423GENERATE_PYTHON_OP_LIB("contrib_bigquery_reader_ops"
424  DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/cloud/python/ops/gen_bigquery_reader_ops.py)
425GENERATE_PYTHON_OP_LIB("contrib_gcs_config_ops"
426  DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/cloud/python/ops/gen_gcs_config_ops.py)
427GENERATE_PYTHON_OP_LIB("debug_ops"
428  DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/python/debug/ops/gen_debug_ops.py)
429
430add_custom_target(tf_python_ops SOURCES ${tf_python_ops_generated_files} ${PYTHON_PROTO_GENFILES})
431add_dependencies(tf_python_ops tf_python_op_gen_main)
432
433
434############################################################
435# Build the SWIG-wrapped library for the TensorFlow runtime.
436############################################################
437
438find_package(SWIG REQUIRED)
439# Generate the C++ and Python source code for the SWIG wrapper.
440# NOTE(mrry): We always regenerate the SWIG wrapper, which means that we must
441# always re-link the Python extension, but we don't have to track the
442# individual headers on which the SWIG wrapper depends.
443add_custom_command(
444      OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/python/pywrap_tensorflow_internal.py"
445             "${CMAKE_CURRENT_BINARY_DIR}/pywrap_tensorflow_internal.cc"
446      DEPENDS tf_python_touchup_modules __force_rebuild
447      COMMAND ${SWIG_EXECUTABLE}
448      ARGS -python -c++
449           -I${tensorflow_source_dir}
450           -I${CMAKE_CURRENT_BINARY_DIR}
451           -module pywrap_tensorflow_internal
452           -outdir ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/python
453           -o ${CMAKE_CURRENT_BINARY_DIR}/pywrap_tensorflow_internal.cc
454           -globals ''
455           ${tensorflow_source_dir}/tensorflow/python/tensorflow.i
456      COMMENT "Running SWIG to generate Python wrappers"
457      VERBATIM )
458
459add_library(tf_c_python_api OBJECT
460  "${tensorflow_source_dir}/tensorflow/c/python_api.cc"
461  "${tensorflow_source_dir}/tensorflow/c/python_api.h"
462)
463add_dependencies(
464  tf_c_python_api
465  tf_c
466  tf_core_lib
467  tf_core_framework
468  tf_protos_cc
469  tf_python_protos_cc)
470
471set (pywrap_tensorflow_internal_src
472    "${tensorflow_source_dir}/tensorflow/core/profiler/internal/print_model_analysis.h"
473    "${tensorflow_source_dir}/tensorflow/core/profiler/internal/print_model_analysis.cc"
474    "${tensorflow_source_dir}/tensorflow/python/eager/pywrap_tfe.h"
475    "${tensorflow_source_dir}/tensorflow/python/eager/pywrap_tensor.cc"
476    "${tensorflow_source_dir}/tensorflow/python/eager/pywrap_tfe_src.cc"
477    "${tensorflow_source_dir}/tensorflow/python/client/tf_session_helper.h"
478    "${tensorflow_source_dir}/tensorflow/python/client/tf_session_helper.cc"
479    "${tensorflow_source_dir}/tensorflow/python/framework/cpp_shape_inference.h"
480    "${tensorflow_source_dir}/tensorflow/python/framework/cpp_shape_inference.cc"
481    "${tensorflow_source_dir}/tensorflow/python/framework/python_op_gen.h"
482    "${tensorflow_source_dir}/tensorflow/python/framework/python_op_gen.cc"
483    "${tensorflow_source_dir}/tensorflow/python/framework/python_op_gen_internal.h"
484    "${tensorflow_source_dir}/tensorflow/python/framework/python_op_gen_internal.cc"
485    "${tensorflow_source_dir}/tensorflow/python/lib/core/bfloat16.h"
486    "${tensorflow_source_dir}/tensorflow/python/lib/core/bfloat16.cc"
487    "${tensorflow_source_dir}/tensorflow/python/lib/core/numpy.h"
488    "${tensorflow_source_dir}/tensorflow/python/lib/core/numpy.cc"
489    "${tensorflow_source_dir}/tensorflow/python/lib/core/ndarray_tensor.h"
490    "${tensorflow_source_dir}/tensorflow/python/lib/core/ndarray_tensor.cc"
491    "${tensorflow_source_dir}/tensorflow/python/lib/core/ndarray_tensor_bridge.h"
492    "${tensorflow_source_dir}/tensorflow/python/lib/core/ndarray_tensor_bridge.cc"
493    "${tensorflow_source_dir}/tensorflow/python/lib/core/py_func.h"
494    "${tensorflow_source_dir}/tensorflow/python/lib/core/py_func.cc"
495    "${tensorflow_source_dir}/tensorflow/python/lib/core/py_exception_registry.h"
496    "${tensorflow_source_dir}/tensorflow/python/lib/core/py_exception_registry.cc"
497    "${tensorflow_source_dir}/tensorflow/python/lib/core/py_seq_tensor.h"
498    "${tensorflow_source_dir}/tensorflow/python/lib/core/py_seq_tensor.cc"
499    "${tensorflow_source_dir}/tensorflow/python/lib/core/py_util.h"
500    "${tensorflow_source_dir}/tensorflow/python/lib/core/py_util.cc"
501    "${tensorflow_source_dir}/tensorflow/python/lib/core/safe_ptr.h"
502    "${tensorflow_source_dir}/tensorflow/python/lib/core/safe_ptr.cc"
503    "${tensorflow_source_dir}/tensorflow/python/lib/io/py_record_reader.h"
504    "${tensorflow_source_dir}/tensorflow/python/lib/io/py_record_reader.cc"
505    "${tensorflow_source_dir}/tensorflow/python/lib/io/py_record_writer.h"
506    "${tensorflow_source_dir}/tensorflow/python/lib/io/py_record_writer.cc"
507    "${tensorflow_source_dir}/tensorflow/python/util/kernel_registry.h"
508    "${tensorflow_source_dir}/tensorflow/python/util/kernel_registry.cc"
509    "${tensorflow_source_dir}/tensorflow/python/util/util.h"
510    "${tensorflow_source_dir}/tensorflow/python/util/util.cc"
511    "${tensorflow_source_dir}/tensorflow/cc/framework/ops.cc"
512    "${tensorflow_source_dir}/tensorflow/cc/framework/scope.cc"
513    "${CMAKE_CURRENT_BINARY_DIR}/pywrap_tensorflow_internal.cc"
514)
515
516if(WIN32)
517    # Windows: build a static library with the same objects as tensorflow.dll.
518    # This can be used to build for a standalone exe and also helps us to
519    # find all symbols that need to be exported from the dll which is needed
520    # to provide the tensorflow c/c++ api in tensorflow.dll.
521    # From the static library we create the def file with all symbols that need to
522    # be exported from tensorflow.dll. Because there is a limit of 64K sybmols
523    # that can be exported, we filter the symbols with a python script to the namespaces
524    # we need.
525    #
526    add_library(pywrap_tensorflow_internal_static STATIC
527        ${pywrap_tensorflow_internal_src}
528        $<TARGET_OBJECTS:tf_c>
529        $<TARGET_OBJECTS:tf_c_eager>
530        $<TARGET_OBJECTS:tf_c_python_api>
531        $<TARGET_OBJECTS:tf_core_lib>
532        $<TARGET_OBJECTS:tf_core_cpu>
533        $<TARGET_OBJECTS:tf_core_framework>
534        $<TARGET_OBJECTS:tf_core_profiler>
535        $<TARGET_OBJECTS:tf_core_eager_runtime>
536        $<TARGET_OBJECTS:tf_cc>
537        $<TARGET_OBJECTS:tf_cc_ops>
538        $<TARGET_OBJECTS:tf_cc_while_loop>
539        $<TARGET_OBJECTS:tf_core_ops>
540        $<TARGET_OBJECTS:tf_core_direct_session>
541        $<TARGET_OBJECTS:tf_grappler>
542        $<TARGET_OBJECTS:tf_tools_transform_graph_lib>
543        $<$<BOOL:${tensorflow_ENABLE_GRPC_SUPPORT}>:$<TARGET_OBJECTS:tf_core_distributed_runtime>>
544        $<TARGET_OBJECTS:tf_core_kernels>
545        $<$<BOOL:${tensorflow_ENABLE_GPU}>:$<TARGET_OBJECTS:tf_core_kernels_cpu_only>>
546        $<$<BOOL:${tensorflow_ENABLE_GPU}>:$<TARGET_OBJECTS:tf_stream_executor>>
547    )
548
549    target_include_directories(pywrap_tensorflow_internal_static PUBLIC
550        ${PYTHON_INCLUDE_DIR}
551        ${NUMPY_INCLUDE_DIR}
552    )
553    #target_link_libraries(pywrap_tensorflow_internal_static
554    #   tf_protos_cc
555    #   tf_python_protos_cc
556    #)
557    add_dependencies(pywrap_tensorflow_internal_static tf_protos_cc tf_python_protos_cc)
558    set(pywrap_tensorflow_internal_static_dependencies
559        $<TARGET_FILE:pywrap_tensorflow_internal_static>
560        $<TARGET_FILE:tf_protos_cc>
561        $<TARGET_FILE:tf_python_protos_cc>
562    ${nsync_STATIC_LIBRARIES}
563    )
564
565    if(${CMAKE_GENERATOR} MATCHES "Visual Studio.*")
566        set(pywrap_tensorflow_deffile "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/pywrap_tensorflow.def")
567    else()
568        set(pywrap_tensorflow_deffile "${CMAKE_CURRENT_BINARY_DIR}/pywrap_tensorflow.def")
569    endif()
570    set_source_files_properties(${pywrap_tensorflow_deffile} PROPERTIES GENERATED TRUE)
571    math(EXPR tensorflow_target_bitness "${CMAKE_SIZEOF_VOID_P}*8")
572    add_custom_command(TARGET pywrap_tensorflow_internal_static POST_BUILD
573        COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/tools/create_def_file.py
574            --input "${pywrap_tensorflow_internal_static_dependencies}"
575            --output "${pywrap_tensorflow_deffile}"
576            --target _pywrap_tensorflow_internal.pyd
577            --bitness "${tensorflow_target_bitness}"
578        BYPRODUCTS ${pywrap_tensorflow_deffile} # Required for Ninja
579    )
580endif(WIN32)
581
582# pywrap_tensorflow_internal is a shared library containing all of the
583# TensorFlow runtime and the standard ops and kernels. These are installed into
584# tf_python/tensorflow/python/.
585add_library(pywrap_tensorflow_internal SHARED
586    ${pywrap_tensorflow_internal_src}
587    $<TARGET_OBJECTS:tf_c>
588    $<TARGET_OBJECTS:tf_c_eager>
589    $<TARGET_OBJECTS:tf_c_python_api>
590    $<TARGET_OBJECTS:tf_core_lib>
591    $<TARGET_OBJECTS:tf_core_cpu>
592    $<TARGET_OBJECTS:tf_core_framework>
593    $<TARGET_OBJECTS:tf_core_profiler>
594    $<TARGET_OBJECTS:tf_core_eager_runtime>
595    $<TARGET_OBJECTS:tf_cc>
596    $<TARGET_OBJECTS:tf_cc_ops>
597    $<TARGET_OBJECTS:tf_cc_while_loop>
598    $<TARGET_OBJECTS:tf_core_ops>
599    $<TARGET_OBJECTS:tf_core_direct_session>
600    $<TARGET_OBJECTS:tf_grappler>
601    $<TARGET_OBJECTS:tf_tools_transform_graph_lib>
602    $<$<BOOL:${tensorflow_ENABLE_GRPC_SUPPORT}>:$<TARGET_OBJECTS:tf_core_distributed_runtime>>
603    $<TARGET_OBJECTS:tf_core_kernels>
604    $<$<BOOL:${tensorflow_ENABLE_GPU}>:$<$<BOOL:${BOOL_WIN32}>:$<TARGET_OBJECTS:tf_core_kernels_cpu_only>>>
605    $<$<BOOL:${tensorflow_ENABLE_GPU}>:$<TARGET_OBJECTS:tf_stream_executor>>
606    ${pywrap_tensorflow_deffile}
607)
608
609# There is a bug in GCC 5 resulting in undefined reference to a __cpu_model function when
610# linking to the tensorflow library. Adding the following libraries fixes it.
611if(CMAKE_COMPILER_IS_GNUCC AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 5.0)
612    target_link_libraries(pywrap_tensorflow_internal PRIVATE gcc_s gcc)
613endif()
614
615if(WIN32)
616    add_dependencies(pywrap_tensorflow_internal pywrap_tensorflow_internal_static)
617endif(WIN32)
618
619target_include_directories(pywrap_tensorflow_internal PUBLIC
620    ${PYTHON_INCLUDE_DIR}
621    ${NUMPY_INCLUDE_DIR}
622)
623
624if(CMAKE_COMPILER_IS_GNUCC AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 5.0)
625	# There is a bug in GCC 5 resulting in undefined reference to a __cpu_model function when
626	# linking to the tensorflow library. Adding the following libraries fixes it.
627	# See issue on github: https://github.com/tensorflow/tensorflow/issues/9593
628	target_link_libraries(pywrap_tensorflow_internal PRIVATE
629    ${tf_core_gpu_kernels_lib}
630    ${tensorflow_EXTERNAL_LIBRARIES}
631    tf_protos_cc
632    tf_python_protos_cc
633    ${PYTHON_LIBRARIES}
634    gcc_s
635    gcc
636)
637else()
638	target_link_libraries(pywrap_tensorflow_internal PRIVATE
639    ${tf_core_gpu_kernels_lib}
640    ${tensorflow_EXTERNAL_LIBRARIES}
641    tf_protos_cc
642    tf_python_protos_cc
643    ${PYTHON_LIBRARIES}
644)
645endif()
646
647if(WIN32)
648
649    # include contrib/periodic_resample as .so
650    #
651    set(tf_periodic_resample_srcs
652       "${tensorflow_source_dir}/tensorflow/contrib/periodic_resample/kernels/periodic_resample_op.cc"
653       "${tensorflow_source_dir}/tensorflow/contrib/periodic_resample/kernels/periodic_resample_op.h"
654       "${tensorflow_source_dir}/tensorflow/contrib/periodic_resample/ops/array_ops.cc"
655    )
656
657    AddUserOps(TARGET _periodic_resample_op
658        SOURCES "${tf_periodic_resample_srcs}"
659        DEPENDS pywrap_tensorflow_internal tf_python_ops
660        DISTCOPY ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/periodic_resample/python/ops/)
661
662    # include contrib/nearest_neighbor as .so
663    #
664    set(tf_nearest_neighbor_srcs
665        "${tensorflow_source_dir}/tensorflow/contrib/nearest_neighbor/kernels/heap.h"
666        "${tensorflow_source_dir}/tensorflow/contrib/nearest_neighbor/kernels/hyperplane_lsh_probes.h"
667        "${tensorflow_source_dir}/tensorflow/contrib/nearest_neighbor/kernels/hyperplane_lsh_probes.cc"
668        "${tensorflow_source_dir}/tensorflow/contrib/nearest_neighbor/ops/nearest_neighbor_ops.cc"
669    )
670
671    AddUserOps(TARGET _nearest_neighbor_ops
672        SOURCES "${tf_nearest_neighbor_srcs}"
673        DEPENDS pywrap_tensorflow_internal tf_python_ops
674        DISTCOPY ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/nearest_neighbor/python/ops/)
675endif(WIN32)
676
677if(WIN32)
678    # include contrib/rnn as .so
679    #
680    set(tf_gru_srcs
681        "${tensorflow_source_dir}/tensorflow/contrib/rnn/kernels/blas_gemm.cc"
682        "${tensorflow_source_dir}/tensorflow/contrib/rnn/kernels/blas_gemm.h"
683        "${tensorflow_source_dir}/tensorflow/contrib/rnn/kernels/gru_ops.cc"
684        "${tensorflow_source_dir}/tensorflow/contrib/rnn/kernels/gru_ops.h"
685        "${tensorflow_source_dir}/tensorflow/contrib/rnn/ops/gru_ops.cc"
686    )
687    set(tf_gru_gpu_srcs
688        "${tensorflow_source_dir}/tensorflow/contrib/rnn/kernels/gru_ops_gpu.cu.cc"
689    )
690
691    set(tf_lstm_srcs
692        "${tensorflow_source_dir}/tensorflow/contrib/rnn/kernels/blas_gemm.cc"
693        "${tensorflow_source_dir}/tensorflow/contrib/rnn/kernels/blas_gemm.h"
694        "${tensorflow_source_dir}/tensorflow/contrib/rnn/kernels/lstm_ops.cc"
695        "${tensorflow_source_dir}/tensorflow/contrib/rnn/kernels/lstm_ops.h"
696        "${tensorflow_source_dir}/tensorflow/contrib/rnn/ops/lstm_ops.cc"
697    )
698    set(tf_lstm_gpu_srcs
699        "${tensorflow_source_dir}/tensorflow/contrib/rnn/kernels/lstm_ops_gpu.cu.cc"
700    )
701
702    AddUserOps(TARGET _gru_ops
703        SOURCES "${tf_gru_srcs}"
704        GPUSOURCES ${tf_gru_gpu_srcs}
705        DEPENDS pywrap_tensorflow_internal tf_python_ops
706        DISTCOPY ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/rnn/python/ops/)
707
708    AddUserOps(TARGET _lstm_ops
709        SOURCES "${tf_lstm_srcs}"
710        GPUSOURCES ${tf_lstm_gpu_srcs}
711        DEPENDS pywrap_tensorflow_internal tf_python_ops
712        DISTCOPY ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/rnn/python/ops/)
713endif(WIN32)
714
715# include contrib/seq2seq as .so
716#
717set(tf_beam_search_srcs
718    "${tensorflow_source_dir}/tensorflow/contrib/seq2seq/kernels/beam_search_ops.cc"
719    "${tensorflow_source_dir}/tensorflow/contrib/seq2seq/kernels/beam_search_ops.h"
720    "${tensorflow_source_dir}/tensorflow/contrib/seq2seq/ops/beam_search_ops.cc"
721)
722
723set(tf_beam_search_gpu_srcs
724    "${tensorflow_source_dir}/tensorflow/contrib/seq2seq/kernels/beam_search_ops_gpu.cu.cc"
725)
726
727AddUserOps(TARGET _beam_search_ops
728    SOURCES "${tf_beam_search_srcs}"
729    GPUSOURCES ${tf_beam_search_gpu_srcs}
730    DEPENDS pywrap_tensorflow_internal tf_python_ops
731    DISTCOPY ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/seq2seq/python/ops/)
732
733if(WIN32)
734  if(${CMAKE_GENERATOR} MATCHES "Visual Studio.*")
735    add_custom_command(TARGET pywrap_tensorflow_internal POST_BUILD
736      COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/$(Configuration)/pywrap_tensorflow_internal.dll
737                                       ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/python/_pywrap_tensorflow_internal.pyd
738      COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/$(Configuration)/pywrap_tensorflow_internal.lib
739                                       ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/python/)
740  else()
741    add_custom_command(TARGET pywrap_tensorflow_internal POST_BUILD
742      COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/pywrap_tensorflow_internal.dll
743                                       ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/python/_pywrap_tensorflow_internal.pyd
744      COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/pywrap_tensorflow_internal.lib
745                                       ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/python/)
746  endif()
747else()
748  add_custom_command(TARGET pywrap_tensorflow_internal POST_BUILD
749    COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/libpywrap_tensorflow_internal${CMAKE_SHARED_LIBRARY_SUFFIX}
750                                     ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/python/_pywrap_tensorflow_internal.so)
751endif()
752
753
754########################################################
755# Generate API __init__.py files.
756########################################################
757
758# Parse tensorflow/python/tools/api/generator/BUILD to get list of generated files.
759FILE(READ ${tensorflow_source_dir}/tensorflow/python/tools/api/generator/api_init_files.bzl api_generator_BUILD_text)
760STRING(REGEX MATCH "# BEGIN GENERATED FILES.*# END GENERATED FILES" api_init_files_text ${api_generator_BUILD_text})
761string(REPLACE "# BEGIN GENERATED FILES" "" api_init_files_text ${api_init_files_text})
762string(REPLACE "# END GENERATED FILES" "" api_init_files_text ${api_init_files_text})
763string(REPLACE "," ";" api_init_files_list ${api_init_files_text})
764
765set(api_init_files "")
766foreach(api_init_file ${api_init_files_list})
767    string(STRIP "${api_init_file}" api_init_file)
768    if(api_init_file)
769        string(REPLACE "\"" "" api_init_file "${api_init_file}")  # Remove quotes
770        list(APPEND api_init_files "${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/${api_init_file}")
771    endif()
772endforeach(api_init_file)
773set(api_init_list_file "${tensorflow_source_dir}/api_init_files_list.txt")
774file(WRITE "${api_init_list_file}" "${api_init_files}")
775
776# Run create_python_api.py to generate __init__.py files.
777
778### TODO
779# In order to download and compile MKL/MKL-DNN automatically in cmake script, mkl-built libraries should be added to system path
780# to be loaded by python executor. However `add_custom_command` has an issue with `COMMAND ${CMAKE_COMMAND} -E env PATH=`, where
781# arguments of multiple paths (such as D:/;D:/mkl) will be parsed in to seperate string without semicolon and that command fail to
782# recongnize paths. As CUDA isn't built with MKL, the MKL built directory is the only path to this command to work around that issue.
783# To not override the CUDA and system path in other circumstances, `if-else` branch used here to handle this problem,
784# and should be removed if the path issue can be resolved.
785# UPDATE: Below block appears to handle multiple items in PATH correctly, but risks command line limits if PATH is large.
786# If you have issues, try `set(PY_RUNTIME_ENV "PATH=${mkl_BIN_DIRS}")` instead.
787###
788
789set(PY_RUNTIME_ENV "")
790if(tensorflow_ENABLE_MKL_SUPPORT)
791    # add mkl dist dlls to system path for python
792    file(TO_CMAKE_PATH "$ENV{PATH}" PY_RUNTIME_ENV)
793    set(PY_RUNTIME_ENV ${mkl_BIN_DIRS} ${PY_RUNTIME_ENV})
794    file(TO_NATIVE_PATH "${PY_RUNTIME_ENV}" PY_RUNTIME_ENV)
795    set(PY_RUNTIME_ENV "PATH=${PY_RUNTIME_ENV}")
796endif(tensorflow_ENABLE_MKL_SUPPORT)
797
798add_custom_command(
799      OUTPUT ${api_init_files}
800      DEPENDS tf_python_ops tf_python_copy_scripts_to_destination pywrap_tensorflow_internal tf_python_touchup_modules tf_extension_ops
801
802      # tensorflow/__init__.py depends on files generated in this step. So, remove it while
803      # this step is running since the files aren't there yet.
804      COMMAND ${CMAKE_COMMAND} -E remove -f ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/__init__.py
805      COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/__init__.py
806
807      # Run create_python_api.py to generate API init files.
808      COMMAND ${CMAKE_COMMAND} -E env PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}/tf_python "${PY_RUNTIME_ENV}" ${PYTHON_EXECUTABLE}
809              "${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/python/tools/api/generator/create_python_api.py"
810              "--root_init_template=${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/api_template.__init__.py"
811              "--apidir=${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow"
812              "--package=tensorflow.python"
813              "--apiname=tensorflow"
814              "${api_init_list_file}"
815
816      COMMENT "Generating __init__.py files for Python API."
817      WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/tf_python"
818      VERBATIM
819)
820
821add_custom_target(tf_python_api SOURCES ${api_init_files})
822add_dependencies(tf_python_api tf_python_ops)
823
824# TODO(mikecase): This can be removed once tf.estimator is moved
825# out of TensorFlow.
826########################################################
827# Generate API __init__.py files for tf.estimator.
828########################################################
829
830# Parse tensorflow/python/tools/api/generator/BUILD to get list of generated files.
831FILE(READ ${tensorflow_source_dir}/tensorflow/python/tools/api/generator/api_init_files.bzl api_generator_BUILD_text)
832STRING(REGEX MATCH "# BEGIN GENERATED FILES.*# END GENERATED FILES" api_init_files_text ${api_generator_BUILD_text})
833string(REPLACE "# BEGIN GENERATED FILES" "" api_init_files_text ${api_init_files_text})
834string(REPLACE "# END GENERATED FILES" "" api_init_files_text ${api_init_files_text})
835string(REPLACE "," ";" api_init_files_list ${api_init_files_text})
836
837set(api_init_files "")
838foreach(api_init_file ${api_init_files_list})
839    string(STRIP "${api_init_file}" api_init_file)
840    if(api_init_file)
841        string(REPLACE "\"" "" api_init_file "${api_init_file}")  # Remove quotes
842        list(APPEND api_init_files "${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/python/estimator/api/${api_init_file}")
843    endif()
844endforeach(api_init_file)
845set(estimator_api_init_list_file "${tensorflow_source_dir}/estimator_api_init_files_list.txt")
846file(WRITE "${estimator_api_init_list_file}" "${api_init_files}")
847
848# Run create_python_api.py to generate __init__.py files.
849add_custom_command(
850      OUTPUT ${api_init_files}
851      DEPENDS tf_python_ops tf_python_copy_scripts_to_destination pywrap_tensorflow_internal tf_python_touchup_modules tf_extension_ops
852
853      # Run create_python_api.py to generate API init files.
854      COMMAND ${CMAKE_COMMAND} -E env PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}/tf_python "${PY_RUNTIME_ENV}" ${PYTHON_EXECUTABLE}
855              "${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/python/tools/api/generator/create_python_api.py"
856              "--apidir=${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/python/estimator/api"
857              "--package=tensorflow.python.estimator"
858              "--apiname=estimator"
859          "--output_package=tensorflow.python.estimator.api"
860              "${estimator_api_init_list_file}"
861
862      COMMENT "Generating __init__.py files for Python API."
863      WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/tf_python"
864)
865
866add_custom_target(estimator_python_api SOURCES ${api_init_files})
867add_dependencies(estimator_python_api tf_python_ops)
868############################################################
869# Build a PIP package containing the TensorFlow runtime.
870############################################################
871add_custom_target(tf_python_build_pip_package)
872add_dependencies(tf_python_build_pip_package
873    pywrap_tensorflow_internal
874    tf_python_copy_scripts_to_destination
875    tf_python_touchup_modules
876    tf_python_ops
877    tf_python_api
878    estimator_python_api
879    tf_extension_ops)
880
881# Fix-up Python files that were not included by the add_python_module() macros.
882add_custom_command(TARGET tf_python_build_pip_package POST_BUILD
883  COMMAND ${CMAKE_COMMAND} -E copy ${tensorflow_source_dir}/tensorflow/tools/pip_package/setup.py
884                                   ${CMAKE_CURRENT_BINARY_DIR}/tf_python/)
885# This file is unfortunately excluded by the regex that excludes *_test.py
886# files, but it is imported into tf.contrib, so we add it explicitly.
887add_custom_command(TARGET tf_python_copy_scripts_to_destination PRE_BUILD
888  COMMAND ${CMAKE_COMMAND} -E copy ${tensorflow_source_dir}/tensorflow/contrib/testing/python/framework/util_test.py
889                                   ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/testing/python/framework/)
890add_custom_command(TARGET tf_python_build_pip_package POST_BUILD
891  COMMAND ${CMAKE_COMMAND} -E copy ${tensorflow_source_dir}/tensorflow/tools/pip_package/README
892                                   ${CMAKE_CURRENT_BINARY_DIR}/tf_python/)
893add_custom_command(TARGET tf_python_build_pip_package POST_BUILD
894  COMMAND ${CMAKE_COMMAND} -E copy ${tensorflow_source_dir}/tensorflow/tools/pip_package/MANIFEST.in
895                                   ${CMAKE_CURRENT_BINARY_DIR}/tf_python/)
896
897# Copy datasets for tf.contrib.learn.
898add_custom_command(TARGET tf_python_build_pip_package POST_BUILD
899  COMMAND ${CMAKE_COMMAND} -E copy ${tensorflow_source_dir}/tensorflow/contrib/learn/python/learn/datasets/data/boston_house_prices.csv
900                                   ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/learn/python/learn/datasets/data/)
901add_custom_command(TARGET tf_python_build_pip_package POST_BUILD
902  COMMAND ${CMAKE_COMMAND} -E copy ${tensorflow_source_dir}/tensorflow/contrib/learn/python/learn/datasets/data/iris.csv
903                                   ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/learn/python/learn/datasets/data/)
904add_custom_command(TARGET tf_python_build_pip_package POST_BUILD
905  COMMAND ${CMAKE_COMMAND} -E copy ${tensorflow_source_dir}/tensorflow/contrib/learn/python/learn/datasets/data/text_test.csv
906                                   ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/learn/python/learn/datasets/data/)
907add_custom_command(TARGET tf_python_build_pip_package POST_BUILD
908  COMMAND ${CMAKE_COMMAND} -E copy ${tensorflow_source_dir}/tensorflow/contrib/learn/python/learn/datasets/data/text_train.csv
909                                   ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/learn/python/learn/datasets/data/)
910
911# Create include header directory
912add_custom_command(TARGET tf_python_build_pip_package PRE_BUILD
913  COMMAND ${CMAKE_COMMAND} -E make_directory
914  ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/include/)
915
916# tensorflow headers
917add_custom_command(TARGET tf_python_build_pip_package PRE_BUILD
918  COMMAND ${CMAKE_COMMAND} -E make_directory
919  ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/include/tensorflow)
920add_custom_command(TARGET tf_python_build_pip_package PRE_BUILD
921  COMMAND ${CMAKE_COMMAND} -E make_directory
922  ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/include/tensorflow/core)
923add_custom_command(TARGET tf_python_build_pip_package PRE_BUILD
924  COMMAND ${CMAKE_COMMAND} -E make_directory
925  ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/include/tensorflow/stream_executor)
926add_custom_command(TARGET tf_python_build_pip_package POST_BUILD
927  COMMAND ${CMAKE_COMMAND} -E copy_directory ${tensorflow_source_dir}/tensorflow/core
928                                   ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/include/tensorflow/core)
929add_custom_command(TARGET tf_python_build_pip_package POST_BUILD
930  COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_BINARY_DIR}/tensorflow/core
931                                   ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/include/tensorflow/core)
932add_custom_command(TARGET tf_python_build_pip_package POST_BUILD
933  COMMAND ${CMAKE_COMMAND} -E copy_directory ${tensorflow_source_dir}/tensorflow/stream_executor
934                                   ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/include/tensorflow/stream_executor)
935
936# google protobuf headers
937add_custom_command(TARGET tf_python_build_pip_package PRE_BUILD
938  COMMAND ${CMAKE_COMMAND} -E make_directory
939  ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/include/google)
940add_custom_command(TARGET tf_python_build_pip_package POST_BUILD
941  COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_BINARY_DIR}/protobuf/src/protobuf/src/google
942                                   ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/include/google)
943
944# Eigen directory
945add_custom_command(TARGET tf_python_build_pip_package PRE_BUILD
946  COMMAND ${CMAKE_COMMAND} -E make_directory
947  ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/include/Eigen)
948add_custom_command(TARGET tf_python_build_pip_package POST_BUILD
949  COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_BINARY_DIR}/eigen/src/eigen/Eigen
950                                   ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/include/Eigen)
951
952# external directory
953add_custom_command(TARGET tf_python_build_pip_package PRE_BUILD
954  COMMAND ${CMAKE_COMMAND} -E make_directory
955  ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/include/external)
956add_custom_command(TARGET tf_python_build_pip_package PRE_BUILD
957  COMMAND ${CMAKE_COMMAND} -E make_directory
958  ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/include/external/eigen_archive)
959add_custom_command(TARGET tf_python_build_pip_package POST_BUILD
960  COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_BINARY_DIR}/external/eigen_archive
961                                   ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/include/external/eigen_archive)
962
963# third_party eigen directory
964add_custom_command(TARGET tf_python_build_pip_package PRE_BUILD
965  COMMAND ${CMAKE_COMMAND} -E make_directory
966  ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/include/third_party)
967add_custom_command(TARGET tf_python_build_pip_package PRE_BUILD
968  COMMAND ${CMAKE_COMMAND} -E make_directory
969  ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/include/third_party/eigen3)
970add_custom_command(TARGET tf_python_build_pip_package POST_BUILD
971  COMMAND ${CMAKE_COMMAND} -E copy_directory ${tensorflow_source_dir}/third_party/eigen3
972                                   ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/include/third_party/eigen3)
973
974# unsupported Eigen directory
975add_custom_command(TARGET tf_python_build_pip_package PRE_BUILD
976  COMMAND ${CMAKE_COMMAND} -E make_directory
977  ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/include/unsupported)
978add_custom_command(TARGET tf_python_build_pip_package PRE_BUILD
979  COMMAND ${CMAKE_COMMAND} -E make_directory
980  ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/include/unsupported/Eigen)
981add_custom_command(TARGET tf_python_build_pip_package POST_BUILD
982  COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_BINARY_DIR}/eigen/src/eigen/unsupported/Eigen
983                                   ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/include/unsupported/Eigen)
984
985if(${tensorflow_TF_NIGHTLY})
986  if(${tensorflow_ENABLE_GPU})
987    add_custom_command(TARGET tf_python_build_pip_package POST_BUILD
988      COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/tf_python/setup.py bdist_wheel --project_name tf_nightly_gpu
989      WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/tf_python)
990  else()
991    add_custom_command(TARGET tf_python_build_pip_package POST_BUILD
992      COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/tf_python/setup.py bdist_wheel --project_name tf_nightly
993      WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/tf_python)
994  endif(${tensorflow_ENABLE_GPU})
995else()
996  if(${tensorflow_ENABLE_GPU})
997    add_custom_command(TARGET tf_python_build_pip_package POST_BUILD
998      COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/tf_python/setup.py bdist_wheel --project_name tensorflow_gpu
999      WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/tf_python)
1000  else()
1001    add_custom_command(TARGET tf_python_build_pip_package POST_BUILD
1002      COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/tf_python/setup.py bdist_wheel
1003      WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/tf_python)
1004  endif(${tensorflow_ENABLE_GPU})
1005endif(${tensorflow_TF_NIGHTLY})
1006