cmake:cmake-buildsystem

2023-11-13

介绍

基于cmake的构建系统被组织为一组高级逻辑目标。每个目标对应于一个可执行文件或者库,或者是一个包含自定义命令的自定义目标。目标之间的依赖关系在buildsystem中表示,以确定生成顺序和响应更改的重新生成规则

二进制目标

可执行文件和库是使用add_executable()和add_library()命令定义的。生成的二进制文件是具有针对目标平台的适当前缀、后缀和扩展名。二进制目标之间的依赖关系使用target_link_libraries()命令表示:

add_library(archive archive.cpp zip.cpp lzma.cpp)
add_executable(zipapp zipapp.cpp)
target_link_libraries(zipapp archive)
  • archive被定义为一个静态库—一个包含从archive.cpp、 zip.cpp、 lzma.cpp编译的对象的归档。
  • zipapp被定义为听过编译和链接zipapp.cpp而形成的可执行文件。
  • 当链接zipapp可执行文件时,将链接archive静态库

二进制可执行文件

add_executable()命令定义了一个可执行的目标:

add_executable(mytool mytool.cpp)

add_custom_command()之类的命令可以透明的将EXECUTABLE目标用作COMMAND可执行文件,它生成在构建时运行的规则。构建系统规则将确保在尝试运行命令之前构建可执行文件

二进制库类型

正常库

除非指定了类型,否则add_library()默认定义静态库。指定动态库还是静态库的命令如下:

add_library(archive SHARED archive.cpp zip.cpp lzma.cpp)
add_library(archive STATIC archive.cpp zip.cpp lzma.cpp)

默认情况下,可以启用BUILD_SHARED_LIBS变量来改变add_library()的行为来构建共享库。

在构建系统定义作为一个整体的上下文中,特定的库是共享的还是静态的很大程序上是无关紧要的------命令、依赖规范和其他API的工作方式与库类型无关。MODULE库类型的不同之处在于它通常没有被链接到------它没有被用在target_link_libraries()命令的右侧。它是一种使用运行时技术作为插件加载的类型。如果库没有导出任何非托管符号(例如Windows资源DLL, c++ /CLI DLL),则要求该库不是共享库,因为CMake期望共享库至少导出一个符号。

add_library(archive MODULE 7z.cpp)

Apple Frameworks

  • 一个共享库可以被标记为【FRAMEWORK】目标属性来创建一个macOS或iOS框架包。
  • 带有FRAMEWORK目标属性的库也应该设置【FRAMEWORK_VERSION】目标属性。macOS约定通常将此属性设置为“A”值。
  • 【MACOSX_FRAMEWORK_IDENTIFIER】设置CFBundleIdentifier键值,它唯一地标识bundle。
add_library(MyFramework SHARED MyFramework.cpp)
set_target_properties(MyFramework PROPERTIES
  FRAMEWORK TRUE
  FRAMEWORK_VERSION A # Version "A" is macOS convention
  MACOSX_FRAMEWORK_IDENTIFIER org.cmake.MyFramework
)

OBJECT 库

OBJECT库类型定义了编译给定源文件所产生的对象文件的非归档集合。对象文件集合可以使用$语法作为其他目标的源输入。这是一个生成器表达式,可用于向其他目标提供OBJECT库内容:

add_library(archive OBJECT archive.cpp zip.cpp lzma.cpp)

add_library(archiveExtras STATIC $<TARGET_OBJECTS:archive> extras.cpp)

add_executable(test_exe $<TARGET_OBJECTS:archive> test.cpp)

那些其他目标的链接(或归档)步骤除了使用来自它们自己源的文件外,还将使用目标文件集合。

或者,对象库可以链接到其他目标:

add_library(archive OBJECT archive.cpp zip.cpp lzma.cpp)

add_library(archiveExtras STATIC extras.cpp)
target_link_libraries(archiveExtras PUBLIC archive)

add_executable(test_exe test.cpp)
target_link_libraries(test_exe archive)

那些其他目标的链接(或存档)步骤将使用直接链接的object库中的对象文件。此外,在编译其他目标中的源代码时,OBJECT库的使用需求将得到尊重。此外,这些使用需求将传递到其他目标的依赖项。

在使用add_custom_command(TARGET)命令签名时,不能将对象库用作目标。但是,add_custom_command(OUTPUT)或file(GENERATE)可以使用$来使用对象列表。

  • CMake的library目标,有一个OBJECT模式,这个模式的library不会被archive成静态库,而是一个“假的”库,产物是一堆对象文件。
add_library(my_library OBJECT foo.cpp bar.cpp baz.cpp)
  • 使用时比较特别,你必须使用“这个目标的对象文件”的生成表达式,放在add_executable、add_library放源代码的位置,而不是target_link_library的位置:
add_executable(my_app my_app.cpp $<TARGET_OBJECTS:my_library>)
add_library(my_static_lib STATIC some_other_source.cpp $<TARGET_OBJECTS:my_library>)
  • 不过这种需求并不太寻常,大部分情况下你可以用静态库目标来做同样的事情,因为静态库实际上就是对象文件打包,没有做特别的事情。我能想到的唯一必须这么做的理由,就是你想把项目分成几个部分,而这几个部分之间的符号依赖是一锅粥,打包成静态库之后,链接时顺序搞不定。

构建规范和使用要求

target_include_directories()、target_compile_definitions()和target_compile_options()命令指定了二进制目标的构建规范和使用要求。这些命令分别填充INCLUDE_DIRECTORIES、COMPILE_DEFINITIONS和COMPILE_OPTIONS目标属性,以及/或INTERFACE_INCLUDE_DIRECTORIES、INTERFACE_COMPILE_DEFINITIONS和INTERFACE_COMPILE_OPTIONS目标属性。

每个命令都有一个PRIVATE、PUBLIC和INTERFACE【interface_接口)】模式。

  • PRIVATE模式仅填充目标属性的非INTERFACE_变体,
  • INTERFACE模式仅填充INTERFACE_变体。
  • PUBLIC模式填充各自目标属性的两个变体。

每个命令可以通过多个关键字来调用:

target_compile_definitions(archive
  PRIVATE BUILDING_WITH_LZMA
  INTERFACE USING_ARCHIVE_LIB
)

请注意,使用需求并不是为了方便而让下游使用特定的COMPILE_OPTIONS或compile_definition等。属性的内容必须是要求,而不仅仅是建议或方便。

请参阅cmake-packages(7)手册的“创建可重定位包”一节,讨论在为重分配创建包时指定使用要求时必须注意的额外事项。

目标属性(Target Properties)

当编译二进制目标的源文件时,INCLUDE_DIRECTORIES, COMPILE_DEFINITIONS和COMPILE_OPTIONS目标属性的内容被适当地使用。

  • INCLUDE_DIRECTORIES中的条目以-I或- system前缀和属性值中出现的顺序添加到编译行。
  • COMPILE_DEFINITIONS中的条目以-D或/D作为前缀,并以未指定的顺序添加到编译行中。DEFINE_SYMBOL目标属性也被添加为编译定义,作为SHARED和MODULE库目标的一种特殊方便的情况。
  • COMPILE_OPTIONS中的条目被转义为shell,并按属性值中出现的顺序添加。有几个编译选项有特殊的单独处理,比如POSITION_INDEPENDENT_CODE。

INTERFACE_INCLUDE_DIRECTORIES、INTERFACE_COMPILE_DEFINITIONS和INTERFACE_COMPILE_OPTIONS目标属性的内容是使用需求——它们指定用户必须使用的内容,以便正确编译并与显示它们的目标链接。对于任何二进制目标,target_link_libraries()命令中指定的每个目标上的每个INTERFACE_属性的内容都会被消耗:

set(srcs archive.cpp zip.cpp)
if (LZMA_FOUND)
  list(APPEND srcs lzma.cpp)
endif()
add_library(archive SHARED ${srcs})
if (LZMA_FOUND)
  # The archive library sources are compiled with -DBUILDING_WITH_LZMA
  target_compile_definitions(archive PRIVATE BUILDING_WITH_LZMA)
endif()
target_compile_definitions(archive INTERFACE USING_ARCHIVE_LIB)

add_executable(consumer)
# Link consumer to archive and consume its usage requirements. The consumer
# executable sources are compiled with -DUSING_ARCHIVE_LIB.
target_link_libraries(consumer archive)

因为通常需要将源目录和相应的构建目录添加到INCLUDE_DIRECTORIES中,所以可以启用CMAKE_INCLUDE_CURRENT_DIR变量来方便地将相应的目录添加到所有目标的INCLUDE_DIRECTORIES中。可以启用变量CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE,将相应的目录添加到所有目标的INTERFACE_INCLUDE_DIRECTORIES中。通过使用target_link_libraries()命令,可以方便地使用多个不同目录中的目标。

可传递的使用要求

目标的使用需求可以传递到依赖项。target_link_libraries()命令具有PRIVATE、INTERFACE和PUBLIC关键字来控制传播。

add_library(archive archive.cpp)
target_compile_definitions(archive INTERFACE USING_ARCHIVE_LIB)

add_library(serialization serialization.cpp)
target_compile_definitions(serialization INTERFACE USING_SERIALIZATION_LIB)

add_library(archiveExtras extras.cpp)
target_link_libraries(archiveExtras PUBLIC archive)
target_link_libraries(archiveExtras PRIVATE serialization)
# archiveExtras is compiled with -DUSING_ARCHIVE_LIB
# and -DUSING_SERIALIZATION_LIB

add_executable(consumer consumer.cpp)
# consumer is compiled with -DUSING_ARCHIVE_LIB
target_link_libraries(consumer archiveExtras)

因为archive是archiveExtras的公共依赖项,所以它的使用需求也会传播给消费者。因为序列化是archiveExtras的私有依赖项,所以它的使用需求不会传播给消费者。

  • 通常,如果依赖项只在库的实现中使用,而不是在头文件中使用,则应该使用target_link_libraries()和PRIVATE关键字指定依赖项。
  • 如果一个依赖项在库的头文件中被额外使用(例如用于类继承),那么它应该被指定为PUBLIC依赖项。
  • 一个库的实现没有使用的依赖项,而只有它的头文件使用的依赖项,应该被指定为一个INTERFACE依赖项。

target_link_libraries()命令可以通过多个关键字调用:

target_link_libraries(archiveExtras
  PUBLIC archive
  PRIVATE serialization
)

通过从依赖项中读取目标属性的INTERFACE_变量并将值附加到操作数的非INTERFACE_变量来传播。

例如,读取依赖项的INTERFACE_INCLUDE_DIRECTORIES并将其附加到操作数的INCLUDE_DIRECTORIES。如果顺序是相关的,并且由target_link_libraries()调用产生的顺序不允许正确的编译,那么使用适当的命令直接设置属性可以更新顺序。

例如,如果目标的链接库必须按顺序lib1 lib2 lib3指定,但包含目录必须按顺序lib3 lib1 lib2指定:

target_link_libraries(myExe lib1 lib2 lib3)
target_include_directories(myExe
  PRIVATE $<TARGET_PROPERTY:lib3,INTERFACE_INCLUDE_DIRECTORIES>)

请注意,在指定目标的使用要求时必须小心,这些目标将使用install(EXPORT)命令导出用于安装。有关更多信息,请参见创建包

兼容的接口属性

一些目标属性需要在目标和每个依赖项的接口之间兼容。比如,POSITION_INDEPENDENT_CODE 目标属性可以指定一个bool值,即是否应该将目标编译为位置独立的代码,这具有特定于平台的结果。目标还可以指定使用要求INTERFACE_POSITION_INDEPENDENT_CODE来通信,即消费者必须编译为位置无关码

add_executable(exe1 exe1.cpp)
set_property(TARGET exe1 PROPERTY POSITION_INDEPENDENT_CODE ON)

add_library(lib1 SHARED lib1.cpp)
set_property(TARGET lib1 PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE ON)

add_executable(exe2 exe2.cpp)
target_link_libraries(exe2 lib1)

这里,exe1和exec2都被编译为位置无关码。lib1也将编译为位置无关码,因为这是共享库的默认设置。如果依赖是有冲突的,不兼容的需求,cmake会发出一个诊断

add_library(lib1 SHARED lib1.cpp)
set_property(TARGET lib1 PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE ON)

add_library(lib2 SHARED lib2.cpp)
set_property(TARGET lib2 PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE OFF)

add_executable(exe1 exe1.cpp)
target_link_libraries(exe1 lib1)
set_property(TARGET exe1 PROPERTY POSITION_INDEPENDENT_CODE OFF)

add_executable(exe2 exe2.cpp)
target_link_libraries(exe2 lib1 lib2)

lib1要求INTERFACE_POSITION_INDEPENDENT_CODE与exe1目标的POSITION_INDEPENDENT_CODE属性不“兼容”。库要求消费者构建为位置无关的代码,而可执行文件指定不构建为位置无关的代码,因此会发出诊断。

lib1和lib2需求不“兼容”。其中一个要求消费者是作为位置无关的代码构建的,而另一个要求消费者不是作为位置无关的代码构建的。因为exe2链接到两者,并且它们在冲突中,一个CMake错误消息被发出:

CMake Error: The INTERFACE_POSITION_INDEPENDENT_CODE property of "lib2" does
not agree with the value of POSITION_INDEPENDENT_CODE already determined
for "exe2".

要做到“兼容”,POSITION_INDEPENDENT_CODE属性(如果设置了该属性)必须在布尔意义上与所有传递指定的依赖项的INTERFACE_POSITION_INDEPENDENT_CODE属性相同。

通过在COMPATIBLE_INTERFACE_BOOL目标属性的内容中指定该属性,“兼容接口需求”的这个属性可以扩展到其他属性。每个指定的属性必须在消费目标和每个依赖项中带有INTERFACE_前缀的相应属性之间兼容:

add_library(lib1Version2 SHARED lib1_v2.cpp)
set_property(TARGET lib1Version2 PROPERTY INTERFACE_CUSTOM_PROP ON)
set_property(TARGET lib1Version2 APPEND PROPERTY
  COMPATIBLE_INTERFACE_BOOL CUSTOM_PROP
)

add_library(lib1Version3 SHARED lib1_v3.cpp)
set_property(TARGET lib1Version3 PROPERTY INTERFACE_CUSTOM_PROP OFF)

add_executable(exe1 exe1.cpp)
target_link_libraries(exe1 lib1Version2) # CUSTOM_PROP will be ON

add_executable(exe2 exe2.cpp)
target_link_libraries(exe2 lib1Version2 lib1Version3) # Diagnostic

非布尔属性也可以参与“兼容接口”的计算。在COMPATIBLE_INTERFACE_STRING属性中指定的属性必须是未指定的,或者在所有传递指定的依赖项中与相同的字符串进行比较。这有助于确保库的多个不兼容版本不会通过目标的传递需求链接到一起:

add_library(lib1Version2 SHARED lib1_v2.cpp)
set_property(TARGET lib1Version2 PROPERTY INTERFACE_LIB_VERSION 2)
set_property(TARGET lib1Version2 APPEND PROPERTY
  COMPATIBLE_INTERFACE_STRING LIB_VERSION
)

add_library(lib1Version3 SHARED lib1_v3.cpp)
set_property(TARGET lib1Version3 PROPERTY INTERFACE_LIB_VERSION 3)

add_executable(exe1 exe1.cpp)
target_link_libraries(exe1 lib1Version2) # LIB_VERSION will be "2"

add_executable(exe2 exe2.cpp)
target_link_libraries(exe2 lib1Version2 lib1Version3) # Diagnostic

COMPATIBLE_INTERFACE_NUMBER_MAX目标属性指定内容将以数字方式计算,并计算所有指定内容中的最大数量:

add_library(lib1Version2 SHARED lib1_v2.cpp)
set_property(TARGET lib1Version2 PROPERTY INTERFACE_CONTAINER_SIZE_REQUIRED 200)
set_property(TARGET lib1Version2 APPEND PROPERTY
  COMPATIBLE_INTERFACE_NUMBER_MAX CONTAINER_SIZE_REQUIRED
)

add_library(lib1Version3 SHARED lib1_v3.cpp)
set_property(TARGET lib1Version3 PROPERTY INTERFACE_CONTAINER_SIZE_REQUIRED 1000)

add_executable(exe1 exe1.cpp)
# CONTAINER_SIZE_REQUIRED will be "200"
target_link_libraries(exe1 lib1Version2)

add_executable(exe2 exe2.cpp)
# CONTAINER_SIZE_REQUIRED will be "1000"
target_link_libraries(exe2 lib1Version2 lib1Version3)

类似地,可以使用COMPATIBLE_INTERFACE_NUMBER_MIN从依赖项计算属性的最小数值。

每个计算出的“兼容的”属性值可以在生成时使用生成器表达式在消费者中读取。

请注意,对于每个依赖项,在每个兼容接口属性中指定的属性集不能与任何其他属性中指定的属性集相交。

Property Origin Debugging

因为构建规范可以由依赖关系决定,缺少创建目标的代码和负责设置构建规范的代码的局地性可能会使得代码更难以推理。cmake提供了一个调试工具来打印属性内容来源,这些属性可能由依赖关系决定。可以调试的属性在CMAKE_DEBUG_TARGET_PROPERTIES变量文档中列出:

set(CMAKE_DEBUG_TARGET_PROPERTIES
  INCLUDE_DIRECTORIES
  COMPILE_DEFINITIONS
  POSITION_INDEPENDENT_CODE
  CONTAINER_SIZE_REQUIRED
  LIB_VERSION
)
add_executable(exe1 exe1.cpp)

对于在COMPATIBLE_INTERFACE_BOOL或COMPATIBLE_INTERFACE_STRING中列出的属性,调试输出显示了哪个目标负责设置该属性,以及哪个其他依赖项也定义了该属性。在COMPATIBLE_INTERFACE_NUMBER_MAX和COMPATIBLE_INTERFACE_NUMBER_MIN的情况下,调试输出显示每个依赖项的属性值,以及该值是否决定了新的极限。

使用生成器表达式构建规范

构建规范可以使用包含有条件内容或仅在生成时已知内容的生成器表达式。例如,一个属性的“compatible”值可以用TARGET_PROPERTY表达式读取:

add_library(lib1Version2 SHARED lib1_v2.cpp)
set_property(TARGET lib1Version2 PROPERTY
  INTERFACE_CONTAINER_SIZE_REQUIRED 200)
set_property(TARGET lib1Version2 APPEND PROPERTY
  COMPATIBLE_INTERFACE_NUMBER_MAX CONTAINER_SIZE_REQUIRED
)

add_executable(exe1 exe1.cpp)
target_link_libraries(exe1 lib1Version2)
target_compile_definitions(exe1 PRIVATE
    CONTAINER_SIZE=$<TARGET_PROPERTY:CONTAINER_SIZE_REQUIRED>
)

在本例中,将使用-DCONTAINER_SIZE=200编译exe1源文件。

可以使用CONFIG生成器表达式方便地设置配置确定的构建规范。

target_compile_definitions(exe1 PRIVATE
    $<$<CONFIG:Debug>:DEBUG_BUILD>
)

链接库和生成器表达式

与构建规范一样,可以使用生成器表达式条件来指定链接库。然而,由于使用需求的消耗是基于来自链接依赖项的收集,因此存在一个额外的限制,即链接依赖项必须形成一个“有向无环图”。也就是说,如果对目标的链接依赖于目标属性的值,则该目标属性可能不依赖于所链接的依赖项:

add_library(lib1 lib1.cpp)
add_library(lib2 lib2.cpp)
target_link_libraries(lib1 PUBLIC
  $<$<TARGET_PROPERTY:POSITION_INDEPENDENT_CODE>:lib2>
)
add_library(lib3 lib3.cpp)
set_property(TARGET lib3 PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE ON)

add_executable(exe1 exe1.cpp)
target_link_libraries(exe1 lib1 lib3)

由于exe1目标的POSITION_INDEPENDENT_CODE属性的值依赖于被链接的库(lib3),而链接exe1的边缘由相同的POSITION_INDEPENDENT_CODE属性决定,上面的依赖关系图包含了一个循环。Cmake(1)发出一个错误消息。

输出构件

由add_library()和add_executable()命令创建的构建系统目标创建规则来创建二进制输出。二进制文件的准确输出位置只能在生成时确定,因为它可以依赖于链接依赖的构建配置和链接语言等。TARGET_FILE、TARGET_LINKER_FILE和相关表达式可以用来访问生成的二进制文件的名称和位置。然而,这些表达式并不适用于OBJECT库,因为这些库生成的文件中没有一个是与表达式相关的。

有三种类型的输出工件可以由目标构建,如下面的部分中详细介绍。它们的分类在DLL平台和非DLL平台之间是不同的。包括Cygwin在内的所有基于windows的系统都是DLL平台。

运行时输出构件

构建系统目标的运行时输出构件可能是:

  • 由add_executable()命令创建的可执行目标的可执行文件(例如.exe)。
  • 在DLL平台上:由add_library()命令和shared选项创建的共享库目标的可执行文件(例如. DLL)。

RUNTIME_OUTPUT_DIRECTORY和RUNTIME_OUTPUT_NAME目标属性可以用于控制构建树中运行时输出构件的位置和名称。

库输出构件

构建系统目标的库输出构件可能是:

  • 模块库目标的可加载模块文件(例如.dll或.so),由add_library()命令和module选项创建。
  • 在非dll平台上:由add_library()命令和shared选项创建的共享库目标的共享库文件(例如.so或.dylib)。

LIBRARY_OUTPUT_DIRECTORY和LIBRARY_OUTPUT_NAME目标属性可以用来控制库输出构件在构建树中的位置和名称。

档案输出构件

构建系统目标的存档输出构件可能是:

  • 由add_library()命令和static选项创建的静态库目标的静态库文件(例如.lib或.a)。
  • 在DLL平台上:通过add_library()命令和shared选项创建的共享库目标的导入库文件(例如.lib)。只有当库导出至少一个非托管符号时,才保证此文件存在。
  • 在DLL平台上:当设置了ENABLE_EXPORTS目标属性时,由add_executable()命令创建的可执行目标的导入库文件(例如.lib)。
  • 在AIX上:当设置了ENABLE_EXPORTS目标属性时,由add_executable()命令创建的可执行目标的连接器导入文件(例如.imp)。

ARCHIVE_OUTPUT_DIRECTORY和ARCHIVE_OUTPUT_NAME目标属性可以用来控制归档输出工件在构建树中的位置和名称。

Directory-Scoped命令

target_include_directories()、target_compile_definitions()和target_compile_options()命令一次只能对一个目标生效。命令add_compile_definitions()、add_compile_options()和include_directories()具有类似的功能,但是为了方便起见,它们是在目录作用域而不是目标作用域操作的。

伪目标

有些目标类型并不表示构建系统的输出,而是只表示外部依赖项、别名或其他非构建构件等输入。生成的构建系统中不表示伪目标。

导入目标

导入的目标表示预先存在的依赖项。通常这样的目标是由上游包定义的,应该被视为不可变的。在声明一个导入的目标之后,可以通过使用习惯的命令,如target_compile_definitions()、target_include_directories()、target_compile_options()或target_link_libraries()来调整它的目标属性,就像其他常规目标一样。

导入的目标可能具有与二进制目标相同的使用需求属性,例如INTERFACE_INCLUDE_DIRECTORIES、INTERFACE_COMPILE_DEFINITIONS、INTERFACE_COMPILE_OPTIONS、INTERFACE_LINK_LIBRARIES和INTERFACE_POSITION_INDEPENDENT_CODE。

LOCATION也可以从导入的目标读取,尽管很少有这样做的理由。像add_custom_command()这样的命令可以透明地使用导入的可执行目标作为COMMAND可执行文件。

导入目标定义的范围是定义它的目录。它可以从子目录访问和使用,但不能从父目录或兄弟目录访问和使用。作用域类似于cmake变量的作用域。

也可以定义一个在构建系统中可以全局访问的全局导入目标。

关于使用导入的目标创建包的更多信息,请参阅cmake-packages(7)手册

别名目标

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

cmake:cmake-buildsystem 的相关文章

  • 如何使用 C# 中的参数将用户重定向到 paypal

    如果我有像下面这样的简单表格 我可以用它来将用户重定向到 PayPal 以完成付款
  • C 编程 - 文件 - fwrite

    我有一个关于编程和文件的问题 while current NULL if current gt Id Doctor 0 current current gt next id doc current gt Id Doctor if curre
  • Asp.NET WebApi 中类似文件名称的路由

    是否可以在 ASP NET Web API 路由配置中添加一条路由 以允许处理看起来有点像文件名的 URL 我尝试添加以下条目WebApiConfig Register 但这不起作用 使用 URIapi foo 0de7ebfa 3a55
  • 如何使用 ICU 解析汉字数字字符?

    我正在编写一个使用 ICU 来解析由汉字数字字符组成的 Unicode 字符串的函数 并希望返回该字符串的整数值 五 gt 5 三十一 gt 31 五千九百七十二 gt 5972 我将区域设置设置为 Locale getJapan 并使用
  • 在 Windows 窗体中保存带有 Alpha 通道的单色位图会保存不同(错误)的颜色

    在 C NET 2 0 Windows 窗体 Visual Studio Express 2010 中 我保存由相同颜色组成的图像 Bitmap bitmap new Bitmap width height PixelFormat Form
  • 关于 C++ 转换:参数 1 从“[some_class]”到“[some_class]&”没有已知的转换

    我正在研究 C 并且遇到了一个错误 我不知道确切的原因 我已经找到了解决方案 但仍然想知道原因 class Base public void something Base b int main Base b b something Base
  • 带动态元素的 WPF 启动屏幕。如何?

    我是 WPF 新手 我需要一些帮助 我有一个加载缓慢的 WPF 应用程序 因此我显示启动屏幕作为权宜之计 但是 我希望能够在每次运行时更改屏幕 并在文本区域中显示不同的引言 这是一个生产力应用程序 所以我将使用非愚蠢但激励性的引言 当然 如
  • 使用 Bearer Token 访问 IdentityServer4 上受保护的 API

    我试图寻找此问题的解决方案 但尚未找到正确的搜索文本 我的问题是 如何配置我的 IdentityServer 以便它也可以接受 授权带有 BearerTokens 的 Api 请求 我已经配置并运行了 IdentityServer4 我还在
  • 如何设计以 char* 指针作为类成员变量的类?

    首先我想介绍一下我的情况 我写了一些类 将 char 指针作为私有类成员 而且这个项目有 GUI 所以当单击按钮时 某些函数可能会执行多次 这些类是设计的单班在项目中 但是其中的某些函数可以执行多次 然后我发现我的项目存在内存泄漏 所以我想
  • SolrNet连接说明

    为什么 SolrNet 连接的容器保持静态 这是一个非常大的错误 因为当我们在应用程序中向应用程序发送异步请求时 SolrNet 会表现异常 在 SolrNet 中如何避免这个问题 class P static void M string
  • 如何序列化/反序列化自定义数据集

    我有一个 winforms 应用程序 它使用强类型的自定义数据集来保存数据进行处理 它由数据库中的数据填充 我有一个用户控件 它接受任何自定义数据集并在数据网格中显示内容 这用于测试和调试 为了使控件可重用 我将自定义数据集视为普通的 Sy
  • 这些作业之间是否存在顺序点?

    以下代码中的两个赋值之间是否存在序列点 f f x 1 1 x 2 不 没有 在这种情况下 标准确实是含糊不清的 如果你想确认这一点 gcc 有这个非常酷的选项 Wsequence point在这种情况下 它会警告您该操作可能未定义
  • 对现有视频添加水印

    我正在寻找一种用 C 在视频上加水印的方法 就像在上面写文字一样 图片或文字标签 我该怎么做 谢谢 您可以使用 Nreco 视频转换器 代码看起来像 NReco VideoConverter FFMpegConverter wrap new
  • 通过指向其基址的指针删除 POD 对象是否安全?

    事实上 我正在考虑那些微不足道的可破坏物体 而不仅仅是POD http en wikipedia org wiki Plain old data structure 我不确定 POD 是否可以有基类 当我读到这个解释时is triviall
  • 如何将带有 IP 地址的连接字符串放入 web.config 文件中?

    我们当前在 web config 文件中使用以下连接字符串 add name DBConnectionString connectionString Data Source ourServer Initial Catalog ourDB P
  • 将控制台重定向到 .NET 程序中的字符串

    如何重定向写入控制台的任何内容以写入字符串 对于您自己的流程 Console SetOut http msdn microsoft com en us library system console setout aspx并将其重定向到构建在
  • C# 成员变量继承

    我对 C 有点陌生 但我在编程方面有相当广泛的背景 我想做的事情 为游戏定义不同的 MapTiles 我已经像这样定义了 MapTile 基类 public class MapTile public Texture2D texture pu
  • Windows 和 Linux 上的线程

    我在互联网上看到过在 Windows 上使用 C 制作多线程应用程序的教程 以及在 Linux 上执行相同操作的其他教程 但不能同时用于两者 是否存在即使在 Linux 或 Windows 上编译也能工作的函数 您需要使用一个包含两者的实现
  • C++ 标准是否指定了编译器的 STL 实现细节?

    在写答案时this https stackoverflow com questions 30909296 can you put a pimpl class inside a vector我遇到了一个有趣的情况 这个问题演示了这样一种情况
  • 对来自流读取器的过滤数据执行小计

    编辑问题未得到解答 我有一个基于 1 个标准的过滤输出 前 3 个数字是 110 210 或 310 给出 3 个不同的组 从流阅读器控制台 问题已编辑 因为第一个答案是我给出的具体示例的字面解决方案 我使用的实际字符串长度为 450 个

随机推荐

  • 如何使用微服务架构进行项目开发?

    随着软件开发的发展 微服务架构在企业和互联网项目中越来越普遍 内部功能模块独立 高度可扩展和可移植 可在团队成员中实现不同项目的部署和管理 使用微服务架构需要了解相关技术和工具来简化我们的开发工作流程 在本文中 我们将讨论一下微服务架构的实
  • 快速解决AndroidStudio代码提示失效问题

    在编写代码时 代码不自动提示 发现代码自动提示设置正常 所以查询到问题原因在于节能模式的开启 具体解决方式如下 关闭节能模式 如上图所示 将Power Save Mode前面的对勾去掉 则完成节能模式的关闭 代码提示功能正常
  • 【满分】【华为OD机试真题2023B卷 JAVA&JS】篮球比赛

    华为OD2023 B卷 机试题库全覆盖 刷题指南点这里 篮球比赛 知识点广搜 时间限制 1s 空间限制 64MB 限定语言 不限 题目描述 篮球 5V5 比赛中 每个球员拥有一个战斗力 每个队伍的所有球员战斗力之和为该队伍的总体战斗力 现有
  • Makefile “multiple target patterns. Stop.”解决方案

    几天在帮一个同事编译Xen中的tools时 我改了一些config文件 然后就遇到了一个错误 Makefile 72 multiple target patterns Stop 花了大约半个小时才找到了这个错误是自己写错了一个配置的原因 将
  • 《reStructured Pre-training》笔记

    reStructured Pre training 笔记 本文主要记录论文中我觉得比较重要的部分 并加入个人的理解 如有错误请可直接指出 由于格式问题 强烈建议去notion观看 完整版内容请移步notion网页进行详细阅读 谢谢 Abst
  • 【探索Linux】—— 强大的命令行工具 P.5(yum工具、git 命令行提交代码)

    阅读导航 前言 一 软件包管理器 yum 1 yum的概念 yum的基本指令 使用例子 二 git 命令行提交代码 总结 温馨提示 前言 前面我们讲了C语言的基础知识 也了解了一些数据结构 并且讲了有关C 的一些知识 也学习了一些Linux
  • docker java -jar_Docker 部署java jar包

    1 创建一个Dockerfile文件 将Dockerfile文件和jar包放到同一个文件夹下 Dockerfile文件内容 基于java8来构建镜像 FROM java 8 参数设置 ENV PARAMS 设置时区 ENV TZ RPC R
  • 吃鸡账号显示连接不了服务器,《绝地求生》“与Steam服务器连接时出现了一个问题”怎么解决...

    导 读 用STEAM正版的玩家 无论是CSGO DOTA2 CSS的游戏玩家近期升级后会遇到steam错误 无法连接至steam网络这个问题 弄得很头疼 有的玩家说在线等升级其实不是这样 这样根本不能解决这个 用STEAM正版的玩家 无论是
  • 华为云云耀云服务器L实例评测|使用宝塔面板管理服务器教学

    目录 一 概述 1 1 华为云云耀云服务器L实例 1 2 BT 宝塔 1 3 资源和成本规划 二 购买云耀云服务器L实例并进行相关配置 2 1 购买云耀云服务器L实例 2 2 设置服务器密码 2 3 配置安全组 2 4 设置Nginx安全级
  • VJ2-Perfect Squares

    A Perfect Squares time limit per test 1 second memory limit per test 256 megabytes input standard input output standard
  • Qt设置窗口背景,但是不影响控件

    设置窗口背景 代码如下 mainWidget gt setStyleSheet border image url icon 123 但是当添加一些控件之后 会出现下面这种情况 解决方法 只给窗口设置样式 mainWidget gt setO
  • 【Docker】容器化应用程序的配置管理策略与实践

    一 引言 1 1 Docker的背景和优势 Docker是一种开源的容器化平台 简化应用程序的打包 交付和运行过程 基于Linux容器技术 通过提供一个轻量级 可移植和自包含的容器来实现应用程序的隔离和部署 在传统的应用程序开发和部署中 往
  • c语言输入20个数,从小到大建立一个单链表

    一 要求输入20个数 按照从小到大的顺序存入链表中 可以分四步 获取数据 进行排序 插入链表 打印链表 1 定义一个整型数组 用来存储获得的20个数 int a 20 int i for i 0 i lt 20 i scanf d a i
  • 081200计算机科学与技术专业,研究生计算机科学与技术专业排名

    研究生计算机科学与技术专业排名 作者 admin 点击 次 南京大学考研网 nandakaoyan com 南京大学排名 研究生计算机科学与技术专业排名 唯一权威的南京大学考研网站为大家提供 研究生计算机科学与技术专业排名 本站由南京大学研
  • 时间序列预测之区间预测方法(PIs:MVE&Delta&Bayesian&Bootstrap&LUBE)

    文章目录 前言 一 预测区间的评价指标 1 PICP PI coverage probability 2 PINAW PI normalized averaged width 3 CWC coverage width based crite
  • sql developer使用技巧,快捷键

    PL SQL Developer使用技巧 快捷键 1 类SQL PLUS窗口 File gt New gt Command Window 这个类似于oracle的客户端工具sql plus 但比它好用多了 2 设置关键字自动大写 Tools
  • python异常

    一 什么是异常 异常是一个事件 该事件会在程序执行过程中发生 会影响程序的正常运行 一般情况下 python无法正常处理一个异常 会导致程序中断 在出现异常时 为了不影响程序的正常运行 我们需要捕获异常 在python中异常是一个对象 表示
  • UE4 C++创建继承于UEditorSubsystem类时报错

    使用UEditorSubsystem需要在Build cs里加上EditorSubsystem模块的引用 因为这是编辑器模块 if Target bBuildEditor PublicDependencyModuleNames AddRan
  • 人工智能在电力系统中的应用前景怎么样

    人工智能在电力系统中的应用现状 随着人工智能技术的兴起 人工智能技术应用在电力系统的运行 控制 管理等领域 人工智能技术在电力系统中的应用不仅拓展了人工智能技术的应用范围 而且扩展了人工智能技术凭借自动化和智能化程度高等优势 提升了电力产业
  • cmake:cmake-buildsystem

    介绍 基于cmake的构建系统被组织为一组高级逻辑目标 每个目标对应于一个可执行文件或者库 或者是一个包含自定义命令的自定义目标 目标之间的依赖关系在buildsystem中表示 以确定生成顺序和响应更改的重新生成规则 二进制目标 可执行文