假设我有10 * .hpp和* .cpp文件,我需要编译代码。我知道我将需要许多不同代码的相同文件。我可以使用那些允许我简单编写
的文件创建一个“包”#include<mypackage>
而不是
#include"file1.hpp"
#include"file2.hpp"
...
#include"file10.hpp"
每次我需要这个“包”时,我都不需要编写一个makefile。
更确切地说,我使用的是linux。
答案 0 :(得分:36)
CPP源(H文件和CPP文件)的集合可以一起编译到“库”中,然后可以在其他程序和库中使用。有关如何执行此操作的具体信息是特定于平台和工具链的,因此我将其留给您以发现详细信息。但是,我将提供一些您可以阅读的链接:
Creating a shared and static library with the gnu compiler [gcc]
Walkthrough: Creating and Using a Dynamic Link Library (C++)
库可以分为两种类型:源代码库和二进制库。也可以有这两种类型的混合 - 库既可以是源库,也可以是二进制库。源代码库就是这样的:代码集合作为源代码分发;通常是头文件。大多数Boost库都属于这种类型。二进制库被编译到一个可由客户端程序运行时加载的包中。
即使在二进制库的情况下(显然在源库的情况下),也必须向库的用户提供头文件(或多个头文件)。这告诉编译器客户端程序在库中查找哪些函数等。库编写者经常做的是单个主头文件由库导出的所有内容的声明组成,客户端将#include
该头。稍后,对于二进制库,客户端程序将“链接”到库,这会将标头中提到的所有名称解析为可执行地址。
编写客户端头文件时,请记住复杂性。在某些情况下,您的某些客户只想使用您库中的一些部分。如果您编写一个包含库中所有内容的主头文件,则会不必要地增加客户端编译时间。
解决此问题的常用方法是为库的相关部分提供单独的头文件。如果你想到Boost的一个库,那么Boost就是一个例子。 Boost是一个庞大的库,但如果你想要的只是正则表达式功能,你只能#include
与正则表达式相关的标题来获得该功能。如果您想要的只是正则表达式,那么您不必包含所有的Boost。
在Windows和Linux下,二进制库可以进一步细分为两种类型:动态和静态。在静态库的情况下,库的代码实际上是“导入”(缺少更好的术语)到客户端程序的可执行文件中。您可以分发静态库,但只有客户端在编译步骤中才需要这样做。当您不希望强制客户端必须使用其程序分发其他文件时,这很方便。它也有助于避免Dependancy Hell。另一方面,动态库不会直接“导入”到客户端程序中,而是在执行时由客户端程序动态加载。在多个程序使用相同的动态库的情况下,这既减小了客户端程序的大小又减小了磁盘占用空间,但是库二进制文件必须是分布式的。与客户端程序一起安装。
答案 1 :(得分:1)
假设你的“file1.hpp”和“file2.hpp”等密切相关并且(几乎)总是一起使用,那么制作一个包含其他组件包含的“mypacakge.h”是一个好主意(它它本身并没有成为一个库 - 这是一个完全不同的过程。
如果它们没有密切相关和/或一起使用,那么你就不应该拥有这样一个“大型包含”,因为它只会拖入一堆不需要的东西。
创建库需要构建一次代码,并生成.lib文件或共享库(.dll或.so文件)。这样做的确切步骤取决于您使用的系统,这对我来说有点太复杂了。
编辑:进一步解释:所有的C ++库实际上都是一个库文件或共享库文件[以及一些包含一些代码和使用库中代码所需的声明的头文件]。但是你分别包括<iostream>
和<vector>
- 在一个<allcpplibrary>
中包含所有不同C ++库标题中的所有内容会变得非常糟糕,即使它涉及的打字要少得多。它被分成几个部分,每个头文件做一件事。所以你从一个头文件中得到一个“完整”的集合,但不是你实际上不需要的太多其他东西。
答案 2 :(得分:0)
如果一个客户端需要所有十个标题来实际使用你的“包”(库),那就是非常糟糕的界面设计。
如果客户端只需要某些标头,则根据您使用的库部分,让客户端包含相应的标头,因此只会引入一组最小的标识符。这有助于范围,模块化和编译时间。
如果所有其他方法都失败了,您可以创建一个“接口标题”供外部使用,这与您在内部实际编译库时使用的不同。这将是安装的,并包含来自其他标头的必要内容。 (我仍然认为你的lib中的每个标题都不需要所有。)
我会劝阻萨尔加的解决方案。您 具有单独的标头,或是单个标头。提供单独的标题 plus 一个简单包含其他标题的中心标题会让我感觉非常糟糕。
我所做的不明白无异于Makefiles就是这样做的。标头依赖项应该由Makefile / build系统自动解决,即这里的头文件是如何布局的并不重要。
答案 3 :(得分:0)
是和否。
您可以编写包含所有标头,以便#include "myLib.h"
足够,因为您通过单个标头包含所有这些标头。但是,这并不意味着单个包含足以使10'.cpp'文件的内容自动链接到您的项目。您必须将它们编译到库中,并将该单个库(而不是所有目标文件)链接到使用“myLib.h”的项目。库二进制文件作为静态和动态库提供,文件通常分别命名为.lib
和.dll
(windows)以及.a
和.so
(linux),分别用于静态和动态库。
如何构建和链接这些库取决于您的构建系统,您可能希望在网上讨论这些条款。
另一种方法是通过定义标题中的所有函数来删除.cpp
文件。这样您就不必链接其他库,但这会增加构建时间,因为每次将标头直接或间接地包含在一个翻译单元中时,编译器就必须处理所有这些功能。
答案 4 :(得分:0)
在Linux上:
g ++ FLAGS -shared -Wl,-soname,libLIBNAME.so.1 -o libLIBNAME.VERSION OBJECT_FILES
,其中
FLAGS:典型的标志(例如-g,-Wall,-Wextra等)
LIBNAME:您图书馆的名称
OBJECT_FILES:编译cpp文件产生的对象文件
VERSION:您的图书馆版本