CMake构建工具使用教程

news2025/3/1 9:30:02

1.简介

CMake是一个开源的、跨平台的C++构建工具,通过平台和编译器无关的配置文件来声明构建目标,支持Make、ninja、MSBuild等多种底层构建工具,大多数IDE(例如CLion、Visual Studio、Visual Studio Code等)也都支持CMake。

  • 网站:https://cmake.org/
  • 官方文档:CMake Reference Documentation
  • 官方教程:CMake Tutorial

2.安装

  • 下载链接
  • 安装指引

2.1 Windows

在Windows上安装CMake有以下几种方式:

(1)下载MSI安装文件(例如cmake-3.25.2-windows-x86_64.msi)并按照指引安装。

(2)下载压缩文件(例如cmake-3.25.2-windows-x86_64.zip),解压后将其中的bin目录添加到PATH环境变量。

(3)如果安装了Visual Studio,可以通过Visual Studio Installer安装“适用于Windows的C++ CMake工具”,如下图所示。

Visual Studio Installer

2.2 Linux

在Linux上安装CMake有以下几种方式:

(1)下载压缩文件(例如cmake-3.25.2-linux-x86_64.tar.gz),解压后将其中的bin目录添加到PATH环境变量。

(2)下载安装脚本(例如cmake-3.25.2-linux-x86_64.sh)并按照指引安装。

(3)从源代码构建:下载源代码(例如cmake-3.25.2.tar.gz),解压后依次执行以下命令:

./bootstrap
make
make install

2.3 macOS

下载镜像文件(例如cmake-3.25.2-macos-universal.dmg)或压缩文件(例如cmake-3.25.2-macos-universal.tar.gz),将CMake.app拷贝到/Applications目录下,运行后按照 “How to Install For Command Line Use” 菜单项中的指引安装命令行工具,如下图所示。

macOS CMake

安装成功后应该能够在命令行中执行cmake命令:

$ cmake
Usage

  cmake [options] <path-to-source>
  cmake [options] <path-to-existing-build>
  cmake [options] -S <path-to-source> -B <path-to-build>

Specify a source directory to (re-)generate a build system for it in the
current working directory.  Specify an existing build directory to
re-generate its build system.

Run 'cmake --help' for more information.

3.示例

下面使用CMake创建一个简单的C++ Hello World项目。

3.1 创建工作目录

首先创建项目根目录cmake-demo,并在根目录下创建一个文件CMakeLists.txt和一个子目录hello:

mkdir cmake-demo && cd cmake-demo
touch CMakeLists.txt
mkdir hello

其中项目根目录cmake-demo可以在任意位置。

CMake通过名为CMakeLists.txt的文件声明构建目标和依赖关系。 根目录下的CMakeLists.txt内容如下:

cmake_minimum_required(VERSION 3.20)
project(cmake-demo)

set(CMAKE_CXX_STANDARD 14)

其中,cmake_minimum_required()命令指定该项目要求的最低CMake版本,project()命令设置项目名称,set()命令设置CMake变量的值,CMAKE_CXX_STANDARD变量指定C++标准版本。

3.2 实现hello库

在hello目录下创建hello.h和hello.cpp两个文件,内容如下:

hello.h

#pragma once

#include <string>

void hello(const std::string& to);

hello.cpp

#include "hello.h"

#include <iostream>

void hello(const std::string& to) {
    std::cout << "Hello, " << to << "!\n";
}

这两个文件构成了一个函数库hello。

在hello目录下创建另一个CMakeLists.txt文件,在其中声明hello库:

add_library(hello hello.cpp)
target_include_directories(hello INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})

其中,add_library()命令添加了一个函数库构建目标,名字为 “hello”、源文件为hello.cpp;target_include_directories()命令表示所有链接到hello库的构建目标都需要将当前源代码目录(即cmake-demo/hello)添加到头文件包含目录,从而可以直接#include "hello.h"

之后在项目根目录下的CMakeLists.txt结尾添加:

add_subdirectory(hello)

从而将子目录hello中的构建目标包含进来。

3.3 实现hello_world程序

下面创建一个hello_world程序,在main()函数中调用hello库提供的函数来打印信息。

在项目根目录下创建源文件hello_world.cpp,内容如下:

#include "hello.h"

int main() {
    hello("world");
    return 0;
}

在项目根目录下的CMakeLists.txt结尾添加:

add_executable(hello_world hello_world.cpp)
target_link_libraries(hello_world hello)

其中,add_executable()命令添加了一个可执行程序构建目标,名字为 “hello_world”、源文件为hello_world.cpp;target_link_libraries()命令声明了构建目标之间的依赖关系:hello_world依赖hello,即hello_world程序需要链接到hello库。

3.4 构建和运行

为了构建hello_world程序,在项目根目录下执行以下命令:

$ cmake -S . -B cmake-build
-- The C compiler identification is GNU 7.5.0
-- The CXX compiler identification is GNU 7.5.0
...
-- Build files have been written to: .../cmake-demo/cmake-build

$ cmake --build cmake-build
[ 25%] Building CXX object hello/CMakeFiles/hello.dir/hello.cpp.o
[ 50%] Linking CXX static library libhello.a
[ 50%] Built target hello
[ 75%] Building CXX object CMakeFiles/hello_world.dir/hello_world.cpp.o
[100%] Linking CXX executable hello_world
[100%] Built target hello_world

其中,第一步是配置CMake,第二步是生成构建目标。构建完成后将在cmake-build目录下生成可执行程序hello_world,直接执行即可:

$ cmake-build/hello_world 
Hello, world!

完整的项目目录结构如下:

cmake-demo/
    CMakeLists.txt
    hello_world.cpp
    hello/
        CMakeLists.txt
        hello.h
        hello.cpp
    cmake-build/        # CMake自动创建
        ...
        hello_world     # 可执行程序
        hello/
            ...
            libhello.a  # hello库

4.CMake命令行工具

CMake命令行工具cmake的文档见cmake(1)。Linux或macOS系统也可以通过cmake --helpman cmake查看。

cmake命令的常用功能包括配置和构建。

4.1 配置

配置(configure)是指根据CMakeLists.txt声明的构建目标(build target)和依赖关系(dependencies),针对特定的底层构建工具生成构建系统(buildsystem)(由一系列构建文件组成),所使用的底层构建工具叫做生成器(generator)。

配置命令的用法如下:

cmake [<options>] -S <path-to-source> -B <path-to-build>

其中,-S选项指定源代码目录(source directory),-B选项指定构建目录(build/binary directory),构建目录用于存放底层构建工具的构建文件(例如Makefile)和构建目标的输出(例如库文件和可执行文件)。如果仅指定了二者之一,则另一个默认为当前工作目录。

当构建目标或依赖关系发生变化(即CMakeLists.txt文件发生变化)时,需要重新配置。

注:在实际项目中,通常将构建目录与源代码目录区分开,从而可以方便地从Git中排除。

4.1.1 生成器

生成器是CMake使用的底层构建工具,用于指定CMake配置命令生成哪种构建文件、使用哪种编译器和链接器:

生成器底层构建工具构建文件编译器
Unix MakefilesGNU MakeMakefileGCC
MinGW MakefilesMinGW MakeMakefileGCC
Visual StudioMSBuild.sln和.vcxprojMSVC

CMake支持不同平台上的多种生成器,详见cmake-generators(7)。可通过配置命令的-G选项指定要使用的生成器,如果未指定则使用当前平台的默认生成器。CMake在当前平台上支持的生成器和默认生成器可通过cmake --help命令查看。

例如,在Linux系统上可以使用Unix Makefiles生成器:

cmake -G "Unix Makefiles" -S . -B cmake-build

在Windows系统上可以使用Visual Studio生成器(需要安装对应版本的Visual Studio):

cmake -G "Visual Studio 17 2022" -A x64 -B cmake-build

4.2 构建

配置完成后,就可以根据构建系统生成构建目标。

构建命令的用法如下:

cmake [<options>] --build <path-to-build>

构建目标将被输出到构建目录中对应的子目录下。如果只有源代码发生变化,CMakeLists.txt文件没有变化,则只需重新构建,不需要重新配置。

构建命令的常用选项:

  • -t <name>, --target <name>:仅构建指定的目标及其上游依赖。可以指定多个目标,用空格分隔。如果未指定则构建所有目标。目标clean用于清除构建输出。
  • --config <cfg>:对于多配置的构建工具指定使用的配置,例如Debug或Release。

5.CMake命令

CMakeLists.txt文件本身也是一种语言,叫做“CMake语言”,语法说明见cmake-language(7)。

CMake语言的核心是命令(command),这些命令用于声明构建目标和依赖关系、指定编译和链接选项、设置CMake变量的值等。完整列表见cmake-commands(7)。

CMake命令的语法格式如下:

command_name(arg1 arg2 ...)
command_name(KEYWORD1 arg1 KEYWORD2 arg2 ...)

下面是一些常用的CMake命令(有些命令并未列出全部参数)。

5.1 脚本命令

cmake_minimum_required

指定项目要求的最低CMake版本。

cmake_minimum_required(VERSION <min>)

set

设置CMake变量的值。

set(<variable> <value>...)

可以通过${var}的形式引用变量。如果指定了多个值,则变量的实际值是分号分隔的列表。例如:

set(srcs a.c b.c c.c)  # sets "srcs" to "a.c;b.c;c.c"

message

输出日志消息。

message("message text" ...)

include

从指定的文件或模块加载并运行CMake命令。

include(<file|module>)

if

条件语句。

if(<condition>)
  <commands>
elseif(<condition>) # optional block, can be repeated
  <commands>
else()              # optional block
  <commands>
endif()

其中,if()支持的表达式语法和逻辑运算符见if - Condition Syntax。例如:

if(WIN32)
  set(output_file NUL)
else()
  set(output_file /dev/null)
endif()

foreach

对列表中的每个值执行一组命令。

foreach(<loop_var> <items>)
  <commands>
endforeach()

该命令有几种变体:

(1)遍历整数

foreach(<loop_var> RANGE <stop>)
foreach(<loop_var> RANGE <start> <stop> [<step>])

遍历0 ~ stopstart ~ stop之间的整数,包含上界。其中,startstopstep必须是非负整数,且stop大于等于startstep默认为1。

例如:

foreach(i RANGE 1 3)
  add_executable(prog${i} prog${i}.cpp)
endforeach()

等价于

add_executable(prog1 prog1.cpp)
add_executable(prog2 prog2.cpp)
add_executable(prog3 prog3.cpp)

(2)遍历列表

foreach(<loop_var> IN ITEMS <items>)

其中items是分号分隔的列表。

例如:

foreach(i IN ITEMS foo;bar;baz)
  add_executable(${i} ${i}.cpp)
endforeach()

等价于

add_executable(foo foo.cpp)
add_executable(bar bar.cpp)
add_executable(baz baz.cpp)

function

定义函数。

function(<name> [<arg1> ...])
  <commands>
endfunction()

该命令定义了一个名为name的函数,可以接受参数,在函数体中可以用${arg1}引用参数arg1。函数体中的命令只有在函数被调用时才会执行。

例如:

function(add_gui_executable name source)
  add_executable(${name} ${source})
  target_link_libraries(${name} GUI)
endfunction()

add_gui_executable(foo foo.cpp)
add_gui_executable(bar bar.cpp)

等价于

add_executable(foo foo.cpp)
target_link_libraries(foo GUI)
add_executable(bar bar.cpp)
target_link_libraries(bar GUI)

在函数体中,除了${arg1}等形式参数,还可以使用以下变量:

  • ARGC:实际参数的个数
  • ARGV0ARGV1ARGV2等:各实际参数的值
  • ARGV:所有参数的列表
  • ARGN:最后一个期望的参数之后所有参数的列表

这些变量可用于创建带有可选参数的函数。

例如,上面定义的函数add_gui_executable()只能接受单个源文件参数source。要接受多个源文件可修改为:

function(add_gui_executable name)
  add_executable(${name} ${GUI_TYPE} ${ARGN})
  target_link_libraries(${name} GUI)
endfunction()

add_gui_executable(foo foo.cpp bar.cpp)

注:function()命令仅支持位置参数(positional parameter),使用cmake_parse_arguments()命令可以实现关键字参数(keyword parameter)。

cmake_parse_arguments

解析函数参数。

cmake_parse_arguments(<prefix> <options> <one_value_keywords> <multi_value_keywords> <args>...)

其中,options指定所有的选项关键字(即没有值的关键字参数),one_value_keywords指定所有的单值关键字,multi_value_keywords指定所有的多值关键字,<args>...是要被处理的参数。解析结果将被保存到各关键字对应的变量中,命名格式为<prefix>_<keyword>

例如:

function(my_install)
  set(options OPTIONAL FAST)
  set(one_value_keywords DESTINATION RENAME)
  set(multi_value_keywords TARGETS CONFIGURATIONS)
  cmake_parse_arguments(MY_INSTALL "${options}" "${one_value_keywords}" "${multi_value_keywords}" ${ARGN})
  # ...
endfunction()

如果像这样调用my_install()

my_install(TARGETS foo bar DESTINATION bin OPTIONAL blub CONFIGURATIONS)

则在函数体中调用cmake_parse_arguments()后将定义以下变量:

MY_INSTALL_OPTIONAL = TRUE
MY_INSTALL_FAST = FALSE # was not used in call to my_install
MY_INSTALL_DESTINATION = "bin"
MY_INSTALL_RENAME <UNDEFINED> # was not used
MY_INSTALL_TARGETS = "foo;bar"
MY_INSTALL_CONFIGURATIONS <UNDEFINED> # was not used
MY_INSTALL_UNPARSED_ARGUMENTS = "blub" # nothing expected after "OPTIONAL"
MY_INSTALL_KEYWORDS_MISSING_VALUES = "CONFIGURATIONS"

5.2 项目命令

project

设置项目名称。

project(<name>)

该命令将设置以下变量:

  • PROJECT_NAME:项目名称
  • PROJECT_SOURCE_DIR:项目源代码目录
  • PROJECT_BINARY_DIR:项目构建目录

add_executable

添加可执行程序构建目标。

add_executable(<name> <source>...)

可执行文件名为<name> (Linux)或<name>.exe (Windows)。

add_library

添加函数库构建目标。

add_library(<name> [STATIC|SHARED] <source>...)

可以指定库文件的类型:

  • STATIC:静态链接库(默认),库文件名为lib<name>.a (Linux)或<name>.lib (Windows)
  • SHARED:动态链接库,库文件名为lib<name>.so (Linux)或<name>.dll (Windows)

add_test

添加测试,详见第7节。

target_include_directories

为给定的目标添加包含目录(相当于GCC编译器的-I选项)。

target_include_directories(<target> <PUBLIC|INTERFACE|PRIVATE> <dir>...)

其中,PUBLICINTERFACEPRIVATE关键字用于指定该选项的作用域:

  • PUBLIC:对该目标及其下游依赖均生效
  • INTERFACE:仅对该目标的下游依赖生效
  • PRIVATE:仅对该目标生效

例如:

add_library(foo foo.cpp)
target_include_directories(foo INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})

定义了一个函数库foo,并指定foo的下游依赖要将当前源代码目录添加到包含目录,从而可以直接包含当前目录下的头文件。

target_link_directories

为给定的目标添加依赖库(相当于GCC编译器的-L选项)。

target_link_directories(<target> <PUBLIC|INTERFACE|PRIVATE> <dir>...)

注:一般不需要使用该命令,直接使用target_link_libraries()即可。

target_link_libraries

为给定的目标添加依赖库,即上游依赖(相当于GCC编译器的-l选项)。构建可执行文件时,依赖库将参与链接。

target_link_libraries(<target> <PUBLIC|INTERFACE|PRIVATE> <item>...)
target_link_libraries(<target> <item>...)

其中,第二种形式等价于PUBLIC,即为给定的目标及其下游依赖均添加依赖库,从而依赖关系具有传递性。

例如:

add_library(foo foo.cpp)
add_library(bar bar.cpp)
add_library(baz baz.cpp)
target_link_libraries(bar foo)
target_link_libraries(baz INTERFACE foo)

定义了三个库foo、bar和baz,bar及其下游依赖均依赖foo,baz的下游依赖均依赖foo,但baz本身不依赖foo。

target_link_options

为给定的目标添加链接选项。

target_link_options(<target> <PUBLIC|INTERFACE|PRIVATE> <item>...)

add_subdirectory

将指定的子目录加入构建。

add_subdirectory(<dir>)

如果dir是相对路径,则相对于当前目录。CMake执行该命令时将立即处理子目录中的CMakeLists.txt文件。

5.3 生成器表达式

cmake-generator-expressions(7)

6.CMake内置变量

CMake提供了很多内置变量,完整列表见cmake-variables(7)。下面是一些常用的变量。

6.1 路径相关变量

  • CMAKE_COMMAND:cmake命令的完整路径
  • CMAKE_GENERATOR:构建项目使用的生成器
  • CMAKE_SOURCE_DIR:顶层源代码目录
  • CMAKE_BINARY_DIR:顶层构建目录
  • CMAKE_CURRENT_SOURCE_DIR:当前源代码目录
  • CMAKE_CURRENT_BINARY_DIR:当前构建目录
  • PROJECT_NAME:最近调用project()命令的项目名称
  • PROJECT_SOURCE_DIR:最近调用project()命令的项目源代码目录
  • PROJECT_BINARY_DIR:最近调用project()命令的项目构建目录

6.2 系统相关变量

  • LINUX:如果目标系统是Linux则设置为TRUE
  • WIN32:如果目标系统是Windows则设置为TRUE
  • APPLE:如果目标系统是macOS则设置为TRUE

6.3 语言相关变量

  • CMAKE_C_STANDARD:默认C标准版本,可选的值为90、99、11、17、23等
  • CMAKE_CXX_STANDARD:默认C++标准版本,可选的值为98、11、14、17、20、23、26等

7.测试

CMake通过CTest模块提供了测试支持。

首先在项目根目录下的CMakeLists.txt中调用enable_testing()命令,之后可以在任意的CMakeLists.txt中通过add_test()命令添加测试。

7.1 添加测试

add_test()命令的用法如下:

add_test(
  NAME <name>
  COMMAND <command> [<arg>...]
  [WORKING_DIRECTORY <dir>])

其中,command指定测试命令,如果是一个可执行文件目标,将会被自动替换为构建生成的可执行文件路径。如果命令的返回码为0则认为测试通过,否则测试失败。

7.2 运行测试

用于运行测试的命令行工具是ctest,文档见ctest(1)。

添加测试并配置、构建完成后,在构建目录下直接执行ctest命令即可。

注:CTest本身不提供任何断言或比较功能,如何执行测试完全由测试命令确定。

7.3 GoogleTest

GoogleTest是一个常用的C++测试框架,CMake通过GoogleTest模块提供了对GoogleTest的支持。

示例见GoogleTest使用教程。

8.模块

CMake自带一些提供额外功能的模块(module),例如前面提到的CTestGoogleTest,可以通过include()命令加载。完整列表见cmake-modules(7)。

8.1 FetchContent

FetchContent模块提供了在配置时自动加载外部项目的功能,主要命令是FetchContent_Declare()FetchContent_MakeAvailable()

示例:

  • GoogleTest: GoogleTest使用教程 3.2节
  • FLTK: 《C++程序设计原理与实践》笔记 第12章 一个显示模型 12.8.2节

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/361040.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【ZOJ 1067】Color Me Less 题解(vector+开方)

问题 颜色缩减是从一组离散颜色到较小颜色的映射。这个问题的解决方案需要在标准的24位RGB颜色空间中执行这样的映射。输入由十六个RGB颜色值的目标集合和要映射到目标集合中最接近的颜色的任意RGB颜色集合组成。为了我们的目的&#xff0c;RGB颜色被定义为有序三元组&#xff…

OpenGL ES 绘制一张图片

GLSL 语法与内建函数 GLSL 的修饰符与数据类型 GLSL 中变量的修饰符 const&#xff1a;修饰不可被外界改变的常量attribute&#xff1a;修饰经常更改的变量&#xff0c;只可以在顶点着色器中使用uniform&#xff1a;修饰不经常更改的变量&#xff0c;可用于顶点着色器和片段…

vue中go.js的使用教学(五:数据绑定)

一、一个简单的数据绑定&#xff08;go.Binding&#xff09;看注释为绑定 diagram.nodeTemplate $(go.Node, "Auto",$(go.Shape, "RoundedRectangle",{ fill: "white" },new go.Binding("fill", "color")), // shape.fill …

Nginx 部署 Vue 项目以及 Vue 项目刷新出现 404 的问题(完整步骤)(亲测有效)

Nginx 部署 Vue 项目以及 Vue 项目刷新出现 404 的问题&#xff08;完整步骤&#xff09;&#xff08;亲测有效&#xff09; 1.流程步骤&#xff08;本教程下载的是1.20.2版本&#xff0c;放在D盘&#xff09; 1-1. 首先去官方下载 nginx &#xff0c;然后在当前目录下创建ht…

大幅提升爬取效率的一款实用工具

在做爬虫的时候&#xff0c;我们往往可能这些情况&#xff1a;网站比较复杂&#xff0c;会碰到很多重复请求。有时候爬虫意外中断了&#xff0c;但我们没有保存爬取状态&#xff0c;再次运行就需要重新爬取。还有诸如此类的问题。那怎么解决这些重复爬取的问题呢&#xff1f;大…

什么国产蓝牙耳机颜值高又好用?好用且高颜值蓝牙耳机推荐

随着蓝牙耳机的受欢迎程度加深&#xff0c;其受众群体也越来越多样。什么国产蓝牙耳机颜值高又好用&#xff1f;针对这个问题&#xff0c;我来给大家推荐几款好用且颜值高的蓝牙耳机&#xff0c;可以当个参考。 一、南卡小音舱蓝牙耳机 参考价&#xff1a;239 蓝牙版本&…

Go进阶(3):上下文context

一、背景 在 Go http包的Server中&#xff0c;每一个请求在都有一个对应的 goroutine去处理。请求处理函数通常会启动额外的goroutine用来访问后端服务&#xff0c;比如数据库和RPC服务。一个上游服务通常需要访问多个下游服务&#xff0c;比如终端用户的身份认证信息、验证相关…

【网工最关心的问题,看Chat GPT怎么回答?】

最近打开微信群聊&#xff0c;都是在说ChatGPT相关内容 那ChatGPT是什么&#xff1f; ChatGPT是由美国人工智能实验室OpenAI开发的一个对话AI模型&#xff0c;于2022年11月正式推出。它因其极其出色的文本生成和对话交互能力在世界范围内迅速走红&#xff0c;五天内用户破百万&…

19岁就患老年痴呆!这些前兆别忽视!

在大部分人的印象中&#xff0c;阿尔兹海默症好像是专属于老年人的疾病&#xff0c;而且它的另一个名字就是老年痴呆症。然而&#xff0c;前不久&#xff0c;一位19岁的男生患上了阿尔兹海默症&#xff0c;是迄今为止最年轻的患者。这个男生从17岁开始&#xff0c;就出现了注意…

return和finally执行顺序、运行时异常与一般异常异同、error和exception区别、Java异常处理机制原理与应用

文章目录1.try {}里有一个return语句&#xff0c;那么紧跟在这个try后的finally{}里的code会不会被执行&#xff0c;什么时候被执行&#xff0c;在return前还是后?2.运行时异常与一般异常有何异同&#xff1f;3.java 程序中的错误有三种类型分别是什么4.error和exception有什么…

GitHub推送报错:You‘re using an RSA key with SHA-1, which is no longer allowed

文章目录1、问题描述2、解决方案&#xff1a;重新生成密钥对3、将生成的公钥添加到GitHub4、向GitHub推送代码测试1、问题描述 在向GitHub推送代码的时候&#xff0c;执行git push命令出现如下问题&#xff1a; 原因是github不再支持RSA算法生成的密钥了&#xff0c;我们需要重…

《爆肝整理》保姆级系列教程python接口自动化(二十)--token登录(详解)

简介 为了验证用户登录情况以及减轻服务器的压力&#xff0c;减少频繁的查询数据库&#xff0c;使服务器更加健壮。有些登录不是用 cookie 来验证的&#xff0c;是用 token 参数来判断是否登录。token 传参有两种一种是放在请求头里&#xff0c;本质上是跟 cookie 是一样的&…

微机原理学习总结0:前言

近期结束了微机课程的学习&#xff0c;&#xff08;指刚考完试&#xff09;&#xff0c;正常情况下&#xff0c;后面应该不会再接触这门课程了&#xff0c;故在此记录自己这段时间的收获。 首先&#xff0c;十分推荐b站的一门课程&#xff0c;老师讲的很细致&#xff0c;很适合…

21个有用的python工具

Python是最流行的编程语言之一。 它简单、强大&#xff0c;并且由一个致力于开源项目的社区驱动。Python的大量使用是它如此流行的原因; 您可以免费构建软件、开发Web服务、执行数据分析和可视化以及训练机器学习模型。 Python开发工具 开发工具帮助我们构建快速可靠的Python…

生物素点击试剂1884349-58-9,Alkyne-PEG3-Biotin Diazo,炔基PEG3生物素重氮

Diazo Biotin-PEG3-alkyne&#xff0c;Alkyne-PEG3-Biotin Diazo&#xff0c;重氮生物素-PEG3-炔烃&#xff0c;重氮生物素PEG3炔烃&#xff0c;炔基PEG3生物素重氮产品结构式&#xff1a;产品规格&#xff1a;1.CAS号&#xff1a;1884349-58-92.分子式&#xff1a;C39H53N7O9S…

HANA SDA-远程数据源访问

我们需要把其他系统的数据拿过来&#xff0c;到BW里和财务的数据集成。 HANA SDA就是不复制数据&#xff0c;建立虚拟表&#xff08;virtual table&#xff09;来映射到远程数据源。通过这个虚拟表访问其他系统的数据。 对虚拟表的操作现在也可以查询&#xff0c;更新&#xff…

熵权法计算权重

文章目录1. 多属性决策问题2. 熵&#xff08;entropy&#xff09;3. 信息熵4. 熵权法5. 熵权法的实现基于信息论的熵值法是根据各指标所含信息有序程度的差异性来确定指标权重的客观赋权方法&#xff0c;仅依赖于数据本身的离散程度。熵用于度量不确定性&#xff0c;指标的离散…

LeetCode-Kotlin-Array-EASY-21至30题

关键字 PriorityQueuePairHashMap和HashSet的区别 1.HashMap实现了Map接口&#xff0c;而HashSet实现了Set接口。2.HashMap用于存储键值对&#xff0c;而HashSet用于存储对象。3.HashMap不允许有重复的键&#xff0c;可以允许有重复的值。HashSet不允许有重复元素。4.HashMap…

新库上线 | CnOpenData专精特新“小巨人”企业工商注册基本信息数据

专精特新“小巨人”企业工商注册基本信息数据 一、数据简介 “专精特新”一词最早来源于2011年7月&#xff0c;由时任工信部总工程师朱宏任在《中国产业发展和产业政策报告&#xff08;2011&#xff09;》新闻发布会上首次提出。“专精特新”是指具备专业化、精细化、特色化、…

第三届区块链服务网络(BSN)全球合作伙伴大会在杭州成功举办

为持续推动分布式技术和产业创新发展&#xff0c;2023年2月17日&#xff0c;由杭州市人民政府指导&#xff0c;杭州市拱墅区人民政府、国家信息中心主办&#xff0c;中国移动通信集团有限公司、区块链服务网络&#xff08;BSN&#xff09;发展联盟承办&#xff0c;中国移动通信…