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

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

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

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

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

121 122
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

  list(REMOVE_DUPLICATES merge_LIBS)
  set(index 1)
  set(offset 1)
  # the dummy target would be consisted of limit size libraries
  set(limit ${merge_LIMIT})
  list(LENGTH merge_LIBS libs_len)
L
Leo Chen 已提交
198
  message("libs_len ${libs_len}")
199 200 201
  foreach(lib ${merge_LIBS})
    list(APPEND merge_list ${lib})
    list(LENGTH merge_list listlen)
202 203 204
    if((${listlen} GREATER ${limit}) OR (${offset} EQUAL ${libs_len}))
      message(
        "Merge and generate static library: ${TARGET_NAME}_static_${index}")
205 206 207 208 209 210
      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})
211
      math(EXPR index "${index}+1")
212
    endif()
213
    math(EXPR offset "${offset}+1")
214 215 216 217
  endforeach()
  cc_library(${TARGET_NAME} DEPS ${${TARGET_NAME}_list})
endfunction()

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

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

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

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

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

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

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

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

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

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

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

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

L
liaogang 已提交
337
function(cc_library TARGET_NAME)
338
  set(options STATIC static SHARED shared INTERFACE interface)
L
liaogang 已提交
339 340
  set(oneValueArgs "")
  set(multiValueArgs SRCS DEPS)
341 342
  cmake_parse_arguments(cc_library "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
D
dzhwinter 已提交
343
  if(WIN32)
344 345 346 347
    # 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}")
348
  endif()
L
Liu Yiqun 已提交
349
  if(cc_library_SRCS)
350 351 352 353 354 355 356 357 358 359 360
    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 已提交
361
    if(cc_library_DEPS)
362
      # Don't need link libwarpctc.so
L
Liu Yiqun 已提交
363
      if("${cc_library_DEPS};" MATCHES "warpctc;")
364 365 366
        list(REMOVE_ITEM cc_library_DEPS warpctc)
        add_dependencies(${TARGET_NAME} warpctc)
      endif()
367 368 369 370 371 372 373
      # 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 已提交
374 375
        if(WIN32)
          target_link_libraries(${TARGET_NAME} ${MKLML_IOMP_LIB})
376
        else()
377 378
          target_link_libraries(${TARGET_NAME}
                                "-L${MKLML_LIB_DIR} -liomp5 -Wl,--as-needed")
379
        endif()
380
      endif()
T
update  
typhoonzero 已提交
381 382 383 384 385
      # 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 已提交
386 387 388 389
        if(WIN32)
          target_link_libraries(${TARGET_NAME} ${PYTHON_LIBRARIES})
        else()
          target_link_libraries(${TARGET_NAME} "-Wl,-undefined,dynamic_lookup")
390
        endif()
T
update  
typhoonzero 已提交
391
      endif()
392
      target_link_libraries(${TARGET_NAME} ${cc_library_DEPS})
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
    cc_test_run(${TARGET_NAME} COMMAND ${TARGET_NAME} ARGS ${cc_test_ARGS})
W
wuhuanzhou 已提交
579
  elseif(WITH_TESTING AND NOT TEST ${TARGET_NAME})
580 581
    add_test(NAME ${TARGET_NAME} COMMAND ${CMAKE_COMMAND} -E echo CI skip
                                         ${TARGET_NAME}.)
582
  endif()
583
endfunction()
L
liaogang 已提交
584 585

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

623 624
        target_link_libraries(${TARGET_NAME} ${nv_library_DEPS})
        add_dependencies(${TARGET_NAME} ${nv_library_DEPS})
625 626 627
      else()
        message(FATAL "Please specify source file or library in nv_library.")
      endif()
628
    endif()
629 630 631 632 633
    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 已提交
634
    endif()
635
  endif()
636
endfunction()
L
liaogang 已提交
637 638

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

function(nv_test TARGET_NAME)
T
tianshuo78520a 已提交
661
  if(WITH_GPU AND WITH_TESTING)
662 663
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS)
664 665
    cmake_parse_arguments(nv_test "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
T
T8T9 已提交
666 667 668 669 670
    # 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 已提交
671
    get_property(os_dependency_modules GLOBAL PROPERTY OS_DEPENDENCY_MODULES)
672 673 674
    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 已提交
675
    common_link(${TARGET_NAME})
676
    add_test(${TARGET_NAME} ${TARGET_NAME})
677 678 679 680 681 682 683 684 685 686 687
    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 已提交
688
    endif()
L
liaogang 已提交
689
  endif()
690
endfunction()
L
liaogang 已提交
691

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

        target_link_libraries(${TARGET_NAME} ${hip_library_DEPS})
        add_dependencies(${TARGET_NAME} ${hip_library_DEPS})
734
      else()
735
        message(FATAL "Please specify source file or library in hip_library.")
736
      endif()
737
    endif()
738
  endif()
739
endfunction()
740 741

function(hip_binary TARGET_NAME)
742
  if(WITH_ROCM)
743 744 745
    set(options "")
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS)
746 747
    cmake_parse_arguments(hip_binary "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
748
    # FindHIP.cmake defined hip_add_executable, HIP_SOURCE_PROPERTY_FORMAT is requried for .cc files
749 750 751 752
    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 已提交
753
      common_link(${TARGET_NAME})
754 755
    endif()
  endif()
756
endfunction()
757 758

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

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

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

function(xpu_binary TARGET_NAME)
852
  if(WITH_XPU_KP)
L
Liu-xiandong 已提交
853 854 855
    set(options "")
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS)
856 857
    cmake_parse_arguments(xpu_binary "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
L
Liu-xiandong 已提交
858 859 860 861 862 863 864
    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()
865
endfunction()
L
Liu-xiandong 已提交
866 867

function(xpu_test TARGET_NAME)
T
tianshuo78520a 已提交
868
  if(WITH_XPU_KP AND WITH_TESTING)
L
Liu-xiandong 已提交
869 870
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS)
871 872
    cmake_parse_arguments(xpu_test "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
L
Liu-xiandong 已提交
873 874 875 876
    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)
877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895
    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 已提交
896 897
    common_link(${TARGET_NAME})
    add_test(${TARGET_NAME} ${TARGET_NAME})
898 899 900 901 902 903
    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 已提交
904
  endif()
905
endfunction()
L
Liu-xiandong 已提交
906

L
liaogang 已提交
907
function(go_library TARGET_NAME)
L
liaogang 已提交
908
  set(options STATIC static SHARED shared)
L
liaogang 已提交
909
  set(oneValueArgs "")
L
liaogang 已提交
910
  set(multiValueArgs DEPS)
911 912
  cmake_parse_arguments(go_library "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
L
liaogang 已提交
913

914
  if(go_library_SHARED OR go_library_shared)
L
liaogang 已提交
915
    set(BUILD_MODE "-buildmode=c-shared")
916 917 918
    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 已提交
919 920
  else()
    set(BUILD_MODE "-buildmode=c-archive")
921 922 923
    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 已提交
924
  endif()
L
liaogang 已提交
925 926

  set(dummyfile ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}_dummy.c)
927 928 929

  # This custom command will always run since it depends on a not
  # existing file.
930 931
  add_custom_command(OUTPUT dummy_rebulid_${TARGET_NAME} COMMAND cmake -E touch
                                                                 ${dummyfile})
932 933 934
  # 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`.
935
  add_custom_target(rebuild_${TARGET_NAME} DEPENDS dummy_rebulid_${TARGET_NAME})
936 937

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

950 951 952 953 954 955
  # 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})

956 957 958
  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 已提交
959

960 961 962 963 964 965
  file(
    GLOB GO_SOURCE
    RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
    "*.go")
  string(REPLACE "${PADDLE_GO_PATH}/" "" CMAKE_CURRENT_SOURCE_REL_DIR
                 ${CMAKE_CURRENT_SOURCE_DIR})
966

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

function(go_binary TARGET_NAME)
  set(options OPTIONAL)
  set(oneValueArgs "")
  set(multiValueArgs SRCS DEPS)
985 986 987 988
  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 已提交
989

990 991 992 993 994 995
  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 已提交
996
    WORKING_DIRECTORY "${PADDLE_IN_GOPATH}/go")
997 998 999
  add_custom_target(
    ${TARGET_NAME} ALL DEPENDS go_vendor ${TARGET_NAME}_timestamp
                               ${go_binary_DEPS})
L
liaogang 已提交
1000
  install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME} DESTINATION bin)
1001 1002 1003

  check_coverage_opt(${TARGET_NAME} ${go_binary_SRCS})

1004
endfunction()
L
liaogang 已提交
1005 1006 1007 1008

function(go_test TARGET_NAME)
  set(options OPTIONAL)
  set(oneValueArgs "")
1009
  set(multiValueArgs DEPS)
1010 1011 1012 1013
  cmake_parse_arguments(go_test "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
  string(REPLACE "${PADDLE_GO_PATH}" "" CMAKE_CURRENT_SOURCE_REL_DIR
                 ${CMAKE_CURRENT_SOURCE_DIR})
1014
  add_custom_target(${TARGET_NAME} ALL DEPENDS go_vendor ${go_test_DEPS})
1015 1016 1017 1018 1019 1020 1021
  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}"
1022
    WORKING_DIRECTORY "${PADDLE_IN_GOPATH}/go")
1023 1024
  add_test(
    NAME ${TARGET_NAME}
1025
    COMMAND ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}
1026
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
1027
endfunction()
Y
Yu Yang 已提交
1028

1029 1030 1031 1032 1033 1034
# 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)
1035 1036 1037
    message(
      SEND_ERROR
        "Error: paddle_protobuf_generate_cpp() called without any proto files")
1038 1039 1040 1041 1042 1043 1044 1045 1046
    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 已提交
1047

1048 1049 1050 1051
    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 已提交
1052

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

  set_source_files_properties(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE)
1065 1066 1067 1068 1069 1070
  set(${SRCS}
      ${${SRCS}}
      PARENT_SCOPE)
  set(${HDRS}
      ${${HDRS}}
      PARENT_SCOPE)
1071 1072
endfunction()

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

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

function(py_test TARGET_NAME)
  if(WITH_TESTING)
1100
    set(options "")
L
liaogang 已提交
1101
    set(oneValueArgs "")
1102
    set(multiValueArgs SRCS DEPS ARGS ENVS)
1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117
    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})
1118
    else()
1119 1120 1121 1122 1123 1124 1125 1126
      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})
1127
    endif()
1128

1129 1130
    if(WIN32)
      set_tests_properties(${TARGET_NAME} PROPERTIES TIMEOUT 150)
1131
    endif()
1132 1133
    if(APPLE)
      set_tests_properties(${TARGET_NAME} PROPERTIES TIMEOUT 20)
1134
    endif()
1135

L
liaogang 已提交
1136 1137
  endif()
endfunction()
武毅 已提交
1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150

# 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 "")
1151 1152
  cmake_parse_arguments(grpc_library "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
武毅 已提交
1153 1154 1155 1156 1157 1158 1159

  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)

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

  # 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
1183 1184 1185
      COMPILE_FLAGS
      "-Wno-non-virtual-dtor -Wno-error=non-virtual-dtor -Wno-error=delete-non-virtual-dtor"
  )
武毅 已提交
1186 1187 1188 1189 1190
  cc_library("${TARGET_NAME}_grpc" SRCS "${grpc_grpc_srcs}")

  set_source_files_properties(
    ${grpc_library_SRCS}
    PROPERTIES
1191 1192 1193 1194 1195 1196 1197
      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}")
武毅 已提交
1198
endfunction()
G
gongweibao 已提交
1199 1200 1201 1202 1203

function(brpc_library TARGET_NAME)
  set(oneValueArgs PROTO)
  set(multiValueArgs SRCS DEPS)
  set(options "")
1204 1205
  cmake_parse_arguments(brpc_library "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
G
gongweibao 已提交
1206 1207 1208 1209 1210 1211 1212

  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)

1213
  paddle_protobuf_generate_cpp(brpc_proto_srcs brpc_proto_hdrs "${ABS_PROTO}")
G
gongweibao 已提交
1214
  cc_library("${TARGET_NAME}_proto" SRCS "${brpc_proto_srcs}")
1215 1216 1217 1218
  cc_library(
    "${TARGET_NAME}"
    SRCS "${brpc_library_SRCS}"
    DEPS "${TARGET_NAME}_proto" "${brpc_library_DEPS}")
G
gongweibao 已提交
1219
endfunction()
1220

1221 1222 1223
# 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)
1224

1225
  # this is a dummy target for custom command, should always be run firstly to update ${dst_file}
1226 1227 1228 1229 1230
  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)
1231 1232

  add_dependencies(extern_glog copy_${FILE_NAME}_command)
1233
endfunction()
1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244

# 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 "")
1245 1246
  cmake_parse_arguments(dummy "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
1247 1248 1249 1250 1251 1252 1253 1254 1255 1256
  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)
1257
    set(dummy_CONTENT "${dummy_LIB_NAME}_dummy.c for lib ${dummy_LIB_NAME}")
1258 1259
  endif()

1260 1261
  configure_file(${PROJECT_SOURCE_DIR}/cmake/dummy.c.in ${dummy_FILE_PATH}
                 @ONLY)
1262 1263 1264
  add_library(${dummy_LIB_NAME} STATIC ${dummy_FILE_PATH})
endfunction()

1265
function(math_library TARGET)
1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277
  # 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)
1278
    endif()
1279 1280 1281 1282
  endif()
  set(multiValueArgs DEPS)
  cmake_parse_arguments(math_library "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
1283

1284 1285 1286 1287 1288 1289 1290 1291 1292
  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()
1293

1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310
  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()
1311
endfunction()