Build SCons和/或CMake:自动映射自;在编译过程中包含标题“;至;相应的对象文件必须链接到";?
超级简单,完全无聊的设置:我有一个目录,里面满是.hpp和.cpp文件。其中一些.cpp文件需要内置到可执行文件中;当然,这些.cpp文件#包括同一目录中的一些.hpp文件,然后可能包括其他文件,等等。大多数.hpp文件都有相应的.cpp文件,也就是说:如果某个_application.cpp#直接或通过传递包含foo.hpp,很可能还有一个foo.cpp文件需要编译并链接到some_应用程序的可执行文件中 超级简单,但我仍然不知道构建它的“最佳”方式是什么,无论是在SCons还是CMake中(这两个方面我都没有任何专业知识,除了盯着最后一天左右的文档并变得悲伤)。我担心在大多数构建系统中,我想要的那种解决方案可能实际上是不可能实现的(或者至少是非常复杂的),但如果是这样的话,我很高兴知道这一点,这样我就可以放弃,不再那么挑剔了。当然,我希望我是错的,考虑到我对构建系统(一般来说,尤其是对CMake和SCons)的无知,这也就不足为奇了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中(
CGube和SCons当然可以自动检测到某个应用程序。无论何时,它都依赖于(直接或传递)更改的头文件,需要重新编译。因为它们能够很好地解析C++文件,以挑选出这些依赖关系。好的,很好:我们不必手动列出每个.cpp-#includes-.hpp依赖项。但是:当实际生成每个可执行文件时,我们仍然需要确定需要将哪些对象文件子集发送到链接器
据我所知,解决这部分问题的两个最直接的办法是:- A.手动明确且费力地列举“使用此对象文件的任何内容也需要使用这些其他对象文件”依赖项,即使这些依赖项被相应的-.cpp准确地镜像,,也可以传递地包括相应的-.hpp依赖项,构建系统已经为我们解决了这个问题。为什么?因为电脑
- B.将此目录中的所有对象文件转储到单个“库”中,然后使所有可执行文件依赖并链接到该库中。这要简单得多,我知道大多数人都会这么做,但也有点草率。大多数可执行文件实际上并不需要该库中的所有内容,而且如果只更改了一个或两个.cpp文件的内容,也不需要重新构建。这不正是所谓的“构建系统”应该避免的那种不必要的计算吗?(我想,如果库是动态链接的,它们可能不需要重建,但可以说我不喜欢动态链接的库是出于其他原因。)
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))
我不确定这是否适用于所有可能的设置,但至少对我来说是有效的。这正是我所担心的。不幸的是,“将它们组织到更小的库中”只是“手动镜像”的另一种说法