A good way to learn how to use CMake effectively is to look at other projects. LLVM and its subprojects are a good example.
Typically, good coding methods translate into good CMake methods; you want modularity, clear style and flexibility.
An example of this is having rules for creating an executable in the src directory, and then using that target in the project root folder. Something like that:
-my_proj | ----CMakeLists.txt //contains directives for top-level dependencies and linking, includes subfolders ----src | ----CMakeLists.txt //contains definition of your main executable target ----internal_lib | ----CMakeLists.txt //contains definition of your internal static libraries
my_proj / CMakeLists.txt
add_subdirectory(src) find_package (Threads REQUIRED) #find pthreads package target_link_libraries (my_exe my_lib ${CMAKE_THREAD_LIBS_INIT}) #link against pthreads and my_lib
my_proj / SRC / CMakeLists.txt
add_subdirectory(internal_lib) add_executable(my_exe my_source1.cpp mysource2.cpp)
my_proj / SRC / internal_lib / CMakeLists.txt
add_library(my_lib my_lib_source1.cpp my_lib_source2.cpp)
source share