使用make构建我的项目
我正在努力改进对于Bitfighter的冗长的Linux构建过程,并且遇到了make问题。我的过程其实很简单,因为make(几乎)是普遍的,所以如果可以的话,我想坚持下去。使用make构建我的项目
下面我附上我目前的Makefile,它的工作原理,但很笨拙。我正在寻找改进它的方法,并且在这一点上有三个具体问题。
第一个,该项目可以建立几个选项。我们来看看这个例子的调试和专用。专用选项将排除所有UI代码,并为托管(但不玩游戏)创建更有效的二进制文件。调试选项向编译器添加一个标志,激活调试代码。人们可能希望用这两种选项中的任何一种或两种选项来构建游戏。
所以问题是,我该如何做这项工作?正如您从下面makefile中的注释中所看到的那样,通过设置DFLAGS = -DTNL_DEBUG来启用调试。我想有用户类型
make dedicated debug
而不是
make dedicated DFLAGS=-DTNL_DEBUG
我如何重写我的makefile所以,这将工作?
其次,当我在不同版本的Linux上安装lualibs包时,我得到不同的库。例如,在Ubuntu上,当我使用apt-get安装lualib软件包时,我在我的/ usr/lib文件夹中获得了lua5.1.a。在Centos上,当我用yum安装相同的东西时,我在我的/ usr/lib文件夹中以liblua.a结束。我怎样才能弄清楚我拥有哪个图书馆,并将其链接到?很明显,-l指令不够聪明。我希望用户不必担心Lua在安装时结束的位置,以及makefile才能正常工作。
最后,有没有什么办法让使检测是否一定需要的包(freeglut,例如)尚未安装,并可以自动安装它们,或者至少提醒用户他们需要得到事实他们安装(而不是简单地终止一个神秘的错误消息)?
谢谢!
这是我的Makefile。
# Bitfighter Makefile ####################################### # # Configuration # # # Some installs of lua call the lua library by different names, and you # may need to override the default lua library path. For the ServerHitch # CENTOS installs, for example, you will need to specify the lua library # on the make command line: # LUALIB=/usr/lib/liblua.a # # # To compile Bitfighter with debugging enabled, specify # DFLAGS=-DTNL_DEBUG # on the make command line # # # Building with make on Windows is still highly experimental. You will # probably need to add # WFLAGS="-DWIN32 -D_STDCALL_SUPPORTED" THREADLIB= GLUT=-lglut32 INPUT=winJoystick.o # to the make command line to have any hope of getting it to work! :-) # # ####################################### CC=g++ -g -I../tnl -I../glut -I../openal -DTNL_ENABLE_LOGGING THREADLIB= -lpthread GLUT=-lGL -lGLU -lglut INPUT=linuxInput.o OBJECTS_ZAP=\ CTFGame.o\ ...many more... BotNavMeshZone.o\ ../master/masterInterface.o\ CFLAGS= DFLAGS= EXEFILE=bitfighter OPENAL=../openal/linux/libopenal.a LUALIB=-llua5.1 WFLAGS= .c.o: $(CC) $(DFLAGS) $(WFLAGS) -c $(CFLAGS) $< .cpp.o : $(CC) $(DFLAGS) $(WFLAGS) -c $(CFLAGS) $< default: ../exe/bitfighter bitfighter: ../exe/bitfighter dedicated: CFLAGS=-DZAP_DEDICATED dedicated: GLUT= dedicated: OPENAL= dedicated: EXEFILE=bitfighterd dedicated: ../exe/bitfighter ../exe/bitfighter: $(OBJECTS_ZAP) $(CC) -o ../exe/$(EXEFILE) $(OBJECTS_ZAP) ../tnl/libtnl.a \ ../libtomcrypt/libtomcrypt.a \ $(OPENAL) $(GLUT) $(THREADLIB) $(LUALIB) -lstdc++ -lm ../master/masterInterface.o: make -C ../master clean: rm -f $(OBJECTS_ZAP) ../exe/bitfighter ../exe/bitfightered cleano: rm -f $(OBJECTS_ZAP)
原始make
并不真正支持任何这些用途。 make
认为在命令行中传入的目标是要构建的不同程序或要采取的不同操作,并且没有使用传入的两个目标切换单个构建的独立选项的概念。 make
也没有任何内置的支持来检查安装的软件包版本。
这是一个陡峭的学习曲线,但所有这些问题最常见的解决方案是使用GNU autotools工具链(特别是Autoconf和Automake)。这些工具的编写是为了帮助编写可移植,可配置的构建系统,它可以探测系统在不同位置的库,并根据配置选项和用户系统生成Makefile。
如果您曾经运行./configure; make; make install
,您可能使用了使用Autoconf和Automake生成的configure
脚本。
Wikipedia article提供了一些概述,Automake manual提供了一个教程介绍工具链。
对于您的使用情况,你可能会想要做的就是创建一个configure
使用的Autoconf这需要选项,如--enable-debug
和--enable-dedicated
,以设置生成你的Makefile选项。然后你可以将你的Makefile移植到Automake,或者你可以简单地把你的Makefile变成一个Makefile.in
,其中有一些Autoconf在生成Makefile
时会填写的变量。
尽管GNU Autotools系统非常完整,并且支持很多平台,但它有点巴洛克式。还有一些支持一些类似自动配置行为的替代构建系统,如CMake和SCons,如果Autotools感觉太多,可能值得考虑。
对于检测某些库的特定任务,并找到需要链接到它们的选项,可以使用pkg-config
;然而,并非所有的库都安装了pkg-config
的定义,并且并非所有的系统甚至安装了pkg-config
,所以它不是一个通用的解决方案,但它可以成为一种快速而简单的方式来构建一些东西,而不会在其中包含任何选项确实有效。
pkgconfig将回答你很多问题。
要检测是否安装了LUA,检查
pkg-config --exists lua
的返回值(如果已安装的Lua应该返回0)使用
pkg-config --cflags --libs lua
,看看有什么应该在命令传递在系统上与lua进行编译。 (你可能想把它添加到CFLAGS中)。
首先,Make不会帮助你。你给它的命令指定目标,而不是选项。你会想使用类似autoconf的东西来生成一个./configure脚本。从这里,你的用户可以输入./configure --enable-debug --enable-dedicated(或者用--disable- *明确地关闭它们)。只要您的依赖关系使用pkg-config(大多数* nix程序所做的,不确定freeglut),那么使用autoconf中的PKG_CHECK_MODULES宏可以很容易地给出友好的错误消息,并为这些库获取正确的命令行参数。
由于它看起来像要用Windows构建,您可能需要考虑使用CMake来生成特定于所用系统和所需配置的Makefile。输出看起来更好,它应该仍然可以与pkg-config配合使用。
是的,这将有助于检测thinkgs。但是它没有提供构建适当makefile的框架。 – 2009-12-29 00:26:54
对不起,如果它不清楚,但autoconf将这样做与PKG_CHECK_MODULES和相关的宏 – sargas 2010-01-02 07:25:17
我会从推荐CMake开始(就像我一直这样做)。它会从更高级别的抽象中为您生成makefile。如果你想构建不同的配置二进制文件,你可以让CMake生成具有不同参数的不同构建树(一个用于“调试”,另一个用于“专用”)。这将为您提供两组独立的Makefile,一组构建调试二进制文件,另一组构建专用二进制文件,全部来自同一组源代码。 (目前大多数常用平台的CMake可用二进制形式提供,Linux,Solaris,Windows,OSX等等,也可以从其他平台上的源代码构建。)
CMake也支持检测外部库的存在,虽然我很少使用它的经验。
如果你想使用GMAKE继续,我会通过递归调用make,这样解决了“调试与专用”的问题:
default: debug
debug:
$(MAKE) all FLAGS=....
dedicated:
$(MAKE) all FLAGS=...
感谢您的建议。这似乎无法很好地处理“专用调试”情况。然而,我会考虑CMake,看看它是否给我我所需要的。 – Watusimoto 2010-01-04 18:40:36
CMake非常灵活;通常有几种方法来解决这样的问题。 – JesperE 2010-01-04 21:35:34
有第一个点一个快捷方式,不完全令人满意的。用途:
make dedicated DEBUG=1
,并在你的Makefile:
ifdef DEBUG
DFLAGS += -DTNL_DEBUG
endif
它也能打开其他选项,例如:
ifdef DEBUG
# Turn on gdb symbols
CFLAGS += -ggdb3
# Pass a specific DEBUG level to your code
CFLAGS += -DDEBUG=$(DEBUG)
# And so on
endif
我认为,对于我的情况,而不是陷入autotools的复杂性,我会创建一个简单的bash脚本,找出哪些标志传递制造。如果我的构建比现在更复杂,那么我会采纳你的建议。对于我现在需要的东西来说,看起来似乎过分了。 – Watusimoto 2010-01-04 18:38:49