Add CMake guide in STYLE.md

Thu, 24 May 2018 14:56:09 +0200

author
David Demelier <markand@malikania.fr>
date
Thu, 24 May 2018 14:56:09 +0200
changeset 25
9573e6c9ac97
parent 24
91c36b9134ad
child 26
9d24e37a289c

Add CMake guide in STYLE.md

STYLE.md file | annotate | diff | comparison | revisions
--- 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})
+```

mercurial