MSVC库构建的标准或“最常用”命名约定是什么。
例如,对于以下平台,库foo
具有以下约定:
Linux / gcc:
shared: libfoo.so
import: ---
static: libfoo.a
的Cygwin / GCC:
shared: cygfoo.dll
import: libfoo.dll.a
static: libfoo.a
视窗/ MinGW的:
shared: libfoo.dll
import: libfoo.dll.a
static: libfoo.a
MSVC buidls应该使用什么?据我所知,通常名称为foo.dll
和foo.lib
,但您通常如何区分导入库和静态库?
注意:我问,因为CMake
在他们之间创建了非常unpleasant的冲突,将导入和静态库命名为foo.lib
。见bug report。答案会
帮助我说服开发人员修复这个错误。
答案 0 :(得分:5)
正如其他人所说,没有标准,但有流行的惯例。我不确定如何明确地判断什么是最受欢迎的惯例。除了你提到的静态与导入库的命名之外,Release库与Debug库的命名之间也有类似的区别,特别是在Windows上。
这两种情况(即静态与导入,调试与发布)都可以通过以下两种方式之一进行处理:不同的名称或不同的目录位置。我通常选择使用不同的名称,因为我觉得它可以最大限度地减少以后误读库类型的可能性,特别是在安装或其他文件移动活动之后。
我通常在Windows上使用foo.dll
和foo.lib
,在静态库中使用foo_static.lib
,当我希望同时拥有共享和静态版本时。我见过其他人使用这个约定,所以它可能是“最受欢迎的”。
所以我建议你在桌子上添加以下内容:
视窗/ MSVC:
shared: foo.dll
import: foo.lib
static: foo_static.lib
然后在cmake,你可以
add_library(foo_static STATIC foo.cpp)
或
add_library(FooStatic STATIC foo.cpp)
set_target_properties(FooStatic PROPERTIES OUTPUT_NAME "foo_static")
如果由于某种原因您不希望使用“foo_static”作为符号库名称。
答案 1 :(得分:4)
您可以通过扩展名区分库和.dll。但您可以通过 filename 区分导入库和静态库,而不是扩展名。
对于一组构建为静态库的代码,或者存在dll的静态库,不存在导入库的情况。这是两件不同的事情。
没有单一的MSVC标准文件名约定。通常,以“D”结尾的库名称通常是库代码msvcrtd.dll
vs msvcrt.dll
的调试版本,但除此之外,没有标准。
答案 2 :(得分:2)
据我所知,没有真正的“标准”,至少没有大多数软件符合的标准。
我的约定是将动态和静态.lib
命名为,但如果项目恰好支持静态和动态链接,则将它们放在不同的目录中。例如:
foo-static
foo.lib
foo
foo.lib
foo.dll
要链接的库取决于库目录的选择,因此它几乎完全与构建过程的其余部分分离(如果使用MSVC的#pragma comment(lib,"foo.lib")
工具,它将不会出现在源代码中,并且它没有出现在链接器的导入库列表中。)
我已经看过很多次了。此外,我认为基于MSVC / Windows的项目倾向于更频繁地使用单一的官方链接类型 - 静态,或动态。但这只是我个人的观察。
简而言之: 视窗/ MSVC
shared: foo.dll
import: foo.lib
static: foo.lib
您应该能够将此基于目录的模式与CMAKE一起使用(从未使用过它)。此外,我不认为这是一个'错误'。这只是缺乏标准化。如果每个人都喜欢不同的话,CMAKE会(imho)做正确的事情而不是来建立伪标准。
答案 3 :(得分:2)
库没有标准的命名约定。传统的库名称以lib
为前缀。许多链接器可以选择在命令行中将lib
添加到库名称。
静态和动态库通常通过文件扩展名来标识;虽然这不是必需的。因此libmath.a
将是一个静态库,而libmath.so
或libmath.dll
将是一个动态库。
常见的命名约定是将库的类别附加到名称。例如,调试静态数学库将是“libmathd.a”或Windows中的“lib_math_debug”。一些商店还将Unicode添加为文件名属性。
如果需要,可以将_msvc
附加到库名称以指示库需要或由MSVC创建(以区分GCC和其他工具)。使用多个平台时,一种流行的约定是将对象和库放在特定于平台的文件夹中。例如,./linux/
文件夹将包含Linux的对象和库,同样适用于Microsoft Windows平台的./msw/
。
这是一个风格问题。风格问题通常被视为宗教问题:没有一个是错的,没有普遍的风格,而且它们是个人偏好。你选择什么样的系统,只要保持一致。
答案 4 :(得分:2)
正如其他人所说,在Windows上没有单一的标准来命名文件。
对于我们完整的产品库,它涵盖了100个exes,dlls和static libs,我们已经成功使用了以下多年,它已经节省了很多混乱。它基本上是我多年来看到的几种方法的混合。
简而言之,我们所有的前缀和后缀文件(不包括扩展本身)。它们都以“om”(基于我们公司名称)开头,然后有一个或两个字符组合,大致标识代码区域。
后缀解释了它们是什么类型的构建文件,并且最多包含三个字母组合,具体取决于构建,包括Unicode,静态,调试(Dll构建是默认的,没有明确的后缀标识符)。当我们开始使用这个系统时,Unicode并不是那么普遍,我们不得不同时支持Unicode和非unicode构建(在Windows 2000操作系统之前),现在所有内容都是专门构建的unicode,但我们仍然使用相同的命名法。
因此典型的.lib“set”文件可能看起来像
omfThreadud.lib (Unicode/Debug/Dll)
omfThreadusd.lib (Unicode/Static/Debug)
omfThreadu.lib (Unicode/Release/Dll)
omfThreadus.lib (Unicode/static)
所有文件都内置在一个公共bin文件夹中,这为开发人员消除了很多dll-hell问题,也使得调整编译器/链接器设置变得更加简单 - 它们都指向使用相对路径的相同位置永远不需要手动(或自动)复制项目所需的库。拥有这些后缀还可以消除您可能拥有的文件类型的任何混淆,并保证您不会有混合方案,您将调试dll放在发行套件上,反之亦然。所有exes也使用类似的后缀(Unicode / Debug)并构建到相同的bin文件夹中。
同样有一个“include”文件夹,每个库在include文件夹中有一个头文件,与库/ dll的名称相匹配(例如omfthread.h)该文件本身#include所有其他项目由该图书馆曝光。如果你想要foo.dll中的功能你只需要#include“foo.h”,这就更简单了。我们的库被功能区域高度分割 - 实际上我们没有任何“瑞士军刀”dll,所以包括库整个功能都有意义。 (这些标头中的每一个还包括其他先决条件标头,无论它们是我们的内部库还是其他供应商SDK)
其中每个包含文件都在内部使用宏,这些宏使用#pramga将相应的库名称添加到链接器行,因此各个项目不需要关心。我们的大多数库都可以静态构建或作为DLL构建,并且#define OM_LINK_STATIC(如果已定义)用于确定单个项目想要的内容(我们通常使用DLL,但在某些情况下,内置于.exe make中的静态库)更有意义的部署或其他原因)
#if defined(OM_LINK_STATIC)
#pragma comment (lib, OMLIBNAMESTATIC("OMFTHREAD"))
#else
#pragma comment (lib, OMLIBNAME("OMFTHREAD"))
#endif
这些宏(OMLIBNAMESTATIC& OMLIBNAME)使用_DEBUG确定它是什么类型的构建,并生成适当的库名称以添加到链接器行。
我们在静态和放大器中使用通用定义。 dll版本的库,用于控制dll版本中类/函数的正确导出。从库中导出的每个类或函数都使用此宏进行修饰(其名称与库的基本名称相匹配,但这在很大程度上并不重要)
class OMUTHREAD_DECLARE CThread : public CThreadBase
在项目设置的DLL版本中,我们定义了OMFTHREAD_DECLARE = __ declspec(dllexport),在库的静态库版本中,我们将OMFTHREAD_DECLARE定义为 empty 。
在库头文件中,我们根据客户端尝试链接到它的方式来定义它
#if defined(OM_LINK_STATIC)
#define OMFTHREAD_DECLARE
#else
#define OMFTHREAD_DECLARE __declspec(dllimport)
#endif
一个想要使用我们的内部库的典型项目只是将相应的include添加到他们的stdafx.h(通常)并且它只是工作,如果他们需要链接静态版本他们只是将OM_LINK_STATIC添加到他们的编译器设置(或在stdafx.h中定义),它再次起作用。
答案 5 :(得分:1)
据我所知,目前还没有任何约定。以下是我如何做的一个例子:
(项目)的 {子模块} {平台} {架构} {编译器运行} _ {BuildType}的.lib / DLL
完整文件名应仅为小写,并且只包含带有预先指定的下划线的字母数字。子模块字段(包括其前导下划线)是可选的。
项目:保存项目名称/标识符。优选尽可能短。即" dna"
SubModule:可选。持有模块名称。优选尽可能短。即" dna_audio"
平台:标识二进制编译的平台。即" win32" (Windows)," winrt"," xbox"," android"。
架构:描述编译二进制文件的体系结构。 ie" x86"," x64"," arm"。对于各种位,架构名称相同的位置使用其名称后跟位数。即。 " name16"," name32"," name64"
CompilerRuntime:可选。并非所有二进制文件都链接到编译器运行时,但如果有,则包含在此处。即" vc90" (Visual Studio 2008)," gcc"。适用的公寓可以包括在内,即" vc90mt"
BuildType:可选。这可以包含字母(以任何所需的顺序),每个字母都可以说明构建特定的内容。 d = debug(如果发布则省略)t = static(如果是动态则省略)a = ansi(如果是unicode则省略)
示例(假设项目名为" DNA"): dna_win32_x86_vc90.lib / DLL dna_win32_x64_vc90_d.lib / DLL dna_win32_x86_vc90_sd.lib dna_audio_win32_x64_vc90.lib / DLL dna_audio_winrt_x64_vc110.lib / DLL