用CMake编译lua

最近的工作是基于premake做一个适合我们公司的C++的编译系统,了解一下已经比较成熟的CMake,是非常有参考价值的。

【CMake初印象】

CMake和premake一样,都是meta build system,可以针对不同的平台产生相应的编译系统,比如Windows上的VS Projects, Linux下的Makefile。但CMake要比premake更加成熟,这点可以从其支持的feature,使用的项目,以及完善的文档、社区支持可以看出来,premake简直就是一个小娃娃。

所以,让我来评价,CMake之于premake,最大的优势在于功能强大且久经考验,除了基本的静态库、动态库、可执行文件的创建,不同编译系统文件的产生,还支持code generation, rpath handing等等,如所列, 另外,CMake项目已经超出一个build system的范畴了,提供了测试的CTest,打包的CPack,以及管理report,CI的CDash,俨然成了一个完整的SDLC系统。如果要很快上马一个项目,选CMake无疑是最舒心的,而选premake可能就需要一些波折了:你要么等那位作者(不错,主要就一位)加feature,要么看是不是可以弄个workaround出来(premake用lua语言,所以扩这还是很灵活的)。

而premake之于CMake,优势在于优良的基因, 不错,premake采用了业界口碑最好,代码简单优美的lua语言:灵活、优美、知识复用 - 而CMake采用的则是一个自定义的格式,劣势十分明显。当然,这不能怪CMake,它当年出生的时候,还没有lua这么好的一个选择,当时最好的嵌入式语言是tcl,而如果采用tcl的话,骂都被人骂死了。

所以,premake虽然后来,但前途还是不可限量的。

【一些不错的链接】

【编译lua】

lua的基本情况在《用premake编译lua》中已经说明,主要是三个binary,源代码在同一个src目录下,其CMakeLists.txt如下:

cmake_minimum_required (VERSION 2.6)
project (lua)  # project here actually means solution in premake

if(WIN32)
        add_definitions( -D_CRT_SECURE_NO_WARNINGS )
endif()

# 1. lua static library
# how to rename library name?
add_library (lualib STATIC lapi.c lcode.c lctype.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c lmem.c lobject.c lopcodes.c lparser.c lstate.c lstring.c ltable.c ltm.c lundump.c lvm.c lzio.c lauxlib.c lbaselib.c lbitlib.c lcorolib.c ldblib.c liolib.c lmathlib.c loslib.c lstrlib.c ltablib.c loadlib.c linit.c)
set_target_properties(lualib PROPERTIES OUTPUT_NAME "lua") # rename the library output name

# 2. lua interpreter
link_directories (${LUA_BINARY_DIR})
add_executable (lua lua.c)
target_link_libraries (lua lualib)
if(UNIX)
        target_link_libraries( lua m )
endif()

# 3. lua compiler
link_directories (${LUA_BINARY_DIR})
add_executable (luac luac.c)
target_link_libraries (luac lualib)
if(UNIX)
        target_link_libraries( luac m )
endif()

编译的时候,最好采用out-of-source模式,将文件产生到另外一个目录下:

cd ..
mkdir build
cd build
cmake -G "Visual Studio 9 2008" ../src

文件是产生到当前目录的, 然后:

msbuild lua.sln

即可。

注意,这里对不同的系统设置,可以用:

if (${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
    add_definitions( -D_CRT_SECURE_NO_WARNINGS )
endif(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")

或者,一种简化的方式:

if(WIN32)
        add_definitions( -D_CRT_SECURE_NO_WARNINGS )
endif()

而针对不同的target,则可以用set_target_properties, 这个可以用来设置编译、链接的属性,也可以改变产生的library的名字,如:

set_target_properties(lualib PROPERTIES OUTPUT_NAME "lua") # rename the library output name

因为lua的library的target名字是:liblua, 而lua的executable的target名字是lua,但我们又不同把两个project的名字都设为lua,于是把lua library称为lualib,但同时把其target设为最终的lua即可。