comake使用详解
automake的教程

转一个automake的教程2008年06月24日星期二下午 03:03使用 GNU autotools 改造一个软件项目本文不是一篇规范的教程,而是用一个软件项目作为例子,演示使用 GNU autotools 进行软件管理的思路和过程目录· 示例项目· 软件布局· Makefile 分析· GNU 的软件风格· 准备 autotools· 改造文件布局· autoscan· configure.ac 的基本结构· Makefile 文件的产生· 编写 Makefile.am软件根目录 Makefile.amsrc/Makefile.amdata/Makefile.amdocs/Makefile.amfonts/Makefile.amimages/Makefile.ammusic/Makefile.amsound/Makefile.am· 运行 autotools· SDL 库的侦测· 软件使用的数据文件· configure 选项· autotools 脚本· 使用 configure 产生的 Makefile· 最终的 configure.ac 文件· 结束语示例项目这里借用了 Wei Mingzhi <whistler_wmz@> 开发的麻将游戏来进行演示,在此,先对他表示感谢!示例软件下载:软件布局将下载的软件包解压到一个目录$ cd ~/work$ tar xjf mahjong.tar.bz2可以看到这是一个典型的 Windows 风格的软件项目布局,在 mahjong 目录下放着程序的源码,程序运行时使用的数据文件放在子目录下面作者还提供了一个 Makefile,一个 DOS 风格的 !play.bat 批处理文件,一个编译好的mj.exe 可执行文件在 Win32 平台上运行 !play.bat 就可以直接运行程序在Unix/Linux 系统上,进入 mahjong 目录,键入 make 命令,如果一切顺利的话,将生成 mj 可执行文件,然后在命令行上运行 ./mj 程序,也可以启动麻将游戏对于一个 Windows 程序来讲,该软件布局可以说非常清晰明了但在 Unix/Linux 系统上,执行 make 命令就可能遇到问题:编译找不到头文件,或者连接找不到库文件而在make 成功以后,运行麻将程序必须先进入该 majiong 目录,才能执行程序如果要像其他的程序一样,可以在任意目录使用,就要专门为这一个程序修改 PATH 环境变量,或者再写一个启动脚本,并将它复制到 /usr/bin 这样的目录下Makefile 分析1 #2 # Copyright (c) 2005, Wei Mingzhi. All rights reserved.3 #4 # Use, redistributions and modifications of this file is5 # unrestricted provided the above copyright notice is6 # preserved.7 #89 OBJ = \10 bot.o config.o game.o general.o hand.o ini.o main.o \11 player.o text.o tile.o util.o1213 HEADERS = \14 bot.h game.h general.h hand.h ini.h main.h player.h \15 tile.h1617 CC = gcc18 CXX = g++1920 TARGET = mj2122 BASEFLAGS = -g3 -D_DEBUG=123 #BASEFLAGS = -s -O32425 CFLAGS = ${BASEFLAGS} `sdl-config --cflags`26 LDFLAGS = ${BASEFLAGS} `sdl-config --libs` -lSDL_image -lSDL_mixer -lSDL_ttf2728 all: ${TARGET}2930 ${TARGET}: ${OBJ}31 ${CXX} ${LDFLAGS} -o ${TARGET} ${OBJ}3233 clean:34 rm -f *.o ${TARGET}3536 distclean:37 rm -f *.o ${TARGET}3839 %.o: %.cpp ${HEADERS}40 ${CXX} ${CFLAGS} -c $< -o $@4142 %.o: %.c ${HEADERS}43 ${CC} ${CFLAGS} -c $< -o $@Makefile 很清楚:第 20 行定义 TARGET 变量为 mj,第 28 行表明 make 默认的 target也就是生成 `mj';第 22 行加入编译时的调试信息;第 2526 行使用了sdl-config 工具侦测 SDL 开发库编译链接信息,在 26 行还指明需要连接SDL_imageSDL_mixser 和SDL_ttf 库GNU 的软件风格一个标准的 GNU 软件,编译安装都是使用下面三个步骤:$ ./configure$ make$ make installconfigure 脚本运行时可以侦测系统的环境,确定软件安装目录,然后生成Makefile 文件make 调用系统中的编译器进行编译和连接make install 将软件安装到设定的目录用户执行 configure 时可以通过它的命令行参数指定自己所需的编译选项,比如安装目录通过 --prefix=PREFIX 设置,如果不指定,缺省情况下 PREFIX 是 /usr/local 默认安装时,执行文件安装到 /usr/local/bin 目录,库安装到 /usr/local/lib 目录,数据文件安装到 /usr/local/share 目录由于 GNU 的软件风格方便易用,通用性好,可移植性高,现在大多数 Unix/Linux 系统上的自由软件都采用这种方式分发软件准备 autotoolsGNU autotools 主要包含三个软件: autoconf,automake 和 libtool当前流行的有新旧两个版本,本例采用的是新版本,分别对应的是: autoconf 2.59, automake 1.9.6和 libtool 1.5.18很多 linux 发行版都会默认安装这几个工具本例是在 NetBSD 下进行操作,安装这几个软件包是通过 pkgsrc,它们在 pkgsrc 目录为 devel/autoconfdevel/automake 和devel/libtool改造文件布局原来软件的根目录下面放的是程序的源码,按照 GNU 的习惯,将它们放到 src 子目录,根目录留给 configure 这类文件使用,其他的数据文件保持不变,仍然放在各自的子目录先创建一个目录 majiang,然后根据需要将 mahjong 目录下的文件复制过来由于是为Unix/Linux 系统进行改写,原目录里的 win32 相关文件就不用复制到新目录$ cd ~/work/majiang$ lsdata/ docs/ fonts/ images/ music/ sound/ src/autoscanautoconf 软件包里面的 autoscan 工具可以扫描工作目录,生成一个configure.ac 的模板文件 configure.scan$ cd ~/work/majiang$ autoscanautoscan 命令在当前目录生成的 configure.scan 文件内容为:1 # -*- Autoconf -*-2 # Process this file with autoconf to produce a configure script. 34 AC_PREREQ(2.59)5 AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)6 AC_CONFIG_SRCDIR([src/bot.h])7 AC_CONFIG_HEADER([config.h])89 # Checks for programs.10 AC_PROG_CXX11 AC_PROG_CC1213 # Checks for libraries.1415 # Checks for header files.16 AC_HEADER_STDC17 AC_CHECK_HEADERS([limits.h malloc.h stdlib.h string.h unistd.h])1819 # Checks for typedefs, structures, and compiler characteristics.20 AC_HEADER_STDBOOL21 AC_C_CONST22 AC_C_INLINE2324 # Checks for library functions.25 AC_FUNC_MALLOC26 AC_FUNC_REALLOC27 AC_CHECK_FUNCS([memset strcasecmp strchr strdup])28 AC_OUTPUT# 号开始的行是注释,其他都是 m4 宏命令将它改名为 configure.ac,然后在此基础上进行修改configure.ac 的基本结构configure.ac 文件是 autoconf 的输入文件,经过 autoconf 处理,展开里面的 m4 宏,输出的是 configure 脚本第 4 行声明本文件要求的 autoconf 版本,因为本例使用了新版本 2.59,所以在此注明第 5 行 AC_INIT 宏用来定义软件的名称和版本等信息,本例写成:AC_INIT(majiang, 1.0)这里省略了 BUG-REPORT-ADDRESS 参数,它是可选项,一般写成作者的邮件地址第 6 行 AC_CONFIG_SRCDIR 宏通过侦测所指定的源码文件是否存在,来确定源码目录的有效性可以选择源码目录中的任何一个文件作为代表,比如将 autoscan 选择的bot.h文件改成 main.cpp:AC_CONFIG_SRCDIR([src/main.cpp])宏参数中使用 `[ ]',是为了表明其中的字符串是一个整体第 7 行的 AC_CONFIG_HEADER 宏用于生成 config.h 文件,里面存放configure 脚本侦测到的信息如果程序需要使用其中的定义,就在源码中加入#include <config.h>其他的一些宏是标准的侦测过程,可以保留不动configure.ac 文件要求 AC_INIT 宏必须放在开头位置,AC_OUTPUT 放在文件末,中间用来检测编译环境的各种宏没有特别的先后次序要求,由宏之间相互关系决定Makefile 文件的产生前面 configure.ac 里面的宏,主要作用是侦测系统,并没有编译相关的设置因为这些信息是写在 Makefile.am 里面,然后用 automake 工具转换成 Makefile.in,configure脚本执行时再读取 Makefile.in,并与侦测信息一起写到 Makefile 文件在 autotools 的命名习惯中,后缀 ac 的文件是 autoconf 的输入文件,后缀am 的文件是 automake 的输入文件,后缀 in 的文件是 configure 的输入文件autoconf 旧版本中 configure.in 等同于 configure.ac,虽然新版本也可以识别,但它不符合命名规则,所以新版本的文件应该使用 ac 后缀简单的 Makefile.in 可以手动编写,如果使用 automake 产生,需要在configure.ac里面加入 AM_INIT_AUTOMAKE 宏进行声明要输出 Makefile,还需要在 configure.ac 中使用 AC_CONFIG_FILES 宏指明该宏并不是只处理 Makefile,而是将 FILE.in 文件转换为 FILE 文件因为 make 可以遍历子目录,如果子目录中存在 Makefile,也将同时处理在本例中 src 目录下是源码,其他是数据文件,可以使用单独一个 Makefile 放在根目录下面,也可以用多个Makefile由于每个子目录的 Makefile 只处理本目录的文件,分工明确,是模块化的方法,推荐使用因此在 configure.ac 里面增加下面的宏,表示软件根目录和子目录中都需要生成Makefile 文件:AC_CONFIG_FILES([Makefilesrc/Makefiledata/Makefiledocs/Makefilefonts/Makefileimages/Makefilemusic/Makefilesound/Makefile])编写 Makefile.am软件根目录 Makefile.am由于该目录下面保存的是与 autotools 相关的文件,没有需要编译安装的文件,所以只注明需要进一步处理的子目录信息:SUBDIRS = src data docs fonts images music soundsrc/Makefile.am此目录里是源代码,最终生成 mj 可执行文件,在其 Makefile.am 中写入bin_PROGRAMS = mjmj_SOURCES = bot.h \bot.cpp \config.cpp \game.h \game.cpp \general.h \general.cpp \hand.h \hand.cpp \ini.h \ini.cpp \main.h \main.cpp \player.h \player.cpp \text.cpp \tile.h \tile.cpp \util.cppam 文件里变量通过命名判断其含义,保留的字符串间用下划线分隔bin_PROGRAMS 表示列出二进制的程序,值为多个空格分开的程序列表,这里仅有一个 mjmj_SOURCES 列出的是组成 mj 程序的文件,文件比较多的时候,每个文件写成一行容易看清楚data/Makefile.am本目录的文件是 mj 运行时读取的数据,它的 Makefile.am 可以这样写mjdatadir = $(pkgdatadir)/datamjdata_DATA = mj.ini titles.txtEXTRA_DIST = $(mjdata_DATA)因为 datadir 是保留的关键字,所以用 mjdatadir 代替,pkgdatadir 指向$prefix/share/FULL-PACKAGE-NAME 目录,因为在 AC_INIT 中已经声明FULL-PACKAGE-NAME 为majiang,pkgdatadir 就等于 $prefix/share/majiang 目录其中 mjdatadir 让 data 目录下的文件安装到 $prefix/share/majiang/data 目录里面mjdata_DATA 列出此目录下需要安装的文件,然后用 EXTRA_DIST 变量注明余下几个子目录都与 data 目录类似docs/Makefile.amdocsdir = $(pkgdatadir)/docsdocs_DATA = gkai00mp.txt gpl.html readme.txtEXTRA_DIST = $(docs_DATA)fonts/Makefile.amfontsdir = $(pkgdatadir)/fontsfonts_DATA = brush.ttf gkai00mp.ttfEXTRA_DIST = $(fonts_DATA)images/Makefile.amimagesdir = $(pkgdatadir)/imagesimages_DATA = bgame.jpg \mjgirl1a.jpg \mjgirl2a.jpg \mjgirl3a.jpg \mjgirl4a.jpg \tiles.jpg \electron.jpg \mjgirl1b.jpg \mjgirl2b.jpg \mjgirl3b.jpg \mjgirl4b.jpg \gameover.jpg \mjgirl1c.jpg \mjgirl2c.jpg \mjgirl3c.jpg \mjgirl4c.jpgEXTRA_DIST = $(images_DATA) music/Makefile.ammusicdir = $(pkgdatadir)/music music_DATA = bet.ogg \ bonus.ogg \music.ogg \musicb.ogg \musice.ogg \win.ogg \bgame.ogg \gameover.ogg \music1.ogg \musicc.ogg \musicp.oggEXTRA_DIST = $(music_DATA) sound/Makefile.amsounddir = $(pkgdatadir)/sound sound_DATA = boom.wav \ding.wav \discard.wav \discard2.wav \flash.wav \snd1.wav \snd2.wav \snd3.wav \EXTRA_DIST = $(sound_DATA)运行 autotools准备好 configure.ac 和 Makefile.am,就可以用 autotools 的命令处理这些文件开始可能会出现错误,不过没关系,可以按照错误信息的提示逐步进行修正首先要使用的是 aclocal 命令,它根据 configure.ac 的定义,将需要使用的m4 宏定义复制到 aclocal.m4 里面缺省时,搜索 m4 宏是从 autoconf 的安装目录和系统的aclocal 目录如果需要使用其他路径下的宏,可以通过命令行的 -I 选项指定接着使用 autoheader 命令,它负责生成 config.h.in 文件,这里面的 C 语言宏定义也是通过解析 configure.ac 产生下来运行 automake 命令处理 Makefile.am,生成 Makefile.inGNU 对自己发布的软件有严格的规范,比如必须附带许可证声明文件 COPYING 等等,否则 automake 执行时会报错automake 提供了三种软件等级: foreigngnu 和 gnits,让用户选择采用,默认等级为 gnu本例使用 foreign 等级,它只检测必须的文件有一些必需的脚本文件可以从 automake 软件包里复制过来,在执行时使用 --add-missing 选项可以让automake 自动添加,默认方式是采用符号链接,如加上 --copy 选项则可以使用复制方式本例中,automake 的命令如下:$ automake --foreign --add-missing --copy最后,使用 autoconf 命令生成 configure 脚本文件SDL 库的侦测这个麻将游戏是基于 SDL 库开发的,一般系统默认不会安装,因此 configure 脚本的一个任务就是检查用户的系统中是否有该软件包autoconf 提供了很多宏可以实现侦测功能,但首先应该查看 SDL 软件包是否已应的宏通过 pkgsrc 的工具可以看到:$ pkg_info -L SDL|grep m4/usr/pkg/share/aclocal/sdl.m4即 SDL 软件包提供了一个 sdl.m4 宏,放在系统的 aclocal 目录下在这个宏文件的注释中说明了使用的方法:dnlAM_PATH_SDL([MINIMUM-VERSION,[ACTION-IF-FOUND[,ACTION-IF-NOT-FOUND]]] )dnl Test for SDL, and define SDL_CFLAGS and SDL_LIBS也就是说在 configure.ac 里面调用 AM_PATH_SDL 宏,就可以侦测 SDL找到SDL 库以后,该宏还输出 SDL_CFLAGS 和 SDL_LIBS 编译连接选项,它们实际上就是调用`sdl-config --cflags` 和 `sdl-config --libs`于是在 configure.ac 里面加入 AM_PATH_SDL 宏# Checks for libraries.SDL_VERSION=1.2.0AM_PATH_SDL($SDL_VERSION,:,AC_MSG_ERROR([*** SDL version $SDL_VERSION not found!]))当前 SDL 的版本为 1.2.9,于是 MINIMUM-VERSION 就设为 1.2.0如果在系统中侦测到需要的库,没什么额外的操作,假如没有找到,则给出错误信息AM_PATH_SDL 输出 SDL_CFLAGS 和 SDL_LIBS 编译参数,需要添加到src/Makefile.am 里面:mj_CPPFLAGS = @SDL_CFLAGS@mj_LDFLAGS = @SDL_LIBS@用 `@' 包围的变量会在 configure 执行时被替换从 mahjong 的 Makefile 中看到,这个软件还要使用 SDL_imageSDL_mixser 和SDL_ttf 库,但它们不属于 SDL 软件包,需要另外安装由于这些库在 sdl.m4 中也没有进行侦测,所以自己要写一些脚本autotools 提供了一个 AC_CHECK_LIB 宏可以用来检测库,现在就使用它来检测这几个SDL 库该宏的语法为:AC_CHECK_LIB (LIBRARY, FUNCTION, [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND], [OTHER-LIBRARIES])第一个参数是库名,第二个参数是库中的一个函数,第三个参数是检测到以后进行的动作,第四个参数是未检测到以后的动作,第五个参数是其他的库对于 SDL_imageSDL_mixer 和 SDL_ttf 对应的使用方法如下:# Check for SDL_image libraryAC_CHECK_LIB(SDL_image, IMG_LoadPNG_RW, , AC_MSG_ERROR([*** Unable to find SDL_image libary with PNG support(/projects/SDL_image/)]), `sdl-config --libs`)# Check for SDL_mixer libraryAC_CHECK_LIB(SDL_mixer, Mix_LoadOGG_RW, , AC_MSG_ERROR([*** Unable to find SDL_mixer libary with OGG support(/projects/SDL_mixer/)]), `sdl-config --libs`)# Check for SDL_ttf libraryAC_CHECK_LIB(SDL_ttf, TTF_OpenFont, , AC_MSG_ERROR([*** Unable to find SDL_ttf libary(/projects/SDL_ttf/)]), `sdl-config --libs`)软件使用的数据文件原来 mj 读取数据是从执行时目录的子目录中读取,但现在将数据放到$prefix/share/majiang 目录下,需要通过一种途径让程序可以知道数据文件被安放的位置要达到这个目的有很多方法,这里采用最直接的一种:将数据文件安装目录变量通过CPPFLAGS 编译参数传递给程序于是修改 src/Makefile.am 的 CPPFLAGS:mj_CPPFLAGS = @SDL_CFLAGS@ -DDATA_DIR=\"${datadir}/majiang\"相应地修改 src 目录下的源码,在读取数据文件的地方,将读取的路径改成DATA_DIR里对应的子目录例如,原先 config.cpp 中是:void LoadCfg(){cfg.Load("data/mj.ini");}现改成:void LoadCfg(){char ini_file[260];sprintf(ini_file, "%s/data/mj.ini", DATA_DIR);cfg.Load(ini_file);}configure 选项原来 mahjong 的 Makefile 第 22 行定义了 debug 调试选项,虽然也可以照样放到 src/Makefile.am 的 CPPFLAGS 里面实现,但 autotools 提供了一种更灵活的机制configure 脚本可以通过选项来设置编译参数,现增加一个 --enable-debug 选项,需要DEBUG 时,在命令行上加上它来打开,默认则关闭这项功能是使用 AC_ARG_ENABLE 宏实现:AC_ARG_ENABLE (FEATURE, HELP-STRING, [ACTION-IF-GIVEN],[ACTION-IF-NOT-GIVEN])其中 FEATURE 是名称,HELP_STRING 为说明信息,在使用 ./configure --help 时可以看到最后两个分别对应打开和关闭时的操作现在将 DEBUG 功能加入 configure.ac:AC_ARG_ENABLE(debug,[ --enable-debug turn on debug],CXXFLAGS="$CXXFLAGS -g3 -D_DEBUG=1")autotools 脚本每次修改了 configure.ac 或 Makefile.am 等 autotools 输入文件后都需要再次运行aclocalautomakeautoconf 这些命令,为了方便起见,可以将他们放到一个shell脚本里面,例如:#! /bin/shset -xaclocalautoheaderautomake --foreign --add-missing --copyautoconf将上面内容保存到 autogen.sh 文件,并修改文件属性为 755每次需要重新生成configure 脚本时,执行 ./autogen.sh 即可使用 configure 产生的 Makefile现在执行 ./autogen.sh 得到的 configure 脚本已经可以正常工作了,进入~/work/majiang 目录,执行 ./configure,可以看到它检查系统的过程,包括 SDL 和SDL_image 等库的侦测结果使用 ./configure --help 可以看到 autotools 提供的帮助信息configure 执行的完毕,输出软件根目录和几个子目录下面的 Makefile 文件这些Makefile 有几个常用的 target:· make all不加任何 target,默认就是 all,作用是编译软件· make install安装软件包,如果安装到系统目录,需要 root 权限· make clean清除编译产生的目标文件· make distclean可以同时清除编译的结果和 configure 输出的文件· make tags生成 etags 使用的 TAGS 文件· make dist生成软件发布包,为 tar.gz 格式的压缩包,文件名由软件包名和版本组成最终的 configure.ac 文件# -*- Autoconf -*-# Process this file with autoconf to produce a configure script.AC_PREREQ(2.59)AC_INIT([majiang], [1.0])AC_CONFIG_SRCDIR([src/main.cpp])AC_CONFIG_HEADER([config.h])AC_CANONICAL_HOSTAC_CANONICAL_TARGETAM_INIT_AUTOMAKE# Checks for programs.AC_PROG_CXXAC_PROG_CCAC_LANG(C++)# Checks for libraries.SDL_VERSION=1.2.0AM_PATH_SDL($SDL_VERSION,:,AC_MSG_ERROR([*** SDL version $SDL_VERSION not found!]))# Check for SDL_image libraryAC_CHECK_LIB(SDL_image, IMG_LoadPNG_RW, , AC_MSG_ERROR([*** Unable to find SDL_image libary with PNG support(/projects/SDL_image/)]), `sdl-config --libs`)# Check for SDL_mixer libraryAC_CHECK_LIB(SDL_mixer, Mix_LoadOGG_RW, , AC_MSG_ERROR([*** Unable to find SDL_mixer libary with OGG support(/projects/SDL_mixer/)]), `sdl-config --libs`)# Check for SDL_ttf libraryAC_CHECK_LIB(SDL_ttf, TTF_OpenFont, , AC_MSG_ERROR([*** Unable to find SDL_ttf libary(/projects/SDL_ttf/)]), `sdl-config --libs`)# Checks for header files.AC_HEADER_STDCAC_CHECK_HEADERS([limits.h malloc.h stdlib.h string.h unistd.h])# Checks for typedefs, structures, and compiler characteristics. AC_HEADER_STDBOOLAC_C_CONSTAC_C_INLINE# Checks for library functions.AC_FUNC_MALLOCAC_FUNC_REALLOCAC_CHECK_FUNCS([memset strcasecmp strchr strdup])AC_ARG_ENABLE(debug,[ --enable-debug turn on debug],CXXFLAGS="$CXXFLAGS -g3 -D_DEBUG=1")AC_CONFIG_FILES([Makefilesrc/Makefiledata/Makefiledocs/Makefilefonts/Makefileimages/Makefilemusic/Makefilesound/Makefile])AC_OUTPUT结束语GNU 的很多工具经常给人一种感觉: 功能很强大,但也很难学autotools 可以说是这类工具的一个典型,它需要用户对 shellmake软件编译m4 宏语言,以及Unix/Linux操作系统各方面知识都有一定的了解使用时又要 autoconf automakelibtool 多个工具相互配合^1,如果要给软件增加国际化功能,还要再了解和掌握 gettextpo 等工具和规则与学习其他知识一样,所谓难,其实是不了解,不熟悉本文通过一个范例演示使用autotools 的过程,是让不了解的人熟悉这个工具但真正的理解,还需要将它运用到自己的软件项目当中,不断地实践,不断地思考和总结脚注... 多个工具相互配合^1由于本例软件中没有生成库文件,所以没有涉及 libtool 工具的使用。
CMake用法导览

CMake⽤法导览本⽂下述内容是⼀个⼿把⼿的使⽤指南;它涵盖了CMake需要解决的公共构建系统的⼀些问题。
这些主题中的许多主题已经在Mastering CMake⼀书中以单独的章节被介绍过,但是通过⼀个样例⼯程看⼀看它们如何⼯作也是⾮常有帮助的。
本指南可以在CMake源码树的Tests/Tutorial路径下找到。
每⼀步都有它⾃⼰的⼦路径,其中包含该步骤的⼀个完整的指南。
作为基础的起始点(步骤1) 最基本的⼯程是⼀个从源代码⽂件中构建可执⾏⽂件的例⼦。
对于简单⼯程,只要⼀个两⾏的CMakeLists⽂件就⾜够了。
这将会作为我们指南的起点。
这份CMakeLists⽂件看起来像是这样:cmake_minimum_required (VERSION 2.6)project (Tutorial)add_executable(Tutorial tutorial.cxx) 注意到这个例⼦在CMakeLists⽂件中使⽤了⼩写。
CMake⽀持⼤写、⼩写、混合⼤⼩写的命令。
tutorial.cxx中的源代码⽤来计算⼀个数的平⽅根,并且它的第⼀版⾮常简单,如下所⽰:// A simple program that computes the square root of a number// 计算⼀个数的平⽅根的简单程序#include <stdio.h>#include <stdlib.h>#include <math.h>int main (int argc, char *argv[]){if (argc < 2){fprintf(stdout,"Usage: %s number\n",argv[0]);return 1;}double inputValue = atof(argv[1]);double outputValue = sqrt(inputValue);fprintf(stdout,"The square root of %g is %g\n",inputValue, outputValue);return 0;}我们添加的第⼀个特性⽤来为⼯程和可执⾏⽂件指定⼀个版本号。
超详细的cmake入门教程

超详细的cmake⼊门教程什么是cmake你或许听过好⼏种 Make ⼯具,例如 GNU Make ,QT 的 qmake ,微软的 MSnmake,BSD Make(pmake),Makepp,等等。
这些 Make ⼯具遵循着不同的规范和标准,所执⾏的 Makefile 格式也千差万别。
这样就带来了⼀个严峻的问题:如果软件想跨平台,必须要保证能够在不同平台编译。
⽽如果使⽤上⾯的 Make ⼯具,就得为每⼀种标准写⼀次 Makefile ,这将是⼀件让⼈抓狂的⼯作。
CMake CMake附图 1 CMake就是针对上⾯问题所设计的⼯具:它⾸先允许开发者编写⼀种平台⽆关的 CMakeList.txt ⽂件来定制整个编译流程,然后再根据⽬标⽤户的平台进⼀步⽣成所需的本地化 Makefile 和⼯程⽂件,如 Unix 的 Makefile 或Windows 的 Visual Studio ⼯程。
从⽽做到“Write once, run everywhere”。
显然,CMake 是⼀个⽐上述⼏种 make 更⾼级的编译配置⼯具。
⼀些使⽤ CMake 作为项⽬架构系统的知名开源项⽬有 VTK、ITK、KDE、OpenCV、OSG 等。
在 linux 平台下使⽤ CMake ⽣成 Makefile 并编译的流程如下:1. 编写 CMake 配置⽂件 CMakeLists.txt 。
2. 执⾏命令 cmake PATH 或者 ccmake PATH ⽣成 Makefile。
其中, PATH 是 CMakeLists.txt 所在的⽬录。
(ccmake 和cmake 的区别在于前者提供了⼀个交互式的界⾯)3. 使⽤ make 命令进⾏编译。
⼊门案例:单个源⽂件本节对应的源代码所在⽬录:Demo1。
对于简单的项⽬,只需要写⼏⾏代码就可以了。
例如,假设现在我们的项⽬中只有⼀个源⽂件 ,该程序的⽤途是计算⼀个数的指数幂。
camke的使用方法

CMake的使用方法什么是CMake?CMake是一个跨平台的开源构建系统,用于管理C++项目的编译过程。
它可以生成与平台无关的构建脚本,使开发者可以轻松地在不同的操作系统和编译器上构建他们的代码。
CMake使用一种名为CMakeLists.txt的简单文本文件来描述项目的构建过程。
通过定义目标、源文件、依赖关系和编译选项等信息,CMake可以自动生成适用于各种构建工具(如make、ninja等)的构建脚本。
安装CMake在开始使用CMake之前,首先需要安装它。
你可以从[CMake官方网站](下载适合你操作系统的安装包,并按照指示进行安装。
编写CMakeLists.txt创建一个新目录作为你的项目根目录,并在该目录下创建一个名为CMakeLists.txt的文件。
这个文件将包含所有关于项目构建过程的信息。
基本语法一个基本的CMakeLists.txt文件由一系列命令组成,每个命令占据一行,并以分号结尾。
下面是一个简单例子:cmake_minimum_required(VERSION 3.10) # 指定最低要求版本project(MyProject) # 设置项目名称add_executable(MyApp main.cpp) # 添加一个可执行文件添加源文件使用add_executable命令可以将源文件添加到你的项目中。
该命令的第一个参数是目标名称(可执行文件名),后面是源文件列表。
例如:add_executable(MyApp main.cpp utils.cpp)添加子目录如果你的项目包含多个子目录,可以使用add_subdirectory命令将它们添加到项目中。
这样,每个子目录都可以有自己的CMakeLists.txt文件来描述构建过程。
add_subdirectory(subdir)链接库如果你的项目依赖于外部库,可以使用target_link_libraries命令将它们链接到你的可执行文件中。
C语言make和Makefile介绍及使用

C语⾔make和Makefile介绍及使⽤1:make和Makefile的介绍:概念在软件的⼯程中的源⽂件是不计其数的,其按照类型,功能,模块分别放在若⼲个⽬录中,哪些⽂件需要编译,那些⽂件需要后编译,那些⽂件需要重新编译,甚⾄进⾏更复杂的功能操作,这就引⼊了我们的系统编译的⼯具:在linux和unix中,有⼀个强⼤的使⽤程序,叫make,可以⽤它来管理多模块程序的编译和链接,直⾄⽣成可执⾏⽂件make使⽤程序读取⼀个说明⽂件,称为Makefile,Makefile⽂件中描述了整个软件⼯程的编译规则和各个⽂件之间的依赖关系;Makefile就像是⼀个Shell脚本⼀样,其中可以执⾏操作系统的命令,它带来的好处就是我们能够实现“⾃动化编译”,⼀旦写好,只要⼀个make命令,整个软件功能就完全⾃动编译,极⼤的提⾼了软件开发的效率;make是⼀个命令⼯具,是⼀个解释Makefile中指令的命令⼯具,⼀般来说⼤多数IDE都有这个命令使⽤make可以是重新编译的次数达到最⼩化;2:make和Makefile1:make的使⽤语法:make使⽤语法:make [选项][⽬标][宏定义]选项列表:-d 显⽰调试信息(debug)-f<⽂件> 指定从那个⽂件中读取以来关系,默认⽂件是"Makefile"或者"makefile","-"表⽰从标准输⼊(file)-h 显⽰所有选项的简要说明(help)-n 不运⾏任何Makefile命令,只去现实它们(no)-s 安静的⽅式运⾏,不显⽰任何信息(silence)可以使⽤-h来获取更多的选项:2:Makefile的编写原则和规则当make命令不带选项运⾏的时候,它从Makefile中读取指定规则当制定规则不同与Makefile(makefile)的其他⽂件中时候,就要运⾏带有-f选项的make命令。
Make命令完全详解教程

Make命令完全详解教程Make命令完全详解教程无论是在Linux还是在Unix环境中,make都是一个非常重要的编译命令。
不管是自己进行项目开发还是安装应用软件,我们都经常要用到make或make install。
利用make工具,我们可以将大型的开发项目分解成为多个更易于管理的模块,对于一个包括几百个源文件的应用程序,使用make和makefile工具就可以简洁明快地理顺各个源文件之间纷繁复杂的相互关系。
而且如此多的源文件,如果每次都要键入gcc命令进行编译的话,那对程序员来说简直就是一场灾难。
而make工具则可自动完成编译工作,并且可以只对程序员在上次编译后修改过的部分进行编译。
因此,有效的利用make和makefile工具可以大大提高项目开发的效率。
同时掌握make和makefile之后,您也不会再面对着Linux下的应用软件手足无措了。
一、Make程序的命令行选项和参数Make命令参数的典型序列如下所示:make [-f makefile文件名][选项][宏定义][目标]这里用[]括起来的表示是可选的。
命令行选项由破折号“–”指明,后面跟选项,如如果需要多个选项,可以只使用一个破折号,如也可以每个选项使用一个破折号,如Make命令本身的命令行选项较多,这里只介绍在开发程序时最为常用的三个,它们是:–k:如果使用该选项,即使make程序遇到错误也会继续向下运行;如果没有该选项,在遇到第一个错误时make程序马上就会停止,那么后面的错误情况就不得而知了。
我们可以利用这个选项来查出所有有编译问题的源文件。
–n:该选项使make程序进入非执行模式,也就是说将原来应该执行的命令输出,而不是执行。
–f :指定作为makefile的文件的名称。
如果不用该选项,那么make 程序首先在当前目录查找名为makefile的文件,如果没有找到,它就会转而查找名为Makefile的文件。
如果您在Linux下使用GNU Make 的话,它会首先查找GNUmakefile,之后再搜索makefile和Makefile。
Automake中文手册

automake中文手册收藏GNU AutomakeFor version 1.3, 3 April 1998 David MacKenzie and Tom Tromey目录·介绍·通用性概念o通用操作o深度o严格性o统一命名机制o派生变量是如何命名的·一些实例软件包o一个简单的例子,从起点到终点o一个经典的程序o创建etags和ctags·创建`Makefile.in'·扫描`configure.in'o配置需求oAutomake能够识别的其它事情o自动生成的aclocal.m4o由Automake支持的Autoconf宏 o编写你自己的aclocal宏·顶层`Makefile.am'·创建程序和库o创建一个程序o创建一个库o对LIBOBJS和ALLOCA的特别处理 o创建一个共享库o创建一个程序时使用的变量o对Yacc和Lex的支持oC++和其它语言o自动de-ANSI-ficationo自动的依赖性(dependency)跟踪·其它派生对象o可执行的脚本o头文件o与体系结构无关(Architecture-independent)的数据文件o已创建的源代码·其它GNU工具oEmacs LispoGettextoGuileoLibtooloJava·创建文档oTexinfooMan手册·安装了些什么·清除了些什么·需要发布哪些文件·对测试套件(test suites)的支持·改变Automake的行为·其它规则o与etags之间的界面o处理新的文件扩展名·条件(Conditionals)·--gnuand --gnits的效果·--cygnus的效果·什么时候Automake不够用·发布`Makefile.in'·未来的某些想法·索引@dircategory GNU admin @direntry * automake: (automake). Making Makefile.in's @dircategory Individual utilities @direntry * aclocal: (automake)Invoking aclocal. Generating aclocal.m4Copyright (C) 1995, 96 Free Software Foundation, Inc.这是GNU Automake文档的第一版,并且是针对GNU Automake 1.3的。
automake详解

Autoconf/Automake工具组主要包括autoconf、automake、perl语言环境和m4。其中FC4默认安装的autoconf和automake软件包信息如下:
[root@localhost hello]# rpm -qa |grep autoconf //查看是否安装autoconf
使用Autoconf/Automake工具自动生成Makefile文件的流程图如图2-5所示。在此过程中使用的命令主要有aclocal、autoscan、autoconf、autoheader和automake。由图可知运行步骤如下:
(点击查看大图)图2-5自动创建Makefile文件流程
(1)创建源代码文件,使用"autoscan"生成configure.scan文件,将其重命名为configure.ac,并做适当修改,然后使用"aclocal"命令生成aclocal.m4文件,使用"autoconf"命令由configure.ac和aclocal.m4文件生成configure文件。
AC_PREREQ(2.59)
AC_INIT(hello,1.0,yangzongde@) //在此行内容中设置当前软件包信息
AM_INIT_AUTOMAKE(hello,1.0) //automake所必备的宏,必须添加
AC_CONFIG_SRCDIR([hello.c]) //源文件名
autoscan.log configure.ac configure.scan hello.c
[root@localhost hello]# cat configure.ac
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Comake2使用详解1、适用用户范围:第一次使用comake2工具使用comake2搭建环境:这时用户不需要关心COMAKE文件细节,和第一次使用comake2工具时的情形差不多,第一次使用comake2工具初始化环境$mkdir --parent ps/se/ac/make$cd ps/se/ac/make$comake2 -S$comake2 -UBcomake2 -S //初始化COMAKE文件comake2 -S表示从平台最新基线版本获取依赖列表;comake2 -S -r 1.0.1.0表示从平台1.0.1.0版本获取依赖列表友情提示:如果你的代码库里已有COMAKE文件,可跳过这一步;如果你的模块路径是ps/se/ac/make,请cd ps/se/ac/make再执行comake2 -S命令comake2 -UB //下载并编译依赖代码2、comake2命令$ comake2 -hcomake[com make]能够自动帮助用户搭建环境,并且生成Makefile工具.程序会读取目录下面的COMAKE文件,产生Makefile和环境.用户需要提供这个COMAKE文件. 参数:-h --help 查看帮助-D --debug 开启debug选项[默认不打开].-D -D可以查看更多调试信息.-S --scratch 创建一个默认的COMAKE文件-r --revision 从平台检出模块cvspath指定的TAG对应的依赖列表,配合-S使用,如-S -r 1.0.0.0-E --export-configs 导出模块的4位版本依赖,存放在COMAKE.CONFIGS下面.比如-E public/ub@1.0.0.0-W --watch-configs 查看本地依赖模块.-W -W可以查看模块引入来源.-W -W -W可以查看依赖模块的依赖.-I --import-files 在解释COMAKE文件之前导入模块-C --change directory 切换到directory下面执行[默认当前目录]-Q --quiet 安静模式[默认不打开]-U --update-configs 更新环境-B --build-configs 构建环境-F --force 构建环境时强制进行[默认不进行]-e --export-local-configs 导出本地环境到CONFIGS.SCM文件-f --scmfile= 重现编译环境-d --devdiff 存在本地修改的共同开发依赖列表(多模块共同开发时适用)-J --make-thread-number= 如果模块使用COMAKE生成的Makefile的话,编译线程数[默认是4]-j --modules-thread-number= 并发下载、编译模块的线程数[默认是1]-K --keep-going 构建/更新环境中途出错的话,忽略错误继续[已废弃]-P --pretreatment 生成Makefile时不进行预处理[默认进行预处理]-O --quot-all-deps 生成Makefile时引用所有头文件依赖[默认过滤目录外依赖]--parent-module 支持父子模块添加进编译依赖--no-recursive 不递归生成每个目录下面的Makefile[默认情况下是递归生成]--no-revert 不恢复依赖模块的本地修改,配合-U使用[默认恢复]--time-compile-link 计时编译和链接时间[默认不打开]--recache 强制更新comake2缓存的依赖列表--old-da 使用2.1.2及以前的依赖打平策略--new-da 最新打平策略在help中未列出的参数如下:--dump-da=da|dc|df|ds|dm 查看依赖完整关系图(分别以不同的形式组织,All|Collected|Flatten|Sorted|Map)-A --scmaudit 导出依赖树--old-api--conf 指定config文件CONF_FILE--dd= 和平台依赖模块进行对比# --dd and --dump-cfgs share same mode when analyzing deps.--dump-cfgs 列出所有依赖--dump-cfgs-scmpf= 列出平台依赖--get-remote-revision 与--dump-cfgs、--dd=等一起使用,获取依赖的代码当前最新版本--redirect-file= 与--dump-cfgs、--dd=等一起使用,将输出重定位到文件里--show-unstable-urls 与--dump-cfgs、--dd=等一起使用,列出不稳定的编译依赖--warn-downgrade-only 与--dump-cfgs、--dd=等一起使用,列出低版本--permissive-guilty-workroot 容忍错误的工作环境(只提示不退出)初始化COMAKE:comake2 -S搭建环境:基本命令是comake2 -UB,其中-U是下载代码,-B是编译模块并发搭建环境:comake2 -UB -j 4表示并发4线程下载和编译模块单线程编译:comake2 -B -J 1表示使用make命令编译某个依赖模块时不进行并发(如该依赖模块的Makefile不支持并发,则适用于该情况);强制重新搭建环境:comake2 -UB -F,即使依赖已经编译过,也会重新编译不revert本地修改:comake2 -UB --no-revert生成Makefile:comake2 [-P],-P会跳过预处理环节,加快生成Makefile的过程查看依赖完整关系图:comake2 -U --dump-da=da查看本地修改的编译依赖模块:comake2 -d和平台依赖进行对比:comake2 --dd=1.0.0.0重现编译环境:comake2 --scmfile=模块名.COMAKE.CONFIGS.SCM配置文件COMAKE语法#coding:gbk工作路径.层数=CVS路径的层数WORKROOT('../../')使用硬链接copy.CopyUsingHardLink(True)支持32位/64位平台编译ENABLE_MULTI_LIBS(True)C预处理器参数.CPPFLAGS('-D_GNU_SOURCE -D__STDC_LIMIT_MACROS -DVERSION=\\\"1.9.8.7\\\"')为32位目标编译指定额外的预处理参数CPPFLAGS_32('-D_XOPEN_SOURE=500')C编译参数.CFLAGS('-g -pipe -W -Wall -fPIC')C++编译参数.CXXFLAGS('-g -pipe -W -Wall -fPIC')IDL编译参数IDLFLAGS('--compack')UBRPC编译参数UBRPCFLAGS('--compack')头文件路径.INCPATHS('. ./include ./output ./output/include')使用库LIBS('./libci-tools.a')链接参数.LDFLAGS('-lpthread -lcrypto -lrt')依赖模块CONFIGS('lib2/ullib')为32位/64位指定不同的依赖路径.CONFIGS_32('lib2/ullib')CONFIGS_64('lib2-64/ullib')user_sources=''user_headers=''可执行文件Application('ci-tools',Sources(user_sources))静态库StaticLibrary('ci-tools',Sources(user_sources),HeaderFiles(user_headers))共享库SharedLibrary('ci-tools',Sources(user_sources),HeaderFiles(user_headers))子目录Directory('demo')编译标签元素名称作用example 注意事项WORKROOT 当前工作路径WORKROOT('../../') 最好使用相对路径MakeThreadNumber 使用多少个线程进行make MakeThreadNumber(4) 相当于执行使用make -j[废弃]CopyUsingHardLink copy使用硬链接CopyUsingHardLink(True)ENABLE_MULTI_LIBS 多环境编译ENABLE_MULTI_LIBS(True) 支持多环境编译,生成32位/64位通用的MakefileCPPFLAGS C预处理参数 CPPFLAGS('-DGNU\_SOURCE')CFLAGS C编译参数CFLAGS('-g -Wall','-O2')CXXFLAGS C++编译参数CXXFLAGS('-g -Wall','-O2')INCPATHS 搜索头文件路径INCPATHS('. ./include')这里不要加上-I前缀.INCPATHS允许使用$开头,代表路径相对于WORKROOT.比如INCPATHS('$public/ub')LIBS 链接使用的库文件LIBS('./libmock.a')LDFLAGS 链接参数LDFLAGS('-lpthread -lcrypto')IDLFLAGS IDL编译参数IDLFLAGS('--compack --ns=mock') 实际上是mcy的编译参数UBRPCFLAGS UBRPCGEN编译参数UBRPCFLAGS('--compack')PROTOFLAGS proto编译参数PROTOFLAGS('--proto_path=./')PROTOC protobuf路径 PROTOC('../../thirdsrc/protobuf/install/bin/protoc') ImportConfigsFrom 从其他目录的COMAKE继承编译依赖ImportConfigsFrom('..') ReplaceExtNameWith 替换文件后缀名ReplaceExtNameWith('x.cpp y.cpp','.cpp','.o') GetEnv 获得环境变量GetEnv('USER') 如果没有特定key的话,返回'undefined' BuildVersion 获取编译版本BuildVersion() 等效于GetEnv('COMAKE2_BUILD_VERSION') CCHECKFLAGS ccheck参数CCHECKFLAGS('-c cc.conf')PCLINTFLAGS pclint参数PCLINTFLAGS('-c pclint.conf')。