generic.cmake 46.9 KB
Newer Older
1
# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved.
2
#
L
liaogang 已提交
3 4 5
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
6
#
L
liaogang 已提交
7
# http://www.apache.org/licenses/LICENSE-2.0
8
#
L
liaogang 已提交
9 10 11 12 13
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
14
#
15

Y
Yi Wang 已提交
16 17 18
# generic.cmake defines CMakes functions that look like Bazel's
# building rules (https://bazel.build/).
#
W
wuyi05 已提交
19
#
L
liaogang 已提交
20
# -------------------------------------------
21
#     C++        CUDA C++       Go
L
liaogang 已提交
22
# -------------------------------------------
23 24 25
# cc_library    nv_library   go_library
# cc_binary     nv_binary    go_binary
# cc_test       nv_test      go_test
L
liaogang 已提交
26
# -------------------------------------------
W
wuyi05 已提交
27
#
Y
Yi Wang 已提交
28 29
# To build a static library example.a from example.cc using the system
#  compiler (like GCC):
W
wuyi05 已提交
30
#
31
#   cc_library(example SRCS example.cc)
W
wuyi05 已提交
32
#
Y
Yi Wang 已提交
33 34
# To build a static library example.a from multiple source files
# example{1,2,3}.cc:
W
wuyi05 已提交
35
#
36
#   cc_library(example SRCS example1.cc example2.cc example3.cc)
W
wuyi05 已提交
37
#
38
# To build a shared library example.so from example.cc:
W
wuyi05 已提交
39
#
40
#   cc_library(example SHARED SRCS example.cc)
W
wuyi05 已提交
41
#
Y
Yi Wang 已提交
42 43
# To build a library using Nvidia's NVCC from .cu file(s), use the nv_
# prefixed version:
W
wuyi05 已提交
44
#
45
#   nv_library(example SRCS example.cu)
W
wuyi05 已提交
46
#
47
# To specify that a library new_example.a depends on other libraies:
W
wuyi05 已提交
48
#
49
#   cc_library(new_example SRCS new_example.cc DEPS example)
W
wuyi05 已提交
50
#
51
# Static libraries can be composed of other static libraries:
W
wuyi05 已提交
52
#
53
#   cc_library(composed DEPS dependent1 dependent2 dependent3)
W
wuyi05 已提交
54
#
Y
Yi Wang 已提交
55 56
# To build an executable binary file from some source files and
# dependent libraries:
W
wuyi05 已提交
57
#
58
#   cc_binary(example SRCS main.cc something.cc DEPS example1 example2)
W
wuyi05 已提交
59
#
Y
Yi Wang 已提交
60 61
# To build an executable binary file using NVCC, use the nv_ prefixed
# version:
W
wuyi05 已提交
62
#
63
#   nv_binary(example SRCS main.cc something.cu DEPS example1 example2)
W
wuyi05 已提交
64
#
Y
Yi Wang 已提交
65 66
# To build a unit test binary, which is an executable binary with
# GoogleTest linked:
W
wuyi05 已提交
67
#
68
#   cc_test(example_test SRCS example_test.cc DEPS example)
W
wuyi05 已提交
69
#
70
# To build a unit test binary using NVCC, use the nv_ prefixed version:
W
wuyi05 已提交
71
#
72
#   nv_test(example_test SRCS example_test.cu DEPS example)
73
#
Y
Yi Wang 已提交
74 75 76
# It is pretty often that executable and test binaries depend on
# pre-defined external libaries like glog and gflags defined in
# /cmake/external/*.cmake:
77
#
78
#   cc_test(example_test SRCS example_test.cc DEPS example glog gflags)
L
liaogang 已提交
79 80 81 82 83 84 85 86 87
#
# To build a go static library using Golang, use the go_ prefixed version:
#
#   go_library(example STATIC)
#
# To build a go shared library using Golang, use the go_ prefixed version:
#
#   go_library(example SHARED)
#
L
liaogang 已提交
88

Y
Yu Yang 已提交
89
# including binary directory for generated headers.
90
include_directories(${CMAKE_CURRENT_BINARY_DIR})
M
MRXLT 已提交
91 92
# including io directory for inference lib paddle_api.h
include_directories("${PADDLE_SOURCE_DIR}/paddle/fluid/framework/io")
Y
Yu Yang 已提交
93

94
if(NOT APPLE AND NOT WIN32)
Y
Yiqun Liu 已提交
95 96
  find_package(Threads REQUIRED)
  link_libraries(${CMAKE_THREAD_LIBS_INIT})
T
tangwei12 已提交
97
  if(WITH_PSLIB OR WITH_DISTRIBUTE)
98
    set(CMAKE_CXX_LINK_EXECUTABLE
L
LiYuRio 已提交
99
        "${CMAKE_CXX_LINK_EXECUTABLE} -pthread -ldl -lrt -lz -lssl -lcrypto")
100
  else()
101 102
    set(CMAKE_CXX_LINK_EXECUTABLE
        "${CMAKE_CXX_LINK_EXECUTABLE} -pthread -ldl -lrt")
103
  endif()
104
endif()
105

T
typhoonzero 已提交
106 107 108 109 110
set_property(GLOBAL PROPERTY FLUID_MODULES "")
# find all fluid modules is used for paddle fluid static library
# for building inference libs
function(find_fluid_modules TARGET_NAME)
  get_filename_component(__target_path ${TARGET_NAME} ABSOLUTE)
111 112
  string(REGEX REPLACE "^${PADDLE_SOURCE_DIR}/" "" __target_path
                       ${__target_path})
T
typhoonzero 已提交
113 114 115 116 117 118
  string(FIND "${__target_path}" "fluid" pos)
  if(pos GREATER 1)
    get_property(fluid_modules GLOBAL PROPERTY FLUID_MODULES)
    set(fluid_modules ${fluid_modules} ${TARGET_NAME})
    set_property(GLOBAL PROPERTY FLUID_MODULES "${fluid_modules}")
  endif()
119
endfunction()
T
typhoonzero 已提交
120

121 122 123 124 125 126 127 128 129 130 131 132 133
# NOTE(Aurelius84): NOT_INFER_MODULES is used to tag
# and not considered as DEPS for inference libs.
set_property(GLOBAL PROPERTY NOT_INFER_MODULES "")

function(ignore_infer_modules TARGET_NAME)
  get_property(not_infer_modules GLOBAL PROPERTY NOT_INFER_MODULES)
  list(FIND not_infer_modules TARGET_NAME is_found)
  if(is_found EQUAL -1) # NOT FOUND
    set(not_infer_modules ${not_infer_modules} ${TARGET_NAME})
    set_property(GLOBAL PROPERTY NOT_INFER_MODULES "${not_infer_modules}")
  endif()
endfunction()

134 135
set_property(GLOBAL PROPERTY PHI_MODULES "")
# find all phi modules is used for paddle static library
136
# for building inference libs
137
function(find_phi_modules TARGET_NAME)
138
  get_filename_component(__target_path ${TARGET_NAME} ABSOLUTE)
139 140
  string(REGEX REPLACE "^${PADDLE_SOURCE_DIR}/" "" __target_path
                       ${__target_path})
141
  string(FIND "${__target_path}" "phi" pos)
142
  if(pos GREATER 1)
143 144 145
    get_property(phi_modules GLOBAL PROPERTY PHI_MODULES)
    set(phi_modules ${phi_modules} ${TARGET_NAME})
    set_property(GLOBAL PROPERTY PHI_MODULES "${phi_modules}")
146
  endif()
147
endfunction()
148

Y
Yu Yang 已提交
149
function(common_link TARGET_NAME)
150
  if(WITH_PROFILER)
Y
Yu Yang 已提交
151 152 153 154
    target_link_libraries(${TARGET_NAME} gperftools::profiler)
  endif()
endfunction()

D
dzhwinter 已提交
155 156 157 158 159
# find all third_party modules is used for paddle static library
# for reduce the dependency when building the inference libs.
set_property(GLOBAL PROPERTY FLUID_THIRD_PARTY)
function(find_fluid_thirdparties TARGET_NAME)
  get_filename_component(__target_path ${TARGET_NAME} ABSOLUTE)
160 161
  string(REGEX REPLACE "^${PADDLE_SOURCE_DIR}/" "" __target_path
                       ${__target_path})
D
dzhwinter 已提交
162 163 164 165 166 167
  string(FIND "${__target_path}" "third_party" pos)
  if(pos GREATER 1)
    get_property(fluid_ GLOBAL PROPERTY FLUID_THIRD_PARTY)
    set(fluid_third_partys ${fluid_third_partys} ${TARGET_NAME})
    set_property(GLOBAL PROPERTY FLUID_THIRD_PARTY "${fluid_third_partys}")
  endif()
168
endfunction()
D
dzhwinter 已提交
169

170 171 172 173 174 175 176 177 178 179 180 181
function(create_static_lib TARGET_NAME)
  set(libs ${ARGN})
  list(REMOVE_DUPLICATES libs)
  if(WIN32)
    set(dummy_index 1)
    set(dummy_offset 1)
    # the dummy target would be consisted of limit size libraries
    set(dummy_limit 60)
    list(LENGTH libs libs_len)
    foreach(lib ${libs})
      list(APPEND dummy_list ${lib})
      list(LENGTH dummy_list listlen)
182 183
      if((${listlen} GREATER ${dummy_limit}) OR (${dummy_offset} EQUAL
                                                 ${libs_len}))
184 185
        merge_static_libs(${TARGET_NAME}_dummy_${dummy_index} ${dummy_list})
        set(dummy_list)
186 187 188
        list(APPEND ${TARGET_NAME}_dummy_list
             ${TARGET_NAME}_dummy_${dummy_index})
        math(EXPR dummy_index "${dummy_index}+1")
189
      endif()
190
      math(EXPR dummy_offset "${dummy_offset}+1")
191 192 193 194 195 196 197
    endforeach()
    merge_static_libs(${TARGET_NAME} ${${TARGET_NAME}_dummy_list})
  else()
    merge_static_libs(${TARGET_NAME} ${libs})
  endif()
endfunction()

198 199 200 201
function(create_dummy_static_lib TARGET_NAME)
  set(options "")
  set(oneValueArgs "")
  set(multiValueArgs LIBS DEPS LIMIT)
202 203
  cmake_parse_arguments(merge "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
204 205 206 207 208 209 210

  list(REMOVE_DUPLICATES merge_LIBS)
  set(index 1)
  set(offset 1)
  # the dummy target would be consisted of limit size libraries
  set(limit ${merge_LIMIT})
  list(LENGTH merge_LIBS libs_len)
L
Leo Chen 已提交
211
  message("libs_len ${libs_len}")
212 213 214
  foreach(lib ${merge_LIBS})
    list(APPEND merge_list ${lib})
    list(LENGTH merge_list listlen)
215 216 217
    if((${listlen} GREATER ${limit}) OR (${offset} EQUAL ${libs_len}))
      message(
        "Merge and generate static library: ${TARGET_NAME}_static_${index}")
218 219 220 221 222 223
      merge_static_libs(${TARGET_NAME}_static_${index} ${merge_list})
      if(merge_DEPS)
        target_link_libraries(${TARGET_NAME}_static_${index} ${merge_DEPS})
      endif()
      set(merge_list)
      list(APPEND ${TARGET_NAME}_list ${TARGET_NAME}_static_${index})
224
      math(EXPR index "${index}+1")
225
    endif()
226
    math(EXPR offset "${offset}+1")
227 228 229 230
  endforeach()
  cc_library(${TARGET_NAME} DEPS ${${TARGET_NAME}_list})
endfunction()

231
function(merge_static_libs TARGET_NAME)
L
liaogang 已提交
232 233
  set(libs ${ARGN})
  list(REMOVE_DUPLICATES libs)
234

235
  # Get all propagation dependencies from the merged libraries
L
liaogang 已提交
236
  foreach(lib ${libs})
237 238
    list(APPEND libs_deps ${${lib}_LIB_DEPENDS})
  endforeach()
239 240 241
  if(libs_deps)
    list(REMOVE_DUPLICATES libs_deps)
  endif()
242

243 244 245 246
  # To produce a library we need at least one source file.
  # It is created by add_custom_command below and will helps
  # also help to track dependencies.
  set(target_SRCS ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}_dummy.c)
247

248 249 250
  # Make the generated dummy source file depended on all static input
  # libs. If input lib changes,the source file is touched
  # which causes the desired effect (relink).
251 252
  add_custom_command(
    OUTPUT ${target_SRCS}
253 254
    COMMAND ${CMAKE_COMMAND} -E touch ${target_SRCS}
    DEPENDS ${libs})
255 256 257 258

  # Generate dummy staic lib
  generate_dummy_static_lib(LIB_NAME ${TARGET_NAME} FILE_PATH ${target_SRCS}
                            GENERATOR "generic.cmake:merge_static_libs")
259
  target_link_libraries(${TARGET_NAME} ${libs_deps})
260

261 262
  # OSX: use 'libtool' to merge archives
  if(APPLE)
263 264 265 266
    foreach(lib ${libs})
      # Get the file names of the libraries to be merged
      set(libfiles ${libfiles} $<TARGET_FILE:${lib}>)
    endforeach()
267 268 269
    add_custom_command(
      TARGET ${TARGET_NAME}
      POST_BUILD
270
      COMMENT "Merge and generate static lib: lib${TARGET_NAME}.a"
271
      COMMAND rm "${CMAKE_CURRENT_BINARY_DIR}/lib${TARGET_NAME}.a"
272 273
      COMMAND /usr/bin/libtool -static -o
              "${CMAKE_CURRENT_BINARY_DIR}/lib${TARGET_NAME}.a" ${libfiles})
274
  endif()
275

276 277
  # LINUX: use "ar" to extract objects and re-add to a common lib
  if(LINUX)
278 279 280 281 282 283 284
    set(mri_file
        ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}.mri
        CACHE INTERNAL "phi_static.mri file")
    get_property(
      ABS_MERGE_LIB_PATH
      TARGET ${TARGET_NAME}
      PROPERTY LOCATION)
285
    file(WRITE ${mri_file} "create ${ABS_MERGE_LIB_PATH}\n")
286

287
    foreach(lib ${libs})
288 289 290 291
      get_property(
        ABS_LIB_PATH
        TARGET ${lib}
        PROPERTY LOCATION)
292
      file(APPEND ${mri_file} "addlib ${ABS_LIB_PATH}\n")
L
liaogang 已提交
293
    endforeach()
294
    file(APPEND ${mri_file} "save\nend\n")
295

296 297 298 299 300 301
    add_custom_command(
      TARGET ${TARGET_NAME}
      POST_BUILD
      COMMENT "Merge and generate static lib: lib${TARGET_NAME}.a"
      COMMAND ${CMAKE_AR} -M < ${mri_file}
      COMMAND ${CMAKE_RANLIB} "$<TARGET_FILE:${TARGET_NAME}>")
302
  endif()
D
dzhwinter 已提交
303

304 305
  # Windows do not support gcc/nvcc combined compiling. Use msvc 'lib.exe' to merge libs.
  if(WIN32)
D
dzhwinter 已提交
306 307 308
    foreach(lib ${libs})
      set(libfiles ${libfiles} $<TARGET_FILE:${lib}>)
    endforeach()
309
    # msvc compiler will put libarary in directory of "/Release/xxxlib" by default
310 311 312
    add_custom_command(
      TARGET ${TARGET_NAME}
      POST_BUILD
313
      COMMENT "Merge and generate static lib: lib${TARGET_NAME}.lib"
314
      COMMAND cmake -E make_directory $<TARGET_FILE_DIR:${TARGET_NAME}>
315
      COMMAND lib /OUT:$<TARGET_FILE:${TARGET_NAME}> ${libfiles})
316 317
  endif()
endfunction()
318

319
function(check_coverage_opt TARGET_NAME SRCS)
320
  if(WITH_COVERAGE AND WITH_INCREMENTAL_COVERAGE)
321
    # if pybind.cc add '-g -O0 -fprofile-arcs -ftest-coverage' only, some testcase will fail.
322 323
    if("$ENV{PADDLE_GIT_DIFF_H_FILE}" STREQUAL ""
       AND (NOT ("$ENV{PADDLE_GIT_DIFF_CC_FILE}" MATCHES "pybind.cc")))
324
      if(NOT ("$ENV{PADDLE_GIT_DIFF_CC_FILE}" STREQUAL ""))
325 326
        string(REPLACE "," ";" CC_FILE_LIST $ENV{PADDLE_GIT_DIFF_CC_FILE})
        set(use_coverage_opt FALSE)
327
        foreach(cc_file ${CC_FILE_LIST})
328 329 330 331
          if("${SRCS};" MATCHES "${cc_file}")
            set(use_coverage_opt TRUE)
            break()
          endif()
332
        endforeach()
333

334
        if(use_coverage_opt)
335
          message(STATUS "cc changed, add coverage opt for ${TARGET_NAME}")
336 337
          target_compile_options(${TARGET_NAME} PRIVATE -g -O0 -fprofile-arcs
                                                        -ftest-coverage)
338
          target_link_libraries(${TARGET_NAME} -fprofile-arcs)
339 340 341 342 343
          get_target_property(WH_TARGET_COMPILE_OPTIONS ${TARGET_NAME}
                              COMPILE_OPTIONS)
          message(
            STATUS "property for ${TARGET_NAME} is ${WH_TARGET_COMPILE_OPTIONS}"
          )
344 345 346 347
        endif()
      endif()
    endif()
  endif()
348
endfunction()
349

L
liaogang 已提交
350
function(cc_library TARGET_NAME)
351 352 353 354 355 356 357 358 359
  set(options
      STATIC
      static
      SHARED
      shared
      INTERFACE
      interface
      NOT_FOR_INFER
      not_for_infer)
L
liaogang 已提交
360 361
  set(oneValueArgs "")
  set(multiValueArgs SRCS DEPS)
362 363
  cmake_parse_arguments(cc_library "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
D
dzhwinter 已提交
364
  if(WIN32)
365 366 367 368
    # add libxxx.lib prefix in windows
    set(${TARGET_NAME}_LIB_NAME
        "${CMAKE_STATIC_LIBRARY_PREFIX}${TARGET_NAME}${CMAKE_STATIC_LIBRARY_SUFFIX}"
        CACHE STRING "output library name for target ${TARGET_NAME}")
369
  endif()
L
Liu Yiqun 已提交
370
  if(cc_library_SRCS)
371 372 373
    if(cc_library_NOT_FOR_INFER OR cc_library_not_for_infer)
      ignore_infer_modules(${TARGET_NAME})
    endif()
374 375 376 377 378 379 380 381 382 383 384
    if(cc_library_SHARED OR cc_library_shared) # build *.so
      add_library(${TARGET_NAME} SHARED ${cc_library_SRCS})
    elseif(cc_library_INTERFACE OR cc_library_interface)
      generate_dummy_static_lib(
        LIB_NAME ${TARGET_NAME} FILE_PATH ${target_SRCS} GENERATOR
        "generic.cmake:cc_library")
    else()
      add_library(${TARGET_NAME} STATIC ${cc_library_SRCS})
      find_fluid_modules(${TARGET_NAME})
      find_phi_modules(${TARGET_NAME})
    endif()
L
Liu Yiqun 已提交
385
    if(cc_library_DEPS)
386
      # Don't need link libwarpctc.so
L
Liu Yiqun 已提交
387
      if("${cc_library_DEPS};" MATCHES "warpctc;")
388 389 390
        list(REMOVE_ITEM cc_library_DEPS warpctc)
        add_dependencies(${TARGET_NAME} warpctc)
      endif()
391

T
update  
typhoonzero 已提交
392 393 394 395 396
      # remove link to python, see notes at:
      # https://github.com/pybind/pybind11/blob/master/docs/compiling.rst#building-manually
      if("${cc_library_DEPS};" MATCHES "python;")
        list(REMOVE_ITEM cc_library_DEPS python)
        add_dependencies(${TARGET_NAME} python)
P
peizhilin 已提交
397 398 399 400
        if(WIN32)
          target_link_libraries(${TARGET_NAME} ${PYTHON_LIBRARIES})
        else()
          target_link_libraries(${TARGET_NAME} "-Wl,-undefined,dynamic_lookup")
401
        endif()
T
update  
typhoonzero 已提交
402
      endif()
403
      target_link_libraries(${TARGET_NAME} ${cc_library_DEPS})
Y
Yu Yang 已提交
404
      common_link(${TARGET_NAME})
405
    endif()
C
chengduo 已提交
406

L
liaogang 已提交
407
    # cpplint code style
L
liaogang 已提交
408 409 410 411 412 413
    foreach(source_file ${cc_library_SRCS})
      string(REGEX REPLACE "\\.[^.]*$" "" source ${source_file})
      if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${source}.h)
        list(APPEND cc_library_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/${source}.h)
      endif()
    endforeach()
414 415 416

    check_coverage_opt(${TARGET_NAME} ${cc_library_SRCS})

417
  else()
418
    if(cc_library_DEPS)
419
      list(REMOVE_DUPLICATES cc_library_DEPS)
420

421 422 423
      generate_dummy_static_lib(
        LIB_NAME ${TARGET_NAME} FILE_PATH ${target_SRCS} GENERATOR
        "generic.cmake:cc_library")
424

425
      target_link_libraries(${TARGET_NAME} ${cc_library_DEPS})
426
    else()
427 428 429 430
      message(
        FATAL_ERROR
          "Please specify source files or libraries in cc_library(${TARGET_NAME} ...)."
      )
431
    endif()
432 433
  endif()
endfunction()
L
liaogang 已提交
434

L
liaogang 已提交
435
function(cc_binary TARGET_NAME)
436
  set(options "")
L
liaogang 已提交
437 438
  set(oneValueArgs "")
  set(multiValueArgs SRCS DEPS)
439 440
  cmake_parse_arguments(cc_binary "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
L
liaogang 已提交
441
  add_executable(${TARGET_NAME} ${cc_binary_SRCS})
442
  if(cc_binary_DEPS)
L
liaogang 已提交
443 444
    target_link_libraries(${TARGET_NAME} ${cc_binary_DEPS})
    add_dependencies(${TARGET_NAME} ${cc_binary_DEPS})
Y
Yu Yang 已提交
445
    common_link(${TARGET_NAME})
L
liaogang 已提交
446
  endif()
P
peizhilin 已提交
447 448
  get_property(os_dependency_modules GLOBAL PROPERTY OS_DEPENDENCY_MODULES)
  target_link_libraries(${TARGET_NAME} ${os_dependency_modules})
449 450 451
  if(WITH_ROCM)
    target_link_libraries(${TARGET_NAME} ${ROCM_HIPRTC_LIB})
  endif()
452 453 454

  check_coverage_opt(${TARGET_NAME} ${cc_binary_SRCS})

455
endfunction()
L
liaogang 已提交
456

457
function(cc_test_build TARGET_NAME)
T
tianshuo78520a 已提交
458
  if(WITH_TESTING)
459
    set(oneValueArgs "")
460
    set(multiValueArgs SRCS DEPS)
461 462
    cmake_parse_arguments(cc_test "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
P
peizhilin 已提交
463
    add_executable(${TARGET_NAME} ${cc_test_SRCS})
P
peizhilin 已提交
464 465 466
    if(WIN32)
      if("${cc_test_DEPS};" MATCHES "python;")
        list(REMOVE_ITEM cc_test_DEPS python)
P
peizhilin 已提交
467
        target_link_libraries(${TARGET_NAME} ${PYTHON_LIBRARIES})
P
peizhilin 已提交
468
      endif()
469
    endif()
P
peizhilin 已提交
470
    get_property(os_dependency_modules GLOBAL PROPERTY OS_DEPENDENCY_MODULES)
471 472 473 474
    target_link_libraries(${TARGET_NAME} ${cc_test_DEPS}
                          ${os_dependency_modules} paddle_gtest_main gtest glog)
    add_dependencies(${TARGET_NAME} ${cc_test_DEPS} paddle_gtest_main gtest
                     glog)
Y
Yu Yang 已提交
475
    common_link(${TARGET_NAME})
476 477 478
    if(WITH_ROCM)
      target_link_libraries(${TARGET_NAME} ${ROCM_HIPRTC_LIB})
    endif()
479
    check_coverage_opt(${TARGET_NAME} ${cc_test_SRCS})
480 481 482 483
  endif()
endfunction()

function(cc_test_run TARGET_NAME)
T
tianshuo78520a 已提交
484
  if(WITH_TESTING)
485
    set(oneValueArgs DIR)
486
    set(multiValueArgs COMMAND ARGS)
487 488
    cmake_parse_arguments(cc_test "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
489 490 491
    if(cc_test_DIR STREQUAL "")
      set(cc_test_DIR ${CMAKE_CURRENT_BINARY_DIR})
    endif()
492 493 494
    add_test(
      NAME ${TARGET_NAME}
      COMMAND ${cc_test_COMMAND} ${cc_test_ARGS}
495
      WORKING_DIRECTORY ${cc_test_DIR})
496 497 498 499 500 501
    set_property(TEST ${TARGET_NAME} PROPERTY ENVIRONMENT
                                              FLAGS_cpu_deterministic=true)
    set_property(TEST ${TARGET_NAME} PROPERTY ENVIRONMENT
                                              FLAGS_init_allocated_mem=true)
    set_property(TEST ${TARGET_NAME} PROPERTY ENVIRONMENT
                                              FLAGS_cudnn_deterministic=true)
Y
YUNSHEN XIE 已提交
502
    # No unit test should exceed 2 minutes.
503 504
    if(WIN32)
      set_tests_properties(${TARGET_NAME} PROPERTIES TIMEOUT 150)
505
    endif()
506 507
    if(APPLE)
      set_tests_properties(${TARGET_NAME} PROPERTIES TIMEOUT 20)
508
    endif()
W
wuhuanzhou 已提交
509
  elseif(WITH_TESTING AND NOT TEST ${TARGET_NAME})
510 511
    add_test(NAME ${TARGET_NAME} COMMAND ${CMAKE_COMMAND} -E echo CI skip
                                         ${TARGET_NAME}.)
L
liaogang 已提交
512
  endif()
513 514
endfunction()

515 516
set_property(GLOBAL PROPERTY TEST_SRCS "")
set_property(GLOBAL PROPERTY TEST_NAMES "")
517
function(cc_test TARGET_NAME)
518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565
  if(WITH_TESTING)
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS ARGS)
    cmake_parse_arguments(cc_test "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
    if(WIN32)
      # NOTE(zhiqiu): on windows platform, the symbols should be exported
      # explicitly by __declspec(dllexport), however, there are serveral
      # symbols not exported, and link error occurs.
      # so, the tests are not built against dynamic libraries now.
      cc_test_old(
        ${TARGET_NAME}
        SRCS
        ${cc_test_SRCS}
        DEPS
        ${cc_test_DEPS}
        ARGS
        ${cc_test_ARGS})
    else()
      list(LENGTH cc_test_SRCS len)
      # message("cc_test_SRCS ${cc_test_SRCS}")
      # message("cc_test_ARGS ${cc_test_ARGS}")

      if(${len} GREATER 1)
        message(
          SEND_ERROR
            "The number source file of cc_test should be 1, but got ${len}, the source files are: ${cc_test_SRCS}"
        )
      endif()

      list(LENGTH cc_test_ARGS len_arg)
      if(len_arg GREATER_EQUAL 1)
        set_property(GLOBAL PROPERTY "${TARGET_NAME}_ARGS" "${cc_test_ARGS}")
        #message("${TARGET_NAME}_ARGS arg ${arg}")
      endif()

      get_property(test_srcs GLOBAL PROPERTY TEST_SRCS)
      set(test_srcs ${test_srcs} "${CMAKE_CURRENT_SOURCE_DIR}/${cc_test_SRCS}")
      set_property(GLOBAL PROPERTY TEST_SRCS "${test_srcs}")

      get_property(test_names GLOBAL PROPERTY TEST_NAMES)
      set(test_names ${test_names} ${TARGET_NAME})
      set_property(GLOBAL PROPERTY TEST_NAMES "${test_names}")
    endif()
  endif()
endfunction()

function(cc_test_old TARGET_NAME)
T
tianshuo78520a 已提交
566
  if(WITH_TESTING)
567 568
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS ARGS)
569 570 571
    cmake_parse_arguments(cc_test "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
    cc_test_build(${TARGET_NAME} SRCS ${cc_test_SRCS} DEPS ${cc_test_DEPS})
572 573
    # we dont test hcom op, because it need complex configuration
    # with more than one machine
张春乔 已提交
574
    cc_test_run(${TARGET_NAME} COMMAND ${TARGET_NAME} ARGS ${cc_test_ARGS})
W
wuhuanzhou 已提交
575
  elseif(WITH_TESTING AND NOT TEST ${TARGET_NAME})
576 577
    add_test(NAME ${TARGET_NAME} COMMAND ${CMAKE_COMMAND} -E echo CI skip
                                         ${TARGET_NAME}.)
578
  endif()
579
endfunction()
L
liaogang 已提交
580 581

function(nv_library TARGET_NAME)
582
  if(WITH_GPU)
583
    set(options STATIC static SHARED shared)
584 585
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS)
586 587
    cmake_parse_arguments(nv_library "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
588
    if(nv_library_SRCS)
T
T8T9 已提交
589 590 591 592
      # Attention:
      # 1. cuda_add_library is deprecated after cmake v3.10, use add_library for CUDA please.
      # 2. cuda_add_library does not support ccache.
      # Reference: https://cmake.org/cmake/help/v3.10/module/FindCUDA.html
593
      if(nv_library_SHARED OR nv_library_shared) # build *.so
T
T8T9 已提交
594
        add_library(${TARGET_NAME} SHARED ${nv_library_SRCS})
595
      else()
T
T8T9 已提交
596
        add_library(${TARGET_NAME} STATIC ${nv_library_SRCS})
597
        find_fluid_modules(${TARGET_NAME})
598
        find_phi_modules(${TARGET_NAME})
599
      endif()
600
      if(nv_library_DEPS)
601
        add_dependencies(${TARGET_NAME} ${nv_library_DEPS})
602
        target_link_libraries(${TARGET_NAME} ${nv_library_DEPS})
603
      endif()
L
liaogang 已提交
604 605 606 607
      # cpplint code style
      foreach(source_file ${nv_library_SRCS})
        string(REGEX REPLACE "\\.[^.]*$" "" source ${source_file})
        if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${source}.h)
608 609
          list(APPEND nv_library_HEADERS
               ${CMAKE_CURRENT_SOURCE_DIR}/${source}.h)
L
liaogang 已提交
610 611
        endif()
      endforeach()
612
    else()
613
      if(nv_library_DEPS)
614
        list(REMOVE_DUPLICATES nv_library_DEPS)
615 616 617
        generate_dummy_static_lib(
          LIB_NAME ${TARGET_NAME} FILE_PATH ${target_SRCS} GENERATOR
          "generic.cmake:nv_library")
618

619 620
        target_link_libraries(${TARGET_NAME} ${nv_library_DEPS})
        add_dependencies(${TARGET_NAME} ${nv_library_DEPS})
621 622 623
      else()
        message(FATAL "Please specify source file or library in nv_library.")
      endif()
624
    endif()
625 626 627 628 629
    if((CUDA_VERSION GREATER 9.2)
       AND (CUDA_VERSION LESS 11.0)
       AND (MSVC_VERSION LESS 1910))
      set_target_properties(${TARGET_NAME} PROPERTIES VS_USER_PROPS
                                                      ${WIN_PROPS})
Z
Zhou Wei 已提交
630
    endif()
631
  endif()
632
endfunction()
L
liaogang 已提交
633 634

function(nv_binary TARGET_NAME)
635
  if(WITH_GPU)
636 637 638
    set(options "")
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS)
639 640
    cmake_parse_arguments(nv_binary "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
T
T8T9 已提交
641
    add_executable(${TARGET_NAME} ${nv_binary_SRCS})
642 643 644
    if(nv_binary_DEPS)
      target_link_libraries(${TARGET_NAME} ${nv_binary_DEPS})
      add_dependencies(${TARGET_NAME} ${nv_binary_DEPS})
Y
Yu Yang 已提交
645
      common_link(${TARGET_NAME})
646
    endif()
647
    if((CUDA_VERSION GREATER 9.2)
648 649
       and (CUDA_VERSION LESS 11.0)
       and (MSVC_VERSION LESS 1910))
650 651
      set_target_properties(${TARGET_NAME} PROPERTIES VS_USER_PROPS
                                                      ${WIN_PROPS})
Z
Zhou Wei 已提交
652
    endif()
L
liaogang 已提交
653
  endif()
654
endfunction()
L
liaogang 已提交
655 656

function(nv_test TARGET_NAME)
T
tianshuo78520a 已提交
657
  if(WITH_GPU AND WITH_TESTING)
658 659
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS)
660 661
    cmake_parse_arguments(nv_test "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
T
T8T9 已提交
662 663 664 665 666
    # Attention:
    # 1. cuda_add_executable is deprecated after cmake v3.10, use cuda_add_executable for CUDA please.
    # 2. cuda_add_executable does not support ccache.
    # Reference: https://cmake.org/cmake/help/v3.10/module/FindCUDA.html
    add_executable(${TARGET_NAME} ${nv_test_SRCS})
P
peizhilin 已提交
667
    get_property(os_dependency_modules GLOBAL PROPERTY OS_DEPENDENCY_MODULES)
668
    target_link_libraries(${TARGET_NAME} ${nv_test_DEPS}
669
                          ${os_dependency_modules} paddle_gtest_main phi)
670
    add_dependencies(${TARGET_NAME} ${nv_test_DEPS} paddle_gtest_main)
Y
Yu Yang 已提交
671
    common_link(${TARGET_NAME})
672
    add_test(${TARGET_NAME} ${TARGET_NAME})
673 674 675 676 677 678 679 680 681 682 683
    set_property(TEST ${TARGET_NAME} PROPERTY ENVIRONMENT
                                              FLAGS_cpu_deterministic=true)
    set_property(TEST ${TARGET_NAME} PROPERTY ENVIRONMENT
                                              FLAGS_init_allocated_mem=true)
    set_property(TEST ${TARGET_NAME} PROPERTY ENVIRONMENT
                                              FLAGS_cudnn_deterministic=true)
    if((CUDA_VERSION GREATER 9.2)
       AND (CUDA_VERSION LESS 11.0)
       AND (MSVC_VERSION LESS 1910))
      set_target_properties(${TARGET_NAME} PROPERTIES VS_USER_PROPS
                                                      ${WIN_PROPS})
Z
Zhou Wei 已提交
684
    endif()
L
liaogang 已提交
685
  endif()
686
endfunction()
L
liaogang 已提交
687

688
function(hip_library TARGET_NAME)
689
  if(WITH_ROCM)
690 691 692
    set(options STATIC static SHARED shared)
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS)
693 694
    cmake_parse_arguments(hip_library "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
695
    if(hip_library_SRCS)
696
      # FindHIP.cmake defined hip_add_library, HIP_SOURCE_PROPERTY_FORMAT is requried if no .cu files found
697 698 699 700
      if(NOT (${CMAKE_CURRENT_SOURCE_DIR} MATCHES ".*/operators"
              OR ${CMAKE_CURRENT_SOURCE_DIR} MATCHES ".*/phi/kernels"))
        set_source_files_properties(${hip_library_SRCS}
                                    PROPERTIES HIP_SOURCE_PROPERTY_FORMAT 1)
701
      endif()
702
      if(hip_library_SHARED OR hip_library_shared) # build *.so
703
        hip_add_library(${TARGET_NAME} SHARED ${hip_library_SRCS})
704
      else()
705
        hip_add_library(${TARGET_NAME} STATIC ${hip_library_SRCS})
S
sabreshao 已提交
706
        find_fluid_modules(${TARGET_NAME})
707
        find_phi_modules(${TARGET_NAME})
708
      endif()
709
      if(hip_library_DEPS)
710
        add_dependencies(${TARGET_NAME} ${hip_library_DEPS})
S
sabreshao 已提交
711
        target_link_libraries(${TARGET_NAME} ${hip_library_DEPS})
712 713 714
      endif()
      # cpplint code style
      foreach(source_file ${hip_library_SRCS})
S
sabreshao 已提交
715 716
        string(REGEX REPLACE "\\.[^.]*$" "" source ${source_file})
        if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${source}.h)
717 718
          list(APPEND hip_library_HEADERS
               ${CMAKE_CURRENT_SOURCE_DIR}/${source}.h)
S
sabreshao 已提交
719
        endif()
720
      endforeach()
721
    else()
722
      if(hip_library_DEPS)
723
        list(REMOVE_DUPLICATES hip_library_DEPS)
724 725 726
        generate_dummy_static_lib(
          LIB_NAME ${TARGET_NAME} FILE_PATH ${target_SRCS} GENERATOR
          "generic.cmake:hip_library")
727 728 729

        target_link_libraries(${TARGET_NAME} ${hip_library_DEPS})
        add_dependencies(${TARGET_NAME} ${hip_library_DEPS})
730
      else()
731
        message(FATAL "Please specify source file or library in hip_library.")
732
      endif()
733
    endif()
734
  endif()
735
endfunction()
736 737

function(hip_binary TARGET_NAME)
738
  if(WITH_ROCM)
739 740 741
    set(options "")
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS)
742 743
    cmake_parse_arguments(hip_binary "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
744
    # FindHIP.cmake defined hip_add_executable, HIP_SOURCE_PROPERTY_FORMAT is requried for .cc files
745 746 747 748
    hip_add_executable(${TARGET_NAME} ${hip_binary_SRCS})
    if(hip_binary_DEPS)
      target_link_libraries(${TARGET_NAME} ${hip_binary_DEPS})
      add_dependencies(${TARGET_NAME} ${hip_binary_DEPS})
Y
Yu Yang 已提交
749
      common_link(${TARGET_NAME})
750 751
    endif()
  endif()
752
endfunction()
753 754

function(hip_test TARGET_NAME)
T
tianshuo78520a 已提交
755
  if(WITH_ROCM AND WITH_TESTING)
756 757
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS)
758 759
    cmake_parse_arguments(hip_test "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
760 761
    # FindHIP.cmake defined hip_add_executable,
    # HIP_SOURCE_PROPERTY_FORMAT is requried for .cc files
762 763 764
    hip_add_executable(${TARGET_NAME} ${hip_test_SRCS})
    # "-pthread -ldl -lrt" is defined in CMAKE_CXX_LINK_EXECUTABLE
    target_link_options(${TARGET_NAME} PRIVATE -pthread -ldl -lrt)
P
peizhilin 已提交
765
    get_property(os_dependency_modules GLOBAL PROPERTY OS_DEPENDENCY_MODULES)
766 767 768 769 770 771 772 773
    target_link_libraries(
      ${TARGET_NAME}
      ${hip_test_DEPS}
      paddle_gtest_main
      lod_tensor
      memory
      gtest
      glog
774
      phi
775 776 777 778 779 780 781 782
      ${os_dependency_modules})
    add_dependencies(
      ${TARGET_NAME}
      ${hip_test_DEPS}
      paddle_gtest_main
      lod_tensor
      memory
      gtest
783
      phi
784
      glog)
Y
Yu Yang 已提交
785
    common_link(${TARGET_NAME})
786
    add_test(${TARGET_NAME} ${TARGET_NAME})
787 788 789 790 791 792
    set_property(TEST ${TARGET_NAME} PROPERTY ENVIRONMENT
                                              FLAGS_cpu_deterministic=true)
    set_property(TEST ${TARGET_NAME} PROPERTY ENVIRONMENT
                                              FLAGS_init_allocated_mem=true)
    set_property(TEST ${TARGET_NAME} PROPERTY ENVIRONMENT
                                              FLAGS_cudnn_deterministic=true)
793 794 795 796 797 798
    set_property(
      TEST ${TARGET_NAME}
      PROPERTY
        ENVIRONMENT
        "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/python/paddle/libs:$LD_LIBRARY_PATH"
    )
799
  endif()
800
endfunction()
801

L
Liu-xiandong 已提交
802
function(xpu_library TARGET_NAME)
803
  if(WITH_XPU_KP)
L
Liu-xiandong 已提交
804 805 806
    set(options STATIC static SHARED shared)
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS)
807 808
    cmake_parse_arguments(xpu_library "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
L
Liu-xiandong 已提交
809 810

    if(xpu_library_SRCS)
811 812 813
      if(xpu_library_SHARED OR xpu_library_shared) # build *.so
        message(
          FATAL_ERROR "XPU kernel currently does not support dynamic links")
L
Liu-xiandong 已提交
814
      else()
815 816
        xpu_add_library(${TARGET_NAME} STATIC ${xpu_library_SRCS} DEPENDS
                        ${xpu_library_DEPS})
L
Liu-xiandong 已提交
817
        find_fluid_modules(${TARGET_NAME})
818
        find_phi_modules(${TARGET_NAME})
L
Liu-xiandong 已提交
819
      endif()
820
      if(xpu_library_DEPS)
L
Liu-xiandong 已提交
821 822 823 824 825 826 827
        add_dependencies(${TARGET_NAME} ${xpu_library_DEPS})
        target_link_libraries(${TARGET_NAME} ${xpu_library_DEPS})
      endif()
      # cpplint code style
      foreach(source_file ${xpu_library_SRCS})
        string(REGEX REPLACE "\\.[^.]*$" "" source ${source_file})
        if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${source}.h)
828 829
          list(APPEND xpu_library_HEADERS
               ${CMAKE_CURRENT_SOURCE_DIR}/${source}.h)
L
Liu-xiandong 已提交
830 831
        endif()
      endforeach()
832
    else()
833
      if(xpu_library_DEPS)
L
Liu-xiandong 已提交
834
        list(REMOVE_DUPLICATES xpu_library_DEPS)
835 836 837
        generate_dummy_static_lib(
          LIB_NAME ${TARGET_NAME} FILE_PATH ${target_SRCS} GENERATOR
          "generic.cmake:xpu_library")
L
Liu-xiandong 已提交
838 839 840 841 842
        target_link_libraries(${TARGET_NAME} ${xpu_library_DEPS})
        add_dependencies(${TARGET_NAME} ${xpu_library_DEPS})
      else()
        message(FATAL "Please specify source file or library in xpu_library.")
      endif()
843
    endif()
L
Liu-xiandong 已提交
844
  endif()
845
endfunction()
L
Liu-xiandong 已提交
846 847

function(xpu_binary TARGET_NAME)
848
  if(WITH_XPU_KP)
L
Liu-xiandong 已提交
849 850 851
    set(options "")
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS)
852 853
    cmake_parse_arguments(xpu_binary "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
L
Liu-xiandong 已提交
854 855 856 857 858 859 860
    add_executable(${TARGET_NAME} ${xpu_binary_SRCS})
    if(xpu_binary_DEPS)
      target_link_libraries(${TARGET_NAME} ${xpu_binary_DEPS})
      add_dependencies(${TARGET_NAME} ${xpu_binary_DEPS})
      common_link(${TARGET_NAME})
    endif()
  endif()
861
endfunction()
L
Liu-xiandong 已提交
862 863

function(xpu_test TARGET_NAME)
T
tianshuo78520a 已提交
864
  if(WITH_XPU_KP AND WITH_TESTING)
L
Liu-xiandong 已提交
865 866
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS)
867 868
    cmake_parse_arguments(xpu_test "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
L
Liu-xiandong 已提交
869 870 871 872
    add_executable(${TARGET_NAME} ${xpu_test_SRCS})
    # "-pthread -ldl -lrt" is defined in CMAKE_CXX_LINK_EXECUTABLE
    target_link_options(${TARGET_NAME} PRIVATE -pthread -ldl -lrt)
    get_property(os_dependency_modules GLOBAL PROPERTY OS_DEPENDENCY_MODULES)
873 874 875 876 877 878 879
    target_link_libraries(
      ${TARGET_NAME}
      ${xpu_test_DEPS}
      paddle_gtest_main
      lod_tensor
      memory
      gtest
880
      phi
881 882 883 884 885 886 887 888 889
      glog
      ${os_dependency_modules})
    add_dependencies(
      ${TARGET_NAME}
      ${xpu_test_DEPS}
      paddle_gtest_main
      lod_tensor
      memory
      gtest
890
      phi
891
      glog)
L
Liu-xiandong 已提交
892 893
    common_link(${TARGET_NAME})
    add_test(${TARGET_NAME} ${TARGET_NAME})
894 895 896 897 898 899
    set_property(TEST ${TARGET_NAME} PROPERTY ENVIRONMENT
                                              FLAGS_cpu_deterministic=true)
    set_property(TEST ${TARGET_NAME} PROPERTY ENVIRONMENT
                                              FLAGS_init_allocated_mem=true)
    set_property(TEST ${TARGET_NAME} PROPERTY ENVIRONMENT
                                              FLAGS_cudnn_deterministic=true)
L
Liu-xiandong 已提交
900
  endif()
901
endfunction()
L
Liu-xiandong 已提交
902

L
liaogang 已提交
903
function(go_library TARGET_NAME)
L
liaogang 已提交
904
  set(options STATIC static SHARED shared)
L
liaogang 已提交
905
  set(oneValueArgs "")
L
liaogang 已提交
906
  set(multiValueArgs DEPS)
907 908
  cmake_parse_arguments(go_library "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
L
liaogang 已提交
909

910
  if(go_library_SHARED OR go_library_shared)
L
liaogang 已提交
911
    set(BUILD_MODE "-buildmode=c-shared")
912 913 914
    set(${TARGET_NAME}_LIB_NAME
        "${CMAKE_SHARED_LIBRARY_PREFIX}${TARGET_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}"
        CACHE STRING "output library name for target ${TARGET_NAME}")
L
liaogang 已提交
915 916
  else()
    set(BUILD_MODE "-buildmode=c-archive")
917 918 919
    set(${TARGET_NAME}_LIB_NAME
        "${CMAKE_STATIC_LIBRARY_PREFIX}${TARGET_NAME}${CMAKE_STATIC_LIBRARY_SUFFIX}"
        CACHE STRING "output library name for target ${TARGET_NAME}")
L
liaogang 已提交
920
  endif()
L
liaogang 已提交
921 922

  set(dummyfile ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}_dummy.c)
923 924 925

  # This custom command will always run since it depends on a not
  # existing file.
926 927
  add_custom_command(OUTPUT dummy_rebulid_${TARGET_NAME} COMMAND cmake -E touch
                                                                 ${dummyfile})
928 929 930
  # Create a custom target that depends on the custom command output
  # file, so the custom command can be referenced as a dependency by
  # `add_dependencies`.
931
  add_custom_target(rebuild_${TARGET_NAME} DEPENDS dummy_rebulid_${TARGET_NAME})
932 933

  # Add dummy code to support `make target_name` under Terminal Command
934 935 936
  file(WRITE ${dummyfile}
       "const char *dummy_${TARGET_NAME} = \"${dummyfile}\";")
  if(go_library_SHARED OR go_library_shared)
L
liaogang 已提交
937 938 939 940
    add_library(${TARGET_NAME} SHARED ${dummyfile})
  else()
    add_library(${TARGET_NAME} STATIC ${dummyfile})
  endif()
941 942
  if(go_library_DEPS)
    add_dependencies(${TARGET_NAME} ${go_library_DEPS})
Y
Yu Yang 已提交
943
    common_link(${TARGET_NAME})
944
  endif()
L
liaogang 已提交
945

946 947 948 949 950 951
  # The "source file" of the library is `${dummyfile}` which never
  # change, so the target will never rebuild. Make the target depends
  # on the custom command that touches the library "source file", so
  # rebuild will always happen.
  add_dependencies(${TARGET_NAME} rebuild_${TARGET_NAME})

952 953 954
  set(${TARGET_NAME}_LIB_PATH
      "${CMAKE_CURRENT_BINARY_DIR}/${${TARGET_NAME}_LIB_NAME}"
      CACHE STRING "output library path for target ${TARGET_NAME}")
H
Helin Wang 已提交
955

956 957 958 959 960 961
  file(
    GLOB GO_SOURCE
    RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
    "*.go")
  string(REPLACE "${PADDLE_GO_PATH}/" "" CMAKE_CURRENT_SOURCE_REL_DIR
                 ${CMAKE_CURRENT_SOURCE_DIR})
962

963 964 965
  add_custom_command(
    TARGET ${TARGET_NAME}
    POST_BUILD
H
Helin Wang 已提交
966
    COMMAND rm "${${TARGET_NAME}_LIB_PATH}"
967
    # Golang build source code
968 969 970 971
    COMMAND
      GOPATH=${GOPATH} ${CMAKE_Go_COMPILER} build ${BUILD_MODE} -o
      "${${TARGET_NAME}_LIB_PATH}"
      "./${CMAKE_CURRENT_SOURCE_REL_DIR}/${GO_SOURCE}"
W
wuyi05 已提交
972
    # must run under GOPATH
973
    WORKING_DIRECTORY "${PADDLE_IN_GOPATH}/go")
974
  add_dependencies(${TARGET_NAME} go_vendor)
975
endfunction()
L
liaogang 已提交
976 977 978 979 980

function(go_binary TARGET_NAME)
  set(options OPTIONAL)
  set(oneValueArgs "")
  set(multiValueArgs SRCS DEPS)
981 982 983 984
  cmake_parse_arguments(go_binary "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
  string(REPLACE "${PADDLE_GO_PATH}/" "" CMAKE_CURRENT_SOURCE_REL_DIR
                 ${CMAKE_CURRENT_SOURCE_DIR})
W
wuyi05 已提交
985

986 987 988 989 990 991
  add_custom_command(
    OUTPUT ${TARGET_NAME}_timestamp
    COMMAND
      env GOPATH=${GOPATH} ${CMAKE_Go_COMPILER} build -o
      "${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}"
      "./${CMAKE_CURRENT_SOURCE_REL_DIR}/${go_binary_SRCS}"
G
gongweibao 已提交
992
    WORKING_DIRECTORY "${PADDLE_IN_GOPATH}/go")
993 994 995
  add_custom_target(
    ${TARGET_NAME} ALL DEPENDS go_vendor ${TARGET_NAME}_timestamp
                               ${go_binary_DEPS})
L
liaogang 已提交
996
  install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME} DESTINATION bin)
997 998 999

  check_coverage_opt(${TARGET_NAME} ${go_binary_SRCS})

1000
endfunction()
L
liaogang 已提交
1001 1002 1003 1004

function(go_test TARGET_NAME)
  set(options OPTIONAL)
  set(oneValueArgs "")
1005
  set(multiValueArgs DEPS)
1006 1007 1008 1009
  cmake_parse_arguments(go_test "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
  string(REPLACE "${PADDLE_GO_PATH}" "" CMAKE_CURRENT_SOURCE_REL_DIR
                 ${CMAKE_CURRENT_SOURCE_DIR})
1010
  add_custom_target(${TARGET_NAME} ALL DEPENDS go_vendor ${go_test_DEPS})
1011 1012 1013 1014 1015 1016 1017
  add_custom_command(
    TARGET ${TARGET_NAME}
    POST_BUILD
    COMMAND
      env GOPATH=${GOPATH} ${CMAKE_Go_COMPILER} test -race -c -o
      "${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}"
      ".${CMAKE_CURRENT_SOURCE_REL_DIR}"
1018
    WORKING_DIRECTORY "${PADDLE_IN_GOPATH}/go")
1019 1020
  add_test(
    NAME ${TARGET_NAME}
1021
    COMMAND ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}
1022
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
1023
endfunction()
Y
Yu Yang 已提交
1024

1025 1026 1027 1028 1029 1030
# Modification of standard 'protobuf_generate_cpp()' with protobuf-lite support
# Usage:
#   paddle_protobuf_generate_cpp(<proto_srcs> <proto_hdrs> <proto_files>)

function(paddle_protobuf_generate_cpp SRCS HDRS)
  if(NOT ARGN)
1031 1032 1033
    message(
      SEND_ERROR
        "Error: paddle_protobuf_generate_cpp() called without any proto files")
1034 1035 1036 1037 1038 1039 1040 1041 1042
    return()
  endif()

  set(${SRCS})
  set(${HDRS})

  foreach(FIL ${ARGN})
    get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
    get_filename_component(FIL_WE ${FIL} NAME_WE)
C
chengduo 已提交
1043

1044 1045 1046 1047
    set(_protobuf_protoc_src "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc")
    set(_protobuf_protoc_hdr "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h")
    list(APPEND ${SRCS} "${_protobuf_protoc_src}")
    list(APPEND ${HDRS} "${_protobuf_protoc_hdr}")
C
chengduo 已提交
1048

1049
    add_custom_command(
1050
      OUTPUT "${_protobuf_protoc_src}" "${_protobuf_protoc_hdr}"
1051
      COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}"
R
risemeup1 已提交
1052 1053
      COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} -I${PADDLE_SOURCE_DIR} --cpp_out
              "${PADDLE_BINARY_DIR}" ${ABS_FIL}
1054 1055
      # Set `EXTERN_PROTOBUF_DEPEND` only if need to compile `protoc.exe`.
      DEPENDS ${ABS_FIL} ${EXTERN_PROTOBUF_DEPEND}
1056
      COMMENT "Running C++ protocol buffer compiler on ${FIL}"
1057
      VERBATIM)
1058 1059 1060
  endforeach()

  set_source_files_properties(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE)
1061 1062 1063 1064 1065 1066
  set(${SRCS}
      ${${SRCS}}
      PARENT_SCOPE)
  set(${HDRS}
      ${${HDRS}}
      PARENT_SCOPE)
1067 1068
endfunction()

Y
Yu Yang 已提交
1069
function(proto_library TARGET_NAME)
Y
Yu Yang 已提交
1070
  set(oneValueArgs "")
Y
Yu Yang 已提交
1071
  set(multiValueArgs SRCS DEPS)
1072 1073
  cmake_parse_arguments(proto_library "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
Y
Yu Yang 已提交
1074 1075
  set(proto_srcs)
  set(proto_hdrs)
1076
  paddle_protobuf_generate_cpp(proto_srcs proto_hdrs ${proto_library_SRCS})
1077 1078 1079 1080
  cc_library(
    ${TARGET_NAME}
    SRCS ${proto_srcs}
    DEPS ${proto_library_DEPS} protobuf)
1081
  add_dependencies(extern_xxhash ${TARGET_NAME})
Y
Yu Yang 已提交
1082
endfunction()
1083 1084 1085 1086

function(py_proto_compile TARGET_NAME)
  set(oneValueArgs "")
  set(multiValueArgs SRCS)
1087 1088
  cmake_parse_arguments(py_proto_compile "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
1089 1090
  set(py_srcs)
  protobuf_generate_python(py_srcs ${py_proto_compile_SRCS})
1091
  add_custom_target(${TARGET_NAME} ALL DEPENDS ${py_srcs} protobuf)
1092
endfunction()
L
liaogang 已提交
1093 1094 1095

function(py_test TARGET_NAME)
  if(WITH_TESTING)
1096
    set(options "")
L
liaogang 已提交
1097
    set(oneValueArgs "")
1098
    set(multiValueArgs SRCS DEPS ARGS ENVS)
1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113
    cmake_parse_arguments(py_test "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})

    if(WITH_COVERAGE AND NOT (WITH_INCREMENTAL_COVERAGE
                              AND "$ENV{PADDLE_GIT_DIFF_PY_FILE}" STREQUAL ""))
      add_test(
        NAME ${TARGET_NAME}
        COMMAND
          ${CMAKE_COMMAND} -E env FLAGS_init_allocated_mem=true
          FLAGS_cudnn_deterministic=true FLAGS_cpu_deterministic=true
          PYTHONPATH=${PADDLE_BINARY_DIR}/python ${py_test_ENVS}
          COVERAGE_FILE=${PADDLE_BINARY_DIR}/python-coverage.data
          ${PYTHON_EXECUTABLE} -m coverage run --branch -p ${py_test_SRCS}
          ${py_test_ARGS}
        WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
1114
    else()
1115 1116 1117 1118 1119 1120 1121 1122
      add_test(
        NAME ${TARGET_NAME}
        COMMAND
          ${CMAKE_COMMAND} -E env FLAGS_init_allocated_mem=true
          FLAGS_cudnn_deterministic=true FLAGS_cpu_deterministic=true
          ${py_test_ENVS} ${PYTHON_EXECUTABLE} -u ${py_test_SRCS}
          ${py_test_ARGS}
        WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
1123
    endif()
1124

1125 1126
    if(WIN32)
      set_tests_properties(${TARGET_NAME} PROPERTIES TIMEOUT 150)
1127
    endif()
1128 1129
    if(APPLE)
      set_tests_properties(${TARGET_NAME} PROPERTIES TIMEOUT 20)
1130
    endif()
1131

L
liaogang 已提交
1132 1133
  endif()
endfunction()
武毅 已提交
1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146

# grpc_library generate grpc code using grpc_cpp_plugin and protoc
# then build the generated protobuf code and grpc code with your
# implementation source codes together. Use SRCS argument for your
# implementation source files and PROTO argument for your .proto
# files.
#
# Usage: grpc_library(my_target SRCS my_client.cc PROTO my_target.proto DEPS my_dep)

function(grpc_library TARGET_NAME)
  set(oneValueArgs PROTO)
  set(multiValueArgs SRCS DEPS)
  set(options "")
1147 1148
  cmake_parse_arguments(grpc_library "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
武毅 已提交
1149 1150 1151 1152 1153 1154 1155

  message(STATUS "generating grpc ${grpc_library_PROTO}")

  get_filename_component(ABS_PROTO ${grpc_library_PROTO} ABSOLUTE)
  get_filename_component(PROTO_WE ${grpc_library_PROTO} NAME_WE)
  get_filename_component(PROTO_PATH ${ABS_PROTO} PATH)

1156
  # FIXME(putcn): the follwoing line is supposed to generate *.pb.h and cc, but
C
chengduo 已提交
1157
  # somehow it didn't. line 602 to 604 is to patching this. Leaving this here
X
Xi Chen 已提交
1158
  # for now to enable dist CI.
1159
  paddle_protobuf_generate_cpp(grpc_proto_srcs grpc_proto_hdrs "${ABS_PROTO}")
武毅 已提交
1160 1161 1162 1163 1164
  set(grpc_grpc_srcs "${CMAKE_CURRENT_BINARY_DIR}/${PROTO_WE}.grpc.pb.cc")
  set(grpc_grpc_hdrs "${CMAKE_CURRENT_BINARY_DIR}/${PROTO_WE}.grpc.pb.h")
  cc_library("${TARGET_NAME}_proto" SRCS "${grpc_proto_srcs}")

  add_custom_command(
1165 1166 1167 1168 1169 1170 1171 1172
    OUTPUT "${grpc_grpc_srcs}" "${grpc_grpc_hdrs}"
    COMMAND
      ${PROTOBUF_PROTOC_EXECUTABLE} ARGS --grpc_out
      "${CMAKE_CURRENT_BINARY_DIR}" -I "${PROTO_PATH}"
      --plugin=protoc-gen-grpc="${GRPC_CPP_PLUGIN}" "${ABS_PROTO}"
    COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} ARGS --cpp_out
            "${CMAKE_CURRENT_BINARY_DIR}" -I "${PROTO_PATH}" "${ABS_PROTO}"
    DEPENDS "${ABS_PROTO}" ${PROTOBUF_PROTOC_EXECUTABLE} extern_grpc)
武毅 已提交
1173 1174 1175 1176 1177 1178

  # FIXME(typhoonzero): grpc generated code do not generate virtual-dtor, mark it
  # as compiler warnings instead of error. Should try remove the warnings also.
  set_source_files_properties(
    ${grpc_grpc_srcs}
    PROPERTIES
1179 1180 1181
      COMPILE_FLAGS
      "-Wno-non-virtual-dtor -Wno-error=non-virtual-dtor -Wno-error=delete-non-virtual-dtor"
  )
武毅 已提交
1182 1183 1184 1185 1186
  cc_library("${TARGET_NAME}_grpc" SRCS "${grpc_grpc_srcs}")

  set_source_files_properties(
    ${grpc_library_SRCS}
    PROPERTIES
1187 1188 1189 1190 1191 1192 1193
      COMPILE_FLAGS
      "-Wno-non-virtual-dtor -Wno-error=non-virtual-dtor -Wno-error=delete-non-virtual-dtor"
  )
  cc_library(
    "${TARGET_NAME}"
    SRCS "${grpc_library_SRCS}"
    DEPS "${TARGET_NAME}_grpc" "${TARGET_NAME}_proto" "${grpc_library_DEPS}")
武毅 已提交
1194
endfunction()
G
gongweibao 已提交
1195 1196 1197 1198 1199

function(brpc_library TARGET_NAME)
  set(oneValueArgs PROTO)
  set(multiValueArgs SRCS DEPS)
  set(options "")
1200 1201
  cmake_parse_arguments(brpc_library "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
G
gongweibao 已提交
1202 1203 1204 1205 1206 1207 1208

  message(STATUS "generating brpc ${brpc_library_PROTO}")

  get_filename_component(ABS_PROTO ${brpc_library_PROTO} ABSOLUTE)
  get_filename_component(PROTO_WE ${brpc_library_PROTO} NAME_WE)
  get_filename_component(PROTO_PATH ${ABS_PROTO} PATH)

1209
  paddle_protobuf_generate_cpp(brpc_proto_srcs brpc_proto_hdrs "${ABS_PROTO}")
G
gongweibao 已提交
1210
  cc_library("${TARGET_NAME}_proto" SRCS "${brpc_proto_srcs}")
1211 1212 1213 1214
  cc_library(
    "${TARGET_NAME}"
    SRCS "${brpc_library_SRCS}"
    DEPS "${TARGET_NAME}_proto" "${brpc_library_DEPS}")
G
gongweibao 已提交
1215
endfunction()
1216

1217 1218 1219
# copy_if_different from src_file to dst_file At the beginning of the build.
function(copy_if_different src_file dst_file)
  get_filename_component(FILE_NAME ${dst_file} NAME_WE)
1220

1221
  # this is a dummy target for custom command, should always be run firstly to update ${dst_file}
1222 1223 1224 1225 1226
  add_custom_target(
    copy_${FILE_NAME}_command ALL
    COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src_file} ${dst_file}
    COMMENT "copy_if_different ${dst_file}"
    VERBATIM)
1227 1228

  add_dependencies(extern_glog copy_${FILE_NAME}_command)
1229
endfunction()
1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240

# create a dummy source file, then create a static library.
# LIB_NAME should be the static lib name.
# FILE_PATH should be the dummy source file path.
# GENERATOR should be the file name invoke this function.
# CONTENT should be some helpful info.
# example: generate_dummy_static_lib(mylib FILE_PATH /path/to/dummy.c GENERATOR mylib.cmake CONTENT "helpful info")
function(generate_dummy_static_lib)
  set(options "")
  set(oneValueArgs LIB_NAME FILE_PATH GENERATOR CONTENT)
  set(multiValueArgs "")
1241 1242
  cmake_parse_arguments(dummy "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
1243 1244 1245 1246 1247 1248 1249 1250 1251 1252
  if(NOT dummy_LIB_NAME)
    message(FATAL_ERROR "You must provide a static lib name.")
  endif()
  if(NOT dummy_FILE_PATH)
    set(dummy_FILE_PATH "${CMAKE_CURRENT_BINARY_DIR}/${dummy_LIB_NAME}_dummy.c")
  endif()
  if(NOT dummy_GENERATOR)
    message(FATAL_ERROR "You must provide a generator file name.")
  endif()
  if(NOT dummy_CONTENT)
1253
    set(dummy_CONTENT "${dummy_LIB_NAME}_dummy.c for lib ${dummy_LIB_NAME}")
1254 1255
  endif()

1256 1257
  configure_file(${PROJECT_SOURCE_DIR}/cmake/dummy.c.in ${dummy_FILE_PATH}
                 @ONLY)
1258 1259 1260
  add_library(${dummy_LIB_NAME} STATIC ${dummy_FILE_PATH})
endfunction()

1261
function(math_library TARGET)
1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273
  # math_library is a function to create math library.
  # The interface is the same as cc_library.
  # But it handle split GPU/CPU code and link some common library.
  set(cc_srcs)
  set(cu_srcs)
  set(hip_srcs)
  set(math_common_deps device_context framework_proto enforce)
  if(WITH_GPU)
    if(${CMAKE_CUDA_COMPILER_VERSION} LESS 11.0)
      list(APPEND math_common_deps cub)
    else()
      list(APPEND math_common_deps)
1274
    endif()
1275 1276 1277 1278
  endif()
  set(multiValueArgs DEPS)
  cmake_parse_arguments(math_library "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
1279

1280 1281 1282 1283 1284 1285 1286 1287 1288
  if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${TARGET}.cc)
    list(APPEND cc_srcs ${TARGET}.cc)
  endif()
  if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${TARGET}.cu)
    list(APPEND cu_srcs ${TARGET}.cu)
  endif()
  if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${TARGET}.cu.cc)
    list(APPEND cu_srcs ${TARGET}.cu.cc)
  endif()
1289

1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306
  list(LENGTH cc_srcs cc_srcs_len)
  if(WITH_GPU)
    nv_library(
      ${TARGET}
      SRCS ${cc_srcs} ${cu_srcs}
      DEPS ${math_library_DEPS} ${math_common_deps})
  elseif(WITH_ROCM)
    hip_library(
      ${TARGET}
      SRCS ${cc_srcs} ${cu_srcs}
      DEPS ${math_library_DEPS} ${math_common_deps})
  elseif(${cc_srcs_len} GREATER 0)
    cc_library(
      ${TARGET}
      SRCS ${cc_srcs}
      DEPS ${math_library_DEPS} ${math_common_deps})
  endif()
1307
endfunction()