Cpp Notes

2.dos_donts

CMake dos and don'ts

Don'ts

  1. Avoid Global Functions:

    • Example: Do not use global functions like link_directories or include_libraries. Instead, prefer defining and using CMake targets.
  2. Avoid Unnecessary PUBLIC Requirements:

    • Example: Don’t force options like -Wall on users by adding it to the PUBLIC interface of a target. Instead, use PRIVATE to ensure it’s not exposed to the users of your library.
  3. Do Not GLOB Files:

    • Example: Avoid using file(GLOB ...) to include source files in your project. Instead, list them explicitly. Tools like Make won’t detect new files unless CMake is re-run. While CMake 3.12's CONFIGURE_DEPENDS flag can help, it's better to avoid GLOB where possible.
  4. Don't Link Directly to Built Files:

    • Example: Instead of linking directly to a file like target_link_libraries(MyApp /path/to/libmylib.a), always link to CMake targets, e.g., target_link_libraries(MyApp mylib).
  5. Don't Skip PUBLIC/PRIVATE in Linking:

    • Example: If you write target_link_libraries(MyLib MyDep), it defaults to keyword-less, which can cause issues. Always specify whether the dependency is PUBLIC or PRIVATE.

Do's

  1. Treat CMake as Code:

    • Example: Organize your CMake files clearly, with comments and consistent formatting, just as you would with other programming languages.
  2. Think in Targets:

    • Example: Use targets to represent logical components of your application, such as creating IMPORTED or INTERFACE targets for libraries that are used but not built by your project.
  3. Export Your Interface:

    • Example: Ensure that your library can be used correctly from both the build stage and after installation by exporting its interface properly.
  4. Write a config.cmake File:

    • Example: This file should define how to find and use your library, making it easier for others to include your library in their projects.
  5. Use ALIAS Targets:

    • Example: Use add_library(mylib ALIAS mylib_real) to maintain consistency between add_subdirectory and find_package.
  6. Group Common Functionality:

    • Example: If you have repeated tasks in your CMake scripts, encapsulate them in functions or macros. Prefer using functions for better scoping.
  7. Use Lowercase for Function Names:

    • Example: Always define your functions in lowercase like function my_function(). Reserve uppercase for variables.
  8. Use cmake_policy or Version Ranges:

    • Example: Regularly check and apply the latest policies by using cmake_policy(SET CMP0074 NEW) unless you need to revert for compatibility.
  9. Set an Appropriate Minimum Version:

    • Example: Ensure your CMake version is at least as new as the oldest compiler version you plan to support by adding cmake_minimum_required(VERSION 3.12) at the top of your CMakeLists.txt file.