Beruflich Dokumente
Kultur Dokumente
PauGarciaiQuiles<pgquiles@elpauer.org>
Version0.4.2(200811092042GMT+1)
Slides:http://www.elpauer.org/stuff/learning_cmake.pdf
PartI Buildsystemswhatfor?
Why?
Youwriteanapplication(sourcecode)andneed to:
Youwouldalsoloveifyouwereableto:
Compiling
Manually?
gccDMYDEFINEcmyapp.omyapp.cpp
Unfeasiblewhen:
Youreallywanttoautomatethisstep
Linking
Manually?
ldomyappfile1.ofile2.ofile3.olclmylib
Again,unfeasiableifyouhavemanyfiles, dependenceonplatforms,etc
Youalsowanttoautomatethisstep
Distributeyoursoftware
Traditionalwayofdoingthings:
You'dliketoautomatethisbut,isitpossibleto bringpackagersintothedevelopmentprocess?
Testing
Youalluseunittestswhenyoudevelop software,don'tyou?Youshould!
Whenandhowtorununittests?Usuallyathree stepprocess:
Testingandgatheringresults
Someoneneedstodotestingforfeachplatform, thenmergetheresults
Isitpossibletoautomatethis?maketest?what aboutgatheringtheresults?
Automate!
Yourcorebusinessissoftwaredevelopment,not softwarebuilding
Whatareyouselling?
PartII Buildsystemstour
Autotools
It'sbeeninuseformanyyearsandit'sstillwidely used
Autohell?
YouneedtowritescriptsinBourneshell('sh'),m4 (youalldevelopsoftwareinm4,don'tyou?), OnlyUnixplatform=>VisualStudio,Borland,etcin Win32areunsupported(Cygwin/MinGWsupported) Dependencydiscoveryismostlymanual(nobundled findersgroupingseveralsteps) Usuallylong,difficulttounderstandscripts
AutotoolscreateaMakefilefor'make'
Jam
Theoriginalimplementation(PerforceJam)is quitebuggy
Therearemanyslightlydifferentimplementations
Compilesandlinksbyitself
Userscannotusethetoolstheyareusedto WhatifJamisnotavailableforthatplatform?
Allowsparallellinking
SCons
PythonDSL
Theinterpreterisnotalwaysavailable Youneedtolearnalmostaprogramminglanguage
Waf
Secondgenerationofbksys,triestofixScons
Noinstallation:it'sa100KBscriptyou redistributewithyoursource
It'sasecurityissue:ifabugisfound,everyapp needstoredistributeanewwafversion
Compilesandlinksbyitself
CMake
Crossplatform Verysimplescriptlanguage Dependencydiscoveryisawesome: FIND_PACKAGE Scalesverywell:KDE4isusingit(4+MLOC) CreatesaprojectfilesforMakefile,VisualStudio, Kdevelop,Eclipse,etc
Userscanusethetoolstheyareusedto
CannotovercomethelimitationsthoseIDEs/'make' have
PartIII MeetingCMake
TheKitwarebuildandtestchain
WhatisCMake
ThinkofitasametaMake CMakeisusedtocontrolthesoftware compilationprocessusingsimpleplatformand compilerindependentconfigurationfiles CMakegeneratesnativemakefilesand workspacesthatcanbeusedinthecompiler environmentofyourchoice:VisualC++, Kdevelop3,Eclipse,XCode,makefiles(Unix, NMake,Borland,Watcom,MinGW,MSYS, Cygwin),Code::Blocksetc
ProjectsaredescribedinCMakeLists.txtfiles
Buildflow
CMakeLists.txt
cmake/CMakeSetup/CMakeGui
.vcproj/Makefile/etc
Nativebuildingtools(VisualStudio, Eclipse,KDevelop,etc)
.obj/.o
Nativelinkingtools(lib.exe, link.exe,ld,etc)
.exe/.dll/.lib/.a/.so/.dylib
Toolsthedeveloperisalreadyfamiliarwith
Insourcevsoutofsource
Outofsource:
CMakeprefersoutofsourcebuilds
TheCMakeworkflow
Havethistree:
myapp build trunk cdmyapp/build
IfEclipse:
myapp/trunk myappbuild
cmake../trunk
make(Unix)oropenproject(VC++)
Verysimpleexecutable
Showingverboseinfo
ToseethecommandlineCMakeproduces:
Or:
Or:
Tip:onlyuseitifyourbuildisfailingandyou needtofindoutwhy
Verysimplelibrary
Sharedvsstaticlibs
TheCMakecache
Variables&cache(I)
Unconditionalset SET(var113)
Variables&cache(II)
Reusethecache SET(var217...CACHE...)
Variables&cache(III)
Unconditionalset&overwritecache SET(var323...CACHEFORCE)
Regularexpressions
Back/Forwardcompatibility
PartIV RealworldCMake:
dependenciesbetweentargets
Addingothersources
clockapp ADD_SUBDIRECTORY(libwakeup) build ADD_SUBDIRECTORY(clock) trunk doc SET(wakeup_SRCS img wakeup.cpp) libwakeup wakeup.cpp ADD_LIBRARY(wakeupSHARED ${wakeup_SRCS}) wakeup.h clock SET(clock_SRCSclock.cpp) clock.cpp clock.h ADD_EXECUTABLE(clock$ {clock_SRCS})
PROJECT(clockapp)
Variables
Noneedtodeclarethem Usually,noneedtospecifytype SETcreatesandmodifiesvariables SETcandoeverythingbutLISTmakessome operationseasier UseSEPARATE_ARGUMENTStosplitspace separatedarguments(i.e.astring)intoalist (semicolonseparated) InCmake2.4:global(nameclashingproblems) InCmake2.6:scoped
Changingbuildparameters
Cmakeusescommon,sensibledefaultsforthe preprocessor,compilerandlinker Modifypreprocessorsettingswith ADD_DEFINITIONSand REMOVE_DEFINITIONS Compilersettings:CMAKE_C_FLAGSand CMAKE_CXX_FLAGSvariables Tip:someinternalvariables(CMAKE_*)are readonlyandmustbechangedexecutinga command
Flowcontrol
Processalist:
VisualStudiospecial
UseSOURCE_GROUPifallyoursourcesarein thesamedirectory
Managingdebugandrelease builds
SET(CMAKE_BUILD_TYPEDebug)
Asanyothervariable,itcanbesetfromthe commandline:
cmakeDCMAKE_BUILD_TYPE=Release../trunk
Specifydebugandreleasetargetsand3rdparty libs:
TARGET_LINK_LIBRARIES(wakeupRELEASE$ {wakeup_SRCS}) TARGET_LINK_LIBRARIES(wakeupdDEBUG$ {wakeup_SRCS})
Standarddirectories...not!
makeinstall
Findinginstalledsoftware
FIND_PACKAGE(Qt4REQUIRED)
QtwithCMake
PROJECT(pfrac) FIND_PACKAGE(Qt4REQUIRED) INCLUDE(${QT_USE_FILE}) SET(pfrac_SRCSmain.cppclient.hclient.cpp) SET(pfrac_MOC_HEADERSclient.h) QT4_ADD_RESOURCES(pfrac_SRCS ${PROJECT_SOURCE_DIR}/pfrac.qrc) QT4_WRAP_CPP(pfrac_MOC_SRCS ${pfrac_MOC_HEADERS}) ADD_EXECUTABLE(pfrac${pfrac_SRCS}$ {pfrac_MOC_SRCS} TARGET_LINK_LIBRARIES(pfrac${QT_LIBRARIES})
Platformincludes
CONFIGURE_FILE(InputFileOutputFile [COPYONLY][ESCAPE_QUOTES][@ONLY])
Alsousefulfor.conffiles
Platformincludes(II)
PlatformIncludes(III)
CmakeLists.txt ... INCLUDE(CheckIncludeFiles) CHECK_INCLUDE_FILES( malloc.hHAVE_MALLOC_H) ...
wakeup.cpp #include"wakeup.h" #includewakeup2.h #ifdefHAVE_MALLOC_H #include<malloc.h> #else #include<stdlib.h> #endif voiddo_something(){ void*buf=malloc(1024); ... }
PartVI Macrosandfunctions
Macros
Functions
Newtargets
TargetsdefinedwithADD_CUSTOM_TARGET arealwaysconsideredoutdated(i.e.rebuilt)
TwosignaturesforADD_CUSTOM_COMMAND:
Forexample,youcancreate GENERATE_DOCUMENTATION
GENERATE_DOCUMENTATION (I)
MACRO(GENERATE_DOCUMENTATIONDOXYGEN_CONFIG_FILE) FIND_PACKAGE(Doxygen) SET(DOXYFILE_FOUNDfalse) IF(EXISTS${PROJECT_SOURCE_DIR}/${DOXYGEN_CONFIG_FILE}) SET(DOXYFILE_FOUNDtrue) ENDIF(EXISTS${PROJECT_SOURCE_DIR}/${DOXYGEN_CONFIG_FILE})
IF(DOXYGEN_FOUND) IF(DOXYFILE_FOUND) #Addtarget ADD_CUSTOM_TARGET(docALL${DOXYGEN_EXECUTABLE}"$ {PROJECT_SOURCE_DIR}/${DOXYGEN_CONFIG_FILE}") #Add.tagfileandgenerateddocumentationtothelist offileswemusterasewhendistcleaning #Readdoxygenconfigurationfile FILE(READ${PROJECT_SOURCE_DIR}/${DOXYGEN_CONFIG_FILE} DOXYFILE_CONTENTS) STRING(REGEXREPLACE"\n"";"DOXYFILE_LINES$ {DOXYFILE_CONTENTS}) ...
GENERATE_DOCUMENTATION(II)
#Parse.tagfilenameandaddtolistoffilestodelete ifitexists FOREACH(DOXYLINE${DOXYFILE_CONTENTS}) STRING(REGEXREPLACE".*GENERATE_TAGFILE*=*([^ ^\n]+).*""\\1"DOXYGEN_TAG_FILE${DOXYLINE}) ENDFOREACH(DOXYLINE) ADD_TO_DISTCLEAN(${PROJECT_BINARY_DIR}/$ {DOXYGEN_TAG_FILE}) #Parsedoxygenoutputdocdirandaddtolistoffiles todeleteifitexists FOREACH(DOXYLINE${DOXYFILE_CONTENTS}) STRING(REGEXREPLACE".*OUTPUT_DIRECTORY*=*([^ ^\n]+).*""\\1"DOXYGEN_DOC_DIR${DOXYLINE}) ENDFOREACH(DOXYLINE) ADD_TO_DISTCLEAN(${PROJECT_BINARY_DIR}/$ {DOXYGEN_DOC_DIR}) ADD_TO_DISTCLEAN(${PROJECT_BINARY_DIR}/$ {DOXYGEN_DOC_DIR}.dir) ...
GENERATE_DOCUMENTATION(III)
ELSE(DOXYFILE_FOUND) MESSAGE(STATUS"Doxygenconfigurationfilenotfound Documentationwillnotbegenerated") ENDIF(DOXYFILE_FOUND) ELSE(DOXYGEN_FOUND) MESSAGE(STATUS"DoxygennotfoundDocumentationwill notbegenerated") ENDIF(DOXYGEN_FOUND) ENDMACRO(GENERATE_DOCUMENTATION)
Callingtheoutsideworld
PartVII Creatingyourownfinders
Whatisafinder
Whencompilingapieceofsoftwarewhich linkstothirdpartylibraries,weneedtoknow:
That'sthebasicinformationafinderneedsto return
MESSAGE
Showstatusinformation,warningsorerrors
MESSAGE([SEND_ERROR|STATUS|FATAL_ERROR]
"messagetodisplay"...)
STRING
Manipulatestringsorregularexpressions Manysignatures
FilesandWindowsregistry
GET_FILENAME_COMPONENTinteractswith theoutsideworld
FILE
Readfrom/writetofiles Removefilesanddirectories
TranslatepathsbetweennativeandCmake: \/
Findlibraries
FIND_LIBRARYandthe CMAKE_LIBRARY_PATHvariable
(thisslideisonlyastub)
Findheaderfiles
FIND_FILE (thisslideisonlyastub)
Findgenericfiles
FIND_PATHandtheCMAKE_INCLUDE_PATH variable
(thisslideisonlyastub)
PkgConfigsupport
FIND_PROGRAM (thisslideisonlyastub)
TRY_COMPILE (thisslideisonlyastub)
TRY_RUN (thisslideisonlyastub)
PartVIII Properties
CMAKE_MINIMUM_REQUIRED (thisslideisonlyastub)
OPTION (thisslideisonlyastub)
GET_CMAKE_PROPERTY (thisslideisonlyastub)
GET_TARGET_PROPERTY (thisslideisonlyastub)
SET_TARGET_PROPERTIES (thisslideisonlyastub)
SET_SOURCE_FILES_PROPERTIES (thisslideisonlyastub)
PartIX Usefulvariables
CMAKE_BINARY_DIR/CMAKE_SOURCE_DIR (thisslideisonlyastub)
CMAKE_CURRENT_BINARY_DIR /CMAKE_CURRENT_SOURCE_DIR
(thisslideisonlyastub)
PROJECT_BINARY_DIR/PROJECT_SOURCE_ DIR
(thisslideisonlyastub)
EXECUTABLE_OUTPUT_PATH/LIBRARY_OUT PUT_PATH
(thisslideisonlyastub)
ENV($ENV{name}) (thisslideisonlyastub)
Morevariables
Usethissnippettolistallvariablesandtheir values:
get_cmake_property(PVARIABLES) foreach(VARin${P}) message(STATUS "${VAR}=${${VAR}}") endforeach()
PartX CPack
Features
CPackgeneratesinstallingpackages:
VariablesinCPack
Example
INCLUDE(InstallRequiredSystemLibraries) SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY"Alarmclock") SET(CPACK_PACKAGE_VENDOR"PauGarciaiQuiles") SET(CPACK_PACKAGE_DESCRIPTION_FILE "$CMAKE_CURRENT_SOURCE_DIR}/ReadMe.txt") SET(CPACK_RESOURCE_FILE_LICENSE "$CMAKE_CURRENT_SOURCE_DIR}/Copyright.txt") SET(CPACK_PACKAGE_VERSION_MAJOR"0") SET(CPACK_PACKAGE_VERSION_MINOR"0") SET(CPACK_PACKAGE_VERSION_PATCH"1") SET(CPACK_PACKAGE_INSTALL_DIRECTORY"CMake$ {Cmake_VERSION_MAJOR}.${CMake_VERSION_MINOR}") ...
Example(cont.)
IF(WIN32ANDNOTUNIX) SET(CPACK_PACKAGE_ICON"$ {Cmake_SOURCE_DIR}/Utilities/Release\\\\InstallIcon.bmp") SET(CPACK_NSIS_INSTALLED_ICON_NAME "bin\\\\MyExecutable.exe") SET(CPACK_NSIS_DISPLAY_NAME"$ {CPACK_PACKAGE_INSTALL_DIRECTORY}MyFamousProject") SET(CPACK_NSIS_HELP_LINK"http:\\\\\\\\elpauer.org") SET(CPACK_NSIS_URL_INFO_ABOUT"http:\\\\\\\\elpauer.org") SET(CPACK_NSIS_CONTACT"pgquiles@elpauer.org") ... INCLUDE(CPack)
PartXI CTest
Features
Crossplatformtestingsystemwhich:
Othertests:
memorychecking
Example
Veryeasy!
ENABLE_TESTING() ADD_TEST(testnametestexecutableargs)
Somescriptingneededto:
ItcanbeusedwithnonCMakeprojects
PartXII CDash
Features
Buildresultsonallplatforms Test(Ctest)resultsonallplatforms
CustomizableusingXSL
Example