C++ 如何使用 CMake 正确添加包含目录

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13703647/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 17:39:43  来源:igfitidea点击:

How to properly add include directories with CMake

c++ubuntucmake

提问by Matthieu M.

About a year ago I asked about header dependencies in CMake.

大约一年前,我询问了CMake 中的标头依赖项

I realized recently that the issue seemed to be that CMake considered those header files to be externalto the project. At least, when generating a Code::Blocks project the header files do not appear within the project (the source files do). It therefore seems to me that CMake consider those headers to be externalto the project, and does not track them in the depends.

我最近意识到问题似乎是 CMake 认为这些头文件是项目外部的。至少,在生成 Code::Blocks 项目时,头文件不会出现在项目中(源文件会出现)。因此,在我看来,CMake 认为这些标头是项目外部的,并且不会在依赖项中跟踪它们。

A quick search in the CMake tutorial only pointed to include_directorieswhich does not seem to do what I wish...

在 CMake 教程中的快速搜索只指出include_directories哪个似乎没有做我希望的......

What is the proper way to signal to CMake that a particular directory contains headers to be included, and that those headers should be tracked by the generated Makefile?

向 CMake 发出信号表示特定目录包含要包含的头文件,并且这些头文件应由生成的 Makefile 跟踪的正确方法是什么?

回答by SirDarius

Two things must be done.

必须做两件事。

First add the directory to be included:

首先添加要包含的目录:

target_include_directories(test PRIVATE ${YOUR_DIRECTORY})

In case you are stuck with a very old CMake version (2.8.10 or older) without support for target_include_directories, you can also use the legacy include_directoriesinstead:

如果您在不支持 的情况下使用非常旧的 CMake 版本(2.8.10 或更早版本)target_include_directories,您也可以改用旧版include_directories

include_directories(${YOUR_DIRECTORY})

Then you also must add the header files to the list of your source files for the current target, for instance:

然后,您还必须将头文件添加到当前目标的源文件列表中,例如:

set(SOURCES file.cpp file2.cpp ${YOUR_DIRECTORY}/file1.h ${YOUR_DIRECTORY}/file2.h)
add_executable(test ${SOURCES})

This way, the header files will appear as dependencies in the Makefile, and also for example in the generated Visual Studio project, if you generate one.

这样,头文件将作为依赖项出现在 Makefile 中,例如在生成的 Visual Studio 项目中,如果您生成了一个。

How to use those header files for several targets:

如何将这些头文件用于多个目标:

set(HEADER_FILES ${YOUR_DIRECTORY}/file1.h ${YOUR_DIRECTORY}/file2.h)

add_library(mylib libsrc.cpp ${HEADER_FILES})
target_include_directories(mylib PRIVATE ${YOUR_DIRECTORY})
add_executable(myexec execfile.cpp ${HEADER_FILES})
target_include_directories(myexec PRIVATE ${YOUR_DIRECTORY})

回答by Angew is no longer proud of SO

First, you use include_directories()to tell CMake to add the directory as -Ito the compilation command line. Second, you list the headers in your add_executable()or add_library()call.

首先,您使用include_directories()告诉 CMake 将目录添加-I到编译命令行。其次,您在您的add_executable()oradd_library()电话中列出标题。

As an example, if your project's sources are in src, and you need headers from include, you could do it like this:

例如,如果您的项目源在 中src,并且您需要来自 的标题include,您可以这样做:

include_directories(include)

add_executable(MyExec
  src/main.c
  src/other_source.c
  include/header1.h
  include/header2.h
)

回答by bruziuz

CMake is more like a script language if comparing it with other ways to create Makefile (e.g. make or qmake). It is not very cool like Python, but still.

如果将 CMake 与其他创建 Makefile 的方法(例如 make 或 qmake)进行比较,CMake 更像是一种脚本语言。它不像 Python 那样酷,但仍然如此。

There are no such thing like a "proper way" if looking in various opensource projects how people include directories. But there are two ways to do it.

如果在各种开源项目中查看人们如何包含目录,就没有像“正确的方式”这样的东西。但是有两种方法可以做到。

  1. Crude include_directorieswill append a directory to the current project and all other descendant projects which you will append via a series of add_subdirectorycommands. Sometimes people say that such approach is legacy.

  2. A more elegant way is with target_include_directories. It allows to append a directory for a specific project/target without (maybe) unnecessary inheritance or clashing of various include directories. Also allow to perform even a subtle configuration and append one of the following markers for this command.

  1. 粗略的include_directories将向当前项目和所有其他后代项目追加一个目录,您将通过一系列add_subdirectory命令追加这些项目。有时人们会说这种方法是遗产。

  2. 更优雅的方法是使用target_include_directories。它允许为特定项目/目标附加目录,而无需(可能)不必要的继承或各种包含目录的冲突。还允许执行甚至微妙的配置并为此命令附加以下标记之一。

PRIVATE- use only for this specified build target

PRIVATE- 仅用于此指定的构建目标

PUBLIC- use it for specified target and for targets which links with this project

PUBLIC- 将其用于指定的目标以及与此项目链接的目标

INTERFACE-- use it only for targets which links with the current project

INTERFACE-- 仅用于与当前项目链接的目标

PS:

PS:

  1. Both commands allow to mark a directory as SYSTEM to give a hint that it is not your business that specified directories will contain warnings.

  2. A similar answer is with other pairs of commands target_compile_definitions/add_definitions, target_compile_options/CMAKE_C_FLAGS

  1. 这两个命令都允许将目录标记为 SYSTEM 以提示您指定的目录将包含警告不是您的业务。

  2. 类似的答案是其他命令对target_compile_definitions/ add_definitions, target_compile_options/ CMAKE_C_FLAGS

回答by off99555

Add include_directories("/your/path/here").

添加include_directories("/your/path/here").

This will be similar to calling gccwith -I/your/path/here/option.

这将类似于gcc使用-I/your/path/here/选项调用。

Make sure you put double quotes around the path. Other people didn't mention that and it made me stuck for 2 days. So this answer is for people who are very new to CMake and very confused.

确保在路径周围加上双引号。其他人没有提到这一点,这让我卡住了 2 天。所以这个答案适用于对 CMake 非常陌生并且非常困惑的人。

回答by Seyed Hussein Mirzaki

I had the same problem.

我有同样的问题。

My project directory was like this:

我的项目目录是这样的:

    --project
    ---Classes
    ----Application
    -----.h and .c files
    ----OtherFolders
    --main.cpp

And what I used to include the files in all those folders:

以及我曾经在所有这些文件夹中包含文件的内容:

    file(GLOB source_files
            "*.h"
            "*.cpp"
            "Classes/*/*.cpp"
            "Classes/*/*.h"
    )

    add_executable(Server ${source_files})

And it totally worked.

它完全有效。