为什么我们需要cmake?

Ves*_*ess 5 windows compilation build cmake libraries

我不明白,为什么我们需要cmake来构建库?如果我的问题很愚蠢,对不起,但是我需要在Widnows上使用一些库,我选择的库是什么,我需要用cmake来构建和/或编译它。为什么我不能只是将我需要的东西“包含”到我的项目中,而不能与我的项目同时编译/构建呢?

而且,有时我需要安装Ruby,Perl,Python,它们全部都具有特定的版本,以便cmake可以构建库...为什么需要这些程序,并且也仅在我的项目中需要它们来构建库吗?(具体可以在构建库后卸载那些程序吗?)

Hay*_*ayt 9

目前在不同平台上用 C++ 构建东西是一团糟。

有几种不同的构建系统,并且没有标准的方法来做到这一点。仅提供 Visual Studio 解决方案无助于在 linux 或 mac 上进行编译。

如果为 linux 或 mac 添加 makefile,则需要在解决方案和 makefile 之间重复配置。这会导致大量的维护开销。与现有的新工具相比,makefile 也不是一个真正好的构建工具。

您只有 CMake 库主要是巧合。CMake 目前是一种流行的选择。

有几种解决方案可以统一构建。CMake 是一种特殊方式的构建工具。它可以创建 makefile 并构建它们,但如果您愿意,您也可以告诉 cmake 创建一个 Visual Studio 解决方案。

外部程序也是如此。它们是您使用的库的维护者的选择,并且没有代码生成之类的标准。

虽然 CMake 可能不是“解决方案”(尽管即将到来的 Visual Studio 2015 正在集成 cmake 支持),但那些跨平台构建系统的趋势越来越朝着这个方向发展。


对于您为什么不能只包含标题的问题:

很少有库只是头文件,需要编译。您可以获取预编译的 libs/dll 并只包含标头 + 添加链接器路径。这在 linux 中更容易,因为您可以拥有-dev只安装预构建库的包,并且它是通过包管理器的标头。Windows 本身没有这样的东西。

或者您必须使用库使用的任何构建工具自己构建它。

  • *“Windows 本身没有这样的东西。”* - 无论是否是本机,Visual Studio 都出于同样的目的使用 [NuGet](https://www.nuget.org/),使依赖项的部署同样简单。它是*“Microsoft 开发平台的包管理器”*。NuGet 的优势在于:它是**唯一的** 包管理器,可从 **单个** URL 中提取包。您会发现搜索*“NuGet 故障排除”* 的资源比搜索 Linux 包管理器的资源少得多。 (3认同)

A. *_*dry 5

简而言之,您不需要,但如果没有它,可能很难构建项目。

CMake 不构建代码,而是构建文件生成器。它由 KitWare(2000 年左右的 ITK 项目期间)开发,旨在使跨多个平台的构建代码变得“更简单”。它不是一种易于使用的语言(Kitware 公开承认这一点),但它统一了 Windows、Mac 和 Linux 在构建代码时不同的一些做法。

  • 在 Linux 上,autoconf 通常用于生成构建文件,然后由 gcc/g++(和/或 clang)编译
  • 在 Windows 上,您通常会使用 Visual Studio IDE 并创建他们所谓的“解决方案”,然后由 msvc(Microsoft Visual C++ 编译器)进行编译
  • 在Mac上,我承认我不熟悉所使用的编译器,但我相信这与XCode有关

CMake 允许您编写可用于在多台计算机上构建的单个脚本,并为每台计算机指定不同的选项。

与 C++ 一样,CMake 分为传统/旧式 CMake(版本 < 3.x)和现代 CMake(版本 >= 3.0)。使用现代 CMake。以下是优秀的教程:

  1. 有效的 CMake,作者:Daniel Pfeifer,C++Now 2017 *
  2. 现代 CMake 模式,作者:Matheiu Ropert,CppCon 2017
  3. 更好的 CMake
  4. CMake教程

*荣获 C++Now 2017 大会最有用演讲奖

请按列出的顺序观看这些内容。您将了解现代 CMake(以及旧式 CMake)的样子,并了解如何

  1. CMake 帮助您指定构建顺序和依赖项,以及
  2. 现代 CMake 有助于防止在扩展到更大的项目时创建循环依赖项和常见错误。

此外,最后一个视频介绍了C++ 的包管理器Boost(在使用外部库时很有用,例如,您将在其中使用 CMakefind_package()命令),其中最常见的两个是:

  1. vcpkg
  2. 柯南

一般来说,

  1. target视为对象

    A。有两种,可执行文件,它们是用

add_executable(myexe ...)  # Creates an executable target "myexe"
add_library(mylib ...)  # Creates a library target "mylib"
Run Code Online (Sandbox Code Playgroud)
  1. 每个目标都有属性,它们是目标的变量。但是,它们是用下划线而不是点指定的,并且(通常)使用大写字母
myexe_FOO_PROPERTY  # Foo property for myexe target
Run Code Online (Sandbox Code Playgroud)
  1. CMake 中的函数还可以在运行时设置目标“对象”(在后台)的一些属性
target_compile_definitions()/features()/options()
target_sources()
target_include_directories()
target_link_libraries() 
Run Code Online (Sandbox Code Playgroud)
  1. CMake 是一种命令语言,类似于 shell 脚本,但没有命令的嵌套或管道。反而

    A。每个命令(函数)都在自己的行上,并且执行一件事
    b.所有命令(函数)的参数都是字符串
    c.除非目标名称显式传递给函数,否则该命令适用于上次创建的目标

add_executable(myexe ...)  # Create exe target

target_compile_definitions(...)  # Applies to "myexe"
target_include_directories(...)  # Applies to "myexe"
# ...etc.

add_library(mylib ...)  # Create lib target

target_sources(...)  # Applies to "mylib"
# ...etc.
Run Code Online (Sandbox Code Playgroud)

d. 命令按从上到下的顺序执行(注意:如果一个目标需要另一个目标,则必须先创建目标

  1. 执行范围是当前活动的CMakeLists.txt文件。add_subdirectory()可以使用以下命令运行其他文件(添加到范围)

    A。这与 shell 命令非常相似exec;当前的 CMake 环境(目标和属性,PRIVATE属性除外)被“复制”到新的范围(“shell”)中,并在其中完成额外的工作。

    b. 但是,“环境”不是shell 环境(CMake 目标属性不会作为环境变量传递到 shell,如$PATH)。相反,CMake 语言在顶级全局范围内维护所有目标和属性CACHE

  2. PRIVATE属性由当前模块使用。INTERFACE属性被传递到子目录模块。PUBLIC适用于当前模块和子模块(该属性适用于当前模块并适用于/应该由链接到它的模块使用)。

  3. target_link_libraries用于直接模块依赖关系,但它也解决了所有传递依赖关系。这意味着当您链接到库时,您还将获得PUBLIC父模块的所有属性。

    A。如果您想链接到具有直接路径的库,您可以使用target_link_libraries,

    b. 如果您想链接到带有项目的模块并获取其接口,您还可以使用 target_link_libraries

您可以在文件上运行 CMakeCMakeLists.txt以生成系统所需的构建文件(ninjaLinux Visual Studio solution、Linuxmake等),然后运行这些文件来编译和链接代码。