Yanyg - Software Engineer

CMake Introduction

目录

编译系统从Makefile,到Autoconf,再到CMake,

1 Makefile

Makefile的语法比较好玩(晦涩),提供了各种各样的弹性扩展。06年写过下面这样的 Makefile Demo,现在基本不会写了,也忘记了 $<, $@, $* 的含义。

################################
#  ApFileSubServer  Makefile  #
#    yanyg   2006   10  23     #
################################

CXX      := g++
CXXFLAGS := -g -c
LIB      := -Wl,-Bdynamic -lpthread -lgcc_s -lcrypt -lnsl -lrt
SRC      :=$(wildcard *.cpp)
OBJ      :=$(SRC:.cpp=.o)

all : ApFileMainServer

.SUFFIXES : .o .cpp

.cpp.o :
        @${CXX} ${CXXFLAGS} $< -o $@
        @echo "Compile " $< "success..."
ApFileMainServer : ${OBJ}
        @echo "Link OBJ to ApFileMainServer ..."
        @${CXX} ${LIB} ${OBJ} -o ApFileMainServer
        @echo "Build ApFileMainServer Success!"

.PHONY : clean
clean:
        @echo "Delete OBJ(*.o) && ApFileMainServer..."
        @rm -fr ${OBJ} ApFileMainServery

这个Makefile只是一个Demo,而不是好的示例。一个Makefile要有编译、打包、安装、测试等。想写好的Makefile不是一件简单的事情,Autoconf从一定程度缓解了这个问题。

2 Autoconf

在CMake之前,绝大多数的开源项目用Autoconf编译。花费少量的精力,Autoconf就能帮助生成功能完备的Makefile。写Autoconf需要熟悉automake, autoconf, libtool。之前业余写的几行代码也用autoconf编译:

https://github.com/yygcode/ycc/tree/develop

3 CMake

目前用起来最爽的编译系统了。

3.1 hello world

hello.c

#include <stdio.h>

int main(int argc, char *argv[])
{
  printf("hello world\n");
  return 0;
}

CMakeLists.txt:

project(hello)

add_executable(hello helloc.c)

Compile:

~$yanyg@t430:~/test $ mkdir build
yanyg@t430:~/test $ cd build
yanyg@t430:~/test/build $ cmake ..
-- The C compiler identification is GNU 8.3.0
-- The CXX compiler identification is GNU 8.3.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/yanyg/test/build
yanyg@t430:~/test/build$ ls
CMakeCache.txt  CMakeFiles  cmake_install.cmake  hello  Makefile
yanyg@t430:~/test/build$ ./hello
hello world

3.2 Test

enable_testing() 必须在项目根目录下,否则找不到test case;例如:

Part of platform/CMakeLists.txt:

enable_testing()
set(TESTS_SUITE tests)
set(CMAKE_CTEST_COMMAND ctest)
add_custom_target(${TESTS_SUITE} COMMENT "Building tests suite")
add_custom_target(check
  COMMAND ${CMAKE_CTEST_COMMAND}
  DEPENDS ${TESTS_SUITE})

Part of platform/test/CMakeLists.txt:

enable_language(C CXX)

find_package(GTest)
if (NOT GTEST_FOUND)
  message(WARNING "Test: GTest not found, ignore")
  return()
endif()

include(GoogleTest)
include_directories(${GTEST_INCLUDE_DIRS})
link_libraries(${GTEST_BOTH_LIBRARIES})

find_package(Threads REQUIRED)
if (CMAKE_USE_PTHREADS_INIT)
  add_definitions(-DHAVE_PTHREAD)
endif (CMAKE_USE_PTHREADS_INIT)
link_libraries(pthread)

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src/include)
link_libraries(platform)

add_subdirectory(base)
add_subdirectory(container)
add_subdirectory(memory)

Part of platform/test/base/CMakeLists.txt:

set(TEST_SRC
  test_assert.cc)

set(TEST_TARGET test_base)

add_executable(${TEST_TARGET} ${TEST_SRC})
add_dependencies(${TESTS_SUITE} ${TEST_TARGET})
gtest_discover_tests(${TEST_TARGET}
  PROPERTIES TIMEOUT 10)

Run make check:

  yanyg@t430:~/platform/build$ make check
  [ 13%] Built target platform_memory
  [ 26%] Built target platform_base
  Scanning dependencies of target platform_container
  [ 33%] Building C object src/container/CMakeFiles/platform_container.dir/xarray.c.o
  [ 33%] Built target platform_container
  [ 40%] Linking C static library libplatform.a
  [ 40%] Built target platform
  [ 46%] Linking CXX executable test_memory
  [ 60%] Built target test_memory
  [ 66%] Linking CXX executable test_base
  [ 73%] Built target test_base
  [ 80%] Linking CXX executable test_container
  [100%] Built target test_container
  [100%] Built target tests
  Test project /home/yanyg/platform/build
        Start  1: Assert.Assert
   1/10 Test  #1: Assert.Assert ....................   Passed    0.00 sec
        Start  2: Assert.AssertDebug
   2/10 Test  #2: Assert.AssertDebug ...............   Passed    0.00 sec
        Start  3: TestBitmap.Malloc
   3/10 Test  #3: TestBitmap.Malloc ................   Passed    0.14 sec
        Start  4: TestBitmap.Arena
   4/10 Test  #4: TestBitmap.Arena .................   Passed    0.14 sec
        Start  5: XarrayTest.CreateDestroy
   5/10 Test  #5: XarrayTest.CreateDestroy .........   Passed    0.00 sec
        Start  6: XarrayTest.StoreLoad
   6/10 Test  #6: XarrayTest.StoreLoad .............   Passed    0.01 sec
        Start  7: TestMemCache.Simple
   7/10 Test  #7: TestMemCache.Simple ..............   Passed    0.02 sec
        Start  8: TestMemCache.Small
   8/10 Test  #8: TestMemCache.Small ...............   Passed    0.03 sec
        Start  9: TestMemCache.NoReserve
   9/10 Test  #9: TestMemCache.NoReserve ...........   Passed    0.03 sec
        Start 10: TestArena.Alloc
  10/10 Test #10: TestArena.Alloc ..................   Passed    0.03 sec

  100% tests passed, 0 tests failed out of 10

  Total Test time (real) =   0.41 sec
  [100%] Built target check
yanyg@t430:~/platform/build$ ls Testing/Temporary/
CTestCostData.txt  LastTest.log  LastTestsFailed.log

4 References