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 392
      target_link_libraries(${TARGET_NAME} ${cc_library_DEPS}
                            ${PYTHON_LIBRARIES})
Y
Yu Yang 已提交
393
      common_link(${TARGET_NAME})
394
    endif()
C
chengduo 已提交
395

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

    check_coverage_opt(${TARGET_NAME} ${cc_library_SRCS})

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

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

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

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

  check_coverage_opt(${TARGET_NAME} ${cc_binary_SRCS})

444
endfunction()
L
liaogang 已提交
445

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  check_coverage_opt(${TARGET_NAME} ${go_binary_SRCS})

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

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

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

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

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

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

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

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

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

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

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

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

  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)

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

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

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

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

  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)

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

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

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

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

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

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

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

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

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