Mercurial > template
changeset 25:9573e6c9ac97
Add CMake guide in STYLE.md
author | David Demelier <markand@malikania.fr> |
---|---|
date | Thu, 24 May 2018 14:56:09 +0200 |
parents | 91c36b9134ad |
children | 9d24e37a289c |
files | STYLE.md |
diffstat | 1 files changed, 130 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/STYLE.md Mon Mar 19 16:19:06 2018 +0100 +++ b/STYLE.md Thu May 24 14:56:09 2018 +0200 @@ -364,17 +364,143 @@ We encorage usage of `auto`, it reduces code maintainance as you don't need to change your code when your rename types. -````cpp +```cpp auto it = std::find_if(v.begin(), v.end(), [&] (const auto& obj) { return obj.key() == "foo"; }); for (const auto& pair : a_map) std::cout << pair.first << " = " << pair.second << std::endl; -```` +``` But do not use `auto` to write code like in python, this is not acceptable: -````cpp +```cpp auto o = my_object("foo"); -```` +``` + +CMake +===== + +Style +----- + + - Always use 4 spaces as indentation, + - Use UTF-8 charset, + - Use Unix line endings, + - Try to keep line shorter than 80 columns + - Never write two blank consecutives blank lines. + +### Spaces + +Each programming keyword (e.g. `if`, `foreach`, `while`) requires a single space +before its argument, otherwise write opening parenthese directly after. + +```cmake +foreach (c ${COMPONENTS}) + string(TOUPPER ${c} CMP) + + if (${WITH_${CMP}}) + add_executable(${c} ${c}.cpp) + endif () +endforeach () +``` + +### Line breaks + +When CMake lines goes too long, you should indent arguments at the same level, +it's also common to see named argument values indented even more. + +```cmake +set( + FILES + ${myapp_SOURCE_DIR}/main.cpp + ${myapp_SOURCE_DIR}/foo.cpp + ${myapp_SOURCE_DIR}/bar.cpp +) + +command_with_lot_of_arguments( + TARGET foo + INSTALL On + SOURCES + ${myapp_SOURCE_DIR}/main.cpp + ${myapp_SOURCE_DIR}/foo.cpp + ${myapp_SOURCE_DIR}/bar.cpp + COMMENT "Some comment" +``` + +Modern CMake +------------ + +CMake evolves over time, if you have read very old articles there is a chance +that what you have read is actually deprecated and replaced by other features. +The following list is a short summary of modern CMake features that you must +use. + +### Imported targets + +When they are available, use imported targets rather than plain variables. They +offer complete dependency tracking with options and include directories as well. + +```cmake +find_package(Boost COMPONENTS system) +target_link_libraries(main Boost::system) +``` + +### Use generator expressions + +Use generator expressions as much as you can, they offer much more flexibility +in case of multiple generators. Remember that CMake is not meant to be used only +with Makefiles. + +```cmake +target_link_libraries( + myapp + $<$<STREQUAL:${CMAKE_SYSTEM_NAME},Windows>:shlwapi> + $<$<STREQUAL:${CMAKE_SYSTEM_NAME},Linux>:dl> +``` + +Warning: do never test against `CMAKE_BUILD_TYPE` in any CMakeLists.txt, IDEs + like Visual Studio will mismatch what you'll put in the conditions. + +### Avoid global scoping + +The following commands must be avoided as much as possible: + + - `link_directories`, + - `link_libraries`, + - `include_directories`, + - `add_definitions`. + +They pollute the global namespace, all targets defined after these commands will +be built against those settings. Instead, you should use the per-targets +commands. + +```cmake +target_include_directories( + mylib + PUBLIC + $<BUILD_INTERFACE:${mylib_SOURCE_DIR}> + $<INSTALL_INTERFACE:include> +) +target_link_libraries(mylib foo) +``` + +### Defining sources + +You MUST never use any kind of `file(GLOB)` commands to list sources for an +executable. CMake is designed to be re-called by itself only when required, +having such a construct will not let CMake be able to detect if you have +added/removed files in your source directory. Instead, you MUST always specify +all source by hands. + +```cmake +set( + FILES + ${myapp_SOURCE_DIR}/main.cpp + ${myapp_SOURCE_DIR}/a.cpp + ${myapp_SOURCE_DIR}/b.cpp +) + +add_executable(myapp ${FILES}) +```