generic.cmake 47.4 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
set_property(GLOBAL PROPERTY PHI_MODULES "")
# find all phi modules is used for paddle static library
123
# for building inference libs
124
function(find_phi_modules TARGET_NAME)
125
  get_filename_component(__target_path ${TARGET_NAME} ABSOLUTE)
126 127
  string(REGEX REPLACE "^${PADDLE_SOURCE_DIR}/" "" __target_path
                       ${__target_path})
128
  string(FIND "${__target_path}" "phi" pos)
129
  if(pos GREATER 1)
130 131 132
    get_property(phi_modules GLOBAL PROPERTY PHI_MODULES)
    set(phi_modules ${phi_modules} ${TARGET_NAME})
    set_property(GLOBAL PROPERTY PHI_MODULES "${phi_modules}")
133
  endif()
134
endfunction()
135

Y
Yu Yang 已提交
136
function(common_link TARGET_NAME)
137
  if(WITH_PROFILER)
Y
Yu Yang 已提交
138 139 140 141
    target_link_libraries(${TARGET_NAME} gperftools::profiler)
  endif()
endfunction()

D
dzhwinter 已提交
142 143 144 145 146
# 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)
147 148
  string(REGEX REPLACE "^${PADDLE_SOURCE_DIR}/" "" __target_path
                       ${__target_path})
D
dzhwinter 已提交
149 150 151 152 153 154
  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()
155
endfunction()
D
dzhwinter 已提交
156

157 158 159 160 161 162 163 164 165 166 167 168
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)
169 170
      if((${listlen} GREATER ${dummy_limit}) OR (${dummy_offset} EQUAL
                                                 ${libs_len}))
171 172
        merge_static_libs(${TARGET_NAME}_dummy_${dummy_index} ${dummy_list})
        set(dummy_list)
173 174 175
        list(APPEND ${TARGET_NAME}_dummy_list
             ${TARGET_NAME}_dummy_${dummy_index})
        math(EXPR dummy_index "${dummy_index}+1")
176
      endif()
177
      math(EXPR dummy_offset "${dummy_offset}+1")
178 179 180 181 182 183 184
    endforeach()
    merge_static_libs(${TARGET_NAME} ${${TARGET_NAME}_dummy_list})
  else()
    merge_static_libs(${TARGET_NAME} ${libs})
  endif()
endfunction()

185 186 187 188
function(create_dummy_static_lib TARGET_NAME)
  set(options "")
  set(oneValueArgs "")
  set(multiValueArgs LIBS DEPS LIMIT)
189 190
  cmake_parse_arguments(merge "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
191 192 193 194 195 196 197 198 199 200

  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)
  foreach(lib ${merge_LIBS})
    list(APPEND merge_list ${lib})
    list(LENGTH merge_list listlen)
201 202 203
    if((${listlen} GREATER ${limit}) OR (${offset} EQUAL ${libs_len}))
      message(
        "Merge and generate static library: ${TARGET_NAME}_static_${index}")
204 205 206 207 208 209
      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})
210
      math(EXPR index "${index}+1")
211
    endif()
212
    math(EXPR offset "${offset}+1")
213 214 215 216
  endforeach()
  cc_library(${TARGET_NAME} DEPS ${${TARGET_NAME}_list})
endfunction()

217
function(merge_static_libs TARGET_NAME)
L
liaogang 已提交
218 219
  set(libs ${ARGN})
  list(REMOVE_DUPLICATES libs)
220

221
  # Get all propagation dependencies from the merged libraries
L
liaogang 已提交
222
  foreach(lib ${libs})
223 224
    list(APPEND libs_deps ${${lib}_LIB_DEPENDS})
  endforeach()
225 226 227
  if(libs_deps)
    list(REMOVE_DUPLICATES libs_deps)
  endif()
228

229 230 231 232
  # 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)
233

234 235 236
  # 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).
237 238
  add_custom_command(
    OUTPUT ${target_SRCS}
239 240
    COMMAND ${CMAKE_COMMAND} -E touch ${target_SRCS}
    DEPENDS ${libs})
241 242 243 244

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

247 248
  # OSX: use 'libtool' to merge archives
  if(APPLE)
249 250 251 252
    foreach(lib ${libs})
      # Get the file names of the libraries to be merged
      set(libfiles ${libfiles} $<TARGET_FILE:${lib}>)
    endforeach()
253 254 255
    add_custom_command(
      TARGET ${TARGET_NAME}
      POST_BUILD
256
      COMMENT "Merge and generate static lib: lib${TARGET_NAME}.a"
257
      COMMAND rm "${CMAKE_CURRENT_BINARY_DIR}/lib${TARGET_NAME}.a"
258 259
      COMMAND /usr/bin/libtool -static -o
              "${CMAKE_CURRENT_BINARY_DIR}/lib${TARGET_NAME}.a" ${libfiles})
260
  endif()
261

262 263
  # LINUX: use "ar" to extract objects and re-add to a common lib
  if(LINUX)
264 265 266 267 268 269 270
    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)
271
    file(WRITE ${mri_file} "create ${ABS_MERGE_LIB_PATH}\n")
272

273
    foreach(lib ${libs})
274 275 276 277
      get_property(
        ABS_LIB_PATH
        TARGET ${lib}
        PROPERTY LOCATION)
278
      file(APPEND ${mri_file} "addlib ${ABS_LIB_PATH}\n")
L
liaogang 已提交
279
    endforeach()
280
    file(APPEND ${mri_file} "save\nend\n")
281

282 283 284 285 286 287
    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}>")
288
  endif()
D
dzhwinter 已提交
289

290 291
  # Windows do not support gcc/nvcc combined compiling. Use msvc 'lib.exe' to merge libs.
  if(WIN32)
D
dzhwinter 已提交
292 293 294
    foreach(lib ${libs})
      set(libfiles ${libfiles} $<TARGET_FILE:${lib}>)
    endforeach()
295
    # msvc compiler will put libarary in directory of "/Release/xxxlib" by default
296 297 298
    add_custom_command(
      TARGET ${TARGET_NAME}
      POST_BUILD
299
      COMMENT "Merge and generate static lib: lib${TARGET_NAME}.lib"
300
      COMMAND cmake -E make_directory $<TARGET_FILE_DIR:${TARGET_NAME}>
301
      COMMAND lib /OUT:$<TARGET_FILE:${TARGET_NAME}> ${libfiles})
302 303
  endif()
endfunction()
304

305
function(check_coverage_opt TARGET_NAME SRCS)
306
  if(WITH_COVERAGE AND WITH_INCREMENTAL_COVERAGE)
307
    # if pybind.cc add '-g -O0 -fprofile-arcs -ftest-coverage' only, some testcase will fail.
308 309
    if("$ENV{PADDLE_GIT_DIFF_H_FILE}" STREQUAL ""
       AND (NOT ("$ENV{PADDLE_GIT_DIFF_CC_FILE}" MATCHES "pybind.cc")))
310
      if(NOT ("$ENV{PADDLE_GIT_DIFF_CC_FILE}" STREQUAL ""))
311 312
        string(REPLACE "," ";" CC_FILE_LIST $ENV{PADDLE_GIT_DIFF_CC_FILE})
        set(use_coverage_opt FALSE)
313
        foreach(cc_file ${CC_FILE_LIST})
314 315 316 317
          if("${SRCS};" MATCHES "${cc_file}")
            set(use_coverage_opt TRUE)
            break()
          endif()
318
        endforeach()
319

320
        if(use_coverage_opt)
321
          message(STATUS "cc changed, add coverage opt for ${TARGET_NAME}")
322 323
          target_compile_options(${TARGET_NAME} PRIVATE -g -O0 -fprofile-arcs
                                                        -ftest-coverage)
324
          target_link_libraries(${TARGET_NAME} -fprofile-arcs)
325 326 327 328 329
          get_target_property(WH_TARGET_COMPILE_OPTIONS ${TARGET_NAME}
                              COMPILE_OPTIONS)
          message(
            STATUS "property for ${TARGET_NAME} is ${WH_TARGET_COMPILE_OPTIONS}"
          )
330 331 332 333
        endif()
      endif()
    endif()
  endif()
334
endfunction()
335

L
liaogang 已提交
336
function(cc_library TARGET_NAME)
337
  set(options STATIC static SHARED shared INTERFACE interface)
L
liaogang 已提交
338 339
  set(oneValueArgs "")
  set(multiValueArgs SRCS DEPS)
340 341
  cmake_parse_arguments(cc_library "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
D
dzhwinter 已提交
342
  if(WIN32)
343 344 345 346
    # 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}")
347
  endif()
L
Liu Yiqun 已提交
348
  if(cc_library_SRCS)
349 350 351 352 353 354 355 356 357 358 359
    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 已提交
360
    if(cc_library_DEPS)
361
      # Don't need link libwarpctc.so
L
Liu Yiqun 已提交
362
      if("${cc_library_DEPS};" MATCHES "warpctc;")
363 364 365
        list(REMOVE_ITEM cc_library_DEPS warpctc)
        add_dependencies(${TARGET_NAME} warpctc)
      endif()
366 367 368 369 370 371 372
      # Only deps libmklml.so, not link
      if("${cc_library_DEPS};" MATCHES "mklml;")
        list(REMOVE_ITEM cc_library_DEPS mklml)
        if(NOT "${TARGET_NAME}" MATCHES "dynload_mklml")
          list(APPEND cc_library_DEPS dynload_mklml)
        endif()
        add_dependencies(${TARGET_NAME} mklml)
P
peizhilin 已提交
373 374
        if(WIN32)
          target_link_libraries(${TARGET_NAME} ${MKLML_IOMP_LIB})
375
        else()
376 377
          target_link_libraries(${TARGET_NAME}
                                "-L${MKLML_LIB_DIR} -liomp5 -Wl,--as-needed")
378
        endif()
379
      endif()
T
update  
typhoonzero 已提交
380 381 382 383 384
      # 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 已提交
385 386 387 388
        if(WIN32)
          target_link_libraries(${TARGET_NAME} ${PYTHON_LIBRARIES})
        else()
          target_link_libraries(${TARGET_NAME} "-Wl,-undefined,dynamic_lookup")
389
        endif()
T
update  
typhoonzero 已提交
390
      endif()
391
      target_link_libraries(${TARGET_NAME} ${cc_library_DEPS})
Y
Yu Yang 已提交
392
      common_link(${TARGET_NAME})
393
    endif()
C
chengduo 已提交
394

L
liaogang 已提交
395
    # cpplint code style
L
liaogang 已提交
396 397 398 399 400 401
    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()
402 403 404

    check_coverage_opt(${TARGET_NAME} ${cc_library_SRCS})

405
  else()
406
    if(cc_library_DEPS)
407
      list(REMOVE_DUPLICATES cc_library_DEPS)
408

409 410 411
      generate_dummy_static_lib(
        LIB_NAME ${TARGET_NAME} FILE_PATH ${target_SRCS} GENERATOR
        "generic.cmake:cc_library")
412

413
      target_link_libraries(${TARGET_NAME} ${cc_library_DEPS})
414
    else()
415 416 417 418
      message(
        FATAL_ERROR
          "Please specify source files or libraries in cc_library(${TARGET_NAME} ...)."
      )
419
    endif()
420 421
  endif()
endfunction()
L
liaogang 已提交
422

L
liaogang 已提交
423
function(cc_binary TARGET_NAME)
424
  set(options "")
L
liaogang 已提交
425 426
  set(oneValueArgs "")
  set(multiValueArgs SRCS DEPS)
427 428
  cmake_parse_arguments(cc_binary "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
L
liaogang 已提交
429
  add_executable(${TARGET_NAME} ${cc_binary_SRCS})
430
  if(cc_binary_DEPS)
L
liaogang 已提交
431 432
    target_link_libraries(${TARGET_NAME} ${cc_binary_DEPS})
    add_dependencies(${TARGET_NAME} ${cc_binary_DEPS})
Y
Yu Yang 已提交
433
    common_link(${TARGET_NAME})
L
liaogang 已提交
434
  endif()
P
peizhilin 已提交
435 436
  get_property(os_dependency_modules GLOBAL PROPERTY OS_DEPENDENCY_MODULES)
  target_link_libraries(${TARGET_NAME} ${os_dependency_modules})
437 438 439
  if(WITH_ROCM)
    target_link_libraries(${TARGET_NAME} ${ROCM_HIPRTC_LIB})
  endif()
440 441 442

  check_coverage_opt(${TARGET_NAME} ${cc_binary_SRCS})

443
endfunction()
L
liaogang 已提交
444

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

function(cc_test_run TARGET_NAME)
T
tianshuo78520a 已提交
487
  if(WITH_TESTING)
488
    set(oneValueArgs DIR)
489
    set(multiValueArgs COMMAND ARGS)
490 491
    cmake_parse_arguments(cc_test "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
492 493 494
    if(cc_test_DIR STREQUAL "")
      set(cc_test_DIR ${CMAKE_CURRENT_BINARY_DIR})
    endif()
495 496 497
    add_test(
      NAME ${TARGET_NAME}
      COMMAND ${cc_test_COMMAND} ${cc_test_ARGS}
498
      WORKING_DIRECTORY ${cc_test_DIR})
499 500 501 502 503 504
    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 已提交
505
    # No unit test should exceed 2 minutes.
506 507
    if(WIN32)
      set_tests_properties(${TARGET_NAME} PROPERTIES TIMEOUT 150)
508
    endif()
509 510
    if(APPLE)
      set_tests_properties(${TARGET_NAME} PROPERTIES TIMEOUT 20)
511
    endif()
W
wuhuanzhou 已提交
512
  elseif(WITH_TESTING AND NOT TEST ${TARGET_NAME})
513 514
    add_test(NAME ${TARGET_NAME} COMMAND ${CMAKE_COMMAND} -E echo CI skip
                                         ${TARGET_NAME}.)
L
liaogang 已提交
515
  endif()
516 517
endfunction()

518 519
set_property(GLOBAL PROPERTY TEST_SRCS "")
set_property(GLOBAL PROPERTY TEST_NAMES "")
520
function(cc_test TARGET_NAME)
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 566 567 568
  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 已提交
569
  if(WITH_TESTING)
570 571
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS ARGS)
572 573 574
    cmake_parse_arguments(cc_test "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
    cc_test_build(${TARGET_NAME} SRCS ${cc_test_SRCS} DEPS ${cc_test_DEPS})
575 576
    # we dont test hcom op, because it need complex configuration
    # with more than one machine
577 578 579 580 581 582 583 584 585 586
    if(NOT
       ("${TARGET_NAME}" STREQUAL "c_broadcast_op_npu_test"
        OR "${TARGET_NAME}" STREQUAL "c_allreduce_sum_op_npu_test"
        OR "${TARGET_NAME}" STREQUAL "c_allreduce_max_op_npu_test"
        OR "${TARGET_NAME}" STREQUAL "c_reducescatter_op_npu_test"
        OR "${TARGET_NAME}" STREQUAL "c_allgather_op_npu_test"
        OR "${TARGET_NAME}" STREQUAL "send_v2_op_npu_test"
        OR "${TARGET_NAME}" STREQUAL "c_reduce_sum_op_npu_test"
        OR "${TARGET_NAME}" STREQUAL "recv_v2_op_npu_test"))
      cc_test_run(${TARGET_NAME} COMMAND ${TARGET_NAME} ARGS ${cc_test_ARGS})
587
    endif()
W
wuhuanzhou 已提交
588
  elseif(WITH_TESTING AND NOT TEST ${TARGET_NAME})
589 590
    add_test(NAME ${TARGET_NAME} COMMAND ${CMAKE_COMMAND} -E echo CI skip
                                         ${TARGET_NAME}.)
591
  endif()
592
endfunction()
L
liaogang 已提交
593 594

function(nv_library TARGET_NAME)
595
  if(WITH_GPU)
596
    set(options STATIC static SHARED shared)
597 598
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS)
599 600
    cmake_parse_arguments(nv_library "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
601
    if(nv_library_SRCS)
T
T8T9 已提交
602 603 604 605
      # 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
606
      if(nv_library_SHARED OR nv_library_shared) # build *.so
T
T8T9 已提交
607
        add_library(${TARGET_NAME} SHARED ${nv_library_SRCS})
608
      else()
T
T8T9 已提交
609
        add_library(${TARGET_NAME} STATIC ${nv_library_SRCS})
610
        find_fluid_modules(${TARGET_NAME})
611
        find_phi_modules(${TARGET_NAME})
612
      endif()
613
      if(nv_library_DEPS)
614
        add_dependencies(${TARGET_NAME} ${nv_library_DEPS})
615
        target_link_libraries(${TARGET_NAME} ${nv_library_DEPS})
616
      endif()
L
liaogang 已提交
617 618 619 620
      # cpplint code style
      foreach(source_file ${nv_library_SRCS})
        string(REGEX REPLACE "\\.[^.]*$" "" source ${source_file})
        if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${source}.h)
621 622
          list(APPEND nv_library_HEADERS
               ${CMAKE_CURRENT_SOURCE_DIR}/${source}.h)
L
liaogang 已提交
623 624
        endif()
      endforeach()
625
    else()
626
      if(nv_library_DEPS)
627
        list(REMOVE_DUPLICATES nv_library_DEPS)
628 629 630
        generate_dummy_static_lib(
          LIB_NAME ${TARGET_NAME} FILE_PATH ${target_SRCS} GENERATOR
          "generic.cmake:nv_library")
631

632 633
        target_link_libraries(${TARGET_NAME} ${nv_library_DEPS})
        add_dependencies(${TARGET_NAME} ${nv_library_DEPS})
634 635 636
      else()
        message(FATAL "Please specify source file or library in nv_library.")
      endif()
637
    endif()
638 639 640 641 642
    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 已提交
643
    endif()
644
  endif()
645
endfunction()
L
liaogang 已提交
646 647

function(nv_binary TARGET_NAME)
648
  if(WITH_GPU)
649 650 651
    set(options "")
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS)
652 653
    cmake_parse_arguments(nv_binary "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
T
T8T9 已提交
654
    add_executable(${TARGET_NAME} ${nv_binary_SRCS})
655 656 657
    if(nv_binary_DEPS)
      target_link_libraries(${TARGET_NAME} ${nv_binary_DEPS})
      add_dependencies(${TARGET_NAME} ${nv_binary_DEPS})
Y
Yu Yang 已提交
658
      common_link(${TARGET_NAME})
659
    endif()
660
    if((CUDA_VERSION GREATER 9.2)
661 662
       and (CUDA_VERSION LESS 11.0)
       and (MSVC_VERSION LESS 1910))
663 664
      set_target_properties(${TARGET_NAME} PROPERTIES VS_USER_PROPS
                                                      ${WIN_PROPS})
Z
Zhou Wei 已提交
665
    endif()
L
liaogang 已提交
666
  endif()
667
endfunction()
L
liaogang 已提交
668 669

function(nv_test TARGET_NAME)
T
tianshuo78520a 已提交
670
  if(WITH_GPU AND WITH_TESTING)
671 672
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS)
673 674
    cmake_parse_arguments(nv_test "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
T
T8T9 已提交
675 676 677 678 679
    # 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 已提交
680
    get_property(os_dependency_modules GLOBAL PROPERTY OS_DEPENDENCY_MODULES)
681 682 683
    target_link_libraries(${TARGET_NAME} ${nv_test_DEPS}
                          ${os_dependency_modules} paddle_gtest_main)
    add_dependencies(${TARGET_NAME} ${nv_test_DEPS} paddle_gtest_main)
Y
Yu Yang 已提交
684
    common_link(${TARGET_NAME})
685
    add_test(${TARGET_NAME} ${TARGET_NAME})
686 687 688 689 690 691 692 693 694 695 696
    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 已提交
697
    endif()
L
liaogang 已提交
698
  endif()
699
endfunction()
L
liaogang 已提交
700

701
function(hip_library TARGET_NAME)
702
  if(WITH_ROCM)
703 704 705
    set(options STATIC static SHARED shared)
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS)
706 707
    cmake_parse_arguments(hip_library "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
708
    if(hip_library_SRCS)
709
      # FindHIP.cmake defined hip_add_library, HIP_SOURCE_PROPERTY_FORMAT is requried if no .cu files found
710 711 712 713
      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)
714
      endif()
715
      if(hip_library_SHARED OR hip_library_shared) # build *.so
716
        hip_add_library(${TARGET_NAME} SHARED ${hip_library_SRCS})
717
      else()
718
        hip_add_library(${TARGET_NAME} STATIC ${hip_library_SRCS})
S
sabreshao 已提交
719
        find_fluid_modules(${TARGET_NAME})
720
        find_phi_modules(${TARGET_NAME})
721
      endif()
722
      if(hip_library_DEPS)
723
        add_dependencies(${TARGET_NAME} ${hip_library_DEPS})
S
sabreshao 已提交
724
        target_link_libraries(${TARGET_NAME} ${hip_library_DEPS})
725 726 727
      endif()
      # cpplint code style
      foreach(source_file ${hip_library_SRCS})
S
sabreshao 已提交
728 729
        string(REGEX REPLACE "\\.[^.]*$" "" source ${source_file})
        if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${source}.h)
730 731
          list(APPEND hip_library_HEADERS
               ${CMAKE_CURRENT_SOURCE_DIR}/${source}.h)
S
sabreshao 已提交
732
        endif()
733
      endforeach()
734
    else()
735
      if(hip_library_DEPS)
736
        list(REMOVE_DUPLICATES hip_library_DEPS)
737 738 739
        generate_dummy_static_lib(
          LIB_NAME ${TARGET_NAME} FILE_PATH ${target_SRCS} GENERATOR
          "generic.cmake:hip_library")
740 741 742

        target_link_libraries(${TARGET_NAME} ${hip_library_DEPS})
        add_dependencies(${TARGET_NAME} ${hip_library_DEPS})
743
      else()
744
        message(FATAL "Please specify source file or library in hip_library.")
745
      endif()
746
    endif()
747
  endif()
748
endfunction()
749 750

function(hip_binary TARGET_NAME)
751
  if(WITH_ROCM)
752 753 754
    set(options "")
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS)
755 756
    cmake_parse_arguments(hip_binary "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
757
    # FindHIP.cmake defined hip_add_executable, HIP_SOURCE_PROPERTY_FORMAT is requried for .cc files
758 759 760 761
    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 已提交
762
      common_link(${TARGET_NAME})
763 764
    endif()
  endif()
765
endfunction()
766 767

function(hip_test TARGET_NAME)
T
tianshuo78520a 已提交
768
  if(WITH_ROCM AND WITH_TESTING)
769 770
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS)
771 772
    cmake_parse_arguments(hip_test "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
773 774
    # FindHIP.cmake defined hip_add_executable,
    # HIP_SOURCE_PROPERTY_FORMAT is requried for .cc files
775 776 777
    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 已提交
778
    get_property(os_dependency_modules GLOBAL PROPERTY OS_DEPENDENCY_MODULES)
779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797
    target_link_libraries(
      ${TARGET_NAME}
      ${hip_test_DEPS}
      paddle_gtest_main
      lod_tensor
      memory
      gtest
      gflags
      glog
      ${os_dependency_modules})
    add_dependencies(
      ${TARGET_NAME}
      ${hip_test_DEPS}
      paddle_gtest_main
      lod_tensor
      memory
      gtest
      gflags
      glog)
Y
Yu Yang 已提交
798
    common_link(${TARGET_NAME})
799
    add_test(${TARGET_NAME} ${TARGET_NAME})
800 801 802 803 804 805
    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)
806 807 808 809 810 811
    set_property(
      TEST ${TARGET_NAME}
      PROPERTY
        ENVIRONMENT
        "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/python/paddle/libs:$LD_LIBRARY_PATH"
    )
812
  endif()
813
endfunction()
814

L
Liu-xiandong 已提交
815
function(xpu_library TARGET_NAME)
816
  if(WITH_XPU_KP)
L
Liu-xiandong 已提交
817 818 819
    set(options STATIC static SHARED shared)
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS)
820 821
    cmake_parse_arguments(xpu_library "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
L
Liu-xiandong 已提交
822 823

    if(xpu_library_SRCS)
824 825 826
      if(xpu_library_SHARED OR xpu_library_shared) # build *.so
        message(
          FATAL_ERROR "XPU kernel currently does not support dynamic links")
L
Liu-xiandong 已提交
827
      else()
828 829
        xpu_add_library(${TARGET_NAME} STATIC ${xpu_library_SRCS} DEPENDS
                        ${xpu_library_DEPS})
L
Liu-xiandong 已提交
830
        find_fluid_modules(${TARGET_NAME})
831
        find_phi_modules(${TARGET_NAME})
L
Liu-xiandong 已提交
832
      endif()
833
      if(xpu_library_DEPS)
L
Liu-xiandong 已提交
834 835 836 837 838 839 840
        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)
841 842
          list(APPEND xpu_library_HEADERS
               ${CMAKE_CURRENT_SOURCE_DIR}/${source}.h)
L
Liu-xiandong 已提交
843 844
        endif()
      endforeach()
845
    else()
846
      if(xpu_library_DEPS)
L
Liu-xiandong 已提交
847
        list(REMOVE_DUPLICATES xpu_library_DEPS)
848 849 850
        generate_dummy_static_lib(
          LIB_NAME ${TARGET_NAME} FILE_PATH ${target_SRCS} GENERATOR
          "generic.cmake:xpu_library")
L
Liu-xiandong 已提交
851 852 853 854 855
        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()
856
    endif()
L
Liu-xiandong 已提交
857
  endif()
858
endfunction()
L
Liu-xiandong 已提交
859 860

function(xpu_binary TARGET_NAME)
861
  if(WITH_XPU_KP)
L
Liu-xiandong 已提交
862 863 864
    set(options "")
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS)
865 866
    cmake_parse_arguments(xpu_binary "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
L
Liu-xiandong 已提交
867 868 869 870 871 872 873
    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()
874
endfunction()
L
Liu-xiandong 已提交
875 876

function(xpu_test TARGET_NAME)
T
tianshuo78520a 已提交
877
  if(WITH_XPU_KP AND WITH_TESTING)
L
Liu-xiandong 已提交
878 879
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS)
880 881
    cmake_parse_arguments(xpu_test "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
L
Liu-xiandong 已提交
882 883 884 885
    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)
886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904
    target_link_libraries(
      ${TARGET_NAME}
      ${xpu_test_DEPS}
      paddle_gtest_main
      lod_tensor
      memory
      gtest
      gflags
      glog
      ${os_dependency_modules})
    add_dependencies(
      ${TARGET_NAME}
      ${xpu_test_DEPS}
      paddle_gtest_main
      lod_tensor
      memory
      gtest
      gflags
      glog)
L
Liu-xiandong 已提交
905 906
    common_link(${TARGET_NAME})
    add_test(${TARGET_NAME} ${TARGET_NAME})
907 908 909 910 911 912
    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 已提交
913
  endif()
914
endfunction()
L
Liu-xiandong 已提交
915

L
liaogang 已提交
916
function(go_library TARGET_NAME)
L
liaogang 已提交
917
  set(options STATIC static SHARED shared)
L
liaogang 已提交
918
  set(oneValueArgs "")
L
liaogang 已提交
919
  set(multiValueArgs DEPS)
920 921
  cmake_parse_arguments(go_library "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
L
liaogang 已提交
922

923
  if(go_library_SHARED OR go_library_shared)
L
liaogang 已提交
924
    set(BUILD_MODE "-buildmode=c-shared")
925 926 927
    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 已提交
928 929
  else()
    set(BUILD_MODE "-buildmode=c-archive")
930 931 932
    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 已提交
933
  endif()
L
liaogang 已提交
934 935

  set(dummyfile ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}_dummy.c)
936 937 938

  # This custom command will always run since it depends on a not
  # existing file.
939 940
  add_custom_command(OUTPUT dummy_rebulid_${TARGET_NAME} COMMAND cmake -E touch
                                                                 ${dummyfile})
941 942 943
  # 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`.
944
  add_custom_target(rebuild_${TARGET_NAME} DEPENDS dummy_rebulid_${TARGET_NAME})
945 946

  # Add dummy code to support `make target_name` under Terminal Command
947 948 949
  file(WRITE ${dummyfile}
       "const char *dummy_${TARGET_NAME} = \"${dummyfile}\";")
  if(go_library_SHARED OR go_library_shared)
L
liaogang 已提交
950 951 952 953
    add_library(${TARGET_NAME} SHARED ${dummyfile})
  else()
    add_library(${TARGET_NAME} STATIC ${dummyfile})
  endif()
954 955
  if(go_library_DEPS)
    add_dependencies(${TARGET_NAME} ${go_library_DEPS})
Y
Yu Yang 已提交
956
    common_link(${TARGET_NAME})
957
  endif()
L
liaogang 已提交
958

959 960 961 962 963 964
  # 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})

965 966 967
  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 已提交
968

969 970 971 972 973 974
  file(
    GLOB GO_SOURCE
    RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
    "*.go")
  string(REPLACE "${PADDLE_GO_PATH}/" "" CMAKE_CURRENT_SOURCE_REL_DIR
                 ${CMAKE_CURRENT_SOURCE_DIR})
975

976 977 978
  add_custom_command(
    TARGET ${TARGET_NAME}
    POST_BUILD
H
Helin Wang 已提交
979
    COMMAND rm "${${TARGET_NAME}_LIB_PATH}"
980
    # Golang build source code
981 982 983 984
    COMMAND
      GOPATH=${GOPATH} ${CMAKE_Go_COMPILER} build ${BUILD_MODE} -o
      "${${TARGET_NAME}_LIB_PATH}"
      "./${CMAKE_CURRENT_SOURCE_REL_DIR}/${GO_SOURCE}"
W
wuyi05 已提交
985
    # must run under GOPATH
986
    WORKING_DIRECTORY "${PADDLE_IN_GOPATH}/go")
987
  add_dependencies(${TARGET_NAME} go_vendor)
988
endfunction()
L
liaogang 已提交
989 990 991 992 993

function(go_binary TARGET_NAME)
  set(options OPTIONAL)
  set(oneValueArgs "")
  set(multiValueArgs SRCS DEPS)
994 995 996 997
  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 已提交
998

999 1000 1001 1002 1003 1004
  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 已提交
1005
    WORKING_DIRECTORY "${PADDLE_IN_GOPATH}/go")
1006 1007 1008
  add_custom_target(
    ${TARGET_NAME} ALL DEPENDS go_vendor ${TARGET_NAME}_timestamp
                               ${go_binary_DEPS})
L
liaogang 已提交
1009
  install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME} DESTINATION bin)
1010 1011 1012

  check_coverage_opt(${TARGET_NAME} ${go_binary_SRCS})

1013
endfunction()
L
liaogang 已提交
1014 1015 1016 1017

function(go_test TARGET_NAME)
  set(options OPTIONAL)
  set(oneValueArgs "")
1018
  set(multiValueArgs DEPS)
1019 1020 1021 1022
  cmake_parse_arguments(go_test "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
  string(REPLACE "${PADDLE_GO_PATH}" "" CMAKE_CURRENT_SOURCE_REL_DIR
                 ${CMAKE_CURRENT_SOURCE_DIR})
1023
  add_custom_target(${TARGET_NAME} ALL DEPENDS go_vendor ${go_test_DEPS})
1024 1025 1026 1027 1028 1029 1030
  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}"
1031
    WORKING_DIRECTORY "${PADDLE_IN_GOPATH}/go")
1032 1033
  add_test(
    NAME ${TARGET_NAME}
1034
    COMMAND ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}
1035
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
1036
endfunction()
Y
Yu Yang 已提交
1037

1038 1039 1040 1041 1042 1043
# 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)
1044 1045 1046
    message(
      SEND_ERROR
        "Error: paddle_protobuf_generate_cpp() called without any proto files")
1047 1048 1049 1050 1051 1052 1053 1054 1055
    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 已提交
1056

1057 1058 1059 1060
    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 已提交
1061

1062
    add_custom_command(
1063
      OUTPUT "${_protobuf_protoc_src}" "${_protobuf_protoc_hdr}"
1064
      COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}"
1065 1066
      COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} -I${CMAKE_CURRENT_SOURCE_DIR}
              --cpp_out "${CMAKE_CURRENT_BINARY_DIR}" ${ABS_FIL}
1067 1068
      # Set `EXTERN_PROTOBUF_DEPEND` only if need to compile `protoc.exe`.
      DEPENDS ${ABS_FIL} ${EXTERN_PROTOBUF_DEPEND}
1069
      COMMENT "Running C++ protocol buffer compiler on ${FIL}"
1070
      VERBATIM)
1071 1072 1073
  endforeach()

  set_source_files_properties(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE)
1074 1075 1076 1077 1078 1079
  set(${SRCS}
      ${${SRCS}}
      PARENT_SCOPE)
  set(${HDRS}
      ${${HDRS}}
      PARENT_SCOPE)
1080 1081
endfunction()

Y
Yu Yang 已提交
1082
function(proto_library TARGET_NAME)
Y
Yu Yang 已提交
1083
  set(oneValueArgs "")
Y
Yu Yang 已提交
1084
  set(multiValueArgs SRCS DEPS)
1085 1086
  cmake_parse_arguments(proto_library "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
Y
Yu Yang 已提交
1087 1088
  set(proto_srcs)
  set(proto_hdrs)
1089
  paddle_protobuf_generate_cpp(proto_srcs proto_hdrs ${proto_library_SRCS})
1090 1091 1092 1093
  cc_library(
    ${TARGET_NAME}
    SRCS ${proto_srcs}
    DEPS ${proto_library_DEPS} protobuf)
1094
  add_dependencies(extern_xxhash ${TARGET_NAME})
Y
Yu Yang 已提交
1095
endfunction()
1096 1097 1098 1099

function(py_proto_compile TARGET_NAME)
  set(oneValueArgs "")
  set(multiValueArgs SRCS)
1100 1101
  cmake_parse_arguments(py_proto_compile "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
1102 1103
  set(py_srcs)
  protobuf_generate_python(py_srcs ${py_proto_compile_SRCS})
1104
  add_custom_target(${TARGET_NAME} ALL DEPENDS ${py_srcs} protobuf)
1105
endfunction()
L
liaogang 已提交
1106 1107 1108

function(py_test TARGET_NAME)
  if(WITH_TESTING)
1109
    set(options "")
L
liaogang 已提交
1110
    set(oneValueArgs "")
1111
    set(multiValueArgs SRCS DEPS ARGS ENVS)
1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126
    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})
1127
    else()
1128 1129 1130 1131 1132 1133 1134 1135
      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})
1136
    endif()
1137

1138 1139
    if(WIN32)
      set_tests_properties(${TARGET_NAME} PROPERTIES TIMEOUT 150)
1140
    endif()
1141 1142
    if(APPLE)
      set_tests_properties(${TARGET_NAME} PROPERTIES TIMEOUT 20)
1143
    endif()
1144

L
liaogang 已提交
1145 1146
  endif()
endfunction()
武毅 已提交
1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159

# 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 "")
1160 1161
  cmake_parse_arguments(grpc_library "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
武毅 已提交
1162 1163 1164 1165 1166 1167 1168

  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)

1169
  # FIXME(putcn): the follwoing line is supposed to generate *.pb.h and cc, but
C
chengduo 已提交
1170
  # somehow it didn't. line 602 to 604 is to patching this. Leaving this here
X
Xi Chen 已提交
1171
  # for now to enable dist CI.
1172
  paddle_protobuf_generate_cpp(grpc_proto_srcs grpc_proto_hdrs "${ABS_PROTO}")
武毅 已提交
1173 1174 1175 1176 1177
  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(
1178 1179 1180 1181 1182 1183 1184 1185
    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)
武毅 已提交
1186 1187 1188 1189 1190 1191

  # 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
1192 1193 1194
      COMPILE_FLAGS
      "-Wno-non-virtual-dtor -Wno-error=non-virtual-dtor -Wno-error=delete-non-virtual-dtor"
  )
武毅 已提交
1195 1196 1197 1198 1199
  cc_library("${TARGET_NAME}_grpc" SRCS "${grpc_grpc_srcs}")

  set_source_files_properties(
    ${grpc_library_SRCS}
    PROPERTIES
1200 1201 1202 1203 1204 1205 1206
      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}")
武毅 已提交
1207
endfunction()
G
gongweibao 已提交
1208 1209 1210 1211 1212

function(brpc_library TARGET_NAME)
  set(oneValueArgs PROTO)
  set(multiValueArgs SRCS DEPS)
  set(options "")
1213 1214
  cmake_parse_arguments(brpc_library "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
G
gongweibao 已提交
1215 1216 1217 1218 1219 1220 1221

  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)

1222
  paddle_protobuf_generate_cpp(brpc_proto_srcs brpc_proto_hdrs "${ABS_PROTO}")
G
gongweibao 已提交
1223
  cc_library("${TARGET_NAME}_proto" SRCS "${brpc_proto_srcs}")
1224 1225 1226 1227
  cc_library(
    "${TARGET_NAME}"
    SRCS "${brpc_library_SRCS}"
    DEPS "${TARGET_NAME}_proto" "${brpc_library_DEPS}")
G
gongweibao 已提交
1228
endfunction()
1229

1230 1231 1232
# 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)
1233

1234
  # this is a dummy target for custom command, should always be run firstly to update ${dst_file}
1235 1236 1237 1238 1239
  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)
1240 1241

  add_dependencies(extern_glog copy_${FILE_NAME}_command)
1242
endfunction()
1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253

# 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 "")
1254 1255
  cmake_parse_arguments(dummy "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
1256 1257 1258 1259 1260 1261 1262 1263 1264 1265
  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)
1266
    set(dummy_CONTENT "${dummy_LIB_NAME}_dummy.c for lib ${dummy_LIB_NAME}")
1267 1268
  endif()

1269 1270
  configure_file(${PROJECT_SOURCE_DIR}/cmake/dummy.c.in ${dummy_FILE_PATH}
                 @ONLY)
1271 1272 1273
  add_library(${dummy_LIB_NAME} STATIC ${dummy_FILE_PATH})
endfunction()

1274
function(math_library TARGET)
1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286
  # 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)
1287
    endif()
1288 1289 1290 1291
  endif()
  set(multiValueArgs DEPS)
  cmake_parse_arguments(math_library "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
1292

1293 1294 1295 1296 1297 1298 1299 1300 1301
  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()
1302

1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319
  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()
1320
endfunction()