Introduction to CMakeread.pudn.com/downloads403/ebook/1720931/cmake-overview.pdf · 2011-03-14 ·...

Preview:

Citation preview

貓也會的CMake

高效率開發跨平台專案

Jim Huang ( 黃敬群 )web: http://jserv.sayya.org/blog: http://blog.linux.org.tw/email: <jserv.tw @ gmail.com>

TOSSUG 心得分享 - Mar 18, 2008

It was stupid easy.KDE開發者Matt Rogers如是說

● 鄭玄作易贊及易論云《易》– 簡易

– 變易

– 不易

● make– GNU make, BSD make, Plan9 Mk– imake (x11), dmake (openoffice), qmake

(qt), nmake (Microsoft), Rake (ruby), ...– WMake (Watcom), WSCons, jam, FTjam, ant

(Apache), automake, autoconf, ...

GNU 軟體建構流程

configure.in

Makefile.am

autoconf

automake Makefile.in

configure

Developer User

./configure

GenerateMakefile

Checkfor required

libraries

Makefile

Sourcefiles

Sourcefiles [autoscan] [configure.scan] configure.ac

configure.ac

[acinclude.m4]

autoconf

[autoheader]

configure

[config.h.in]

automakeMakefile.amMakefile.in

configure

[config.h.in]

Makefile.inconfig.status

config.log

config.cache

[config.h]

Makefilemake

Starting,occasional

Developer, on development system

Installer, on target system

distribute

Executables, libraries, documents, etc.End User

面臨的困擾● 「何時會有 MS-Windows版本?」

– 連基本的編譯動作都不知如何下手

● 「 BSD上沒有這些函式庫」– 需要便利有效的環境偵測機制

● 「我討厭 Automake!」

– 不知不覺變成 Autofool● 「天呀,條件編譯好麻煩」

– <pcman>花在 automake的時間還比較多

Autotools sucks

% make lovemake: *** No rule to make target `love'.  Stop.

CMake再次愛上make

cmake● 訴求:跨平台、高度可擴充、整合● 不只是 build system:針對目標端輸出 build

control/project files– UNIX : Makefile/KDevelop– MS-Visual Studio : Workspace/Projects– MacOS X : XCode

● KDE4掛保證CMakeLists.txt CMake Native Build System

Native Build ToolsExecutablesLibraries

cmake vs. automake(1)

● Automake (+ autoconf + libtool + make + sh + perl + m4)

% ./configure --prefix=/foo --enable-debug

% make

# make install

● CMake (+ make)

% cmake -DCMAKE_INSTALL_PREFIX=/foo -DCMAKE_BUILD_TYPE=debugfull .

% make

# make install

● 乍看沒什麼,但是 cmake就是快!

– kdelibs4建構時間比 kdelibs3快 40%– cmake只需 automake空間使用量的一成

cmake vs. automake(2)

使用 cmake 使用 automake

cmake: source/binary tree(1)

● Source tree– CMake輸入檔 (CMakeLists.txt)– 原始程式碼

● Binary tree / Build tree– 平台相依的建構輸出

● Makefile, GNUmakefile, .dsp, .xcodebuild– 執行檔、函式庫

● *.exe, *.so, *.dll, *.lib

CMakeLists.txt CMake Native Build System

Native Build ToolsExecutablesLibraries

CMakeLists.txtSUBDIRS(Dir1 Dir2)

Dir1/CMakeLists.txt

Dir2/CMakeLists.txt

Source Tree

Project

Common

Algorithms

BasicFilter

Numerics

IO

Project

Common

Algorithms

BasicFilter

Numerics

IO

Binary Tree

建議的方式

Out Source Build

InSourceBuild

cmake: source/binary tree(2)

CMakeLists.txt# Project namePROJECT(HELLO)

# Source code subdirectoriesSUBDIRS(src test)

# Create a library from the hello.cxx fileADD_LIBRARY(Hello hello.c)

# Location of library include filesINCLUDE_DIRECTORIES(${HELLO_SOURCE_DIR}/src)

# Library location for the linkerLINK_DIRECTORIES(${HELLO_BINARY_DIR}/src)

# helloDemo executable built from demo.cADD_EXECUTABLE(helloDemo demo.c)

# Link the executable to the Hello library.TARGET_LINK_LIBRARIES(helloDemo Hello)

CMake::Modules● automake採用m4 macro偵測環境之組態● CMake採用若干module$ dpkg ­L cmake | grep Modules

/usr/share/cmake­2.4/Modules

/usr/share/cmake­2.4/Modules/AddFileDependencies.cmake

/usr/share/cmake­2.4/Modules/CheckCCompilerFlag.cmake

/usr/share/cmake­2.4/Modules/CheckCSourceCompiles.cmake

...

/usr/share/cmake­2.4/Modules/FindASPELL.cmake

/usr/share/cmake­2.4/Modules/FindAVIFile.cmake

/usr/share/cmake­2.4/Modules/FindBoost.cmake

/usr/share/cmake­2.4/Modules/FindBZip2.cmake

...

CMake cacheCMakeCache.txt● 用途:表示建構環境的組態

– 只要 cache存在,即可免除重新偵測● 相當於 Autotools的 config.status

● 於組態設定階段更新

– Unix: ccmake– MS-Windows: CmakeSetup

● cmake -C <initial-cache>– Pre-load a script to populate the cache.

操作:命令列$ cd Projects

$ cmake projectFoo ­G”Visual Studio 7” ­DBAR:BOOL=1

● cmake [options] <path-to-source/path-to-existing-build>

● -D <var>:<type>=<value>– 建立 cmake cache項目

● -G <generator-name>– 指定平台相依的編譯產生器

● 透過 UI修改每項 cache內容● UNIX – ccmake, qt4-cmake (v2.6)● MS-Windows - CMakeSetup

操作:互動介面

CMakeSetupCMakeSetup ccmakeccmake

撰寫 CMakeLists.txt● 使用 CMake提供的 scripting language

– Comments – Commands– Lists– Variables– Control structures

# 本行為註解

COMMAND(參數 1 參數 2 ...)

A;B;C # 以分號區隔

IF(條件成立 )

${變數名稱 }

● 語法:

● 範例:

CMakeLists.txt::CommandsCOMMAND(參數 1 “參數 2 包含空白 ABC”

${A_LIST} “${A_STRING}”)

TARGET_LINK_LIBRARIES(myTarget

lib1 lib2)

FIND_LIBRARY(MY_LIB NAMES my1 my2

PATHS /foo /bar)

注意:不區分大小寫

● 永遠是字串形式● 在組態設定階段被決定● 透過 SET一類的 Commands所指定● 範例:

CMakeLists.txt::Variables

SET(A_LIST ${A_LIST} foo)

SET(A_STRING “${A_STRING} bar”)

● IF

● FOREACH

● MACRO

CMakeLists.txt::Control StructuresIF(CONDITION) MESSAGE(“Yes”)ELSE(CONDITION) MESSAGE(“No”)ENDIF(CONDITION)

FOREACH(k A B C) MESSAGE(“${k}: ${${k}}”)ENDFOREACH(k)

MACRO(MY_MACRO arg1 arg2) SET(${arg1} “${${arg2}}”)ENDMACRO(MY_MACRO)MY_MACRO(A B)

範例: Hello World

● PROJECT– 非必要,但建議加入

● ADD_EXECUTABLE– 自指定的 list中產生執行檔

PROJECT( helloworld )SET( hello_SRCS hello.c )ADD_EXECUTABLE( hello ${hello_SRCS} )

CMakeLists.txt

#include <stdio.h>int main(){

printf("Hello World!");return 0;

}

hello.c

建立執行檔

● ADD_LIBRARY– 自指定的 list中產生靜態函式庫

● 指定 SHARED則產生動態函式庫 (.dll / .so)

PROJECT( helloworld )SET( hello_SRCS hello.c )ADD_LIBRARY( hello SHARED ${hello_SRCS} )

CMakeLists.txt

#include <stdio.h>int hello(){

printf("Hello World!");return 0;

}

hello.c

建立函式庫

範例: fdclock

PROJECT( fdclock )FIND_PACKAGE( PkgConfig )PKG_CHECK_MODULES( cairo REQUIRED cairo )INCLUDE_DIRECTORIES( ${cairo_INCLUDE_DIRS} )LINK_DIRECTORIES( ${cairo_LIBRARY_DIRS} )

SET( fdclock_SRCS fdclock.c                  fdface.c                  fdhand.c                  fdlogo.c                  findargb.c )ADD_EXECUTABLE( fdclock ${fdclock_SRCS} )TARGET_LINK_LIBRARIES( fdclock ${cairo_LIBRARIES} )INSTALL( TARGETS fdclock          DESTINATION ${CMAKE_INSTALL_PREFIX}/bin )

CMakeLists.txt

AC_PREREQ(2.57)AC_INIT(FULL­PACKAGE­NAME,VERSION, BUG­REPORT­ADDRESS)AC_CONFIG_SRCDIR([fdclock.c])AM_INIT_AUTOMAKE([dist­bzip2])AM_MAINTAINER_MODEAC_CONFIG_HEADER([config.h])AC_PROG_CCAC_HEADER_STDCPKG_CHECK_MODULES(FDCLOCK, cairo)AC_CONFIG_FILES([Makefile])AC_OUTPUT configure.ac

INCLUDES = @FDCLOCK_CFLAGS@fdclock_SOURCES = \

fdclock.c fdhand.c findargb.c \fdlogo.c fdface.c

bin_PROGRAMS = fdclockfdclock_LDADD = @FDCLOCK_LIBS@

Makefile.am

AC_PREREQ(2.57)AC_INIT(FULL­PACKAGE­NAME,VERSION, BUG­REPORT­ADDRESS)AC_CONFIG_SRCDIR([fdclock.c])AM_INIT_AUTOMAKE([dist­bzip2])AM_MAINTAINER_MODEAC_CONFIG_HEADER([config.h])AC_PROG_CCAC_HEADER_STDCPKG_CHECK_MODULES(FDCLOCK, cairo)AC_CONFIG_FILES([Makefile])AC_OUTPUT configure.ac

包袱:●configure – 176k●Makefile.in – 19k●Depcomp – 16k●missing – 11k●install.sh ­ 9k

案例探討: KDE

$ cd Projects/build

$ cmake .. \

  ­GKDevelop3

$ kdevelop foo.project

CTest/Dart● If it's not tested, it doesn't work!

– Unit testing的重要性– Test-Driven Development– 透過 CMake整合 Unit Test

● 途徑:確保 nightly build得以 ...– 在所有支援的平台建構

– 符合預期行為 PROJECT( ProductA )...ENABLE_TESTING()ADD_EXECUTABLE( foo )ADD_TEST(footest foo )...

CMakeLists.txt

$ make Experimental

QTestLib● Qt4的一部分

– KDE/Qt應用程式可直接運用● 特徵

– Lightweight: 6k LoC, 60 exported symbols.

– Self-contained

– Rapid testing

– Data-driven testing

– Basic GUI testing

– IDE friendly

– Thread-safety

– Type-safety

– Easily extendable

#include <QtCore/QObject>

class KLocaleTest : public QObject{ Q_OBJECT

private Q_SLOTS: void testReadTime(); ...};

klocaletest.h

#include "klocaletest.h"#include <qtest_kde.h>#include <klocale.h>

QTEST_KDEMAIN_CORE(KLocaleTest)

void KLocaleTest::readTime(){    KLocale* locale = KGlobal::locale();    bool ok = false;    QCOMPARE(locale­>readTime("11:22:33", &ok),             QTime(11,22,33));    QVERIFY(ok);}#include "klocaletest.moc"

klocaletest.cpp

QTestLib巨集:QCOMPARE(a, b)QVERIFY(bool)QVERIFY2(bool,          "some bug happened")

...SET(klocaletest_SOURCES klocaletest.cpp)KDE4_AUTOMOC(${klocaletest_SOURCES})KDE4_ADD_UNIT_TEST(klocaletest ${klocaletest_SOURCES})TARGET_LINK_LIBRARIES(klocaletest ${KDE4_KDECORE_LIBS}

${QT_QTTEST_LIBRARY})# Many tests ­> use macro, see kdecore/tests for exampleKDECORE_UNIT_TESTS( klocaletest klocalizedstringtest ...) CMakeLists.txt

$ ./klocaletest********* Start testing of KLocaleTest *********Config: Using QTest library 4.3.0, Qt 4.3.0PASS   : KLocaleTest::initTestCase()PASS   : KLocaleTest::readTime()PASS   : KLocaleTest::cleanupTestCase()Totals: 3 passed, 0 failed, 0 skipped********* Finished testing of KLocaleTest *********

Verify Output

QTEST_KDEMAIN_CORE(KLocaleTest)void KlocaleTest::readTime() {    QCOMPARE(...readTime("...", &ok),             QTime(...));    QVERIFY(ok);}

./klocaletest********* Start testing of KLocaleTest *********Config: Using QTest library 4.3.0, Qt 4.3.0PASS   : KLocaleTest::initTestCase()FAIL!  : KLocaleTest::readTime() Compared values are not the same   Actual (locale­>readTime("11:22:33", &ok)): 11:22:33.000   Expected (QTime(11,22,34)): 11:22:34.000   Loc: [/d/kde/src/4/kdetoys/tests/klocaletest.cpp(13)]PASS   : KLocaleTest::cleanupTestCase()Totals: 2 passed, 1 failed, 0 skipped********* Finished testing of KLocaleTest *********

Verify Output

$ make && make test

$ svn commit

Running tests...Start processing testsTest project /d/kde/build/4/kdelibs/kdecore/tests  1/ 36 Testing klocaletest                      Passed  2/ 36 Testing klocalizedstringtest             Passed   [...] 36/ 36 Testing kmimetypetest                    Passed

100% tests passed, 0 tests failed out of 36

Regression Testing

案例探討:嵌入式系統

嵌入式系統的設計挑戰跨平台開發 , 異質性環境 , 多重目標環境 ,

多樣性 , 相對封閉的環境 , ...

一般開發端與目標端是同樣的環境或相似的硬體配置

跨平台可能完全變換風貌

種種未知情況

SET(SRC_LIST main.c utils/foo.c utils/bar.c)

# add the definitions (or switches) you likeADD_DEFINITIONS(­O2 ­fno­strict­aliasing)

# use the eCos support coming with CMakeINCLUDE(UseEcos)

# add the ecos/install/include/ directory to the header search pathECOS_ADD_INCLUDE_DIRECTORIES()

# we want to crosscompile for an Intel XScale processorECOS_USE_ARM_ELF_TOOLS()

ECOS_ADD_EXECUTABLE(sampleapp ${SRC_LIST} )

sampleapp/                <­ the main directory  |  +­CMakeLists.txt        <­ specifies the source files and how to build the application from them  |  +­main.c                <­ one of the source files, the rest is skipped here  |  +­ecos/                 <­ below this directory the compilation of eCos will take place      |      +­ecos.ecc          <­ the eCos config file      |      +­install/lib/      <­ here you will find the eCos libraries, libtarget.a, libtarget.ld      |      +­install/include/  <­ here you will find the eCos header files, this directory will                             be part if the compiler include path

目錄結構

CMakeLists.txt

bigproject/                      <­ the main directory  |  +­CMakeLists.txt               <­ list the subdirectories  |  +­firmware/                    <­ the root directory for all eCos applications  |   |  |   +­CMakeLists.txt           <­ include UseEcos.cmake and list the subdirectories  |   |  |   +­common/                  <­ common/ is a directory which contains sources and headers generally  |   |  |   +­helloworld/              <­ an embedded application project directory  |       |  |       +­CMakeLists.txt       <­ list the subdirectories  |       |  |       +­ProjectSources.txt   <­ list all source files of your application in this file  |       |  |       +­main.cpp             <­ one of the source files, the other ones are skipped here  |       |  |       +­ecos­synth/          <­ here the application will be compiled for the synth target  |       | |  |       | +­CMakeLists.txt     <­ adjust the compiler settings here  |       | |  |       | +­ecos/              <­ below this directory the eCos compilation will take place  |       |  |       +­ecos­iq80321/        <­ here comes all the stuff from above again, but now for the   |       |                         Intel IQ80321 processor  |       |  |       +­ecos­ppc/            <­ and now for a power pc target  |  +­host/                        <­ the root directory for all host tools      |      +­CMakeLists.txt           <­ list the subdirectories      |      +­sometool/                <­ some tool you might need

針對不同平台調整的目錄結構

參考資料● Wikipedia的詞目 : http://zh.wikipedia.org/wiki/CMake

● Why the KDE project switched to CMake — and how: http://lwn.net/Articles/188693/

● 〈 CMake and Friends〉 , Alexander Neundof● Qt Reference Manual: http://doc.trolltech.com/4.2

● KDE Tutorials: http://developer.kde.org/documentation/tutorials/writingunittests/writingunittests.html

● 〈 Using eCos with CMake〉 : http://linuxdevices.com/articles/AT6762290643.html

Recommended