prepend()是CMake的内置函数还是宏?
我试图阅读Pytorch的源代码,却被它的CMake文件卡住了 正如您在文件中看到的:prepend()是CMake的内置函数还是宏?,cmake,pytorch,Cmake,Pytorch,我试图阅读Pytorch的源代码,却被它的CMake文件卡住了 正如您在文件中看到的: ############################################################################## #宏以更新缓存选项。 宏(caffe2_更新_选项变量值) if(CAFFE2\U CMAKE\U大楼\U带主回购) get_属性(uu帮助_字符串缓存${variable}属性帮助字符串) set(${variable}${value}CACHE BO
##############################################################################
#宏以更新缓存选项。
宏(caffe2_更新_选项变量值)
if(CAFFE2\U CMAKE\U大楼\U带主回购)
get_属性(uu帮助_字符串缓存${variable}属性帮助字符串)
set(${variable}${value}CACHE BOOL${{uuuu help\u string}FORCE)
else()
集合(${variable}${value})
endif()
endmacro()
##############################################################################
#添加依赖于源的接口库定义。
#
#要解释这个宏存在的原因,最简单的方法可能是描述
#如果没有这个宏,情况会是什么样子。
#
#让我们假设我们想要静态链接到火炬。我们已经定义了
#cmake的一个图书馆叫torch,我们可能认为
#目标链接库(我的应用程序公共火炬)。这将导致
#链接器参数“libtorch.a”正在传递给链接器。
#
#不幸的是,这个链接命令是错误的!我们有静电干扰
#libtorch.a中的初始值设定项会被
#默认链接设置。我们真正需要的是你
#做-Wl,-整个档案,libtorch.a-Wl,-没有整个档案要确保
#我们保留所有符号,即使它们(看起来)没有被使用。
#
#caffe2_接口_库所做的是创建一个接口库
#这间接地依赖于真实的库,但建立了链接
#参数,以便获得所需的所有额外链接设置。
#结果不是一个“真正的”库,因此我们必须手动创建
#从原始目标复制必要的属性。
#
#(上面的讨论是关于静态库的,但是类似的
#动态库会出现这样的情况:如果没有从中使用符号
#一个动态库,它将被删减,除非您是--不需要)
宏(caffe2_接口_库SRC DST)
添加库(${DST}接口)
添加依赖项(${DST}${SRC})
#根据源库和编译器的性质,
#确定所需的编译标志。
get_target_属性(uu src_target_type${src}type)
#根据源库的类型,我们将设置
#特定SRC库的link命令。
if(${u\u src\u target\u type}STREQUAL“STATIC\u LIBRARY”)
#对于静态库,我们需要添加整个静态标志。
如果(苹果)
目标链接库(
${DST}接口-Wl,-力荷载,$)
elseif(MSVC)
#在MSVC中,我们将在默认情况下添加整个存档。
目标链接库(
${DST}接口-wholerchive:$)
else()
#假设其他一切都像gcc
目标链接库(${DST}接口
“-Wl,--整个档案,$-Wl,--没有整个档案”)
endif()
#链接src目标的所有接口链接库。
#对于静态库,我们需要显式地依赖于所有库
#是源库的从属库。请注意,我们不能
#使用填充的接口链接库属性,因为如果
#依赖库不是目标,cmake创建$wrapper
#然后就找不到目标“src”。有关更多讨论,请查看
# https://gitlab.kitware.com/cmake/cmake/issues/15415
# https://cmake.org/pipermail/cmake-developers/2013-May/019019.html
#具体如下
#
# """
#对于静态库,我们可以定义PUBLIC/PRIVATE/INTERFACE键
#为链接而忽略,并且它始终填充两个链接库
#链接\接口\库。请注意,对于静态库
#链接库属性将不用于除生成顺序之外的任何内容
#依赖关系。
# """
目标链接库(${DST}接口
$)
elseif(${u_src_target_type}STREQUAL“共享_库”)
如果(${CMAKE\u CXX\u COMPILER\u ID})匹配“GNU”)
目标链接库(${DST}接口
“-Wl,--不需要,$-Wl,--需要时”)
else()
目标链接库(${DST}接口${SRC})
endif()
#链接src目标的所有接口链接库。
#对于共享库,我们可以简单地依赖于接口链接库
#目标的属性。
目标链接库(${DST}接口
$)
else()
消息(致命错误)
您犯了一个CMake生成文件错误:目标“${SRC}
必须是静态\u库或共享\u库的类型。但是
“我得到了“${uuu src\u target\u type}”。”
endif()
#对于所有其他接口属性,请手动从源目标继承。
设置_目标_属性(${DST}属性
接口\u编译\u定义
$
接口\编译\选项
$
接口包括目录
$
接口\系统\包括\目录
$)
endmacro()
##############################################################################
#使用相对路径指定的源创建Caffe2二进制目标。
#用法:
#caffe2_二进制_目标(目标_名称_或_src[][…)
#如果只指定了target\u name\u或\u src,则此目标是使用单个
#源文件和目标名称是文件名中的autogen。否则
#目标名称由第一个参数给出,其余为源文件
#建立目标。
函数(caffe2\u二进制\u目标\u名称\u或\u src)
# https://cmake.org/cmake/help/latest/command/function.html
#检查ARGC是否大于#是确保
#该ARGV#作为额外参数传递给函数。
如果(ARGC大于1)
set(uuu target${target_name_u或_src})
前置(${CMAKE\u CURRENT\u SOURCE\u DIR}/“${ARGN}”)
else()
获取\u文件名\u组件(\u目标${target\u name\u或\u src}name\u WE)
前置(uu srcs“${CMAKE\u CURRENT\u SOURCE\u DIR}/“${target\u name\u或_src}”)
恩迪夫(
##############################################################################
# Macro to update cached options.
macro (caffe2_update_option variable value)
if(CAFFE2_CMAKE_BUILDING_WITH_MAIN_REPO)
get_property(__help_string CACHE ${variable} PROPERTY HELPSTRING)
set(${variable} ${value} CACHE BOOL ${__help_string} FORCE)
else()
set(${variable} ${value})
endif()
endmacro()
##############################################################################
# Add an interface library definition that is dependent on the source.
#
# It's probably easiest to explain why this macro exists, by describing
# what things would look like if we didn't have this macro.
#
# Let's suppose we want to statically link against torch. We've defined
# a library in cmake called torch, and we might think that we just
# target_link_libraries(my-app PUBLIC torch). This will result in a
# linker argument 'libtorch.a' getting passed to the linker.
#
# Unfortunately, this link command is wrong! We have static
# initializers in libtorch.a that would get improperly pruned by
# the default link settings. What we actually need is for you
# to do -Wl,--whole-archive,libtorch.a -Wl,--no-whole-archive to ensure
# that we keep all symbols, even if they are (seemingly) not used.
#
# What caffe2_interface_library does is create an interface library
# that indirectly depends on the real library, but sets up the link
# arguments so that you get all of the extra link settings you need.
# The result is not a "real" library, and so we have to manually
# copy over necessary properties from the original target.
#
# (The discussion above is about static libraries, but a similar
# situation occurs for dynamic libraries: if no symbols are used from
# a dynamic library, it will be pruned unless you are --no-as-needed)
macro(caffe2_interface_library SRC DST)
add_library(${DST} INTERFACE)
add_dependencies(${DST} ${SRC})
# Depending on the nature of the source library as well as the compiler,
# determine the needed compilation flags.
get_target_property(__src_target_type ${SRC} TYPE)
# Depending on the type of the source library, we will set up the
# link command for the specific SRC library.
if (${__src_target_type} STREQUAL "STATIC_LIBRARY")
# In the case of static library, we will need to add whole-static flags.
if(APPLE)
target_link_libraries(
${DST} INTERFACE -Wl,-force_load,$<TARGET_FILE:${SRC}>)
elseif(MSVC)
# In MSVC, we will add whole archive in default.
target_link_libraries(
${DST} INTERFACE -WHOLEARCHIVE:$<TARGET_FILE:${SRC}>)
else()
# Assume everything else is like gcc
target_link_libraries(${DST} INTERFACE
"-Wl,--whole-archive,$<TARGET_FILE:${SRC}> -Wl,--no-whole-archive")
endif()
# Link all interface link libraries of the src target as well.
# For static library, we need to explicitly depend on all the libraries
# that are the dependent library of the source library. Note that we cannot
# use the populated INTERFACE_LINK_LIBRARIES property, because if one of the
# dependent library is not a target, cmake creates a $<LINK_ONLY:src> wrapper
# and then one is not able to find target "src". For more discussions, check
# https://gitlab.kitware.com/cmake/cmake/issues/15415
# https://cmake.org/pipermail/cmake-developers/2013-May/019019.html
# Specifically the following quote
#
# """
# For STATIC libraries we can define that the PUBLIC/PRIVATE/INTERFACE keys
# are ignored for linking and that it always populates both LINK_LIBRARIES
# LINK_INTERFACE_LIBRARIES. Note that for STATIC libraries the
# LINK_LIBRARIES property will not be used for anything except build-order
# dependencies.
# """
target_link_libraries(${DST} INTERFACE
$<TARGET_PROPERTY:${SRC},LINK_LIBRARIES>)
elseif(${__src_target_type} STREQUAL "SHARED_LIBRARY")
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
target_link_libraries(${DST} INTERFACE
"-Wl,--no-as-needed,$<TARGET_FILE:${SRC}> -Wl,--as-needed")
else()
target_link_libraries(${DST} INTERFACE ${SRC})
endif()
# Link all interface link libraries of the src target as well.
# For shared libraries, we can simply depend on the INTERFACE_LINK_LIBRARIES
# property of the target.
target_link_libraries(${DST} INTERFACE
$<TARGET_PROPERTY:${SRC},INTERFACE_LINK_LIBRARIES>)
else()
message(FATAL_ERROR
"You made a CMake build file error: target " ${SRC}
" must be of type either STATIC_LIBRARY or SHARED_LIBRARY. However, "
"I got " ${__src_target_type} ".")
endif()
# For all other interface properties, manually inherit from the source target.
set_target_properties(${DST} PROPERTIES
INTERFACE_COMPILE_DEFINITIONS
$<TARGET_PROPERTY:${SRC},INTERFACE_COMPILE_DEFINITIONS>
INTERFACE_COMPILE_OPTIONS
$<TARGET_PROPERTY:${SRC},INTERFACE_COMPILE_OPTIONS>
INTERFACE_INCLUDE_DIRECTORIES
$<TARGET_PROPERTY:${SRC},INTERFACE_INCLUDE_DIRECTORIES>
INTERFACE_SYSTEM_INCLUDE_DIRECTORIES
$<TARGET_PROPERTY:${SRC},INTERFACE_SYSTEM_INCLUDE_DIRECTORIES>)
endmacro()
##############################################################################
# Creating a Caffe2 binary target with sources specified with relative path.
# Usage:
# caffe2_binary_target(target_name_or_src <src1> [<src2>] [<src3>] ...)
# If only target_name_or_src is specified, this target is build with one single
# source file and the target name is autogen from the filename. Otherwise, the
# target name is given by the first argument and the rest are the source files
# to build the target.
function(caffe2_binary_target target_name_or_src)
# https://cmake.org/cmake/help/latest/command/function.html
# Checking that ARGC is greater than # is the only way to ensure
# that ARGV# was passed to the function as an extra argument.
if (ARGC GREATER 1)
set(__target ${target_name_or_src})
prepend(__srcs "${CMAKE_CURRENT_SOURCE_DIR}/" "${ARGN}")
else()
get_filename_component(__target ${target_name_or_src} NAME_WE)
prepend(__srcs "${CMAKE_CURRENT_SOURCE_DIR}/" "${target_name_or_src}")
endif()
add_executable(${__target} ${__srcs})
target_link_libraries(${__target} ${Caffe2_MAIN_LIBS})
# If we have Caffe2_MODULES defined, we will also link with the modules.
if (DEFINED Caffe2_MODULES)
target_link_libraries(${__target} ${Caffe2_MODULES})
endif()
if (USE_TBB)
target_include_directories(${__target} PUBLIC ${TBB_ROOT_DIR}/include)
endif()
install(TARGETS ${__target} DESTINATION bin)
endfunction()
function(caffe2_hip_binary_target target_name_or_src)
if (ARGC GREATER 1)
set(__target ${target_name_or_src})
prepend(__srcs "${CMAKE_CURRENT_SOURCE_DIR}/" "${ARGN}")
else()
get_filename_component(__target ${target_name_or_src} NAME_WE)
prepend(__srcs "${CMAKE_CURRENT_SOURCE_DIR}/" "${target_name_or_src}")
endif()
caffe2_binary_target(${target_name_or_src})
target_compile_options(${__target} PRIVATE ${HIP_CXX_FLAGS})
target_include_directories(${__target} PRIVATE ${Caffe2_HIP_INCLUDE})
endfunction()
##############################################################################
# Multiplex between loading executables for CUDA versus HIP (AMD Software Stack).
# Usage:
# torch_cuda_based_add_executable(cuda_target)
#
macro(torch_cuda_based_add_executable cuda_target)
IF (USE_ROCM)
hip_add_executable(${cuda_target} ${ARGN})
ELSEIF(USE_CUDA)
cuda_add_executable(${cuda_target} ${ARGN})
ELSE()
ENDIF()
endmacro()
##############################################################################
# Multiplex between adding libraries for CUDA versus HIP (AMD Software Stack).
# Usage:
# torch_cuda_based_add_library(cuda_target)
#
macro(torch_cuda_based_add_library cuda_target)
IF (USE_ROCM)
hip_add_library(${cuda_target} ${ARGN})
ELSEIF(USE_CUDA)
cuda_add_library(${cuda_target} ${ARGN})
ELSE()
ENDIF()
endmacro()
##############################################################################
# Get the NVCC arch flags specified by TORCH_CUDA_ARCH_LIST and CUDA_ARCH_NAME.
# Usage:
# torch_cuda_get_nvcc_gencode_flag(variable_to_store_flags)
#
macro(torch_cuda_get_nvcc_gencode_flag store_var)
# setting nvcc arch flags
if ((NOT EXISTS ${TORCH_CUDA_ARCH_LIST}) AND (DEFINED ENV{TORCH_CUDA_ARCH_LIST}))
message(WARNING
"In the future we will require one to explicitly pass "
"TORCH_CUDA_ARCH_LIST to cmake instead of implicitly setting it as an "
"env variable. This will become a FATAL_ERROR in future version of "
"pytorch.")
set(TORCH_CUDA_ARCH_LIST $ENV{TORCH_CUDA_ARCH_LIST})
endif()
if (EXISTS ${CUDA_ARCH_NAME})
message(WARNING
"CUDA_ARCH_NAME is no longer used. Use TORCH_CUDA_ARCH_LIST instead. "
"Right now, CUDA_ARCH_NAME is ${CUDA_ARCH_NAME} and "
"TORCH_CUDA_ARCH_LIST is ${TORCH_CUDA_ARCH_LIST}.")
set(TORCH_CUDA_ARCH_LIST TORCH_CUDA_ARCH_LIST ${CUDA_ARCH_NAME})
endif()
# Invoke cuda_select_nvcc_arch_flags from proper cmake FindCUDA.
cuda_select_nvcc_arch_flags(${store_var} ${TORCH_CUDA_ARCH_LIST})
endmacro()
##############################################################################
# Add standard compile options.
# Usage:
# torch_compile_options(lib_name)
function(torch_compile_options libname)
set_property(TARGET ${libname} PROPERTY CXX_STANDARD 14)
if (NOT INTERN_BUILD_MOBILE OR NOT BUILD_CAFFE2_MOBILE)
# until they can be unified, keep these lists synced with setup.py
if(MSVC)
if (MSVC_Z7_OVERRIDE)
set(MSVC_DEBINFO_OPTION "/Z7")
else()
set(MSVC_DEBINFO_OPTION "/Zi")
endif()
target_compile_options(${libname} PUBLIC
${MSVC_RUNTIME_LIBRARY_OPTION}
${MSVC_DEBINFO_OPTION}
/EHa
/DNOMINMAX
/wd4267
/wd4251
/wd4522
/wd4522
/wd4838
/wd4305
/wd4244
/wd4190
/wd4101
/wd4996
/wd4275
/bigobj
)
else()
target_compile_options(${libname} PUBLIC
# -std=c++14
-Wall
-Wextra
-Wno-unused-parameter
-Wno-missing-field-initializers
-Wno-write-strings
-Wno-unknown-pragmas
# Clang has an unfixed bug leading to spurious missing braces
# warnings, see https://bugs.llvm.org/show_bug.cgi?id=21629
-Wno-missing-braces
)
if(NOT APPLE)
target_compile_options(${libname} PRIVATE
# Considered to be flaky. See the discussion at
# https://github.com/pytorch/pytorch/pull/9608
-Wno-maybe-uninitialized)
endif()
endif()
if (MSVC)
elseif (WERROR)
target_compile_options(${libname} PRIVATE -Werror -Wno-strict-overflow)
endif()
endif()
if (NOT WIN32 AND NOT USE_ASAN)
# Enable hidden visibility by default to make it easier to debug issues with
# TORCH_API annotations. Hidden visibility with selective default visibility
# behaves close enough to Windows' dllimport/dllexport.
#
# Unfortunately, hidden visibility messes up some ubsan warnings because
# templated classes crossing library boundary get duplicated (but identical)
# definitions. It's easier to just disable it.
target_compile_options(${libname} PRIVATE "-fvisibility=hidden")
endif()
# Use -O2 for release builds (-O3 doesn't improve perf, and -Os results in perf regression)
target_compile_options(${libname} PRIVATE "$<$<OR:$<CONFIG:Release>,$<CONFIG:RelWithDebInfo>>:-O2>")
# ---[ Check if warnings should be errors.
# TODO: Dedupe with WERROR check above
if (WERROR)
target_compile_options(${libname} PRIVATE -Werror)
endif()
endfunction()
##############################################################################
# Set standard target properties.
# Usage:
# torch_set_target_props(lib_name)
function(torch_set_target_props libname)
if(MSVC AND AT_MKL_MT)
set_target_properties(${libname} PROPERTIES LINK_FLAGS_RELEASE "/NODEFAULTLIB:${VCOMP_LIB}")
set_target_properties(${libname} PROPERTIES LINK_FLAGS_DEBUG "/NODEFAULTLIB:${VCOMP_LIB}")
set_target_properties(${libname} PROPERTIES STATIC_LIBRARY_FLAGS "/NODEFAULTLIB:${VCOMP_LIB}")
endif()
endfunction()
list(PREPEND <list> [<element> ...])