Policies/CMake Coding Style: Difference between revisions

    From KDE TechBase
    No edit summary
    (13 intermediate revisions by 4 users not shown)
    Line 1: Line 1:
    This document describes the recommended coding style for CMake files in KDE, i.e. CMakeLists.txt files and *.cmake files.
    This document describes the recommended coding style for CMake files in KDE, i.e. CMakeLists.txt files and *.cmake files.
    =General=
    To put in in one sentence: be as careful when writing the CMake files as when you are writing C++ code.


    ==Indentation==
    ==Indentation==


    Indent all code correctly, i.e. the body of  
    Indent all code correctly, i.e. the body of  
    * IF/ELSE/ENDIF
     
    * FOREACH/ENDFOREACH
    * if/else/endif
    * WHILE/ENDWHILE
    * foreach/endforeach
    * MACRO/ENDMACRO
    * while/endwhile
    * FUNCTION/ENDFUNCTION (CMake 2.6)
    * macro/endmacro
    * function/endfunction


    Use spaces for indenting, 2, 3 or 4 spaces preferably. Use the same amount
    Use spaces for indenting, 2, 3 or 4 spaces preferably. Use the same amount
    of spaces for indenting as is used in the rest of the file.
    of spaces for indenting as is used in the rest of the file. Do not use tabs.


    ==Upper/lower casing==
    ==Upper/lower casing==


    CMake commands are case-insensitiv (only the commands, not the arguments or variable names). So all the following versions work:
    Most important: use consistent upper- or lowercasing within one file !
    <code>
     
    In general, in KDE the '''all-lowercase''' style is preferred.
     
    So, this is recommended:
    <syntaxhighlight lang="cmake">
    add_executable(foo foo.c)
    add_executable(foo foo.c)
    </syntaxhighlight>
    This is also acceptable:
    <syntaxhighlight lang="cmake">
    ADD_EXECUTABLE(bar bar.c)
    ADD_EXECUTABLE(bar bar.c)
    </syntaxhighlight>
    Mixed casing as shown below works too, but should '''not''' be done within KDE:
    <pre>
    Add_Executable(hello hello.c)
    Add_Executable(hello hello.c)
    aDd_ExEcUtAbLe(hello hello.c)
    aDd_ExEcUtAbLe(blub blub.c)
    </code>
    </pre>
     
    == End commands ==
     
    To make the code easier to read, use empty commands for endforeach(), endif(), endfunction(),  endmacro() and endwhile().  Also, use empty else() commands.
     
    For example, do this:
    <syntaxhighlight lang="cmake">
    if(FOOVAR)
      some_command(...)
    else()
      another_command(...)
    endif()
    </syntaxhighlight>
     
    and '''not''' this:
    <pre>
    if(BARVAR)
      some_other_command(...)
    endif(BARVAR)
    </pre>
     
    =Writing CMake Find-modules=
     
    ==(Not) Using pkg-config==


    But this would be ugly.
    You are free to use pkg-config in FindXXX.cmake modules, as long as the following conditions are met:
    In KDE the all-lowercase style is preferred. The all-uppercase style is also ok. Mixing upper- and lowercase should not be done in KDE CMake files.
    * the FindXXX.cmake must also work without pkg-config, as long as the package is either installed to one of the default locations (as /usr or /usr/local) or if CMAKE_PREFIX_PATH is set accordingly
    Although all-lowercase is preferred, if a file is apparently in all-uppercase style, then stay consistent and also use all-uppercase in this file.
    * use only find_package(PkgConfig), don't use include(UsePkgConfig), this one is deprecated
    * make sure the variables created by pkg_check_modules() are all prefixed with "PC_", so they don't mix up with other variables, e.g. set via find_path() etc.
    * FindLibXml2.cmake as shipped with CMake 2.8.5 is a good example how pkg-config should be handled
    * putting something like if(NOT WIN32) around the pkg-config stuff is not necessary (and should be removed if it is somewhere). If pkg-config is not found, e.g. on Windows, the macros simply do nothing.


    ==Writing CMake Find-modules==
    ==Follow CMake's readme.txt==


    Follow the style guide from CMake when writing some FindFoo.cmake module:  
    Follow the style guide from CMake when writing some FindFoo.cmake module:  
    [http://www.cmake.org/cgi-bin/viewcvs.cgi/Modules/readme.txt?root=CMake&view=markup readme.txt]
    [http://www.cmake.org/cgi-bin/viewcvs.cgi/Modules/readme.txt?root=CMake&view=markup readme.txt]
    ==Use FindPackageHandleStandardArgs.cmake==
    For checking the results inside the Find-module, the macro find_package_handle_standard_args() (coming with CMake) should be used, using the new extended syntax, which supports also version checking.
    ==Avoid Micro-Optimzations==
    Micro-optimizations like
    <pre>
    if(FOO_LIBRARY AND FOO_INCLUDE_DIR)
      set(FOO_FOUND TRUE)
    else()
      ... execute the whole find-logic
    endif()
    </pre>
    should be removed, the find-logic should be executed always. These shortcuts can cause problems e.g. when the same file is used from multiple directories but e.g. with different required versions or components etc.
    Also manually quieting the module should not be done:
    <pre>
    if ( SQLITE_INCLUDE_DIR AND SQLITE_LIBRARIES )
      set(Sqlite_FIND_QUIETLY TRUE)
    endif ( SQLITE_INCLUDE_DIR AND SQLITE_LIBRARIES )
    </pre>
    If find_package_handle_standard_args() is used, this is completely unnecessary, since find_package_handle_standard_args() only prints something if the result has changed compared to the previous run. So if, as in this example, sqlite has already been found, find_package_handle_standard_args() will only print this information during the first CMake run, but not on successive runs.
    So, do not add such code. It is unnecessary and makes the modules look more complicated than necessary.
    =Writing FooConfig.cmake files=
    * See http://quickgit.kde.org/?p=kdeexamples.git&a=tree&hb=HEAD&f=buildsystem/HowToInstallALibrary for a fully commented example
    * See also:
    ** http://www.cmake.org/Wiki/CMake/Tutorials/Exporting_and_Importing_Targets
    ** http://www.cmake.org/Wiki/CMake/Tutorials/How_to_create_a_ProjectConfig.cmake_file
    ** http://www.cmake.org/Wiki/CMake/Tutorials/Packaging

    Revision as of 13:46, 15 January 2012

    This document describes the recommended coding style for CMake files in KDE, i.e. CMakeLists.txt files and *.cmake files.

    General

    To put in in one sentence: be as careful when writing the CMake files as when you are writing C++ code.

    Indentation

    Indent all code correctly, i.e. the body of

    • if/else/endif
    • foreach/endforeach
    • while/endwhile
    • macro/endmacro
    • function/endfunction

    Use spaces for indenting, 2, 3 or 4 spaces preferably. Use the same amount of spaces for indenting as is used in the rest of the file. Do not use tabs.

    Upper/lower casing

    Most important: use consistent upper- or lowercasing within one file !

    In general, in KDE the all-lowercase style is preferred.

    So, this is recommended:

    add_executable(foo foo.c)
    

    This is also acceptable:

    ADD_EXECUTABLE(bar bar.c)
    

    Mixed casing as shown below works too, but should not be done within KDE:

    Add_Executable(hello hello.c)
    aDd_ExEcUtAbLe(blub blub.c)
    

    End commands

    To make the code easier to read, use empty commands for endforeach(), endif(), endfunction(), endmacro() and endwhile(). Also, use empty else() commands.

    For example, do this:

    if(FOOVAR)
       some_command(...)
    else()
       another_command(...)
    endif()
    

    and not this:

    if(BARVAR)
       some_other_command(...)
    endif(BARVAR)
    

    Writing CMake Find-modules

    (Not) Using pkg-config

    You are free to use pkg-config in FindXXX.cmake modules, as long as the following conditions are met:

    • the FindXXX.cmake must also work without pkg-config, as long as the package is either installed to one of the default locations (as /usr or /usr/local) or if CMAKE_PREFIX_PATH is set accordingly
    • use only find_package(PkgConfig), don't use include(UsePkgConfig), this one is deprecated
    • make sure the variables created by pkg_check_modules() are all prefixed with "PC_", so they don't mix up with other variables, e.g. set via find_path() etc.
    • FindLibXml2.cmake as shipped with CMake 2.8.5 is a good example how pkg-config should be handled
    • putting something like if(NOT WIN32) around the pkg-config stuff is not necessary (and should be removed if it is somewhere). If pkg-config is not found, e.g. on Windows, the macros simply do nothing.

    Follow CMake's readme.txt

    Follow the style guide from CMake when writing some FindFoo.cmake module: readme.txt

    Use FindPackageHandleStandardArgs.cmake

    For checking the results inside the Find-module, the macro find_package_handle_standard_args() (coming with CMake) should be used, using the new extended syntax, which supports also version checking.

    Avoid Micro-Optimzations

    Micro-optimizations like

    if(FOO_LIBRARY AND FOO_INCLUDE_DIR)
       set(FOO_FOUND TRUE)
    else()
       ... execute the whole find-logic
    endif()
    

    should be removed, the find-logic should be executed always. These shortcuts can cause problems e.g. when the same file is used from multiple directories but e.g. with different required versions or components etc.

    Also manually quieting the module should not be done:

    if ( SQLITE_INCLUDE_DIR AND SQLITE_LIBRARIES )
       set(Sqlite_FIND_QUIETLY TRUE)
    endif ( SQLITE_INCLUDE_DIR AND SQLITE_LIBRARIES )
    

    If find_package_handle_standard_args() is used, this is completely unnecessary, since find_package_handle_standard_args() only prints something if the result has changed compared to the previous run. So if, as in this example, sqlite has already been found, find_package_handle_standard_args() will only print this information during the first CMake run, but not on successive runs.

    So, do not add such code. It is unnecessary and makes the modules look more complicated than necessary.

    Writing FooConfig.cmake files