I wasn't quite sure where to go with this, and this seemed to be the best place I could think of so I thought why not. I threw together a build system for C++ projects today using CMake and I wanted your opinions on it, on things I could do better, or change to better comply with best practices.
Here's my directory structure:
. ├── bin (Compiled executables) │ └── lib (Executables from third-party libraries) ├── build (The CMake build folder) │ ├── CMakeCache.txt │ ├── CMakeFiles │ ├── cmake_install.cmake │ ├── inc │ ├── lib │ ├── Makefile │ └── test ├── CMakeLists.txt ├── inc (Objects used in programming) │ └── CMakeLists.txt | └── fake_object (An example) | └── fake_object.h | └── fake_object.cc ├── lib (External/third-party libraries) │ ├── CMakeLists.txt │ └── gmock (Unit testing) ├── main.cc ├── res (External resources such as images, sounds, fonts) └── test (tests, lol) └── CMakeLists.txt
I decided to take a modular approach to my C++ structure, so each object I build for my programs has its own directory within the inc folder.
Here is my main CMakeLists.txt:
########################################################################
# Basic info #
########################################################################
cmake_minimum_required(VERSION 2.8)
project(skeleton)
########################################################################
# Variables #
########################################################################
# My vars
set(test_prefix ${CMAKE_SOURCE_DIR}/test)
set(GMOCK_DIR ${CMAKE_SOURCE_DIR}/lib/gmock)
set(GMOCK_TEST_LIBS ${CMAKE_SOURCE_DIR}/bin/lib)
# System vars
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
set(CMAKE_CXX_FLAGS -lpthread)
# Play around boiiiiiis
set(CMAKE_VERBOSE_MAKEFILE on)
set(NO_MAIN true)
set(classes) # All objects go here
########################################################################
# Main #
########################################################################
##############
# Includes #
##############
include_directories(inc)
include_directories(res)
include_directories(${GMOCK_DIR}/include)
include_directories(${GMOCK_DIR}/gtest/include)
###########
# Logic #
###########
if(NOT ${NO_MAIN})
add_executable(${CMAKE_PROJECT_NAME} main.cc)
target_link_libraries(${CMAKE_PROJECT_NAME} ${classes})
endif(NOT ${NO_MAIN})
########################################################################
# Where do we go now? #
########################################################################
add_subdirectory(inc)
add_subdirectory(lib)
add_subdirectory(test)
The CMakeLists.txt in the test directory:
########################################################################
# Find GMock/Test Libs #
########################################################################
find_library(GMOCK_LIBRARY
NAMES gmock
libgmock
libgmock.a
PATHS ${GMOCK_TEST_LIBS})
find_library(GMOCK_LIBRARY_MAIN
NAMES gmock_main
libgmock_main
libgmock_main.a
PATHS ${GMOCK_TEST_LIBS})
find_library(GTEST_LIBRARY
NAMES gtest
libgtest
libgtest.a
PATHS ${GMOCK_TEST_LIBS})
find_library(GTEST_LIBRARY_MAIN
NAMES gtest_main
libgtest_main
libgtest.a
PATHS ${GMOCK_TEST_LIBS})
########################################################################
# Compile tests #
########################################################################
#########################
# Grab all test cases #
#########################
set(test_sources)
foreach(TEST ${classes})
list(APPEND test_sources "${TEST}_test.cc")
endforeach(TEST)
#######################
# Create executable #
#######################
if (DEFINED ${test_sources})
add_executable(run_tests ${test_sources})
target_link_libraries(run_tests ${GMOCK_LIBRARY} ${GMOCK_LIBRARY_MAIN})
target_link_libraries(run_tests ${GTEST_LIBRARY} ${GTEST_LIBRARY_MAIN})
target_link_libraries(run_tests ${classes})
endif(DEFINED ${test_sources})
The CMakeLists.txt in the inc directory:
########################################################################
# Make all subdirs libraries #
########################################################################
foreach(INC ${classes})
add_library(${INC} ${INC}/${INC}.cc)
endforeach(INC)
I'm also going to implement a doc directory for documentation (probably using Doxygen), but I've done so before and I know it's relatively easy to implement.