【问题标题】:Why do we need cmake?为什么我们需要 cmake?
【发布时间】:2017-02-26 06:36:22
【问题描述】:

我不明白,为什么我们需要 cmake 来构建库?如果我的问题很愚蠢,我很抱歉,但我需要在 Widnows 上使用一些库,而我选择的任何库都需要构建它和/或用 cmake 编译它。它有什么用?为什么我不能将我需要的东西#include "path" 到我的项目中,而不是可以与我的项目同时编译/构建?

而且,有时我需要安装 Ruby、Perl、Python 所有这些特定版本,以便 cmake 可以构建库...为什么我需要这些程序,我是否只需要它们来构建库或稍后在我的项目也是? (具体我可以在构建库后卸载这些程序吗?)

【问题讨论】:

  • “为什么我不能将我需要的东西#include“path”到我的项目中,而不是可以与我的项目同时编译/构建?” - 听起来很像你甚至不明白,哪些部分组成了一个库,以及它是如何合并到程序中的。您需要了解这里的基础知识。无论如何,如果一个库需要CMake(不要害怕使用网络搜索),它会这样做,因为这是它选择管理其构建系统的工具。

标签: windows build compilation cmake libraries


【解决方案1】:

目前在不同平台上用 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 来实现相同的目的,从而使依赖项的部署同样简单。它是“微软开发平台的包管理器”。 NuGet 的优点:它是唯一的包管理器,从单个 URL 拉取包。您会发现搜索 “NuGet 故障排除” 的资源比搜索 Linux 包管理器少得多。
  • 我喜欢你的总结,只是想添加一些链接:CMake support in Visual StudioThe Architecture of Open Source Applications: CMakeAbout CMake
  • @IInspectable 感谢 NuGet 提及。我还没有使用它,所以我不能在那里为这个主题添加任何东西。
【解决方案2】:

简短的回答是你没有,但没有它可能很难构建项目。

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.0)。 使用现代 CMake。以下是优秀的教程:

  1. Effective CMake, by Daniel Pfeifer, C++Now 2017*
  2. Modern CMake Patterns, by Matheiu Ropert, CppCon 2017
  3. Better CMake
  4. CMake Tutorial

*在 C++Now 2017 大会上获得最有用的演讲

按照列出的顺序观看这些内容。您将了解 Modern CMake(以及旧式 CMake)的外观,并了解其原理

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

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

  1. vcpkg,和
  2. Conan

一般来说,

  1. 目标视为对象

    一个。有两种,executableslibraries,它们是用

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

    一个。每个命令(函数)都在自己的行中并且做一件事
    湾。所有命令(函数)的参数都是字符串
    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.

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

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

    一个。 这很像 shell exec 命令;当前的 CMake 环境(目标和属性,PRIVATE 属性除外)被“复制”到新的范围(“shell”)中,在该范围内完成了额外的工作。

    b.但是,“环境”不是 shell 环境(CMake 目标属性不会像 $PATH 这样的环境变量传递给 shell)。相反,CMake 语言 维护顶级全局范围CACHE

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

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

    一个。如果要链接到具有直接路径的库,可以使用target_link_libraries

    b.如果你想用一个项目链接到一个模块并获取它的接口,你也可以使用target_link_libraries

您在 CMakeLists.txt 文件上运行 CMake 以生成系统所需的构建文件(ninjaVisual Studio solution、Linux make 等)并运行这些文件以编译和链接代码。

【讨论】:

    猜你喜欢
    • 2019-06-09
    • 2014-06-18
    • 2011-04-03
    • 2017-07-27
    • 2020-09-21
    • 2020-03-09
    • 2018-12-24
    • 2012-04-08
    • 1970-01-01
    相关资源
    最近更新 更多