generic.cmake 46.8 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 99
    set(CMAKE_CXX_LINK_EXECUTABLE
        "${CMAKE_CXX_LINK_EXECUTABLE} -pthread -ldl -lrt -lz -lssl")
100
  else()
101 102
    set(CMAKE_CXX_LINK_EXECUTABLE
        "${CMAKE_CXX_LINK_EXECUTABLE} -pthread -ldl -lrt")
103
  endif()
104
endif()
105

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

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

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

D
dzhwinter 已提交
142 143 144 145 146
# find all third_party modules is used for paddle static library
# for reduce the dependency when building the inference libs.
set_property(GLOBAL PROPERTY FLUID_THIRD_PARTY)
function(find_fluid_thirdparties TARGET_NAME)
  get_filename_component(__target_path ${TARGET_NAME} ABSOLUTE)
147 148
  string(REGEX REPLACE "^${PADDLE_SOURCE_DIR}/" "" __target_path
                       ${__target_path})
D
dzhwinter 已提交
149 150 151 152 153 154
  string(FIND "${__target_path}" "third_party" pos)
  if(pos GREATER 1)
    get_property(fluid_ GLOBAL PROPERTY FLUID_THIRD_PARTY)
    set(fluid_third_partys ${fluid_third_partys} ${TARGET_NAME})
    set_property(GLOBAL PROPERTY FLUID_THIRD_PARTY "${fluid_third_partys}")
  endif()
155
endfunction()
D
dzhwinter 已提交
156

157 158 159 160 161 162 163 164 165 166 167 168
function(create_static_lib TARGET_NAME)
  set(libs ${ARGN})
  list(REMOVE_DUPLICATES libs)
  if(WIN32)
    set(dummy_index 1)
    set(dummy_offset 1)
    # the dummy target would be consisted of limit size libraries
    set(dummy_limit 60)
    list(LENGTH libs libs_len)
    foreach(lib ${libs})
      list(APPEND dummy_list ${lib})
      list(LENGTH dummy_list listlen)
169 170
      if((${listlen} GREATER ${dummy_limit}) OR (${dummy_offset} EQUAL
                                                 ${libs_len}))
171 172
        merge_static_libs(${TARGET_NAME}_dummy_${dummy_index} ${dummy_list})
        set(dummy_list)
173 174 175
        list(APPEND ${TARGET_NAME}_dummy_list
             ${TARGET_NAME}_dummy_${dummy_index})
        math(EXPR dummy_index "${dummy_index}+1")
176
      endif()
177
      math(EXPR dummy_offset "${dummy_offset}+1")
178 179 180 181 182 183 184
    endforeach()
    merge_static_libs(${TARGET_NAME} ${${TARGET_NAME}_dummy_list})
  else()
    merge_static_libs(${TARGET_NAME} ${libs})
  endif()
endfunction()

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

  list(REMOVE_DUPLICATES merge_LIBS)
  set(index 1)
  set(offset 1)
  # the dummy target would be consisted of limit size libraries
  set(limit ${merge_LIMIT})
  list(LENGTH merge_LIBS libs_len)
  foreach(lib ${merge_LIBS})
    list(APPEND merge_list ${lib})
    list(LENGTH merge_list listlen)
201 202 203
    if((${listlen} GREATER ${limit}) OR (${offset} EQUAL ${libs_len}))
      message(
        "Merge and generate static library: ${TARGET_NAME}_static_${index}")
204 205 206 207 208 209
      merge_static_libs(${TARGET_NAME}_static_${index} ${merge_list})
      if(merge_DEPS)
        target_link_libraries(${TARGET_NAME}_static_${index} ${merge_DEPS})
      endif()
      set(merge_list)
      list(APPEND ${TARGET_NAME}_list ${TARGET_NAME}_static_${index})
210
      math(EXPR index "${index}+1")
211
    endif()
212
    math(EXPR offset "${offset}+1")
213 214 215 216
  endforeach()
  cc_library(${TARGET_NAME} DEPS ${${TARGET_NAME}_list})
endfunction()

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

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

229 230 231 232
  # To produce a library we need at least one source file.
  # It is created by add_custom_command below and will helps
  # also help to track dependencies.
  set(target_SRCS ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}_dummy.c)
233

234 235 236
  # Make the generated dummy source file depended on all static input
  # libs. If input lib changes,the source file is touched
  # which causes the desired effect (relink).
237 238
  add_custom_command(
    OUTPUT ${target_SRCS}
239 240
    COMMAND ${CMAKE_COMMAND} -E touch ${target_SRCS}
    DEPENDS ${libs})
241 242 243 244

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

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

262 263
  # LINUX: use "ar" to extract objects and re-add to a common lib
  if(LINUX)
264 265 266 267 268 269 270
    set(mri_file
        ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}.mri
        CACHE INTERNAL "phi_static.mri file")
    get_property(
      ABS_MERGE_LIB_PATH
      TARGET ${TARGET_NAME}
      PROPERTY LOCATION)
271
    file(WRITE ${mri_file} "create ${ABS_MERGE_LIB_PATH}\n")
272

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

282 283 284 285 286 287
    add_custom_command(
      TARGET ${TARGET_NAME}
      POST_BUILD
      COMMENT "Merge and generate static lib: lib${TARGET_NAME}.a"
      COMMAND ${CMAKE_AR} -M < ${mri_file}
      COMMAND ${CMAKE_RANLIB} "$<TARGET_FILE:${TARGET_NAME}>")
288
  endif()
D
dzhwinter 已提交
289

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

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

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

L
liaogang 已提交
336
function(cc_library TARGET_NAME)
337
  set(options STATIC static SHARED shared INTERFACE interface)
L
liaogang 已提交
338 339
  set(oneValueArgs "")
  set(multiValueArgs SRCS DEPS)
340 341
  cmake_parse_arguments(cc_library "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
D
dzhwinter 已提交
342
  if(WIN32)
343 344 345 346
    # add libxxx.lib prefix in windows
    set(${TARGET_NAME}_LIB_NAME
        "${CMAKE_STATIC_LIBRARY_PREFIX}${TARGET_NAME}${CMAKE_STATIC_LIBRARY_SUFFIX}"
        CACHE STRING "output library name for target ${TARGET_NAME}")
347
  endif()
L
Liu Yiqun 已提交
348
  if(cc_library_SRCS)
349 350 351 352 353 354 355 356 357 358 359
    if(cc_library_SHARED OR cc_library_shared) # build *.so
      add_library(${TARGET_NAME} SHARED ${cc_library_SRCS})
    elseif(cc_library_INTERFACE OR cc_library_interface)
      generate_dummy_static_lib(
        LIB_NAME ${TARGET_NAME} FILE_PATH ${target_SRCS} GENERATOR
        "generic.cmake:cc_library")
    else()
      add_library(${TARGET_NAME} STATIC ${cc_library_SRCS})
      find_fluid_modules(${TARGET_NAME})
      find_phi_modules(${TARGET_NAME})
    endif()
L
Liu Yiqun 已提交
360
    if(cc_library_DEPS)
361
      # Don't need link libwarpctc.so
L
Liu Yiqun 已提交
362
      if("${cc_library_DEPS};" MATCHES "warpctc;")
363 364 365
        list(REMOVE_ITEM cc_library_DEPS warpctc)
        add_dependencies(${TARGET_NAME} warpctc)
      endif()
366 367 368 369 370 371 372
      # Only deps libmklml.so, not link
      if("${cc_library_DEPS};" MATCHES "mklml;")
        list(REMOVE_ITEM cc_library_DEPS mklml)
        if(NOT "${TARGET_NAME}" MATCHES "dynload_mklml")
          list(APPEND cc_library_DEPS dynload_mklml)
        endif()
        add_dependencies(${TARGET_NAME} mklml)
P
peizhilin 已提交
373 374
        if(WIN32)
          target_link_libraries(${TARGET_NAME} ${MKLML_IOMP_LIB})
375
        else()
376 377
          target_link_libraries(${TARGET_NAME}
                                "-L${MKLML_LIB_DIR} -liomp5 -Wl,--as-needed")
378
        endif()
379
      endif()
T
update  
typhoonzero 已提交
380 381 382 383 384
      # remove link to python, see notes at:
      # https://github.com/pybind/pybind11/blob/master/docs/compiling.rst#building-manually
      if("${cc_library_DEPS};" MATCHES "python;")
        list(REMOVE_ITEM cc_library_DEPS python)
        add_dependencies(${TARGET_NAME} python)
P
peizhilin 已提交
385 386 387 388
        if(WIN32)
          target_link_libraries(${TARGET_NAME} ${PYTHON_LIBRARIES})
        else()
          target_link_libraries(${TARGET_NAME} "-Wl,-undefined,dynamic_lookup")
389
        endif()
T
update  
typhoonzero 已提交
390
      endif()
391
      target_link_libraries(${TARGET_NAME} ${cc_library_DEPS})
Y
Yu Yang 已提交
392
      common_link(${TARGET_NAME})
393
    endif()
C
chengduo 已提交
394

L
liaogang 已提交
395
    # cpplint code style
L
liaogang 已提交
396 397 398 399 400 401
    foreach(source_file ${cc_library_SRCS})
      string(REGEX REPLACE "\\.[^.]*$" "" source ${source_file})
      if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${source}.h)
        list(APPEND cc_library_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/${source}.h)
      endif()
    endforeach()
402 403 404

    check_coverage_opt(${TARGET_NAME} ${cc_library_SRCS})

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

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

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

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

  check_coverage_opt(${TARGET_NAME} ${cc_binary_SRCS})

443
endfunction()
L
liaogang 已提交
444

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

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

function(cc_test TARGET_NAME)
516 517
  # The environment variable `CI_SKIP_CPP_TEST` is used to skip the compilation
  # and execution of test in CI. `CI_SKIP_CPP_TEST` is set to ON when no files
518 519
  # other than *.py are modified.
  if(WITH_TESTING AND NOT "$ENV{CI_SKIP_CPP_TEST}" STREQUAL "ON")
520 521
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS ARGS)
522 523 524
    cmake_parse_arguments(cc_test "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
    cc_test_build(${TARGET_NAME} SRCS ${cc_test_SRCS} DEPS ${cc_test_DEPS})
525 526
    # we dont test hcom op, because it need complex configuration
    # with more than one machine
527 528 529 530 531 532 533 534 535 536
    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})
537
    endif()
W
wuhuanzhou 已提交
538
  elseif(WITH_TESTING AND NOT TEST ${TARGET_NAME})
539 540
    add_test(NAME ${TARGET_NAME} COMMAND ${CMAKE_COMMAND} -E echo CI skip
                                         ${TARGET_NAME}.)
541
  endif()
542
endfunction()
L
liaogang 已提交
543 544

function(nv_library TARGET_NAME)
545
  if(WITH_GPU)
546
    set(options STATIC static SHARED shared)
547 548
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS)
549 550
    cmake_parse_arguments(nv_library "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
551
    if(nv_library_SRCS)
T
T8T9 已提交
552 553 554 555
      # 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
556
      if(nv_library_SHARED OR nv_library_shared) # build *.so
T
T8T9 已提交
557
        add_library(${TARGET_NAME} SHARED ${nv_library_SRCS})
558
      else()
T
T8T9 已提交
559
        add_library(${TARGET_NAME} STATIC ${nv_library_SRCS})
560
        find_fluid_modules(${TARGET_NAME})
561
        find_phi_modules(${TARGET_NAME})
562
      endif()
563
      if(nv_library_DEPS)
564
        add_dependencies(${TARGET_NAME} ${nv_library_DEPS})
565
        target_link_libraries(${TARGET_NAME} ${nv_library_DEPS})
566
      endif()
L
liaogang 已提交
567 568 569 570
      # cpplint code style
      foreach(source_file ${nv_library_SRCS})
        string(REGEX REPLACE "\\.[^.]*$" "" source ${source_file})
        if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${source}.h)
571 572
          list(APPEND nv_library_HEADERS
               ${CMAKE_CURRENT_SOURCE_DIR}/${source}.h)
L
liaogang 已提交
573 574
        endif()
      endforeach()
575
    else()
576
      if(nv_library_DEPS)
577
        list(REMOVE_DUPLICATES nv_library_DEPS)
578 579 580
        generate_dummy_static_lib(
          LIB_NAME ${TARGET_NAME} FILE_PATH ${target_SRCS} GENERATOR
          "generic.cmake:nv_library")
581

582 583
        target_link_libraries(${TARGET_NAME} ${nv_library_DEPS})
        add_dependencies(${TARGET_NAME} ${nv_library_DEPS})
584 585 586
      else()
        message(FATAL "Please specify source file or library in nv_library.")
      endif()
587
    endif()
588 589 590 591 592
    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 已提交
593
    endif()
594
  endif()
595
endfunction()
L
liaogang 已提交
596 597

function(nv_binary TARGET_NAME)
598
  if(WITH_GPU)
599 600 601
    set(options "")
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS)
602 603
    cmake_parse_arguments(nv_binary "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
T
T8T9 已提交
604
    add_executable(${TARGET_NAME} ${nv_binary_SRCS})
605 606 607
    if(nv_binary_DEPS)
      target_link_libraries(${TARGET_NAME} ${nv_binary_DEPS})
      add_dependencies(${TARGET_NAME} ${nv_binary_DEPS})
Y
Yu Yang 已提交
608
      common_link(${TARGET_NAME})
609
    endif()
610
    if((CUDA_VERSION GREATER 9.2)
611 612
       and (CUDA_VERSION LESS 11.0)
       and (MSVC_VERSION LESS 1910))
613 614
      set_target_properties(${TARGET_NAME} PROPERTIES VS_USER_PROPS
                                                      ${WIN_PROPS})
Z
Zhou Wei 已提交
615
    endif()
L
liaogang 已提交
616
  endif()
617
endfunction()
L
liaogang 已提交
618 619

function(nv_test TARGET_NAME)
620 621
  # The environment variable `CI_SKIP_CPP_TEST` is used to skip the compilation
  # and execution of test in CI. `CI_SKIP_CPP_TEST` is set to ON when no files
622
  # other than *.py are modified.
623 624 625
  if(WITH_GPU
     AND WITH_TESTING
     AND NOT "$ENV{CI_SKIP_CPP_TEST}" STREQUAL "ON")
626 627
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS)
628 629
    cmake_parse_arguments(nv_test "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
T
T8T9 已提交
630 631 632 633 634
    # 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 已提交
635
    get_property(os_dependency_modules GLOBAL PROPERTY OS_DEPENDENCY_MODULES)
636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654
    target_link_libraries(
      ${TARGET_NAME}
      ${nv_test_DEPS}
      paddle_gtest_main
      lod_tensor
      memory
      gtest
      gflags
      glog
      ${os_dependency_modules})
    add_dependencies(
      ${TARGET_NAME}
      ${nv_test_DEPS}
      paddle_gtest_main
      lod_tensor
      memory
      gtest
      gflags
      glog)
Y
Yu Yang 已提交
655
    common_link(${TARGET_NAME})
656
    add_test(${TARGET_NAME} ${TARGET_NAME})
657 658 659 660 661 662 663 664 665 666 667
    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 已提交
668
    endif()
L
liaogang 已提交
669
  endif()
670
endfunction()
L
liaogang 已提交
671

672
function(hip_library TARGET_NAME)
673
  if(WITH_ROCM)
674 675 676
    set(options STATIC static SHARED shared)
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS)
677 678
    cmake_parse_arguments(hip_library "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
679
    if(hip_library_SRCS)
680
      # FindHIP.cmake defined hip_add_library, HIP_SOURCE_PROPERTY_FORMAT is requried if no .cu files found
681 682 683 684
      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)
685
      endif()
686
      if(hip_library_SHARED OR hip_library_shared) # build *.so
687
        hip_add_library(${TARGET_NAME} SHARED ${hip_library_SRCS})
688
      else()
689
        hip_add_library(${TARGET_NAME} STATIC ${hip_library_SRCS})
S
sabreshao 已提交
690
        find_fluid_modules(${TARGET_NAME})
691
        find_phi_modules(${TARGET_NAME})
692
      endif()
693
      if(hip_library_DEPS)
694
        add_dependencies(${TARGET_NAME} ${hip_library_DEPS})
S
sabreshao 已提交
695
        target_link_libraries(${TARGET_NAME} ${hip_library_DEPS})
696 697 698
      endif()
      # cpplint code style
      foreach(source_file ${hip_library_SRCS})
S
sabreshao 已提交
699 700
        string(REGEX REPLACE "\\.[^.]*$" "" source ${source_file})
        if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${source}.h)
701 702
          list(APPEND hip_library_HEADERS
               ${CMAKE_CURRENT_SOURCE_DIR}/${source}.h)
S
sabreshao 已提交
703
        endif()
704
      endforeach()
705
    else()
706
      if(hip_library_DEPS)
707
        list(REMOVE_DUPLICATES hip_library_DEPS)
708 709 710
        generate_dummy_static_lib(
          LIB_NAME ${TARGET_NAME} FILE_PATH ${target_SRCS} GENERATOR
          "generic.cmake:hip_library")
711 712 713

        target_link_libraries(${TARGET_NAME} ${hip_library_DEPS})
        add_dependencies(${TARGET_NAME} ${hip_library_DEPS})
714
      else()
715
        message(FATAL "Please specify source file or library in hip_library.")
716
      endif()
717
    endif()
718
  endif()
719
endfunction()
720 721

function(hip_binary TARGET_NAME)
722
  if(WITH_ROCM)
723 724 725
    set(options "")
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS)
726 727
    cmake_parse_arguments(hip_binary "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
728
    # FindHIP.cmake defined hip_add_executable, HIP_SOURCE_PROPERTY_FORMAT is requried for .cc files
729 730 731 732
    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 已提交
733
      common_link(${TARGET_NAME})
734 735
    endif()
  endif()
736
endfunction()
737 738

function(hip_test TARGET_NAME)
739 740 741
  # The environment variable `CI_SKIP_CPP_TEST` is used to skip the compilation
  # and execution of test in CI. `CI_SKIP_CPP_TEST` is set to ON when no files
  # other than *.py are modified.
742 743 744
  if(WITH_ROCM
     AND WITH_TESTING
     AND NOT "$ENV{CI_SKIP_CPP_TEST}" STREQUAL "ON")
745 746
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS)
747 748
    cmake_parse_arguments(hip_test "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
749 750
    # FindHIP.cmake defined hip_add_executable,
    # HIP_SOURCE_PROPERTY_FORMAT is requried for .cc files
751 752 753
    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 已提交
754
    get_property(os_dependency_modules GLOBAL PROPERTY OS_DEPENDENCY_MODULES)
755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773
    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 已提交
774
    common_link(${TARGET_NAME})
775
    add_test(${TARGET_NAME} ${TARGET_NAME})
776 777 778 779 780 781
    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)
782 783 784 785 786 787
    set_property(
      TEST ${TARGET_NAME}
      PROPERTY
        ENVIRONMENT
        "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/python/paddle/libs:$LD_LIBRARY_PATH"
    )
788
  endif()
789
endfunction()
790

L
Liu-xiandong 已提交
791
function(xpu_library TARGET_NAME)
792
  if(WITH_XPU_KP)
L
Liu-xiandong 已提交
793 794 795
    set(options STATIC static SHARED shared)
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS)
796 797
    cmake_parse_arguments(xpu_library "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
L
Liu-xiandong 已提交
798 799

    if(xpu_library_SRCS)
800 801 802
      if(xpu_library_SHARED OR xpu_library_shared) # build *.so
        message(
          FATAL_ERROR "XPU kernel currently does not support dynamic links")
L
Liu-xiandong 已提交
803
      else()
804 805
        xpu_add_library(${TARGET_NAME} STATIC ${xpu_library_SRCS} DEPENDS
                        ${xpu_library_DEPS})
L
Liu-xiandong 已提交
806
        find_fluid_modules(${TARGET_NAME})
807
        find_phi_modules(${TARGET_NAME})
L
Liu-xiandong 已提交
808
      endif()
809
      if(xpu_library_DEPS)
L
Liu-xiandong 已提交
810 811 812 813 814 815 816
        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)
817 818
          list(APPEND xpu_library_HEADERS
               ${CMAKE_CURRENT_SOURCE_DIR}/${source}.h)
L
Liu-xiandong 已提交
819 820
        endif()
      endforeach()
821
    else()
822
      if(xpu_library_DEPS)
L
Liu-xiandong 已提交
823
        list(REMOVE_DUPLICATES xpu_library_DEPS)
824 825 826
        generate_dummy_static_lib(
          LIB_NAME ${TARGET_NAME} FILE_PATH ${target_SRCS} GENERATOR
          "generic.cmake:xpu_library")
L
Liu-xiandong 已提交
827 828 829 830 831
        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()
832
    endif()
L
Liu-xiandong 已提交
833
  endif()
834
endfunction()
L
Liu-xiandong 已提交
835 836

function(xpu_binary TARGET_NAME)
837
  if(WITH_XPU_KP)
L
Liu-xiandong 已提交
838 839 840
    set(options "")
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS)
841 842
    cmake_parse_arguments(xpu_binary "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
L
Liu-xiandong 已提交
843 844 845 846 847 848 849
    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()
850
endfunction()
L
Liu-xiandong 已提交
851 852 853 854 855

function(xpu_test TARGET_NAME)
  # The environment variable `CI_SKIP_CPP_TEST` is used to skip the compilation
  # and execution of test in CI. `CI_SKIP_CPP_TEST` is set to ON when no files
  # other than *.py are modified.
856 857 858
  if(WITH_XPU_KP
     AND WITH_TESTING
     AND NOT "$ENV{CI_SKIP_CPP_TEST}" STREQUAL "ON")
L
Liu-xiandong 已提交
859 860
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS)
861 862
    cmake_parse_arguments(xpu_test "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
L
Liu-xiandong 已提交
863 864 865 866
    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)
867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885
    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 已提交
886 887
    common_link(${TARGET_NAME})
    add_test(${TARGET_NAME} ${TARGET_NAME})
888 889 890 891 892 893
    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 已提交
894
  endif()
895
endfunction()
L
Liu-xiandong 已提交
896

L
liaogang 已提交
897
function(go_library TARGET_NAME)
L
liaogang 已提交
898
  set(options STATIC static SHARED shared)
L
liaogang 已提交
899
  set(oneValueArgs "")
L
liaogang 已提交
900
  set(multiValueArgs DEPS)
901 902
  cmake_parse_arguments(go_library "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
L
liaogang 已提交
903

904
  if(go_library_SHARED OR go_library_shared)
L
liaogang 已提交
905
    set(BUILD_MODE "-buildmode=c-shared")
906 907 908
    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 已提交
909 910
  else()
    set(BUILD_MODE "-buildmode=c-archive")
911 912 913
    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 已提交
914
  endif()
L
liaogang 已提交
915 916

  set(dummyfile ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}_dummy.c)
917 918 919

  # This custom command will always run since it depends on a not
  # existing file.
920 921
  add_custom_command(OUTPUT dummy_rebulid_${TARGET_NAME} COMMAND cmake -E touch
                                                                 ${dummyfile})
922 923 924
  # 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`.
925
  add_custom_target(rebuild_${TARGET_NAME} DEPENDS dummy_rebulid_${TARGET_NAME})
926 927

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

940 941 942 943 944 945
  # 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})

946 947 948
  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 已提交
949

950 951 952 953 954 955
  file(
    GLOB GO_SOURCE
    RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
    "*.go")
  string(REPLACE "${PADDLE_GO_PATH}/" "" CMAKE_CURRENT_SOURCE_REL_DIR
                 ${CMAKE_CURRENT_SOURCE_DIR})
956

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

function(go_binary TARGET_NAME)
  set(options OPTIONAL)
  set(oneValueArgs "")
  set(multiValueArgs SRCS DEPS)
975 976 977 978
  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 已提交
979

980 981 982 983 984 985
  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 已提交
986
    WORKING_DIRECTORY "${PADDLE_IN_GOPATH}/go")
987 988 989
  add_custom_target(
    ${TARGET_NAME} ALL DEPENDS go_vendor ${TARGET_NAME}_timestamp
                               ${go_binary_DEPS})
L
liaogang 已提交
990
  install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME} DESTINATION bin)
991 992 993

  check_coverage_opt(${TARGET_NAME} ${go_binary_SRCS})

994
endfunction()
L
liaogang 已提交
995 996 997 998

function(go_test TARGET_NAME)
  set(options OPTIONAL)
  set(oneValueArgs "")
999
  set(multiValueArgs DEPS)
1000 1001 1002 1003
  cmake_parse_arguments(go_test "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
  string(REPLACE "${PADDLE_GO_PATH}" "" CMAKE_CURRENT_SOURCE_REL_DIR
                 ${CMAKE_CURRENT_SOURCE_DIR})
1004
  add_custom_target(${TARGET_NAME} ALL DEPENDS go_vendor ${go_test_DEPS})
1005 1006 1007 1008 1009 1010 1011
  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}"
1012
    WORKING_DIRECTORY "${PADDLE_IN_GOPATH}/go")
1013 1014
  add_test(
    NAME ${TARGET_NAME}
1015
    COMMAND ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}
1016
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
1017
endfunction()
Y
Yu Yang 已提交
1018

1019 1020 1021 1022 1023 1024
# 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)
1025 1026 1027
    message(
      SEND_ERROR
        "Error: paddle_protobuf_generate_cpp() called without any proto files")
1028 1029 1030 1031 1032 1033 1034 1035 1036
    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 已提交
1037

1038 1039 1040 1041
    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 已提交
1042

1043
    add_custom_command(
1044
      OUTPUT "${_protobuf_protoc_src}" "${_protobuf_protoc_hdr}"
1045
      COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}"
1046 1047
      COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} -I${CMAKE_CURRENT_SOURCE_DIR}
              --cpp_out "${CMAKE_CURRENT_BINARY_DIR}" ${ABS_FIL}
1048 1049
      # Set `EXTERN_PROTOBUF_DEPEND` only if need to compile `protoc.exe`.
      DEPENDS ${ABS_FIL} ${EXTERN_PROTOBUF_DEPEND}
1050
      COMMENT "Running C++ protocol buffer compiler on ${FIL}"
1051
      VERBATIM)
1052 1053 1054
  endforeach()

  set_source_files_properties(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE)
1055 1056 1057 1058 1059 1060
  set(${SRCS}
      ${${SRCS}}
      PARENT_SCOPE)
  set(${HDRS}
      ${${HDRS}}
      PARENT_SCOPE)
1061 1062
endfunction()

Y
Yu Yang 已提交
1063
function(proto_library TARGET_NAME)
Y
Yu Yang 已提交
1064
  set(oneValueArgs "")
Y
Yu Yang 已提交
1065
  set(multiValueArgs SRCS DEPS)
1066 1067
  cmake_parse_arguments(proto_library "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
Y
Yu Yang 已提交
1068 1069
  set(proto_srcs)
  set(proto_hdrs)
1070
  paddle_protobuf_generate_cpp(proto_srcs proto_hdrs ${proto_library_SRCS})
1071 1072 1073 1074
  cc_library(
    ${TARGET_NAME}
    SRCS ${proto_srcs}
    DEPS ${proto_library_DEPS} protobuf)
1075
  add_dependencies(extern_xxhash ${TARGET_NAME})
Y
Yu Yang 已提交
1076
endfunction()
1077 1078 1079 1080

function(py_proto_compile TARGET_NAME)
  set(oneValueArgs "")
  set(multiValueArgs SRCS)
1081 1082
  cmake_parse_arguments(py_proto_compile "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
1083 1084
  set(py_srcs)
  protobuf_generate_python(py_srcs ${py_proto_compile_SRCS})
1085
  add_custom_target(${TARGET_NAME} ALL DEPENDS ${py_srcs} protobuf)
1086
endfunction()
L
liaogang 已提交
1087 1088 1089

function(py_test TARGET_NAME)
  if(WITH_TESTING)
1090
    set(options "")
L
liaogang 已提交
1091
    set(oneValueArgs "")
1092
    set(multiValueArgs SRCS DEPS ARGS ENVS)
1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107
    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})
1108
    else()
1109 1110 1111 1112 1113 1114 1115 1116
      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})
1117
    endif()
1118

1119 1120
    if(WIN32)
      set_tests_properties(${TARGET_NAME} PROPERTIES TIMEOUT 150)
1121
    endif()
1122 1123
    if(APPLE)
      set_tests_properties(${TARGET_NAME} PROPERTIES TIMEOUT 20)
1124
    endif()
1125

L
liaogang 已提交
1126 1127
  endif()
endfunction()
武毅 已提交
1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140

# 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 "")
1141 1142
  cmake_parse_arguments(grpc_library "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
武毅 已提交
1143 1144 1145 1146 1147 1148 1149

  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)

1150
  # FIXME(putcn): the follwoing line is supposed to generate *.pb.h and cc, but
C
chengduo 已提交
1151
  # somehow it didn't. line 602 to 604 is to patching this. Leaving this here
X
Xi Chen 已提交
1152
  # for now to enable dist CI.
1153
  paddle_protobuf_generate_cpp(grpc_proto_srcs grpc_proto_hdrs "${ABS_PROTO}")
武毅 已提交
1154 1155 1156 1157 1158
  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(
1159 1160 1161 1162 1163 1164 1165 1166
    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)
武毅 已提交
1167 1168 1169 1170 1171 1172

  # 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
1173 1174 1175
      COMPILE_FLAGS
      "-Wno-non-virtual-dtor -Wno-error=non-virtual-dtor -Wno-error=delete-non-virtual-dtor"
  )
武毅 已提交
1176 1177 1178 1179 1180
  cc_library("${TARGET_NAME}_grpc" SRCS "${grpc_grpc_srcs}")

  set_source_files_properties(
    ${grpc_library_SRCS}
    PROPERTIES
1181 1182 1183 1184 1185 1186 1187
      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}")
武毅 已提交
1188
endfunction()
G
gongweibao 已提交
1189 1190 1191 1192 1193

function(brpc_library TARGET_NAME)
  set(oneValueArgs PROTO)
  set(multiValueArgs SRCS DEPS)
  set(options "")
1194 1195
  cmake_parse_arguments(brpc_library "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
G
gongweibao 已提交
1196 1197 1198 1199 1200 1201 1202

  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)

1203
  paddle_protobuf_generate_cpp(brpc_proto_srcs brpc_proto_hdrs "${ABS_PROTO}")
G
gongweibao 已提交
1204
  cc_library("${TARGET_NAME}_proto" SRCS "${brpc_proto_srcs}")
1205 1206 1207 1208
  cc_library(
    "${TARGET_NAME}"
    SRCS "${brpc_library_SRCS}"
    DEPS "${TARGET_NAME}_proto" "${brpc_library_DEPS}")
G
gongweibao 已提交
1209
endfunction()
1210

1211 1212 1213
# 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)
1214

1215
  # this is a dummy target for custom command, should always be run firstly to update ${dst_file}
1216 1217 1218 1219 1220
  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)
1221 1222

  add_dependencies(extern_glog copy_${FILE_NAME}_command)
1223
endfunction()
1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234

# 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 "")
1235 1236
  cmake_parse_arguments(dummy "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
1237 1238 1239 1240 1241 1242 1243 1244 1245 1246
  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)
1247
    set(dummy_CONTENT "${dummy_LIB_NAME}_dummy.c for lib ${dummy_LIB_NAME}")
1248 1249
  endif()

1250 1251
  configure_file(${PROJECT_SOURCE_DIR}/cmake/dummy.c.in ${dummy_FILE_PATH}
                 @ONLY)
1252 1253 1254
  add_library(${dummy_LIB_NAME} STATIC ${dummy_FILE_PATH})
endfunction()

1255
function(math_library TARGET)
1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267
  # 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)
1268
    endif()
1269 1270 1271 1272
  endif()
  set(multiValueArgs DEPS)
  cmake_parse_arguments(math_library "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
1273

1274 1275 1276 1277 1278 1279 1280 1281 1282
  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()
1283

1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300
  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()
1301
endfunction()