为什么很多项目不提供预编译的二进制文件?
Why many projects don't provide a pre-compiled binary file?
这个问题已经困扰我很久了。我不经常使用 c++,似乎大多数 cpp 库都以 zip 文件或包含源代码的 tar 球的形式提供。
所以,问题是:
为什么那些项目不提供预编译的二进制文件?
我目前对“autoconf
, make
, make install
, ...”程序的理解是确保一切正确,然后将源代码编译为可执行文件或一些图书馆。但是如果我们最终得到同样的东西,为什么我们每次都要编译它呢?我并不是想为编译的库维护一个单独的项目,但是在调试和测试过程中,这些文件应该会自动生成,为什么不把它们放在发布文件中呢?
例如:FTGL库的源码自带visual studio解决方案文件(.sln),如果他们用这个来开发和调试,为什么不把编译后的二进制文件放到他们的发布文件中呢?
平台通常有一个共同的 C ABI,它规定了符号命名、函数调用约定和其他 low-level 细节。以 ABI 为目标的编译器可以与其他执行相同操作的编译器进行互操作。 Linux 库和 Windows 库不兼容,但通常可以为每个目标平台构建少量版本:一个用于 Linux,一个用于 Windows,等等.
C++ 库没有这样的标准。 Name mangling 因编译器而异。已编译的 C++ 库通常只能由同一版本的同一编译器使用。由同一编译器的不同版本编译的库甚至不一定兼容。要 pre-build 一个库,您必须使用数十个版本的 g++、数十个版本的 clang 等来构建...这是不切实际的。
分发 C++ 库很困难。一些常见的策略是:
创建库 header-only,这样最终用户只需 #include
个库 header。无需编译。
分发 header 和源文件并要求最终用户构建库。
在 C 中实现库并在 header 文件中提供 C++ 包装器。 C 和 C++ 程序都可以使用该库。如果需要,C 部分可以是 pre-built。
与上一条相反,用 C++ 实现库并添加 C 包装器。包装器将定义一堆调用 C++ 代码的独立 extern "C"
函数。
例如,Boost 混合使用策略 1 和 2。如果您只使用 Boost 的 header-only 部分,那么您所要做的就是 #include
他们的 headers 在你的程序中,超级简单。如果您使用非 header-only 部分,例如线程或正则表达式组件,那么您必须编译它们,这需要一段时间。
3 和 4 对于您不想分发代码的专有库很有用。
根据您的平台,生成的二进制文件将大不相同。例如,您可以 运行 Linux、Mac 或 Windows,除此之外,这些可能是 64 位或 32 位架构。
如果我将 windows 32 位二进制文件传递给您,而您的系统是 64 位 Mac,则二进制文件将完全不兼容。
有些项目确实为每个平台提供了一个二进制文件,或者可能 select 少数几个,但是拥有源代码仍然很棒,因为您可能希望修改它,只使用它的某些部分或只是理解它.
这个问题已经困扰我很久了。我不经常使用 c++,似乎大多数 cpp 库都以 zip 文件或包含源代码的 tar 球的形式提供。
所以,问题是:
为什么那些项目不提供预编译的二进制文件?
我目前对“autoconf
, make
, make install
, ...”程序的理解是确保一切正确,然后将源代码编译为可执行文件或一些图书馆。但是如果我们最终得到同样的东西,为什么我们每次都要编译它呢?我并不是想为编译的库维护一个单独的项目,但是在调试和测试过程中,这些文件应该会自动生成,为什么不把它们放在发布文件中呢?
例如:FTGL库的源码自带visual studio解决方案文件(.sln),如果他们用这个来开发和调试,为什么不把编译后的二进制文件放到他们的发布文件中呢?
平台通常有一个共同的 C ABI,它规定了符号命名、函数调用约定和其他 low-level 细节。以 ABI 为目标的编译器可以与其他执行相同操作的编译器进行互操作。 Linux 库和 Windows 库不兼容,但通常可以为每个目标平台构建少量版本:一个用于 Linux,一个用于 Windows,等等.
C++ 库没有这样的标准。 Name mangling 因编译器而异。已编译的 C++ 库通常只能由同一版本的同一编译器使用。由同一编译器的不同版本编译的库甚至不一定兼容。要 pre-build 一个库,您必须使用数十个版本的 g++、数十个版本的 clang 等来构建...这是不切实际的。
分发 C++ 库很困难。一些常见的策略是:
创建库 header-only,这样最终用户只需
#include
个库 header。无需编译。分发 header 和源文件并要求最终用户构建库。
在 C 中实现库并在 header 文件中提供 C++ 包装器。 C 和 C++ 程序都可以使用该库。如果需要,C 部分可以是 pre-built。
与上一条相反,用 C++ 实现库并添加 C 包装器。包装器将定义一堆调用 C++ 代码的独立
extern "C"
函数。
例如,Boost 混合使用策略 1 和 2。如果您只使用 Boost 的 header-only 部分,那么您所要做的就是 #include
他们的 headers 在你的程序中,超级简单。如果您使用非 header-only 部分,例如线程或正则表达式组件,那么您必须编译它们,这需要一段时间。
3 和 4 对于您不想分发代码的专有库很有用。
根据您的平台,生成的二进制文件将大不相同。例如,您可以 运行 Linux、Mac 或 Windows,除此之外,这些可能是 64 位或 32 位架构。
如果我将 windows 32 位二进制文件传递给您,而您的系统是 64 位 Mac,则二进制文件将完全不兼容。
有些项目确实为每个平台提供了一个二进制文件,或者可能 select 少数几个,但是拥有源代码仍然很棒,因为您可能希望修改它,只使用它的某些部分或只是理解它.