Changes between Version 22 and Version 23 of BestPracticeHandbook
- Timestamp:
- May 13, 2015, 11:45:40 PM (7 years ago)
Legend:
- Unmodified
- Added
- Removed
- Modified
-
BestPracticeHandbook
v22 v23 263 263 == 5. QUALITY: Strongly consider per-commit compiling your code with static analysis tools == 264 264 265 In Travis and Appveyor it is easy to configure a special build job which uses the clang static analyser on Linux/OS X and the MSVC static analyser on Windows. These perform lengthy additional static AST analysis tests to detect when your code is doing something stupid and the use of these is an excellent sign that the developer cares about code quality. Static analysis is perfectly suited to be run by a CI as it takes extra time to compile your program, so a CI can trundle off and do the lengthy work itself while you get on with other work.265 In Travis and Appveyor it is easy to configure a special build job which uses the clang static analyser and clang lint tools on Linux/OS X and the MSVC static analyser on Windows. These perform lengthy additional static AST analysis tests to detect when your code is doing something stupid and the use of these is an excellent sign that the developer cares about code quality. Static analysis is perfectly suited to be run by a CI as it takes extra time to compile your program, so a CI can trundle off and do the lengthy work itself while you get on with other work. 266 266 267 267 Enabling Microsoft's static analyser is easy, simply add /analyze to the compiler command line. Your compile will take ten times longer and new warnings will appear. Note though that the MSVC static analyser is quite prone to false positives like miscounting array entries consumed. You can suppress those using the standard #pragma warning(disable: XXX) system around the offending code. … … 286 286 287 287 scan-build will generate a HTML report of the issues found with a pretty graphical display of the logic followed by the analyser into the $REPORTS directory. Jenkins has a plugin which can publish this HTML report for you per build, for other CIs you'll need to copy the generated files onto a website somewhere e.g. committing them to your repo under gh-pages and pushing them back to github. 288 289 Finally, the clang lint tool (called [http://clang.llvm.org/extra/clang-tidy.html clang-tidy]) is not something I have currently enabled in my own code, but it looks very promising. The following checks are default enabled on clang tidy 3.6: 290 291 {{{ 292 Enabled checks: 293 clang-analyzer-core.CallAndMessage 294 clang-analyzer-core.DivideZero 295 clang-analyzer-core.DynamicTypePropagation 296 clang-analyzer-core.NonNullParamChecker 297 clang-analyzer-core.NullDereference 298 clang-analyzer-core.StackAddressEscape 299 clang-analyzer-core.UndefinedBinaryOperatorResult 300 clang-analyzer-core.VLASize 301 clang-analyzer-core.builtin.BuiltinFunctions 302 clang-analyzer-core.builtin.NoReturnFunctions 303 clang-analyzer-core.uninitialized.ArraySubscript 304 clang-analyzer-core.uninitialized.Assign 305 clang-analyzer-core.uninitialized.Branch 306 clang-analyzer-core.uninitialized.CapturedBlockVariable 307 clang-analyzer-core.uninitialized.UndefReturn 308 clang-analyzer-cplusplus.NewDelete 309 clang-analyzer-cplusplus.NewDeleteLeaks 310 clang-analyzer-deadcode.DeadStores 311 clang-analyzer-llvm.Conventions 312 clang-analyzer-security.FloatLoopCounter 313 clang-analyzer-security.insecureAPI.UncheckedReturn 314 clang-analyzer-security.insecureAPI.getpw 315 clang-analyzer-security.insecureAPI.gets 316 clang-analyzer-security.insecureAPI.mkstemp 317 clang-analyzer-security.insecureAPI.mktemp 318 clang-analyzer-security.insecureAPI.rand 319 clang-analyzer-security.insecureAPI.strcpy 320 clang-analyzer-security.insecureAPI.vfork 321 clang-analyzer-unix.API 322 clang-analyzer-unix.Malloc 323 clang-analyzer-unix.MallocSizeof 324 clang-analyzer-unix.MismatchedDeallocator 325 clang-analyzer-unix.cstring.BadSizeArg 326 clang-analyzer-unix.cstring.NullArg 327 }}} 328 329 I also see some default disabled checks which might be interesting: 330 331 {{{ 332 clang-analyzer-alpha.core.BoolAssignment 333 clang-analyzer-alpha.core.CallAndMessageUnInitRefArg 334 clang-analyzer-alpha.core.CastSize 335 clang-analyzer-alpha.core.CastToStruct 336 clang-analyzer-alpha.core.FixedAddr 337 clang-analyzer-alpha.core.IdenticalExpr 338 clang-analyzer-alpha.core.PointerArithm 339 clang-analyzer-alpha.core.PointerSub 340 clang-analyzer-alpha.core.SizeofPtr 341 clang-analyzer-alpha.core.TestAfterDivZero 342 clang-analyzer-alpha.cplusplus.VirtualCall 343 clang-analyzer-alpha.deadcode.UnreachableCode 344 misc-argument-comment 345 misc-bool-pointer-implicit-conversion 346 misc-swapped-arguments 347 misc-undelegated-constructor 348 misc-uniqueptr-reset-release 349 misc-unused-raii 350 misc-use-override 351 readability-braces-around-statements 352 readability-function-size 353 readability-redundant-smartptr-get 354 }}} 288 355 289 356 … … 865 932 == 15. BUILD: Consider defaulting to header only, but actively manage facilities for reducing build times == 866 933 934 Making your library header only is incredibly convenient for your users - they simply drop in a copy of your project and get to work, no build system worries. Hence most Boost libraries and many C++ libraries are header only capable, often header only default. A minority are even header only only. 935 936 One thing noticed in the library review is just how many of the new C++ 11/14 libraries are header only only, and whilst convenient I think library authors should and moreover ''can'' do better. For some statistics to put this in perspective, proposed Boost.AFIO v1.3 provides a range of build configurations for its unit tests: 937 938 1. Header only 939 2. Precompiled header only (default) 940 3. Precompiled not header only (library implementation put into a shared library) 941 4. Precompiled header only with link time optimisation 942 867 943 ||= Build flags =||= Microsoft Windows 8.1 x64 with Visual Studio 2013 =||= Ubuntu 14.04 LTS Linux x64 with GCC 4.9 and gold linker =||= Ubuntu 14.04 LTS Linux x64 with clang 3.4 and gold linker =|| 868 944 || Debug header only || 7m17s || 12m0s || 5m45s || 945 || Debug precompiled header only || 2m10s || 10m26s || 5m46s || 869 946 || Debug precompiled not header only || 0m55s || 3m53s || asio failure || 947 || Release precompiled header only || 2m58s || 9m57s || 8m10s || 870 948 || Release precompiled not header only || 1m10s || 3m22s || asio failure || 871 || Debug precompiled header only || 2m10s || 10m26s || 5m46s ||872 || Release precompiled header only || 2m58s || 9m57s || 8m10s ||873 || Debug precompiled header only link time optimisation || 5m37s || GCC ICE || 5m42s ||874 949 || Release precompiled header only link time optimisation || 7m30s || 13m0s || 8m11s || 950 951 These are for a single core 3.9Ghz i7-3770K computer. I think the results speak for themselves, and note that AFIO is only 8k lines with not much metaprogramming. 952 953 The approaches for improving build times for your library users are generally as follows: 954 955 TODO 875 956 876 957 == 16. COUPLING: Consider allowing your library users to dependency inject your dependencies on other libraries ==