Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Build SCons和/或CMake:自动映射自;在编译过程中包含标题“;至;相应的对象文件必须链接到";?_Build_Cmake_Scons - Fatal编程技术网

Build SCons和/或CMake:自动映射自;在编译过程中包含标题“;至;相应的对象文件必须链接到";?

Build SCons和/或CMake:自动映射自;在编译过程中包含标题“;至;相应的对象文件必须链接到";?,build,cmake,scons,Build,Cmake,Scons,超级简单,完全无聊的设置:我有一个目录,里面满是.hpp和.cpp文件。其中一些.cpp文件需要内置到可执行文件中;当然,这些.cpp文件#包括同一目录中的一些.hpp文件,然后可能包括其他文件,等等。大多数.hpp文件都有相应的.cpp文件,也就是说:如果某个_application.cpp#直接或通过传递包含foo.hpp,很可能还有一个foo.cpp文件需要编译并链接到some_应用程序的可执行文件中 超级简单,但我仍然不知道构建它的“最佳”方式是什么,无论是在SCons还是CMake中(

超级简单,完全无聊的设置:我有一个目录,里面满是.hpp和.cpp文件。其中一些.cpp文件需要内置到可执行文件中;当然,这些.cpp文件#包括同一目录中的一些.hpp文件,然后可能包括其他文件,等等。大多数.hpp文件都有相应的.cpp文件,也就是说:如果某个_application.cpp#直接或通过传递包含foo.hpp,很可能还有一个foo.cpp文件需要编译并链接到some_应用程序的可执行文件中

超级简单,但我仍然不知道构建它的“最佳”方式是什么,无论是在SCons还是CMake中(这两个方面我都没有任何专业知识,除了盯着最后一天左右的文档并变得悲伤)。我担心在大多数构建系统中,我想要的那种解决方案可能实际上是不可能实现的(或者至少是非常复杂的),但如果是这样的话,我很高兴知道这一点,这样我就可以放弃,不再那么挑剔了。当然,我希望我是错的,考虑到我对构建系统(一般来说,尤其是对CMake和SCons)的无知,这也就不足为奇了

CGube和SCons当然可以自动检测到某个应用程序。无论何时,它都依赖于(直接或传递)更改的头文件,需要重新编译。因为它们能够很好地解析C++文件,以挑选出这些依赖关系。好的,很好:我们不必手动列出每个.cpp-#includes-.hpp依赖项。但是:当实际生成每个可执行文件时,我们仍然需要确定需要将哪些对象文件子集发送到链接器

据我所知,解决这部分问题的两个最直接的办法是:

  • A.手动明确且费力地列举“使用此对象文件的任何内容也需要使用这些其他对象文件”依赖项,即使这些依赖项被相应的-.cpp准确地镜像,,也可以传递地包括相应的-.hpp依赖项,构建系统已经为我们解决了这个问题。为什么?因为电脑
  • B.将此目录中的所有对象文件转储到单个“库”中,然后使所有可执行文件依赖并链接到该库中。这要简单得多,我知道大多数人都会这么做,但也有点草率。大多数可执行文件实际上并不需要该库中的所有内容,而且如果只更改了一个或两个.cpp文件的内容,也不需要重新构建。这不正是所谓的“构建系统”应该避免的那种不必要的计算吗?(我想,如果库是动态链接的,它们可能不需要重建,但可以说我不喜欢动态链接的库是出于其他原因。)
CMake或SCons能以任何简单的方式做得比这更好吗?我看到了一些有限的方法来旋转自动生成的依赖关系图,但是没有通用的方法来交互地进行操作(“好的,构建系统,你认为依赖关系是什么?啊。好吧,在此基础上,添加以下依赖关系并重新思考:…”)。我对此并不感到惊讶。我还没有在这两个构建系统中找到一种特殊用途的机制来处理超常见的情况,即链接时依赖关系应该镜像相应的编译时(尽管包括依赖关系)。我在阅读文档的过程中(承认有些草率)遗漏了什么,还是每个人都只是选择(B)选项,并默默地憎恨自己和/或他们的构建系统?

您在A点中的陈述“任何使用此对象文件的操作都需要使用这些其他对象文件”确实需要手工完成。编译器不会自动找到二进制文件所需的对象文件。您必须在链接时明确列出它们。如果我正确理解了您的问题,您不需要显式列出二进制文件所需的对象,而是希望构建工具自动找到它们。我怀疑是否有任何构建也会这样做:SCons和Cmake绝对不会这样做

如果您有一个包含
foo.hpp
(或这些cpp文件使用的其他标题)的应用程序
some\u application.cpp
,并且随后需要链接
foo.cpp
对象,那么在SCON中,您将需要执行以下操作:

env = Environment()
env.Program(target = 'some_application',
            source = ['some_application.cpp', 'foo.cpp'])
仅当“some_application.cpp”、“foo.hpp”或“foo.cpp”发生更改时,此链接才会。假设g++,这将有效地转化为如下内容,独立于SCons或Cmake

g++ -c foo.cpp -o foo.o
g++ some_application.cpp foo.o -o some_application

如果你提到你有一个“满是.hpp和.cpp文件的目录”,我建议你将这些文件组织到库中。不是全部都在一个库中,而是在逻辑上将它们组织成更小的、有凝聚力的库。然后,您的应用程序/二进制文件将链接它们所需的库,从而最大限度地减少由于未使用对象而导致的重新编译。

我遇到了与您大致相同的问题,我解决了以下问题:

import SCons.Scanner
import os

def header_to_source(header_file):
    """Specify the location of the source file corresponding to a given
    header file."""
    return header_file.replace('include/', 'src/').replace('.hpp', '.cpp')

def source_files(main_file, env):
    """Returns list of source files the given main_file depends on.  With
    the function header_to_source one must specify where to look for
    the source file corresponding to a given header.  The resulting
    list is filtered for existing files.  The resulting list contains
    main_file as first element."""
    ## get the dependencies 
    node = File(main_file)
    scanner = SCons.Scanner.C.CScanner()
    path = SCons.Scanner.FindPathDirs("CPPPATH")(env)
    deps = node.get_implicit_deps(env, scanner, path)

    ## collect corresponding source files
    root_path = env.Dir('#').get_abspath()
    res = [main_file]
    for dep in deps:
        source_path = header_to_source(
            os.path.relpath(dep.get_abspath(), root_path))
        if os.path.exists(os.path.join(root_path, source_path)):
            res.append(source_path)

    return res
header_to_source方法是您需要修改的方法,以便它返回与给定头文件对应的源文件。然后,方法source\u file为您提供构建给定主\u文件所需的所有源文件(包括作为第一个元素的主\u文件)。不存在的文件将自动删除。因此,以下内容应足以定义可执行文件的目标:

env.Program(source_files('main.cpp', env))

我不确定这是否适用于所有可能的设置,但至少对我来说是有效的。

这正是我所担心的。不幸的是,“将它们组织到更小的库中”只是“手动镜像”的另一种说法