使用 make 构建我的项目
我正在努力改进 Bitfighter 长期停滞的 Linux 构建过程,但在 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 。我如何才能让 make 找出我拥有的库并将其链接到其中?显然 -l 指令对此不够聪明。我希望用户不必担心 Lua 安装后的位置,并且 makefile 可以正常工作。
最后,有没有办法让 make 检测某些必需的软件包(例如 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)
I'm working to improve the long languishing Linux build process for Bitfighter, and am having problems with make. My process is actually quite simple, and since make is (nearly) universal, I want to stick with it if I can.
Below I've attached my current Makefile, which works, but clumsily so. I'm looking for ways to improve it, and have three specific questions at this point.
First, the project can be built with several options. Let's take debug and dedicated for this example. The dedicated option will exclude all UI code, and create a more efficient binary good for hosting (but not playing) games. The debug option adds a flag to the compiler that activates debugging code. One might want to build the game with either, both, or neither of these options.
So the question is, how do I make this work? As you can see from the comments in the makefile below, debugging is enabled by setting DFLAGS=-DTNL_DEBUG. I'd like to have the user type
make dedicated debug
rather than
make dedicated DFLAGS=-DTNL_DEBUG
How can I rewrite my makefile so that this will work?
Secondly, when I install the lualibs package on different versions of Linux, I get different libraries. For example, on Ubuntu, when I install the lualib package with apt-get, I get lua5.1.a in my /usr/lib folder. On Centos, when I install the same thing with yum, I end up with liblua.a in my /usr/lib folder. How can I get make to figure out which library I've got, and link that in? Obviously the -l directive is not smart enough for that. I'd like the user to not have to worry about where Lua ends up when it gets installed, and for the makefile to just work.
Finally, is there any way to get make to detect whether certain required packages (freeglut, for example) have not been installed, and either install them automatically or at least alert the user to the fact they need to get them installed (as opposed to simply terminating with a cryptic error message)?
Thanks!!
Here is my 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) lt; .cpp.o : $(CC) $(DFLAGS) $(WFLAGS) -c $(CFLAGS) lt; 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)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
Raw
make
并不真正支持任何这些用途。make
将命令行中传入的目标视为要构建的不同程序或要执行的不同操作,并且它没有使用传入的两个目标来切换单个构建的独立选项的概念。make
也没有任何内置的支持来检查已安装的软件包的版本。这是一个有点陡峭的学习曲线,但所有这些问题的最常见解决方案是使用 GNU autotools 工具链(Autoconf 和 Automake,特别是)。这些工具旨在帮助编写可移植的、可配置的构建系统,这些系统可以探测系统中各个位置的库,并根据配置选项和用户的系统生成 Makefile。
如果您曾经运行过
./configure;制作; make install
,您可能使用过由 Autoconf 和 Automake 生成的configure
脚本。维基百科文章提供了一些概述,Automake手册提供了介绍工具链的教程。
对于您的使用,您可能想要做的是使用 Autoconf 创建一个
configure
,它采用--enable-debug
和--enable-dedicated< 等选项/code>,设置生成 Makefile 的选项。然后,您可以将 Makefile 移植到 Automake,或者您可以简单地将 Makefile 转换为
Makefile.in
,其中包含 Autoconf 在生成Makefile
时填充的一些变量。虽然 GNU Autotools 系统非常完整,并且支持很多平台,但它有点巴洛克风格。有一些替代构建系统支持一些类似的自动配置行为,例如 CMake 和 SCons,如果 Autotools 感觉太多了,这可能值得研究一下。
对于检测某些库并查找链接到它们所需的选项的特定任务,
可以使用pkg-config
;但是,并非所有库都安装pkg-config
定义,而且并非所有系统都安装了pkg-config
,因此它不是通用解决方案,但可以是一个快速且快速的解决方案。在它确实有效的情况下,构建一些东西的简单方法,而无需太多混乱的选项。Raw
make
doesn't really support any of these uses.make
considers targets passed in on the command line to be different programs to be built, or different actions to take, and it has no concept of using two targets passed in to switch independent options for a single build.make
also doesn't have any built in support for checking for versions of packages installed.It's a bit of a steep learning curve, but the most common solution for all of these problems is to use the GNU autotools toolchain (Autoconf and Automake, specifically). These tools have been written to help write portable, configurable build systems, that can probe the system for libraries in various locations, and generate Makefiles based on configuration options and the user's system.
If you have ever run
./configure; make; make install
, you have probably used aconfigure
script generated with Autoconf and Automake.The Wikipedia article provides a bit of an overview, and the Automake manual provides a tutorial introducing the toolchain.
For your usage, what you would probably want to do is create a
configure
using Autoconf that takes options like--enable-debug
and--enable-dedicated
, to set options for generating your Makefile. You could then port your Makefile to Automake, or you could simply turn your Makefile into aMakefile.in
with a few variables that Autoconf will fill in when generating theMakefile
.While the GNU Autotools system is very complete, and supports a lot of platforms, it is a bit baroque. There are some alternative build systems that support some similar auto-configuration behavior, like CMake and SCons, that might be worth looking into if Autotools feels like too much.
For the specific task of detecting certain libraries, and finding the options you need to link to them,
pkg-config
can be used; however, not all libraries installpkg-config
definitions, and not all systems even havepkg-config
installed, so it's not a universal solution, but can be a nice quick and easy way to get something building without too much messing with options in the cases in which it does work.pkgconfig 会回答你的很多问题。
的返回值
要检测是否安装了 lua,请检查(如果安装了 lua,则应返回 0)
。 使用查看在系统上使用 lua 进行编译时应在命令行中传递的内容。 (您可能希望将其添加到 CFLAGS)。
首先,Make 不会帮助你。你给它的命令指定目标,而不是选项。您将需要使用 autoconf 之类的东西来生成 ./configure 脚本。由此,您的用户可以输入 ./configure --enable-debug --enable-dedicated (或使用 --disable-* 显式关闭它们)。只要您的依赖项使用 pkg-config (大多数 *nix 程序都这样做,不确定 freeglut),那么在 autoconf 中使用 PKG_CHECK_MODULES 宏来提供友好的错误消息并获取库的正确命令行参数就很简单。
由于您似乎想使用 Windows 进行构建,因此您可能需要考虑使用 CMake 来生成特定于所使用的系统和所需配置的 Makefile。输出看起来确实更好,并且应该仍然可以与 pkg-config 一起使用。
pkgconfig will answer a lot of your questions.
To detect if lua is installed, check the return value of
(which should return 0 if lua is installed) Use
to see what should be passed in the command line to compile with lua on the system. (You'll probably want to add this to CFLAGS).
For the first, Make will not help you. Commands you give it specify targets, not options. You'll want to use something like autoconf to generate a ./configure script. From this, your user could type ./configure --enable-debug --enable-dedicated (or explicitly turn these off with --disable-*). As long as your dependencies use pkg-config (which most *nix programs do, unsure about freeglut), then it is simple to use the PKG_CHECK_MODULES macro in autoconf to give friendly error messages and get the correct command line arguments for the libraries.
Since it looks like you want to build with Windows, you may want to look into using CMake instead to generate the Makefile specific to the system used and the configuration desired. The output does look better and it should still work with pkg-config.
我将首先(一如既往)推荐 CMake。它会从更高的抽象级别为您生成 makefile。如果您想构建不同配置的二进制文件,您可以让 CMake 生成具有不同参数的不同构建树(一个用于“调试”,一个用于“专用”)。这将为您提供两组独立的 Makefile,一组用于构建调试二进制文件,一组用于构建专用二进制文件,全部来自同一组源。 (CMake 以二进制形式适用于当今最常用的平台。Linux、Solaris、Windows、OSX 等,也可以从许多其他平台上的源代码构建。)
CMake 还支持检测外部是否存在库,尽管我几乎没有使用它的经验。
如果您想继续使用 GMake,我会通过递归调用 make 来解决“调试与专用”问题,如下所示:
I'll start (as I always do) by recommending CMake. It'll generate makefiles for you from a higher level of abstraction. If you want to build differently configured binaries you would let CMake generate to different build trees with different parameters (one for "debug" and one for "dedicated"). This will give you two separate sets of Makefiles, one which builds the debug binary and one which builds the dedicated binary, all from the same set of sources. (CMake is available in binary form for most commonly used platforms today. Linux, Solaris, Windows, OSX, etc, and can be built from sources on a number of other platforms as well.)
CMake also has support for detecting the presence of external libraries, although I have very little experience of using that.
If you want to keep using GMake, I'd solve the "debug vs. dedicated" problem by recursively invoking make, like this:
对于第一点有一个捷径,但并不完全令人满意。 使用:
在你的 makefile 中
和:它还允许打开其他选项,例如:
There is a shortcut for the first point, not entirely satisfying. Use:
and in your makefile:
It also allows to turn on other options such as: