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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    check_coverage_opt(${TARGET_NAME} ${cc_library_SRCS})

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

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

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

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

  check_coverage_opt(${TARGET_NAME} ${cc_binary_SRCS})

444
endfunction()
L
liaogang 已提交
445

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

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

function(cc_test TARGET_NAME)
T
tianshuo78520a 已提交
517
  if(WITH_TESTING)
518 519
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS ARGS)
520 521 522
    cmake_parse_arguments(cc_test "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
    cc_test_build(${TARGET_NAME} SRCS ${cc_test_SRCS} DEPS ${cc_test_DEPS})
523 524
    # we dont test hcom op, because it need complex configuration
    # with more than one machine
525 526 527 528 529 530 531 532 533 534
    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})
535
    endif()
W
wuhuanzhou 已提交
536
  elseif(WITH_TESTING AND NOT TEST ${TARGET_NAME})
537 538
    add_test(NAME ${TARGET_NAME} COMMAND ${CMAKE_COMMAND} -E echo CI skip
                                         ${TARGET_NAME}.)
539
  endif()
540
endfunction()
L
liaogang 已提交
541 542

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

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

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

function(nv_test TARGET_NAME)
T
tianshuo78520a 已提交
618
  if(WITH_GPU AND WITH_TESTING)
619 620
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS)
621 622
    cmake_parse_arguments(nv_test "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
T
T8T9 已提交
623 624 625 626 627
    # 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 已提交
628
    get_property(os_dependency_modules GLOBAL PROPERTY OS_DEPENDENCY_MODULES)
629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647
    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 已提交
648
    common_link(${TARGET_NAME})
649
    add_test(${TARGET_NAME} ${TARGET_NAME})
650 651 652 653 654 655 656 657 658 659 660
    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 已提交
661
    endif()
L
liaogang 已提交
662
  endif()
663
endfunction()
L
liaogang 已提交
664

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

        target_link_libraries(${TARGET_NAME} ${hip_library_DEPS})
        add_dependencies(${TARGET_NAME} ${hip_library_DEPS})
707
      else()
708
        message(FATAL "Please specify source file or library in hip_library.")
709
      endif()
710
    endif()
711
  endif()
712
endfunction()
713 714

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

function(hip_test TARGET_NAME)
T
tianshuo78520a 已提交
732
  if(WITH_ROCM AND WITH_TESTING)
733 734
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS)
735 736
    cmake_parse_arguments(hip_test "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
737 738
    # FindHIP.cmake defined hip_add_executable,
    # HIP_SOURCE_PROPERTY_FORMAT is requried for .cc files
739 740 741
    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 已提交
742
    get_property(os_dependency_modules GLOBAL PROPERTY OS_DEPENDENCY_MODULES)
743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761
    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 已提交
762
    common_link(${TARGET_NAME})
763
    add_test(${TARGET_NAME} ${TARGET_NAME})
764 765 766 767 768 769
    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)
770 771 772 773 774 775
    set_property(
      TEST ${TARGET_NAME}
      PROPERTY
        ENVIRONMENT
        "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/python/paddle/libs:$LD_LIBRARY_PATH"
    )
776
  endif()
777
endfunction()
778

L
Liu-xiandong 已提交
779
function(xpu_library TARGET_NAME)
780
  if(WITH_XPU_KP)
L
Liu-xiandong 已提交
781 782 783
    set(options STATIC static SHARED shared)
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS)
784 785
    cmake_parse_arguments(xpu_library "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
L
Liu-xiandong 已提交
786 787

    if(xpu_library_SRCS)
788 789 790
      if(xpu_library_SHARED OR xpu_library_shared) # build *.so
        message(
          FATAL_ERROR "XPU kernel currently does not support dynamic links")
L
Liu-xiandong 已提交
791
      else()
792 793
        xpu_add_library(${TARGET_NAME} STATIC ${xpu_library_SRCS} DEPENDS
                        ${xpu_library_DEPS})
L
Liu-xiandong 已提交
794
        find_fluid_modules(${TARGET_NAME})
795
        find_phi_modules(${TARGET_NAME})
L
Liu-xiandong 已提交
796
      endif()
797
      if(xpu_library_DEPS)
L
Liu-xiandong 已提交
798 799 800 801 802 803 804
        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)
805 806
          list(APPEND xpu_library_HEADERS
               ${CMAKE_CURRENT_SOURCE_DIR}/${source}.h)
L
Liu-xiandong 已提交
807 808
        endif()
      endforeach()
809
    else()
810
      if(xpu_library_DEPS)
L
Liu-xiandong 已提交
811
        list(REMOVE_DUPLICATES xpu_library_DEPS)
812 813 814
        generate_dummy_static_lib(
          LIB_NAME ${TARGET_NAME} FILE_PATH ${target_SRCS} GENERATOR
          "generic.cmake:xpu_library")
L
Liu-xiandong 已提交
815 816 817 818 819
        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()
820
    endif()
L
Liu-xiandong 已提交
821
  endif()
822
endfunction()
L
Liu-xiandong 已提交
823 824

function(xpu_binary TARGET_NAME)
825
  if(WITH_XPU_KP)
L
Liu-xiandong 已提交
826 827 828
    set(options "")
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS)
829 830
    cmake_parse_arguments(xpu_binary "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
L
Liu-xiandong 已提交
831 832 833 834 835 836 837
    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()
838
endfunction()
L
Liu-xiandong 已提交
839 840

function(xpu_test TARGET_NAME)
T
tianshuo78520a 已提交
841
  if(WITH_XPU_KP AND WITH_TESTING)
L
Liu-xiandong 已提交
842 843
    set(oneValueArgs "")
    set(multiValueArgs SRCS DEPS)
844 845
    cmake_parse_arguments(xpu_test "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN})
L
Liu-xiandong 已提交
846 847 848 849
    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)
850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868
    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 已提交
869 870
    common_link(${TARGET_NAME})
    add_test(${TARGET_NAME} ${TARGET_NAME})
871 872 873 874 875 876
    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 已提交
877
  endif()
878
endfunction()
L
Liu-xiandong 已提交
879

L
liaogang 已提交
880
function(go_library TARGET_NAME)
L
liaogang 已提交
881
  set(options STATIC static SHARED shared)
L
liaogang 已提交
882
  set(oneValueArgs "")
L
liaogang 已提交
883
  set(multiValueArgs DEPS)
884 885
  cmake_parse_arguments(go_library "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
L
liaogang 已提交
886

887
  if(go_library_SHARED OR go_library_shared)
L
liaogang 已提交
888
    set(BUILD_MODE "-buildmode=c-shared")
889 890 891
    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 已提交
892 893
  else()
    set(BUILD_MODE "-buildmode=c-archive")
894 895 896
    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 已提交
897
  endif()
L
liaogang 已提交
898 899

  set(dummyfile ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}_dummy.c)
900 901 902

  # This custom command will always run since it depends on a not
  # existing file.
903 904
  add_custom_command(OUTPUT dummy_rebulid_${TARGET_NAME} COMMAND cmake -E touch
                                                                 ${dummyfile})
905 906 907
  # 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`.
908
  add_custom_target(rebuild_${TARGET_NAME} DEPENDS dummy_rebulid_${TARGET_NAME})
909 910

  # Add dummy code to support `make target_name` under Terminal Command
911 912 913
  file(WRITE ${dummyfile}
       "const char *dummy_${TARGET_NAME} = \"${dummyfile}\";")
  if(go_library_SHARED OR go_library_shared)
L
liaogang 已提交
914 915 916 917
    add_library(${TARGET_NAME} SHARED ${dummyfile})
  else()
    add_library(${TARGET_NAME} STATIC ${dummyfile})
  endif()
918 919
  if(go_library_DEPS)
    add_dependencies(${TARGET_NAME} ${go_library_DEPS})
Y
Yu Yang 已提交
920
    common_link(${TARGET_NAME})
921
  endif()
L
liaogang 已提交
922

923 924 925 926 927 928
  # 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})

929 930 931
  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 已提交
932

933 934 935 936 937 938
  file(
    GLOB GO_SOURCE
    RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
    "*.go")
  string(REPLACE "${PADDLE_GO_PATH}/" "" CMAKE_CURRENT_SOURCE_REL_DIR
                 ${CMAKE_CURRENT_SOURCE_DIR})
939

940 941 942
  add_custom_command(
    TARGET ${TARGET_NAME}
    POST_BUILD
H
Helin Wang 已提交
943
    COMMAND rm "${${TARGET_NAME}_LIB_PATH}"
944
    # Golang build source code
945 946 947 948
    COMMAND
      GOPATH=${GOPATH} ${CMAKE_Go_COMPILER} build ${BUILD_MODE} -o
      "${${TARGET_NAME}_LIB_PATH}"
      "./${CMAKE_CURRENT_SOURCE_REL_DIR}/${GO_SOURCE}"
W
wuyi05 已提交
949
    # must run under GOPATH
950
    WORKING_DIRECTORY "${PADDLE_IN_GOPATH}/go")
951
  add_dependencies(${TARGET_NAME} go_vendor)
952
endfunction()
L
liaogang 已提交
953 954 955 956 957

function(go_binary TARGET_NAME)
  set(options OPTIONAL)
  set(oneValueArgs "")
  set(multiValueArgs SRCS DEPS)
958 959 960 961
  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 已提交
962

963 964 965 966 967 968
  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 已提交
969
    WORKING_DIRECTORY "${PADDLE_IN_GOPATH}/go")
970 971 972
  add_custom_target(
    ${TARGET_NAME} ALL DEPENDS go_vendor ${TARGET_NAME}_timestamp
                               ${go_binary_DEPS})
L
liaogang 已提交
973
  install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME} DESTINATION bin)
974 975 976

  check_coverage_opt(${TARGET_NAME} ${go_binary_SRCS})

977
endfunction()
L
liaogang 已提交
978 979 980 981

function(go_test TARGET_NAME)
  set(options OPTIONAL)
  set(oneValueArgs "")
982
  set(multiValueArgs DEPS)
983 984 985 986
  cmake_parse_arguments(go_test "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
  string(REPLACE "${PADDLE_GO_PATH}" "" CMAKE_CURRENT_SOURCE_REL_DIR
                 ${CMAKE_CURRENT_SOURCE_DIR})
987
  add_custom_target(${TARGET_NAME} ALL DEPENDS go_vendor ${go_test_DEPS})
988 989 990 991 992 993 994
  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}"
995
    WORKING_DIRECTORY "${PADDLE_IN_GOPATH}/go")
996 997
  add_test(
    NAME ${TARGET_NAME}
998
    COMMAND ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}
999
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
1000
endfunction()
Y
Yu Yang 已提交
1001

1002 1003 1004 1005 1006 1007
# 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)
1008 1009 1010
    message(
      SEND_ERROR
        "Error: paddle_protobuf_generate_cpp() called without any proto files")
1011 1012 1013 1014 1015 1016 1017 1018 1019
    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 已提交
1020

1021 1022 1023 1024
    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 已提交
1025

1026
    add_custom_command(
1027
      OUTPUT "${_protobuf_protoc_src}" "${_protobuf_protoc_hdr}"
1028
      COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}"
1029 1030
      COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} -I${CMAKE_CURRENT_SOURCE_DIR}
              --cpp_out "${CMAKE_CURRENT_BINARY_DIR}" ${ABS_FIL}
1031 1032
      # Set `EXTERN_PROTOBUF_DEPEND` only if need to compile `protoc.exe`.
      DEPENDS ${ABS_FIL} ${EXTERN_PROTOBUF_DEPEND}
1033
      COMMENT "Running C++ protocol buffer compiler on ${FIL}"
1034
      VERBATIM)
1035 1036 1037
  endforeach()

  set_source_files_properties(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE)
1038 1039 1040 1041 1042 1043
  set(${SRCS}
      ${${SRCS}}
      PARENT_SCOPE)
  set(${HDRS}
      ${${HDRS}}
      PARENT_SCOPE)
1044 1045
endfunction()

Y
Yu Yang 已提交
1046
function(proto_library TARGET_NAME)
Y
Yu Yang 已提交
1047
  set(oneValueArgs "")
Y
Yu Yang 已提交
1048
  set(multiValueArgs SRCS DEPS)
1049 1050
  cmake_parse_arguments(proto_library "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
Y
Yu Yang 已提交
1051 1052
  set(proto_srcs)
  set(proto_hdrs)
1053
  paddle_protobuf_generate_cpp(proto_srcs proto_hdrs ${proto_library_SRCS})
1054 1055 1056 1057
  cc_library(
    ${TARGET_NAME}
    SRCS ${proto_srcs}
    DEPS ${proto_library_DEPS} protobuf)
1058
  add_dependencies(extern_xxhash ${TARGET_NAME})
Y
Yu Yang 已提交
1059
endfunction()
1060 1061 1062 1063

function(py_proto_compile TARGET_NAME)
  set(oneValueArgs "")
  set(multiValueArgs SRCS)
1064 1065
  cmake_parse_arguments(py_proto_compile "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
1066 1067
  set(py_srcs)
  protobuf_generate_python(py_srcs ${py_proto_compile_SRCS})
1068
  add_custom_target(${TARGET_NAME} ALL DEPENDS ${py_srcs} protobuf)
1069
endfunction()
L
liaogang 已提交
1070 1071 1072

function(py_test TARGET_NAME)
  if(WITH_TESTING)
1073
    set(options "")
L
liaogang 已提交
1074
    set(oneValueArgs "")
1075
    set(multiValueArgs SRCS DEPS ARGS ENVS)
1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090
    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})
1091
    else()
1092 1093 1094 1095 1096 1097 1098 1099
      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})
1100
    endif()
1101

1102 1103
    if(WIN32)
      set_tests_properties(${TARGET_NAME} PROPERTIES TIMEOUT 150)
1104
    endif()
1105 1106
    if(APPLE)
      set_tests_properties(${TARGET_NAME} PROPERTIES TIMEOUT 20)
1107
    endif()
1108

L
liaogang 已提交
1109 1110
  endif()
endfunction()
武毅 已提交
1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123

# 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 "")
1124 1125
  cmake_parse_arguments(grpc_library "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
武毅 已提交
1126 1127 1128 1129 1130 1131 1132

  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)

1133
  # FIXME(putcn): the follwoing line is supposed to generate *.pb.h and cc, but
C
chengduo 已提交
1134
  # somehow it didn't. line 602 to 604 is to patching this. Leaving this here
X
Xi Chen 已提交
1135
  # for now to enable dist CI.
1136
  paddle_protobuf_generate_cpp(grpc_proto_srcs grpc_proto_hdrs "${ABS_PROTO}")
武毅 已提交
1137 1138 1139 1140 1141
  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(
1142 1143 1144 1145 1146 1147 1148 1149
    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)
武毅 已提交
1150 1151 1152 1153 1154 1155

  # 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
1156 1157 1158
      COMPILE_FLAGS
      "-Wno-non-virtual-dtor -Wno-error=non-virtual-dtor -Wno-error=delete-non-virtual-dtor"
  )
武毅 已提交
1159 1160 1161 1162 1163
  cc_library("${TARGET_NAME}_grpc" SRCS "${grpc_grpc_srcs}")

  set_source_files_properties(
    ${grpc_library_SRCS}
    PROPERTIES
1164 1165 1166 1167 1168 1169 1170
      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}")
武毅 已提交
1171
endfunction()
G
gongweibao 已提交
1172 1173 1174 1175 1176

function(brpc_library TARGET_NAME)
  set(oneValueArgs PROTO)
  set(multiValueArgs SRCS DEPS)
  set(options "")
1177 1178
  cmake_parse_arguments(brpc_library "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
G
gongweibao 已提交
1179 1180 1181 1182 1183 1184 1185

  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)

1186
  paddle_protobuf_generate_cpp(brpc_proto_srcs brpc_proto_hdrs "${ABS_PROTO}")
G
gongweibao 已提交
1187
  cc_library("${TARGET_NAME}_proto" SRCS "${brpc_proto_srcs}")
1188 1189 1190 1191
  cc_library(
    "${TARGET_NAME}"
    SRCS "${brpc_library_SRCS}"
    DEPS "${TARGET_NAME}_proto" "${brpc_library_DEPS}")
G
gongweibao 已提交
1192
endfunction()
1193

1194 1195 1196
# 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)
1197

1198
  # this is a dummy target for custom command, should always be run firstly to update ${dst_file}
1199 1200 1201 1202 1203
  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)
1204 1205

  add_dependencies(extern_glog copy_${FILE_NAME}_command)
1206
endfunction()
1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217

# 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 "")
1218 1219
  cmake_parse_arguments(dummy "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
1220 1221 1222 1223 1224 1225 1226 1227 1228 1229
  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)
1230
    set(dummy_CONTENT "${dummy_LIB_NAME}_dummy.c for lib ${dummy_LIB_NAME}")
1231 1232
  endif()

1233 1234
  configure_file(${PROJECT_SOURCE_DIR}/cmake/dummy.c.in ${dummy_FILE_PATH}
                 @ONLY)
1235 1236 1237
  add_library(${dummy_LIB_NAME} STATIC ${dummy_FILE_PATH})
endfunction()

1238
function(math_library TARGET)
1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250
  # 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)
1251
    endif()
1252 1253 1254 1255
  endif()
  set(multiValueArgs DEPS)
  cmake_parse_arguments(math_library "${options}" "${oneValueArgs}"
                        "${multiValueArgs}" ${ARGN})
1256

1257 1258 1259 1260 1261 1262 1263 1264 1265
  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()
1266

1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283
  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()
1284
endfunction()