C++ 如何创建库?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16693273/
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
How do I create a library?
提问by PinkFloyd
Let's say I have 10 *.hpp and *.cpp files that I need to compile a code. I know that I will need those same files for many different codes. Can I create a "package" with those files that would allow me to simply write:
假设我有 10 个 *.hpp 和 *.cpp 文件需要编译代码。我知道对于许多不同的代码,我将需要这些相同的文件。我可以用这些文件创建一个“包”,让我简单地编写:
#include <mypackage>
instead of:
代替:
#include "file1.hpp"
#include "file2.hpp"
...
#include "file10.hpp"
I wouldn't then need to write a makefile every time I need this "package".
每次我需要这个“包”时,我都不需要编写makefile。
To be more precise, I use Linux.
更准确地说,我使用Linux。
回答by John Dibling
A collection of CPP sources (H files and CPP files) can be compiled together in to a "library," which can then be used in other programs and libraries. The specifics of how to do this are platform- and toolchain-specific, so I leave it to you to discover the details. However, I'll provide a couple links that you can have a read of:
CPP 源(H 文件和 CPP 文件)的集合可以一起编译到“库”中,然后可以在其他程序和库中使用。如何做到这一点的细节是特定于平台和工具链的,所以我把它留给你去发现细节。但是,我将提供几个链接,您可以阅读:
Creating a shared and static library with the gnu compiler [gcc]
Walkthrough: Creating and Using a Dynamic Link Library (C++)
Libraries can be seperated in to two types: source code libraries, and binary libraries. There can also be hybrids of these two types -- a library can be both a source and binary library. Source code libraries are simply that: a collection of code distributed as just source code; typically header files. Most of the Boost libraries are of this type. Binary libraries are compiled in to a package that is runtime-loadable by a client program.
库可以分为两种类型:源代码库和二进制库。也可以是这两种类型的混合体——一个库既可以是源库,也可以是二进制库。源代码库很简单:作为源代码分发的代码集合;通常是头文件。大多数 Boost 库都属于这种类型。二进制库被编译成一个可由客户端程序运行时加载的包。
Even in the case of binary libraries (and obviously in the case of source libraries), a header file (or multiple header files) must be provided to the user of the library. This tells the compiler of the client program what functions etc to look for in the library. What is often done by library writers is a single, master header file is composed with declarations of everything that is exported by the library, and the client will #include
that header. Later, in the case of binary libraries, the client program will "link" to the library, and this resolves all the names mentioned in the header to executable addresses.
即使在二进制库的情况下(显然在源库的情况下),也必须向库的用户提供一个头文件(或多个头文件)。这告诉客户端程序的编译器要在库中查找哪些函数等。库编写者经常做的是一个单一的主头文件,它由库导出的所有内容的声明组成,客户端将使用#include
该头文件。稍后,在二进制库的情况下,客户端程序将“链接”到库,这会将标题中提到的所有名称解析为可执行地址。
When composing the client-side header file, keep complexity in mind. There may be many cases where some of your clients only want to use some few parts of your library. If you compose one master header file that includes everything from your library, your clients compilation times will be needlessly increased.
在编写客户端头文件时,请记住复杂性。可能在很多情况下,您的一些客户只想使用您图书馆的少数几个部分。如果您编写一个包含库中所有内容的主头文件,您的客户端编译时间将不必要地增加。
A common way of dealing with this problem is to provide individual header files for correlated parts of your library. If you think of all of Boost a single library, then Boost is an example of this. Boost is an enormous library, but if all you want is the regex functionality, you can only #include
the regex-related header(s) to get that functionality. You don't have to include allof Boost if all you want is the regex stuff.
处理此问题的常用方法是为库的相关部分提供单独的头文件。如果您将所有 Boost 视为单个库,那么 Boost 就是一个例子。Boost 是一个庞大的库,但如果您只需要正则表达式功能,则只能使用#include
与正则表达式相关的标头来获得该功能。如果您想要的只是正则表达式,则不必包含所有Boost。
Under both Windows and Linux, binary libraries can be further subdivided in to two types: dynamic and static. In the case of static libraries, the code of the library is actually "imported" (for lack of a better term) in to the executable of the client program. A static library is distributed by you, but this is only needed by the client during the compilation step. This is handy when you do not want to force your client to have to distribute additional files with their program. It also helps to avoid Dependancy Hell. A Dynamic library, on the other hand, is not "imported" in to the client program directly, buy dynamically loaded by the client program when it executes. This both reduces the size of the client program and potentially the disc footprint in cases where multiple programs use the same dynamic library, but the library binary must be distributed & installed with the client program.
在 Windows 和 Linux 下,二进制库可以进一步细分为两种类型:动态和静态。在静态库的情况下,库的代码实际上是“导入”(因为没有更好的术语)到客户端程序的可执行文件中。静态库由您分发,但这仅在编译步骤中由客户端需要。当您不想强迫您的客户必须随他们的程序分发其他文件时,这很方便。它还有助于避免依赖地狱. 另一方面,动态库不是直接“导入”到客户端程序中,而是在客户端程序执行时动态加载。这既减少了客户端程序的大小,也减少了在多个程序使用相同动态库的情况下可能的磁盘占用空间,但库二进制文件必须与客户端程序一起分发和安装。
回答by Mats Petersson
Assuming your "file1.hpp" and "file2.hpp" etc are closely related and (nearly) always used together, then making one "mypacakge.h" that contains the includes of the other components is a good idea (it doesn't in and of itself make it into a library - that is a different process altogether).
假设您的“file1.hpp”和“file2.hpp”等密切相关并且(几乎)总是一起使用,那么制作一个包含其他组件的包含的“mypacakge.h”是一个好主意(它不就其本身而言,使其成为一个库——这是一个完全不同的过程)。
If they are NOT closely related and/or used together, then you shouldn't have such a "mega include", because it just drags in a bunch of things that aren't needed.
如果它们没有密切相关和/或一起使用,那么你不应该有这样一个“超级包含”,因为它只会拖入一堆不需要的东西。
To make a library involves building your code once, and either generating a .lib file or a shared librar (.dll or .so file). The exact steps to do this depends on what system you are using, and it's a little too complicated for me to explain here.
制作库涉及构建一次代码,然后生成 .lib 文件或共享库(.dll 或 .so 文件)。执行此操作的确切步骤取决于您使用的系统,而且我在这里解释有点太复杂了。
Edit: To explain further: All of the C++ library is actually one library file or shared library file [along with a number of header files that contain some of the code and the declarations needed to use the code in the library]. But you include <iostream>
and <vector>
separately - it would become pretty awful to include EVERYTHING from all the different C++ library headers in one <allcpplibrary>
, even if it was a lot less typing involved. It is split into sections that do one thing per headerfile. So you get a "complete" set from one header file, but not a too much other things you don't actually need.
编辑:进一步解释:所有的 C++ 库实际上是一个库文件或共享库文件[以及一些包含一些代码和使用库中代码所需的声明的头文件]。但是你单独包含<iostream>
和<vector>
分开 - 将所有不同的 C++ 库头文件中的所有内容都包含在一个中会变得非常糟糕<allcpplibrary>
,即使它涉及的打字要少得多。它被分成几个部分,每个头文件做一件事。所以你从一个头文件中得到了一个“完整的”集,但没有太多你实际上不需要的其他东西。
回答by Claudio
On Linux:
在 Linux 上:
g++ FLAGS -shared -Wl,-soname,libLIBNAME.so.1 -o libLIBNAME.VERSION OBJECT_FILES
g++ FLAGS -shared -Wl,-soname,libLIBNAME.so.1 -o libLIBNAME.VERSION OBJECT_FILES
where
在哪里
FLAGS: typical flags (e.g., -g, -Wall, -Wextra, etc.)
FLAGS:典型标志(例如,-g、-Wall、-Wextra 等)
LIBNAME: name of your library
LIBNAME:你的图书馆的名字
OBJECT_FILES: objects files resulting from compiling cpp files
OBJECT_FILES:编译cpp文件产生的对象文件
VERSION: version of your library
VERSION:您的库的版本
回答by Arne Mertz
Yes and no.
是和否。
You can write an include-all header so that #include "myLib.h"
is sufficient, because you include all those headers through the single header. However, that does not mean that the single include is enough to have the content of the 10 '.cpp' files linked to your project automagically. You will have to compile them into a library and link that single library (instead of all the object files) to the projects that use "myLib.h". Library binaries come as static and dynamic libraries, the files are typically named .lib
and .dll
(windows) and .a
and .so
(linux) for static and dynamic libraries, respectively.
您可以编写一个包含所有头文件,这样#include "myLib.h"
就足够了,因为您通过单个头文件包含所有这些头文件。但是,这并不意味着单个包含足以将 10 个“.cpp”文件的内容自动链接到您的项目。您必须将它们编译成一个库并将该单个库(而不是所有目标文件)链接到使用“myLib.h”的项目。库二进制文件作为静态和动态库出现,这些文件通常分别命名为.lib
和.dll
(windows).a
和.so
(linux) 用于静态和动态库。
How to build and link such libraries depends on your build system, you might want to loke those terms up on the net.
如何构建和链接此类库取决于您的构建系统,您可能希望在网上查找这些术语。
One alternative is to get rid of the .cpp
files by defininig all the functions in the headers. That way you won't have to link the additional library, but it comes at the cost of increased build times, because the compiler will have to process all those functions every time you include the header directly or indirectly into one of your translation units.
一种替代方法是.cpp
通过定义标题中的所有函数来删除文件。这样你就不必链接额外的库,但它以增加构建时间为代价,因为每次你将头直接或间接地包含到你的翻译单元之一时,编译器都必须处理所有这些函数。
回答by DevSolar
If a client needs all ten headers to actually make use of your "package" (library), that's pretty bad interface design.
如果客户端需要所有十个标头来实际使用您的“包”(库),那是非常糟糕的界面设计。
If a client needs only someheaders, depending on which parts of your library are being used, let the client include the appropriate headers, so only a minimal set of identifiers are introduced. This helps scope, modularization, and compilation times.
如果客户端只需要一些头文件,取决于正在使用的库的哪些部分,让客户端包含适当的头文件,这样只引入了最少的标识符集。这有助于范围、模块化和编译时间。
If all else fails, you can make an "interface header" for external use, which is different from the ones you use internally for actually compiling your library. This would be the one that gets installed, and consists of the necessary contents from the other headers. (I still don't think you would need everythingfrom everyheader in your lib.)
如果所有其他方法都失败了,您可以制作一个“接口头”供外部使用,这与您在内部用于实际编译库的接口不同。这将是安装的那个,并且包含来自其他标题的必要内容。(我仍然不认为你需要的一切,从每一个在你的lib头。)
I would discourage Salgar's solution. You eitherhave individual headers, ora monolithic one. Providing individual headers plusa central one that simply includes the others strikes me as pretty poor layout.
我会劝阻萨尔加的解决方案。你要么有个单独报头,或者单片之一。提供单独的标题加上一个简单的包含其他标题的中央标题让我觉得布局非常糟糕。
What I do notunderstand is inhowfar Makefiles play into this. Header dependencies should be resolved automatically by your Makefile / build system, i.e. it shouldn't matter here how your header files are layed out.
我不明白的是 Makefile 对此有何影响。头文件依赖关系应该由你的 Makefile / 构建系统自动解决,也就是说,这里头文件的布局方式无关紧要。