分享
 
 
 

更友好的发布你的功能库[译]

王朝other·作者佚名  2006-02-01
窄屏简体版  字體: |||超大  

Making Your Libraries Release-Friendly

更友好的发布你的功能库

作者:Sobeit Void

翻译:skywind

原文:http://www.gamedev.net/reference/articles/article2006.asp

内容摘要

今天我写这篇文章是因为我遇到许许多多开发者们在发布他们自己的静态/动态库的时候没有注意到以一种足够“Friendly”的风格来最大可能的减少开发时候碰到的麻烦。功能库的使用者们必须经常做出更多的无益修改,但是这些修改都是没有必要的,然而今天,这一切都将会结束!

接下来的内容将仅针对VC++的类库做讨论,但是其中所涉及到的内容,同样适用于任何C++的编译器。

基本法则

我们从检查整合一个第三方库的所需要基本使用步凑开始,假定这个需要整合的第三方库的名字叫做“Useful”。

1. 拷贝 Useful的头文件和.lib文件到我们的机器中

2. 在我们的工程中 include这些 Useful的头文件

3. 将 Useful的.lib文件加入到连接项中

4. 如果 Useful是一个DLL,拷贝useful.dll到我们工程目录中或一个恰当位置(比如windows\system32)

如果所有的工作都顺利完成,我们的工程就可以愉快的使用 Useful了。有什么地方出错了呢?很多地方,真的。

不好的类库发布

让我们来一起检查这个典型的非常常见的类库发布包,看看我们将会碰到什么问题。

下面是Useful的打包发布状态:

l 头文件都位于 Useful\include。既然头文件很少有 debug/release版本,那么遵从微软的约定是很好的

l 库文件的两个版本位于 Useful\lib\debug和 Useful\lib\release,他们都称为 Useful.lib。将库文件放置在 lib目录是另外一个 Microsoft的约定。

l 两个不同版本的DLL(debug/release)都称作 Useful.dll,他们位于 Useful\bin\debug和 Useful\bin\release两个目录。bin文件夹是另一个标准的目录用于编译器输出二进制结果。

现在我开始将Useful整合到我的工程中。Useful是非常 “useful”的,因为我在五个其他工程里面都使用了它。

注意:VC++中的工程配置就象和 makefile一样,实际上,它正是。

1. 我在编译器的 include search path中增加 Useful\include以便我可以直接在五个不同的工程中使用。万一我将 Useful的目录移动到另一个地方的话(比如从c:\Useful到d:\Useful),我仅需要更改编译器的include搜索路径就可以使我的五个工程毫无麻烦的找到这些头文件了,不错。

2. 对于连接类库来说,这里开始出现问题了。我想让我的debug代码连接debug版本的库文件,release也一样。因为debug/release两个版本都称作 Useful.lib,我不能同事增加他们的目录到编译器的 library搜索目录。编译器不能区分到底该连接哪个。所以唯一的解决方法就是写死 c:\Useful\debug\lib到我的 debug工程配置中,以及 c:\Useful\release\lib到我的 release工程配置中。

3. 不幸的是我必须移动 Useful到一个其他的目录,看看我有多大一堆工作需要做。我不许更改我五个工程的library路径配置。如果你独自工作,这没有问题;如果你和以组开发者一起工作的话,看看将会发生什么。所有安装 Useful在其他目录的(这样做并没有什么过错),当每个开发者从仓库中checkout代码的时候,所有工程的路径配置都必须更改。当他们checkin这些代码的时候,代码同步会检测到这些工程配置的修改情况,并且会对这些改动完成checkin操作,下一个工作者又必须在他checkout以后再次更改这些路径设置。听起来很好笑吧,几乎是很艰辛的。

4. 现在,同样的问题在使用DLL的时候出现了,系统再次无法检测哪个dll是debug哪个又是release,所以我们无法将 Useful.dll放到一个公共的路径中去。(实际上你能做到,如果你希望每次交换 debug/release两个版本的DLL的话)所以我拷贝 Useful.dll分别到我的 debug/release目录中,所以系统可以找到最靠近我执行文件的那个dll,但是这只能适用于一个项目,我需要在五个不同的工程中这么做。

现在,Useful的开发者找到了一个主要的BUG,发布了一个新版本的Useful。我们就必须拷贝新的DLL到每个工程的输出目录。如果Useful发布到另外一个目录(比如c:\UsefulFixed而不是 c:\Useful),我们又必须每次为每个工程配置做一次更改。

通过这些,你可以发现这些问题将在一个项目的Lifetime中一直存在。类库更新了,安装目录更新了,所有的问题将会惯性的发生,我们可怜的开发者们将准备好每次应付这些问题的发生。

微软的解决方案

这里是微软如何完成他们的类库发布的,你可以在你自己的VC++目录中得到验证:

l 头文件被防止到 Useful\include文件夹,include名称只是一个约定,不一定要遵守。

l 库文件被防止到 Useful\lib。Debug版本需要在名称后加一个”_d”,所以我们在c:\Useful\lib中分别得到 Useful_d.lib和 Useful.lib两个文件。

注意,该方法解决了连接问题。在我们的代码中你可以这样连接 Useful库:

#ifdef _DEBUG

#pragma comment( lib, “Useful_d” )

#else

#pragma comment( lib, “Useful” )

#endif

然后我们可以增加 c:\Useful\lib到我们编译器的 library搜索目录。

l Debug版本的DLL同样增加一个”_d”,我们得到 Useful_d.dll和 Useful.dll

这两个都可以同时被放入一个普通的文件夹,尽管微软经常放到windows\system32目录中去。这并不是一个很好的做法,除非是系统DLL。作为开发,你不必这样做,因为开发者通常需要最安装新版本的 DLL。作为一个每天都使用他的用户,这将导致版本冲突最终导致”DLL HELL”。

需要牢记的是,如果你需要发布一个应用程序,那么将你所需要的DLL放到你的本地文件夹里面。你可以使用一个叫做”Dependency Walker”的工具看看你需要哪些DLL。

最终结论

以上的更改对于一个类库的编译过程是很简单的同时不会影响到类库的开发。总之,给你的发布包一点微小的改变,你可以节约成千上万使用你类库的人的时间。

在论坛中讨论该文章

(讨论精选)

Interesting article but I think you missed out a couple of useful facts.

* Try not to put paths into the Directories option in VC++. Instead there is a per build setting option in Project Settings, C/C++, Additional Includes. There is also one for libs under link. This way if Useful comes with a lib\debug\useful.lib and a lib\release\useful.lib you can just link in useful.lib and path to the correct one. This becomes invaluable when doing cross platform. Imagine having debug/release libs of a bunch of xbox, pc, gamecube and ps2. #pragma comment (lib, x) won't work on gamecube or ps2 (as far as I know), even if it did you would have a mess of pragmas for just 1 library, now think about if there were 12 libs.

* Make your includes and libs, where possible, relative paths. If you have your game in a folder called game, have Useful at the same level. This way your path to it would be ..\useful\lib\release\. This works for all so long as they have Game and Useful at the same level.

* If the above isn't an option consider your team subst'ing drives. We subst a drive 'R' to the Renderware install and a drive 'H' to the havok install. This lets people install them to wherever they want without breaking project settings. You can then just path to 'R:\include' for the Renderware includes.

Anyway, that's just my preferences. Hopefully the article will get people thinking think a little more when it comes to distributing their libs.

> But one question I would have for you guys, is how do you

> organise your project solution, source, libs, dlls, etc...

> and what about external libraries ?

As you pointed out, there are no right or wrong answers here and it depends on what product you are building and a lot about team consensus. Where I worked, the main product had around 11 million lines of code. Granted, there was a large amount of comments in there, but even at a 1:1 comment/code ratio that's a pretty huge code base to handle. The product was composed of 92 libraries, 8 of which were developped externally. The product was declined in SGI/Linux/Win32 flavors and in the Debug/Retail/Profiling compilations and in Retail/Demo versions for a total of 18 permutations. We used RCS to align all the libraries under the main product directory and used hard links for libraries that were duplicated across products. We didn't use TMP or such directories because there was one build machine per compilation configuration and it pulled the sources on the local hard disk before starting the build process. Also, we didn't make any difference between external and internal libraries; those that came compiled were inserted in the RCS tree and version-stamped. The libraries were compiled first in .lib/.a files and a final makefile would build the various executables that made up the product. There was a final phase that grabbed executables along with various assets and made the CD images; libraries and header files were 'exported' into a package any developper would pull in for the day's work. Then smoke tests were performed using the product's internal scripting ability, and then QA would perform ad-hoc and regression testing to determine if the build 'passes'.

> To make sure noone screws up, we have this "Build Nazi" dude.

As you can imagine, coordinating a big team around this product was essential; and we wanted to have a full product compiled each night and ready for use the next morning. We used the concept of a "build breaker" where the ones who screwed up were responsible for ensuring that compilations were fixed and restarted, then coordinate QA in testing the product; that usually took the entire day, thus introducing a negative feedback loop in the product development cycle for those loose guns in the team. After 5 build breaks within a period of 3 months, salaries/options/bonuses were revised downward. I guess we didn't have someone 'big enough' in the team... but it worked.

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有