├── .clang-format ├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── LICENSE.md ├── README.md ├── bootstrap.py ├── example ├── CMakeLists.txt └── a.cpp ├── include └── project_name │ ├── component │ └── component_header.hpp │ ├── project_name.hpp │ └── test_header.hpp ├── site ├── CMakeLists.txt ├── Doxyfile.in ├── footer.html ├── header.html └── layout.xml └── test ├── CMakeLists.txt ├── component └── test_a.cpp └── test_b.cpp /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: Google 2 | AccessModifierOffset: -1 3 | AlignEscapedNewlinesLeft: true 4 | AlignTrailingComments: true 5 | AllowAllParametersOfDeclarationOnNextLine: true 6 | AllowShortBlocksOnASingleLine: true 7 | AllowShortFunctionsOnASingleLine: All 8 | AllowShortIfStatementsOnASingleLine: true 9 | AllowShortLoopsOnASingleLine: true 10 | AlwaysBreakBeforeMultilineStrings: false 11 | AlwaysBreakTemplateDeclarations: false 12 | BinPackParameters: true 13 | BreakBeforeBinaryOperators: true 14 | BreakBeforeBraces: Attach 15 | BreakBeforeTernaryOperators: true 16 | BreakConstructorInitializersBeforeComma: true 17 | ColumnLimit: 80 18 | ConstructorInitializerAllOnOneLineOrOnePerLine: true 19 | ConstructorInitializerIndentWidth: 1 20 | ContinuationIndentWidth: 1 21 | Cpp11BracedListStyle: true 22 | DerivePointerBinding: false 23 | ExperimentalAutoDetectBinPacking: false 24 | IndentCaseLabels: true 25 | IndentFunctionDeclarationAfterType: true 26 | IndentWidth: 2 27 | KeepEmptyLinesAtTheStartOfBlocks: false 28 | Language: Cpp 29 | MaxEmptyLinesToKeep: 1 30 | NamespaceIndentation: None 31 | PenaltyBreakBeforeFirstCallParameter: 10 32 | PointerBindsToType: true 33 | SpaceAfterControlStatementKeyword: true 34 | SpaceBeforeAssignmentOperators: true 35 | SpaceBeforeParens: ControlStatements 36 | SpaceInEmptyParentheses: false 37 | SpacesBeforeTrailingComments: 2 38 | SpacesInCStyleCastParentheses: false 39 | SpacesInParentheses: false 40 | SpacesInAngles: false 41 | Standard: Cpp11 42 | TabWidth: 2 43 | UseTab: Never 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | 19 | # Compiled Static libraries 20 | *.lai 21 | *.la 22 | *.a 23 | *.lib 24 | 25 | # Executables 26 | *.exe 27 | *.out 28 | *.app 29 | 30 | # Build directory 31 | build/ 32 | 33 | # emacs 34 | auto-save-list 35 | custom.el 36 | url/ 37 | .org-id-locations 38 | \#* 39 | org-mode-config.el 40 | *~ 41 | .#* 42 | \#*\# 43 | *.log 44 | .DS_Store 45 | org-clock-save.el 46 | emacs-config.el -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # Copyright Louis Dionne 2015 2 | # Distributed under the Boost Software License, Version 1.0. 3 | # (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) 4 | 5 | language: c++ 6 | compiler: clang 7 | os: linux 8 | # sudo: false | TODO: required by python-yaml and lcov 9 | sudo: required 10 | 11 | # This describes the test matrix 12 | # 13 | # env is used to set global variables: 14 | # - COMPILER: selects the compiler 15 | # - Note: clang uses libc++ and gcc uses libstdc++ 16 | # - BUILD_TYPE: selects the build type: Debug/Release 17 | # - ASan: use AddressSanitizer: true/false 18 | # - Valgrind: use valgrind: true/false 19 | # - Site: build code to generate the site: true/false 20 | # - Generates code coverage output 21 | # - Runs the benchmarks 22 | # - Generates documentation 23 | # - Generates website 24 | matrix: 25 | include: 26 | # The first case in the matrix for a given compiler defines how to install 27 | # the compiler under addons, that is, we specify the ubuntu packages required 28 | # and their sources (repositories). 29 | # 30 | # For example, for clang 3.7 trunk we need to get the nightly packages from 31 | # the llvm repository for ubuntu precise. 32 | # 33 | # We store them in the variable clang37 using &clang37 which we can reference 34 | # in the different builds using *clang37. This is done for each compiler. 35 | # 36 | # For each build we also define all the global variables specified above 37 | # TODO: use defaults and define only some of them 38 | 39 | # clang 3.7, debug build 40 | - env: COMPILER=clang++-3.7 BUILD_TYPE=Debug 41 | addons: &clang37 42 | apt: 43 | packages: 44 | - clang-3.7 45 | - valgrind 46 | sources: 47 | - ubuntu-toolchain-r-test 48 | - llvm-toolchain-precise # latest 49 | 50 | # clang 3.7, release build, ASan 51 | - env: COMPILER=clang++-3.7 BUILD_TYPE=Release ASan=true 52 | addons: *clang37 53 | 54 | # clang 3.7, release build, valgrind 55 | - env: COMPILER=clang++-3.7 BUILD_TYPE=Release Valgrind=true 56 | addons: *clang37 57 | 58 | # clang 3.7, release build 59 | - env: COMPILER=clang++-3.7 BUILD_TYPE=Release 60 | addons: *clang37 61 | 62 | # GCC 5, debug build 63 | - env: COMPILER=g++-5 BUILD_TYPE=Debug 64 | addons: &gcc5 65 | apt: 66 | packages: 67 | - g++-5 68 | - valgrind 69 | sources: 70 | - ubuntu-toolchain-r-test 71 | 72 | # GCC 5, release build, valgrind 73 | - env: COMPILER=g++-5 BUILD_TYPE=Release Valgrind=true 74 | addons: *gcc5 75 | 76 | # Site generation job 77 | # 78 | # We define it here instead of in matrix.include because otherwise we end up 79 | # with a job without environment variables within the matrix. 80 | env: 81 | global: 82 | # GitHub token for pushing the documentation, logging in with the 83 | # Travis command line utility and so on. The token is stored in the 84 | # ${GITHUB_TOKEN} environment variable. 85 | - secure: "Qlsp65HRdMW5UWfta/ZoynOnWQFMeVwxE7XU9yF1VnQXxpTEJFfgPY93ikPWX2NV9Hs53RwIwXD60cKXw6rMlqKIPMCrfG0zvJSmSjbP61IRat3jNmpXb6d4R855nk1AOlU6qJdEYtC0uuFYVe1p7XUEaUsEX+r1NKoiO2vg4Tc+zIIQdMEo5lWpH+XxkLipCq+9J9w4YY9phffkL3hPI9CM3tQtjv2l0XMcpKDRLdFXuBEh48yoyD6vf8b4XCVpn3rWw2PGSNLrUm2lCuYJwB5nlNhBSoTu/abNwpt7k69fcRmpGfVZsAyC0xp17ER1Qh5d79uzRZZvC+/H4TblI/djgfpFbGA+aRPe3uNJeOMJatbz3FoGrOkAvQ1thTB+hw+oNI7Z/Y/tS9OuOhVOEoJ3pysx7h2YdRGRprcOkRa39LBeABCsdgLd9IucsbxmJg76yeHWssldK6Tag7mVifOmnegaS0K8JcEXnhjiua98By1+4gtI8GFBynsd90tD5Miv/e9Q0FFM86B+Zf7FMauUQAeoXipqqsG/68+WynyKsbdxQPBHoZlMrmu+Bsma1k2rgg+D4TARC9cNCIkRuDg7nc4dyGS3r1IdeomzWpwU4C4kKudBo4tKRoUB9zaAn47iYqBWk2Q8y+dOlxR/l2mYM5yEkRqyPGxG+v2O/NI=" 86 | matrix: 87 | - COMPILER=clang++-3.7 BUILD_TYPE=Debug Coverage=true Site=true 88 | addons: 89 | apt: 90 | packages: 91 | - clang-3.7 92 | # Not allowed yet: 93 | #- python-yaml 94 | #- lcov 95 | sources: 96 | - ubuntu-toolchain-r-test 97 | - llvm-toolchain-precise # latest 98 | 99 | install: 100 | ############################################################################ 101 | # All the dependencies are installed to the deps/ subdirectory. 102 | ############################################################################ 103 | - DEPS_DIR="${PWD}/deps" 104 | - mkdir ${DEPS_DIR} && cd ${DEPS_DIR} 105 | 106 | ############################################################################ 107 | # Install a recent CMake 108 | ############################################################################ 109 | - CMAKE_URL=http://www.cmake.org/files/v3.2/cmake-3.2.1-Linux-x86_64.tar.gz 110 | - mkdir cmake 111 | - travis_retry wget --quiet -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C cmake 112 | - export PATH=${PWD}/cmake/bin:${PATH} 113 | 114 | ############################################################################ 115 | # Install libc++ and libc++abi 116 | ############################################################################ 117 | - if [[ "${COMPILER}" =~ clang.+ ]]; then LLVM_URL="https://github.com/llvm-mirror/llvm/archive/master.tar.gz"; fi 118 | - if [[ "${COMPILER}" =~ clang.+ ]]; then LIBCXX_URL="https://github.com/llvm-mirror/libcxx/archive/master.tar.gz"; fi 119 | - if [[ "${COMPILER}" =~ clang.+ ]]; then LIBCXXABI_URL="https://github.com/llvm-mirror/libcxxabi/archive/master.tar.gz"; fi 120 | - if [[ "${COMPILER}" =~ clang.+ ]]; then TAR_FMT="-xz"; fi 121 | 122 | - if [[ "${COMPILER}" =~ clang.+ ]]; then mkdir -p llvm llvm/build llvm/projects/libcxx llvm/projects/libcxxabi; fi 123 | - if [[ "${COMPILER}" =~ clang.+ ]]; then travis_retry wget --quiet -O - ${LLVM_URL} | tar --strip-components=1 ${TAR_FMT} -C llvm; fi 124 | - if [[ "${COMPILER}" =~ clang.+ ]]; then travis_retry wget --quiet -O - ${LIBCXX_URL} | tar --strip-components=1 ${TAR_FMT} -C llvm/projects/libcxx; fi 125 | - if [[ "${COMPILER}" =~ clang.+ ]]; then travis_retry wget --quiet -O - ${LIBCXXABI_URL} | tar --strip-components=1 ${TAR_FMT} -C llvm/projects/libcxxabi; fi 126 | - if [[ "${COMPILER}" =~ clang.+ ]]; then (cd llvm/build && cmake .. -DCMAKE_CXX_COMPILER=${COMPILER} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} && make cxx -j2); fi 127 | 128 | ############################################################################ 129 | # Install a recent Doxygen 130 | ############################################################################ 131 | - if [[ "${Site}" == "true" ]]; then DOXYGEN_URL="http://ftp.stack.nl/pub/users/dimitri/doxygen-1.8.9.1.linux.bin.tar.gz"; fi 132 | - if [[ "${Site}" == "true" ]]; then mkdir doxygen && travis_retry wget --quiet -O - ${DOXYGEN_URL} | tar --strip-components=1 -xz -C doxygen; fi 133 | - if [[ "${Site}" == "true" ]]; then export PATH=${PWD}/doxygen/bin:${PATH}; fi 134 | 135 | ############################################################################ 136 | # Install and use a more recent Ruby and install the gems for the benchmarks 137 | ############################################################################ 138 | #- rvm use 2.1 --install --binary --fuzzy 139 | #- gem install ruby-progressbar tilt 140 | 141 | before_script: 142 | ############################################################################ 143 | # Go back to the root of the project. 144 | ############################################################################ 145 | - cd ${TRAVIS_BUILD_DIR} 146 | 147 | ############################################################################ 148 | # Set the git identity (for pushing the documentation and the benchmarks) 149 | ############################################################################ 150 | - git config --global user.name "Travis bot" 151 | 152 | ############################################################################ 153 | # Check baseline memory usage; useful to know when OOMs occur 154 | ############################################################################ 155 | - free 156 | - vmstat 157 | - ps aux --sort=-rss | head -n 10 158 | 159 | ############################################################################ 160 | # Travis VMs do not support anything higher than SSE 4.2 161 | ############################################################################ 162 | - sed -i 's/march=native/msse4.2/' CMakeLists.txt 163 | 164 | ############################################################################ 165 | # Setup the build directory 166 | ############################################################################ 167 | - mkdir build 168 | - cd build 169 | # Export the path to libc++ 170 | - if [[ "${COMPILER}" =~ clang.+ ]]; then export CXXFLAGS="-I ${DEPS_DIR}/llvm/build/include/c++/v1"; fi 171 | - if [[ "${COMPILER}" =~ clang.+ ]]; then export LDFLAGS="-L ${DEPS_DIR}/llvm/build/lib -l c++ -l c++abi"; fi 172 | - if [[ "${COMPILER}" =~ clang.+ ]]; then export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${DEPS_DIR}/llvm/build/lib"; fi 173 | 174 | # We only use the memory checker for some builds, because otherwise it takes 175 | # too long for very little benefit. Concretely, if we have a memory leak or 176 | # something like that, it's either a compiler bug or an error that will show 177 | # up regardless of the Boost version. Hence, we use the memory checker only 178 | # once for each compiler. 179 | - cmake .. -DCMAKE_CXX_COMPILER=${COMPILER} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DPROJECT_NAME_ENABLE_WERROR=ON 180 | - if [[ "${Valgrind}" == "true" ]]; then cmake .. -DPROJECT_NAME_ENABLE_VALGRIND=ON; fi 181 | - if [[ "${ASan}" == "true" ]]; then cmake .. -DPROJECT_NAME_ENABLE_ASAN=ON; fi 182 | 183 | script: 184 | ############################################################################ 185 | # Build the documentation 186 | ############################################################################ 187 | - if [[ "${Site}" == "true" ]]; then make doc; fi 188 | 189 | ############################################################################ 190 | # - Compile with code coverage 191 | ############################################################################ 192 | - if [[ "${Coverage}" == "true" ]]; then cmake .. -DPROJECT_NAME_ENABLE_COVERAGE=ON; fi 193 | 194 | ############################################################################ 195 | # Build and run the unit tests and examples. 196 | ############################################################################ 197 | - make tests -k -j2 198 | - make examples -k -j2 &>/dev/null 199 | - if [[ "${Valgrind}" != "true" ]]; then make check -k; fi 200 | - if [[ "${Valgrind}" == "true" ]]; then ctest -VV -D ExperimentalMemCheck; fi 201 | 202 | after_success: 203 | ############################################################################ 204 | # Update coveralls: 205 | # - download and install lcov, and coveralls-lcov. 206 | # - run lcov to generate coverage report 207 | # - strip test/ and example/ subdirectories from coverage report 208 | # - upload report to coveralls 209 | ############################################################################ 210 | - if [[ "${Coverage}" == "true" ]]; then export NAME=cpp_skeleton; fi 211 | - if [[ "${Coverage}" == "true" ]]; then sudo apt-get install -qq python-yaml lcov; fi 212 | - if [[ "${Coverage}" == "true" ]]; then gem install coveralls-lcov; fi 213 | - if [[ "${Coverage}" == "true" ]]; then lcov --directory ./ --base-directory ./ --capture --output-file coverage.info; fi 214 | - if [[ "${Coverage}" == "true" ]]; then lcov --remove coverage.info "/usr*" "*/$NAME/test/*" "*/$NAME/example/*" -o coverage.info; fi 215 | - if [[ "${Coverage}" == "true" ]]; then coveralls-lcov coverage.info; fi 216 | 217 | ############################################################################ 218 | # Update the documentation 219 | ############################################################################ 220 | - if [[ "${Site}" == "true" && "${TRAVIS_PULL_REQUEST}" == "false" && "${TRAVIS_BRANCH}" == "master" ]]; then make gh-pages.push; fi # &>/dev/null; fi 221 | 222 | 223 | #notifications: 224 | # webhooks: 225 | # urls: https://webhooks.gitter.im/e/ce1e3a2036d94b4a644f 226 | # on_success: change 227 | # on_failure: always 228 | 229 | notifications: 230 | email: false -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright Louis Dionne 2015 2 | # Distributed under the Boost Software License, Version 1.0. 3 | # (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) 4 | 5 | ############################################################################## 6 | # Setup project 7 | ############################################################################## 8 | project(project_name CXX) 9 | cmake_minimum_required(VERSION 3.0) 10 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") 11 | enable_testing() 12 | 13 | 14 | ############################################################################## 15 | # Setup CMake options 16 | ############################################################################## 17 | include(CMakeDependentOption) 18 | option(PROJECT_NAME_ENABLE_VALGRIND "Run the unit tests and examples under Valgrind if it is found." OFF) 19 | option(PROJECT_NAME_ENABLE_ASAN "Run the unit tests and examples using AddressSanitizer." OFF) 20 | option(PROJECT_NAME_ENABLE_COVERAGE "Run the unit tests and examples with code coverage instrumentation." OFF) 21 | option(PROJECT_NAME_ENABLE_WERROR "Fail and stop if a warning is triggered." OFF) 22 | option(PROJECT_NAME_ENABLE_DEBUG_INFORMATION "Includes debug information in the binaries." OFF) 23 | option(PROJECT_NAME_ENABLE_ASSERTIONS "Enables assertions." OFF) 24 | 25 | ############################################################################## 26 | # Setup compiler flags (more can be set on a per-target basis or in subdirectories) 27 | ############################################################################## 28 | # Compiler flags: 29 | include(CheckCXXCompilerFlag) 30 | macro(project_name_append_flag testname flag) 31 | check_cxx_compiler_flag(${flag} ${testname}) 32 | if (${testname}) 33 | add_compile_options(${flag}) 34 | endif() 35 | endmacro() 36 | 37 | # Language flag: version of the C++ standard to use 38 | project_name_append_flag(PROJECT_NAME_HAS_STDCXX14 -std=c++14) 39 | 40 | # PITA warning flags: 41 | project_name_append_flag(PROJECT_NAME_HAS_WSHADOW -Wshadow) 42 | project_name_append_flag(PROJECT_NAME_HAS_WUNUSED -Wunused) 43 | project_name_append_flag(PROJECT_NAME_HAS_WUNUSED_FUNCTION -Wunused-function) 44 | project_name_append_flag(PROJECT_NAME_HAS_WUNUSED_LABEL -Wunused-label) 45 | project_name_append_flag(PROJECT_NAME_HAS_WUNUSED_PARAMETER -Wunused-parameter) 46 | project_name_append_flag(PROJECT_NAME_HAS_WUNUSED_VALUE -Wunused-value) 47 | project_name_append_flag(PROJECT_NAME_HAS_WUNUSED_VARIABLE -Wunused-variable) 48 | 49 | # Warning flags: 50 | project_name_append_flag(PROJECT_NAME_HAS_WALL -Wall) 51 | project_name_append_flag(PROJECT_NAME_HAS_WEXTRA -Wextra) 52 | project_name_append_flag(PROJECT_NAME_HAS_WDEPRECATED -Wdeprecated) 53 | project_name_append_flag(PROJECT_NAME_HAS_WDOCUMENTATION -Wdocumentation) 54 | project_name_append_flag(PROJECT_NAME_HAS_WCOMMENT -Wcomment) 55 | project_name_append_flag(PROJECT_NAME_HAS_PEDANTIC -Wpedantic) 56 | project_name_append_flag(PROJECT_NAME_HAS_WSTACK_PROTECTOR -Wstack-protector) 57 | project_name_append_flag(PROJECT_NAME_HAS_WSTRICT_ALIASING "-Wstrict-aliasing=2") 58 | project_name_append_flag(PROJECT_NAME_HAS_WSTRICT_OVERFLOW "-Wstrict-overflow=5") 59 | project_name_append_flag(PROJECT_NAME_HAS_WDISABLED_OPTIMIZATION -Wdisabled-optimization) 60 | project_name_append_flag(PROJECT_NAME_HAS_WINLINE -Winline) 61 | project_name_append_flag(PROJECT_NAME_HAS_WRETURN_TYPE -Wreturn-type) 62 | project_name_append_flag(PROJECT_NAME_HAS_WCAST_ALIGN -Wcast-align) 63 | project_name_append_flag(PROJECT_NAME_HAS_WCAST_QUAL -Wcast-qual) 64 | project_name_append_flag(PROJECT_NAME_HAS_WSIGN_COMPARE -Wsign-compare) 65 | project_name_append_flag(PROJECT_NAME_HAS_WSIGN_PROMO -Wsign-promo) 66 | project_name_append_flag(PROJECT_NAME_HAS_WFORMAT "-Wformat=2") 67 | project_name_append_flag(PROJECT_NAME_HAS_WFORMAT_NONLITERAL -Wformat-nonliteral) 68 | project_name_append_flag(PROJECT_NAME_HAS_WFORMAT_SECURITY -Wformat-security) 69 | project_name_append_flag(PROJECT_NAME_HAS_WFORMAT_Y2K -Wformat-y2k) 70 | project_name_append_flag(PROJECT_NAME_HAS_WMISSING_BRACES -Wmissing-braces) 71 | project_name_append_flag(PROJECT_NAME_HAS_WMISSING_FIELD_INITIALIZERS -Wmissing-field-initializers) 72 | #project_name_append_flag(PROJECT_NAME_HAS_WMISSING_INCLUDE_DIRS -Wmissing-include-dirs) 73 | project_name_append_flag(PROJECT_NAME_HAS_WOVERLOADED_VIRTUAL -Woverloaded-virtual) 74 | project_name_append_flag(PROJECT_NAME_HAS_WCHAR_SUBSCRIPTS -Wchar-subscripts) 75 | project_name_append_flag(PROJECT_NAME_HAS_WFLOAT_EQUAL -Wfloat-equal) 76 | project_name_append_flag(PROJECT_NAME_HAS_WPOINTER_ARITH -Wpointer-arith) 77 | project_name_append_flag(PROJECT_NAME_HAS_WINVALID_PCH -Winvalid-pch) 78 | project_name_append_flag(PROJECT_NAME_HAS_WIMPORT -Wimport) 79 | project_name_append_flag(PROJECT_NAME_HAS_WINIT_SELF -Winit-self) 80 | project_name_append_flag(PROJECT_NAME_HAS_WREDUNDANT_DECLS -Wredundant-decls) 81 | project_name_append_flag(PROJECT_NAME_HAS_WPACKED -Wpacked) 82 | project_name_append_flag(PROJECT_NAME_HAS_WPARENTHESES -Wparentheses) 83 | project_name_append_flag(PROJECT_NAME_HAS_WSEQUENCE_POINT -Wsequence-point) 84 | project_name_append_flag(PROJECT_NAME_HAS_WSWITCH -Wswitch) 85 | project_name_append_flag(PROJECT_NAME_HAS_WSWITCH_DEFAULT -Wswitch-default) 86 | project_name_append_flag(PROJECT_NAME_HAS_WTRIGRAPHS -Wtrigraphs) 87 | project_name_append_flag(PROJECT_NAME_HAS_WUNINITIALIZED -Wuninitialized) 88 | project_name_append_flag(PROJECT_NAME_HAS_WUNKNOWN_PRAGMAS -Wunknown-pragmas) 89 | project_name_append_flag(PROJECT_NAME_HAS_WUNREACHABLE_CODE -Wunreachable-code) 90 | project_name_append_flag(PROJECT_NAME_HAS_WVARIADIC_MACROS -Wvariadic-macros) 91 | project_name_append_flag(PROJECT_NAME_HAS_WVOLATILE_REGISTER_VAR -Wvolatile-register-var) 92 | project_name_append_flag(PROJECT_NAME_HAS_WWRITE_STRINGS -Wwrite-strings) 93 | project_name_append_flag(PROJECT_NAME_HAS_WNO_ATTRIBUTES -Wno-attributes) 94 | project_name_append_flag(PROJECT_NAME_HAS_WUNNEEDED_INTERNAL_DECLARATION -Wunneeded-internal-declaration) 95 | 96 | # Template diagnostic flags 97 | project_name_append_flag(PROJECT_NAME_HAS_FDIAGNOSTIC_SHOW_TEMPLATE_TREE -fdiagnostics-show-template-tree) 98 | project_name_append_flag(PROJECT_NAME_HAS_FTEMPLATE_BACKTRACE_LIMIT "-ftemplate-backtrace-limit=0") 99 | project_name_append_flag(PROJECT_NAME_HAS___EXTERN_ALWAYS_INLINE -D__extern_always_inline=inline) 100 | 101 | # Compiler flags controlled by CMake options above 102 | if (PROJECT_NAME_ENABLE_WERROR) 103 | project_name_append_flag(PROJECT_NAME_HAS_WERROR -Werror) 104 | project_name_append_flag(PROJECT_NAME_HAS_WX -WX) 105 | endif() 106 | 107 | if (PROJECT_NAME_ENABLE_ASAN) 108 | project_name_append_flag(PROJECT_NAME_HAS_SANITIZE "-fsanitize=address,integer,undefined,leak") 109 | project_name_append_flag(PROJECT_NAME_HAS_NO_OMIT_FRAME_POINTER -fno-omit-frame-pointer) 110 | project_name_append_flag(PROJECT_NAME_HAS_NO_SANITIZE "-fno-sanitize=unsigned-integer-overflow") 111 | else() 112 | project_name_append_flag(PROJECT_NAME_HAS_OMIT_FRAME_POINTER -fomit-frame-pointer) 113 | endif() 114 | 115 | if (PROJECT_NAME_ENABLE_DEBUG_INFORMATION) 116 | project_name_append_flag(PROJECT_NAME_HAS_G3 -g3) 117 | else() 118 | project_name_append_flag(PROJECT_NAME_HAS_G0 -g0) 119 | endif() 120 | 121 | if (NOT PROJECT_NAME_ENABLE_ASSERTIONS) 122 | project_name_append_flag(PROJECT_NAME_HAS_NDEBUG -DNDEBUG) 123 | endif() 124 | 125 | if (PROJECT_NAME_ENABLE_COVERAGE) 126 | if (CMAKE_BUILD_TYPE STREQUAL "Release") 127 | message(FATAL_ERROR "code coverage instrumentation requires CMAKE_BUILD_TYPE=Debug") 128 | endif() 129 | set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage") 130 | endif() 131 | 132 | # Optimization flags: debug 133 | if (CMAKE_BUILD_TYPE STREQUAL "Debug") 134 | project_name_append_flag(PROJECT_NAME_HAS_O0 -O0) 135 | project_name_append_flag(PROJECT_NAME_HAS_NO_INLINE -fno-inline) 136 | project_name_append_flag(PROJECT_NAME_HAS_STACK_PROTECTOR_ALL -fstack-protector-all) 137 | endif() 138 | 139 | # Optimization flags: release 140 | if (CMAKE_BUILD_TYPE STREQUAL "Release") 141 | project_name_append_flag(PROJECT_NAME_HAS_OFAST -Ofast) 142 | project_name_append_flag(PROJECT_NAME_HAS_MARCH_NATIVE "-march=native") 143 | project_name_append_flag(PROJECT_NAME_HAS_MTUNE_NATIVE "-mtune=native") 144 | project_name_append_flag(PROJECT_NAME_HAS_STRICT_ALIASING "-fstrict-aliasing") 145 | project_name_append_flag(PROJECT_NAME_HAS_VECTORIZE "-fvectorize") 146 | # Others could be: -pipe pfdata-sections -ffunction-sections 147 | # for clang: -mllvm -inline-threshold=X (X=1000, 10000, ...) 148 | endif() 149 | 150 | ############################################################################## 151 | # Search for packages. 152 | # 153 | # Behavior when the package is found or not is customized at the 154 | # point where the package is required. 155 | ############################################################################## 156 | 157 | # Git: parses current project commit 158 | find_package(Git) 159 | if (GIT_FOUND) 160 | execute_process( 161 | COMMAND ${GIT_EXECUTABLE} rev-parse --short HEAD 162 | OUTPUT_VARIABLE PROJECT_NAME_CURRENT_COMMIT 163 | OUTPUT_STRIP_TRAILING_WHITESPACE 164 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) 165 | endif() 166 | 167 | # Doxygen 168 | find_package(Doxygen) 169 | 170 | # Valgrid 171 | if (PROJECT_NAME_ENABLE_VALGRIND) 172 | find_program(MEMORYCHECK_COMMAND valgrind) 173 | if(MEMORYCHECK_COMMAND-NOTFOUND) 174 | message(FATAL_ERROR "valgrind not found") 175 | endif() 176 | set(MEMORYCHECK_COMMAND_OPTIONS "--trace-children=yes --leak-check=full") 177 | include(Dart) 178 | endif() 179 | 180 | #find_package(Boost) 181 | 182 | # find_package(Meta) 183 | # find_package(MPL11) 184 | # find_package(PythonInterp 2.7) 185 | # find_package(Ruby 2.1) 186 | 187 | 188 | # if (NOT ${Boost_FOUND}) 189 | # message(WARNING 190 | # "The Boost library headers were not found; targets depending " 191 | # "on Boost won't be available.") 192 | # endif() 193 | 194 | 195 | 196 | ############################################################################## 197 | # Setup the URL to the official repository on GitHub. 198 | # 199 | # If there is a GITHUB_TOKEN environment variable, we assume this token allows 200 | # us to push to the GitHub repository and we use that in the URL. This token 201 | # will give us push access for updating the 'gh-pages' branch and doing other 202 | # useful things e.g. from Travis. Otherwise, if there's no such environment 203 | # variable, the URL just refers to the GitHub repository without authentication. 204 | # In this case, we'll be asked for our username and password when/if we try to 205 | # push to the repository. 206 | ############################################################################## 207 | #if (DEFINED ENV{GITHUB_TOKEN}) 208 | # set(PROJECT_NAME_ORIGIN_URL "https://github_user:$ENV{GITHUB_TOKEN}@github.com/github_user/project_name") 209 | #else() 210 | # set(PROJECT_NAME_ORIGIN_URL "https://github.com/github_user/project_name") 211 | #endif() 212 | 213 | if (DEFINED ENV{GITHUB_TOKEN}) 214 | set(PROJECT_NAME_ORIGIN_URL "https://gnzlbg:$ENV{GITHUB_TOKEN}@github.com/gnzlbg/cpp_skeleton") 215 | else() 216 | set(PROJECT_NAME_ORIGIN_URL "https://github.com/gnzlbg/cpp_skeleton") 217 | endif() 218 | 219 | 220 | ############################################################################## 221 | # Setup custom functions to ease the creation of targets 222 | ############################################################################## 223 | # project_name_target_name_for( [ext]) 224 | # 225 | # Return the target name associated to a source file. If the path of the 226 | # source file relative from the root of project_name is `path/to/source/file.ext`, 227 | # the target name associated to it will be `path.to.source.file`. 228 | # 229 | # The extension of the file should be specified as a last argument. If no 230 | # extension is specified, the `.cpp` extension is assumed. 231 | function(project_name_target_name_for out file) 232 | if (NOT ARGV2) 233 | set(_extension ".cpp") 234 | else() 235 | set(_extension "${ARGV2}") 236 | endif() 237 | 238 | file(RELATIVE_PATH _relative ${project_name_SOURCE_DIR} ${file}) 239 | string(REPLACE "${_extension}" "" _name ${_relative}) 240 | string(REGEX REPLACE "/" "." _name ${_name}) 241 | set(${out} "${_name}" PARENT_SCOPE) 242 | endfunction() 243 | 244 | # project_name_add_test( [...]) 245 | # 246 | # Creates a test called `name`, which runs the given `command` with the given 247 | # `arg`uments. 248 | function(project_name_add_test name) 249 | add_test(${name} ${ARGN}) 250 | endfunction() 251 | 252 | # project_name_list_remove_glob( [globbing expressions]...) 253 | # 254 | # Generates a list of files matching the given glob expressions, and remove 255 | # the matched elements from the given . 256 | macro(project_name_list_remove_glob list glob) 257 | file(${glob} _bhlrg10321023_avoid_macro_clash_matches ${ARGN}) 258 | list(REMOVE_ITEM ${list} ${_bhlrg10321023_avoid_macro_clash_matches}) 259 | endmacro() 260 | 261 | 262 | ############################################################################## 263 | # Setup subdirectories 264 | ############################################################################## 265 | #add_subdirectory(benchmark) 266 | add_subdirectory(site) 267 | add_subdirectory(example) 268 | add_subdirectory(test) 269 | 270 | 271 | ############################################################################## 272 | # Setup the `check` target to build and then run all the tests and examples. 273 | ############################################################################## 274 | add_custom_target(check ALL 275 | COMMAND ${CMAKE_CTEST_COMMAND} --VV #--output-on-failure 276 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} 277 | DEPENDS tests examples 278 | COMMENT "Build and then run all the tests and examples.") 279 | 280 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright 2013-2015 Louis Dionne 2 | 3 | Boost Software License - Version 1.0 - August 17th, 2003 4 | 5 | Permission is hereby granted, free of charge, to any person or organization 6 | obtaining a copy of the software and accompanying documentation covered by this 7 | license (the "Software") to use, reproduce, display, distribute, execute, and 8 | transmit the Software, and to prepare derivative works of the Software, and to 9 | permit third-parties to whom the Software is furnished to do so, all subject to 10 | the following: 11 | 12 | The copyright notices in the Software and this entire statement, including the 13 | above license grant, this restriction and the following disclaimer, must be 14 | included in all copies of the Software, in whole or in part, and all derivative 15 | works of the Software, unless such copies or derivative works are solely in the 16 | form of machine-executable object code generated by a source language processor. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 20 | FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 21 | COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES 22 | OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 23 | OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # C++ Skeleton ![Build Status][badge.Travis] ![Coverage Status][badge.Coveralls] 2 | > Your standard C++ project skeleton 3 | 4 | ## Disclaimer 5 | 6 | > This is buggy and unfinished, use at your own risk! 7 | 8 | This project is a fork from [Hana][]'s build system, so all of the credit goes 9 | to [Louis Dione][] for the great work he is doing. It also steals some ideas 10 | from the build systems of [Paul Fultz II][] [FIT][]'s library and 11 | [Eric Niebler][]'s [range-v3][] library. It is released under the Boost Software 12 | license, but note that some of the libraries that are optionally provided might 13 | have a different license. 14 | 15 | ## Overview 16 | 17 | Setting up a modern C++ project with Continuous Integration is a time-consuming 18 | task. The amount of tools available is daunting, and one really wants to use 19 | them all: [CMake][], [gh-pages][] and [Doxygen][] for documentation, 20 | [Travis-CI][] for continuous integration, [Coveralls][] for displaying code 21 | coverage reports, [clang-format][] for auto-formatting, [valgrind][], 22 | [sanitizers][], [swang][], [static-analyzer][], and many more! 23 | 24 | The aim of this project is to give you a fully-functional starting point for 25 | your own projects, so that you can skip setting up most of these tools 26 | correctly. Every project is different tho, so we expect you to modify your build 27 | system over time. This skeleton is just there to give you the fundamentals, 28 | anything else is up to you! Send a PR if you find something is missing. 29 | 30 | ## What you get 31 | 32 | - [CMake][] as a meta-build system: 33 | - debug/release builds, 34 | - high-optimization for release builds, 35 | - extensive warnings enabled out-of-the-box, 36 | - support for running tests and examples with [valgrind][] and [AddressSanitizer][], 37 | - support for generating code coverage from tests and examples. 38 | - [Travis-CI][] is used for unit-testing: 39 | - compilers: [clang][]-3.7, [gcc][]-5.0, 40 | - test your code in debug/release, w/o [valgrind][], w/o [AddressSanitizer][], 41 | - uploads code coverage automatically to [Coveralls][]. 42 | - [Coveralls][] shows per-line code coverage. 43 | - Automatic [Doxygen][] documentation generation and deployment to [gh-pages][]. 44 | 45 | ## Getting started 46 | 47 | 1. Fork this repository and check-out your fork. 48 | 2. Add your repository to [Travis-CI][] and [Coveralls][]. 49 | 3. Run `bootstrap.py` script to configure it to your needs. 50 | - Replace the secure token with your own and create a gh-pages branch that is empty. 51 | 4. Commit your changes to your repository (including the gh-pages branch). 52 | 5. Start working on your project. 53 | 54 | ### CMake configuration options 55 | 56 | - `PROJECT_NAME_ENABLE_VALGRIND`: Run the unit tests and examples under [valgrind][] if it is found. 57 | - `PROJECT_NAME_ENABLE_ASAN`: Run the unit tests and examples using [AddressSanitizer][]. 58 | - `PROJECT_NAME_ENABLE_COVERAGE`: Run the unit tests and examples with code coverage instrumentation. 59 | - `PROJECT_NAME_ENABLE_WERROR`: Fail and stop if a warning is triggered. 60 | - `PROJECT_NAME_ENABLE_DEBUG_INFORMATION`: Includes debug information in the binaries. 61 | - `PROJECT_NAME_ENABLE_ASSERTIONS`: Enables assertions. 62 | 63 | ### CMake targets 64 | 65 | - `make`: Compiles top-level targets. 66 | - `make tests`: Compiles the tests. 67 | - `make examples`: Compiles the examples. 68 | - `make check`: Runs the test and the examples. 69 | - `make doc`: Generates the documentation. 70 | 71 | ## Directory structure 72 | 73 | The directory structure is as follows: 74 | 75 | ```text 76 | benchmark/ : Benchmarks (reserved for future usage) 77 | cmake/ : CMake files 78 | include/project_name/ : Project header files 79 | site/ : website (reserved for future usage) 80 | src/ : Source files (reserved for future usage) 81 | test/ : Unit-tests 82 | .clang-format : clang-format configuration 83 | .travis.yml : Travis-CI configuration 84 | .gitignore : With C++ defaults 85 | CMakeLists.txt : CMake configuration 86 | ``` 87 | 88 | ## What remains to be done 89 | 90 | - Targets to check the format and reformat your code automatically. 91 | - Semantic versioning. 92 | - Provide FindLib.cmake files for common libraries that automatically. 93 | get the last version from their repository: 94 | - [ASIO][], 95 | - [Catch][], 96 | - [cppformat][], 97 | - [docopt][], 98 | - [Eigen3][], 99 | - [Eggs.Variant][]. 100 | - [FIT][], 101 | - [folly][], 102 | - [Hana][], 103 | - [json][], 104 | - [meta][], 105 | - [range-v3][], 106 | - [spdlog][], 107 | - [Thread Building Blocks][]. 108 | - Benchmarking targets. 109 | - Performance tracking over git revisions (and automatic upload to gh-pages). 110 | - [static-analyzer][]. 111 | - [swang][]. 112 | - [ThreadSanitizer][]. 113 | 114 | 115 | [badge.Travis]: https://travis-ci.org/gnzlbg/cpp_skeleton.svg?branch=master 116 | [badge.Coveralls]: https://coveralls.io/repos/gnzlbg/cpp_skeleton/badge.svg 117 | [Hana]: https://github.com/ldionne/hana 118 | [Louis Dione]: http://ldionne.com/ 119 | [FIT]: https://github.com/pfultz2/Fit 120 | [Paul Fultz II]: http://pfultz2.com/blog/ 121 | [Eric Niebler]: http://ericniebler.com/ 122 | [range-v3]: https://github.com/ericniebler/range-v3 123 | [meta]: https://github.com/ericniebler/meta 124 | [Travis-CI]: https://travis-ci.org/ 125 | [Coveralls]: https://coveralls.io/ 126 | [CMake]: http://www.cmake.org/ 127 | [gh-pages]: https://pages.github.com/ 128 | [Doxygen]: http://www.stack.nl/~dimitri/doxygen/ 129 | [valgrind]: http://valgrind.org/ 130 | [AddressSanitizer]: http://clang.llvm.org/docs/AddressSanitizer.html 131 | [ThreadSanitizer]: http://clang.llvm.org/docs/ThreadSanitizer.html 132 | [sanitizers]: http://clang.llvm.org/docs/index.html 133 | [swang]: https://github.com/berenm/swang 134 | [static-analyzer]: http://clang-analyzer.llvm.org/ 135 | [clang]: http://clang.llvm.org/ 136 | [gcc]: https://gcc.gnu.org/ 137 | [Eggs.Variant]: https://github.com/eggs-cpp/variant 138 | [Eigen3]: http://eigen.tuxfamily.org/ 139 | [cppformat]: https://github.com/cppformat/cppformat 140 | [spdlog]: https://github.com/gabime/spdlog 141 | [FIT]: https://github.com/pfultz2/Fit 142 | [Thread Building Blocks]: https://www.threadingbuildingblocks.org/ 143 | [clang-format]: http://clang.llvm.org/docs/ClangFormat.html 144 | [Catch]: https://github.com/philsquared/Catch 145 | [ASIO]: https://think-async.com/ 146 | [docopt]: https://github.com/docopt/docopt.cpp 147 | [json]: https://github.com/nlohmann/json 148 | [folly]: https://github.com/facebook/folly 149 | -------------------------------------------------------------------------------- /bootstrap.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # TODO: 4 | # In /CMakeLists.txt 5 | # - replace "github_user" with your github's user name 6 | import sys 7 | import subprocess 8 | import argparse 9 | 10 | # List of files in which the project name should be replaced as is and in 11 | # capitalized form 12 | replace_project_name_files = ['CMakeLists.txt', 13 | 'test/CMakeLists.txt', 14 | 'example/CMakeLists.txt', 15 | 'include/project_name/project_name.hpp', 16 | 'include/project_name/test_header.hpp', 17 | 'include/project_name/component/component_header.hpp', 18 | 'test/test_b.cpp', 19 | 'test/component/test_a.cpp', 20 | '.travis.yml'] 21 | 22 | # Replaced `project_name` and `PROJECT_NAME` by the desired project_name 23 | # in the files specified in `replace_project_name_files` 24 | def apply_project_name(project_name): 25 | for file_path in replace_project_name_files: 26 | print("reading " + file_path) 27 | fstr = open(file_path).read() 28 | fstr = fstr.replace('project_name', project_name) 29 | fstr = fstr.replace('project_name_'.upper(), project_name.upper() + '_') 30 | fstr = fstr.replace('cpp_skeleton', project_name) 31 | fstr = fstr.replace('- ./bootstrap.py test_project', 32 | '#- ./bootstrap.py test_project # DISABLED IN USER PROJECTS') 33 | f = open(file_path, 'w') 34 | f.write(fstr) 35 | f.flush() 36 | f.close() 37 | 38 | subprocess.call(["git", "mv", 'include/project_name', 'include/' + project_name]) 39 | 40 | 41 | def main(argv=None): 42 | parser = argparse.ArgumentParser(description='Bootstrap a new C++ project.') 43 | parser.add_argument('project_name', help='The name of the project') 44 | 45 | args = parser.parse_args() 46 | apply_project_name(args.project_name) 47 | 48 | if __name__ == "__main__": 49 | sys.exit(main()) 50 | -------------------------------------------------------------------------------- /example/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright Louis Dionne 2015 2 | # Distributed under the Boost Software License, Version 1.0. 3 | # (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) 4 | 5 | ############################################################################## 6 | # Setup custom functions, master targets and file lists for the examples 7 | ############################################################################## 8 | add_custom_target(examples 9 | COMMENT "Build all the examples.") 10 | 11 | # Several examples have unused parameters because the name of the parameters 12 | # are useful for illustration, even if the implementation is not actually 13 | # presented. We don't want to generate warnings for that or need to comment 14 | # out all unused parameter names. 15 | project_name_append_flag(PROJECT_NAME_HAS_WNO_UNUSED_PARAMETER -Wno-unused-parameter) 16 | 17 | # project_name_add_example( ...) 18 | # 19 | # Equivalent to `project_name_add_test`, except the created test is also added 20 | # as a dependency of the `examples` target. 21 | function(project_name_add_example name) 22 | project_name_add_test(${ARGV}) 23 | add_dependencies(examples ${name}) 24 | endfunction() 25 | 26 | # A list of all the example files 27 | # 28 | # Examples that are not available due to caveats are removed 29 | # from this list below. 30 | file(GLOB_RECURSE PROJECT_NAME_EXAMPLE_SOURCES "${project_name_SOURCE_DIR}/example/*.cpp") 31 | 32 | ############################################################################## 33 | # Include directories 34 | ############################################################################## 35 | include_directories(${project_name_SOURCE_DIR}/include) 36 | 37 | ############################################################################## 38 | # Add all the examples 39 | ############################################################################## 40 | foreach(_file IN LISTS PROJECT_NAME_EXAMPLE_SOURCES) 41 | project_name_target_name_for(_target "${_file}") 42 | add_executable(${_target} EXCLUDE_FROM_ALL "${_file}") 43 | project_name_add_example(${_target} ${CMAKE_CURRENT_BINARY_DIR}/${_target}) 44 | endforeach() -------------------------------------------------------------------------------- /example/a.cpp: -------------------------------------------------------------------------------- 1 | int main() { return 0; } 2 | -------------------------------------------------------------------------------- /include/project_name/component/component_header.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /// \file component_header.hpp Another header file 3 | /// 4 | /// Detailed documentation of the file goes here 5 | 6 | namespace project_name { 7 | 8 | inline namespace v1 { 9 | namespace component { 10 | 11 | /// B struct 12 | struct B { 13 | float a; ///< A float 14 | int b; ///< An int 15 | }; 16 | 17 | /// Returns the value of B::b incremented by 1 18 | int bar(B b) { return b.b + 1; } 19 | 20 | } // namespace component 21 | 22 | } // namespace v1 23 | 24 | } // namespace project_name 25 | -------------------------------------------------------------------------------- /include/project_name/project_name.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /// \file project_name.hpp Includes all header files for the project 3 | #include 4 | #include 5 | 6 | /*! 7 | @mainpage User Manual 8 | 9 | @tableofcontents 10 | 11 | @section tutorial-description Description 12 | 13 | ------------------------------------------------------------------------------ 14 | This is the description of the project_name project. 15 | 16 | @section another-section Another section 17 | 18 | ------------------------------------------------------------------------------ 19 | Another section. 20 | 21 | 22 | */ 23 | -------------------------------------------------------------------------------- /include/project_name/test_header.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /// \file test_header.hpp A header file 3 | 4 | /// Project namespace 5 | /// 6 | /// All the code is in this namespace 7 | namespace project_name { 8 | 9 | /// Version 1 of the project 10 | /// 11 | /// Inline namespaces allow providing different versions of the code 12 | /// without breaking the ABI. 13 | inline namespace v1 { 14 | /// A struct (brief documentation goes in the first paragraph) 15 | /// 16 | /// Detailed documentation follows 17 | struct A { 18 | int a; ///< Inline documentation for member a 19 | float b; ///< Member b 20 | }; 21 | 22 | /// Returns the value of A::a incremented by 1 23 | int foo(A a) { return a.a + 1; } 24 | 25 | } // namespace v1 26 | } // namespace project_name 27 | -------------------------------------------------------------------------------- /site/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright Louis Dionne 2015 2 | # Distributed under the Boost Software License, Version 1.0. 3 | # (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) 4 | 5 | ############################################################################## 6 | # Setup the documentation 7 | ############################################################################## 8 | if (NOT DOXYGEN_FOUND) 9 | message(WARNING "Doxygen was not found; the 'doc' and the various " 10 | "'gh-pages.*' targets will be unavailable.") 11 | return() 12 | endif() 13 | 14 | configure_file(Doxyfile.in Doxyfile @ONLY) 15 | add_custom_target(doc 16 | COMMAND ! ${DOXYGEN_EXECUTABLE} Doxyfile 2>&1 | grep "warning" | grep -v -e "recursive" 17 | COMMENT "Generating API documentation with Doxygen" 18 | VERBATIM 19 | ) 20 | 21 | if (NOT GIT_FOUND) 22 | message(WARNING "Git was not found; the various 'gh-pages.*' targets will be unavailable.") 23 | return() 24 | endif() 25 | 26 | add_custom_target(gh-pages.clone 27 | COMMAND [ -e ${CMAKE_SOURCE_DIR}/site/gh-pages ] || ${GIT_EXECUTABLE} clone ${PROJECT_NAME_ORIGIN_URL} --depth 1 --branch=gh-pages site/gh-pages 28 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} 29 | COMMENT "Cloning the gh-pages branch into the site/gh-pages directory" 30 | VERBATIM 31 | ) 32 | 33 | add_custom_target(gh-pages.clean 34 | COMMAND ${CMAKE_COMMAND} -E remove *.png *.css *.js *.html 35 | COMMAND ${CMAKE_COMMAND} -E remove_directory search 36 | WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/gh-pages 37 | DEPENDS gh-pages.clone 38 | COMMENT "Cleaning up site/gh-pages" 39 | VERBATIM 40 | ) 41 | 42 | add_custom_target(gh-pages.copy 43 | COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_BINARY_DIR}/html ${CMAKE_CURRENT_LIST_DIR}/gh-pages 44 | WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/gh-pages 45 | COMMENT "Copying the documentation from ${CMAKE_CURRENT_BINARY_DIR}/html to site/gh-pages" 46 | DEPENDS doc gh-pages.clean 47 | VERBATIM 48 | ) 49 | 50 | add_custom_target(gh-pages.update 51 | COMMAND ${GIT_EXECUTABLE} add --all . 52 | COMMAND ${GIT_EXECUTABLE} commit --allow-empty -m "Update to ${PROJECT_NAME_CURRENT_COMMIT}" 53 | WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/gh-pages 54 | COMMENT "Updating the gh-pages clone with freshly built documentation" 55 | DEPENDS gh-pages.copy 56 | VERBATIM 57 | ) 58 | 59 | add_custom_target(gh-pages.push 60 | COMMAND ${GIT_EXECUTABLE} push origin gh-pages 61 | WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/gh-pages 62 | COMMENT "Pushing the gh-pages branch to GitHub" 63 | DEPENDS gh-pages.update 64 | VERBATIM 65 | ) -------------------------------------------------------------------------------- /site/Doxyfile.in: -------------------------------------------------------------------------------- 1 | PROJECT_NAME = "project_name" 2 | PROJECT_BRIEF = "Brief description of your project" 3 | PROJECT_LOGO = 4 | PROJECT_NUMBER = 5 | 6 | STRIP_FROM_PATH = @project_name_SOURCE_DIR@/include 7 | BUILTIN_STL_SUPPORT = YES 8 | STRIP_FROM_INC_PATH = @project_name_SOURCE_DIR@/include 9 | ALIASES = 10 | ENABLED_SECTIONS = 11 | 12 | # Resources 13 | OUTPUT_DIRECTORY = 14 | INPUT = @project_name_SOURCE_DIR@/include 15 | FILE_PATTERNS = *.hpp 16 | RECURSIVE = YES 17 | EXCLUDE = 18 | EXCLUDE_PATTERNS = *.erb* 19 | EXAMPLE_PATH = @project_name_SOURCE_DIR@/example \ 20 | @project_name_SOURCE_DIR@/test 21 | EXAMPLE_RECURSIVE = YES 22 | IMAGE_PATH = 23 | WARN_IF_UNDOCUMENTED = NO 24 | 25 | SHOW_GROUPED_MEMB_INC = YES 26 | BRIEF_MEMBER_DESC = YES 27 | REPEAT_BRIEF = YES 28 | ALWAYS_DETAILED_SEC = NO 29 | INLINE_INHERITED_MEMB = NO 30 | JAVADOC_AUTOBRIEF = YES 31 | QT_AUTOBRIEF = YES 32 | MULTILINE_CPP_IS_BRIEF = YES 33 | INHERIT_DOCS = NO 34 | SEPARATE_MEMBER_PAGES = NO 35 | DISTRIBUTE_GROUP_DOC = NO 36 | SUBGROUPING = NO 37 | INLINE_GROUPED_CLASSES = NO 38 | INLINE_SIMPLE_STRUCTS = NO 39 | 40 | # Generated formats 41 | GENERATE_HTML = YES 42 | GENERATE_LATEX = NO 43 | 44 | 45 | GENERATE_TODOLIST = YES 46 | GENERATE_TESTLIST = YES 47 | GENERATE_BUGLIST = YES 48 | GENERATE_DEPRECATEDLIST = YES 49 | SHOW_USED_FILES = NO 50 | SHOW_FILES = YES 51 | SHOW_NAMESPACES = YES 52 | LAYOUT_FILE = @project_name_SOURCE_DIR@/site/layout.xml 53 | 54 | 55 | CLASS_DIAGRAMS = YES 56 | HAVE_DOT = NO 57 | 58 | HIDE_UNDOC_RELATIONS = NO 59 | HIDE_UNDOC_MEMBERS = YES 60 | HIDE_UNDOC_CLASSES = YES 61 | HIDE_FRIEND_COMPOUNDS = NO 62 | HIDE_IN_BODY_DOCS = NO 63 | INTERNAL_DOCS = YES 64 | HIDE_SCOPE_NAMES = NO 65 | SHOW_INCLUDE_FILES = NO 66 | FORCE_LOCAL_INCLUDES = NO 67 | INLINE_INFO = NO 68 | SORT_MEMBER_DOCS = NO 69 | SORT_BRIEF_DOCS = NO 70 | SORT_MEMBERS_CTORS_1ST = NO 71 | SORT_GROUP_NAMES = NO 72 | SORT_BY_SCOPE_NAME = YES 73 | 74 | 75 | ALPHABETICAL_INDEX = NO 76 | COLS_IN_ALPHA_INDEX = 1 77 | 78 | # Preprocessing 79 | ENABLE_PREPROCESSING = YES 80 | MACRO_EXPANSION = YES 81 | EXPAND_ONLY_PREDEF = NO 82 | SEARCH_INCLUDES = YES 83 | INCLUDE_PATH = @project_name_SOURCE_DIR@/include 84 | INCLUDE_FILE_PATTERNS = 85 | PREDEFINED = project_name_DOXYGEN_INVOKED 86 | SKIP_FUNCTION_MACROS = NO 87 | 88 | # Source browsing 89 | SOURCE_BROWSER = NO 90 | INLINE_SOURCES = NO 91 | STRIP_CODE_COMMENTS = YES 92 | REFERENCED_BY_RELATION = YES 93 | REFERENCES_RELATION = YES 94 | REFERENCES_LINK_SOURCE = YES 95 | USE_HTAGS = NO 96 | VERBATIM_HEADERS = NO 97 | # CLANG_ASSISTED_PARSING = NO 98 | # CLANG_OPTIONS = 99 | 100 | # HTML output 101 | HTML_OUTPUT = html 102 | HTML_FILE_EXTENSION = .html 103 | HTML_HEADER = @project_name_SOURCE_DIR@/site/header.html 104 | HTML_FOOTER = @project_name_SOURCE_DIR@/site/footer.html 105 | HTML_EXTRA_STYLESHEET = 106 | HTML_EXTRA_FILES = 107 | HTML_COLORSTYLE_HUE = 212 # 0 - 359 108 | HTML_COLORSTYLE_SAT = 100 # 0 - 255 109 | HTML_COLORSTYLE_GAMMA = 1 110 | HTML_TIMESTAMP = NO 111 | HTML_DYNAMIC_SECTIONS = YES 112 | HTML_INDEX_NUM_ENTRIES = 0 # Fully expand trees in the Indexes by default 113 | DISABLE_INDEX = YES 114 | GENERATE_TREEVIEW = YES 115 | TREEVIEW_WIDTH = 270 116 | EXT_LINKS_IN_WINDOW = NO 117 | FORMULA_FONTSIZE = 10 118 | FORMULA_TRANSPARENT = YES 119 | SEARCHENGINE = YES 120 | 121 | # Mathjax (HTML only) 122 | USE_MATHJAX = YES 123 | MATHJAX_FORMAT = HTML-CSS 124 | MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest 125 | MATHJAX_EXTENSIONS = 126 | MATHJAX_CODEFILE = -------------------------------------------------------------------------------- /site/footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 11 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /site/header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | $projectname: $title 9 | $title 10 | 11 | 12 | 13 | $treeview 14 | $search 15 | $mathjax 16 | 17 | 18 | $extrastylesheet 19 | 20 | 21 |
22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 38 | 39 | 40 | 41 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 |
33 |
$projectname 34 |  $projectnumber 35 |
36 |
$projectbrief
37 |
42 |
$projectbrief
43 |
$searchbox
54 |
55 | 56 | 57 | -------------------------------------------------------------------------------- /site/layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 11 | 12 | 13 | 17 | 19 | 20 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright Louis Dionne 2015 2 | # Distributed under the Boost Software License, Version 1.0. 3 | # (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) 4 | 5 | ############################################################################## 6 | # Setup custom functions, master targets and file lists for the unit tests 7 | ############################################################################## 8 | add_custom_target(test.headers 9 | COMMENT "Build all the header-inclusion unit tests.") 10 | 11 | add_custom_target(tests 12 | DEPENDS test.headers 13 | COMMENT "Build all the unit tests.") 14 | 15 | # project_name_add_unit_test( ...) 16 | # 17 | # Equivalent to `project_name_add_test`, except the test is also added as a 18 | # dependency of the `tests` target. 19 | function(project_name_add_unit_test name) 20 | project_name_add_test(${ARGV}) 21 | add_dependencies(tests ${name}) 22 | endfunction() 23 | 24 | # project_name_add_header_test() 25 | # 26 | # Add a unit test for the public header file `header-name`, which must be a 27 | # relative path from project_name's include directory, e.g. `project_name/project_name.hpp`. 28 | # 29 | # This function creates an executable named `header.header-name` and a test 30 | # of the same name. The only source file of the executable contains an empty 31 | # `main` and it includes the `header-name` file. This is used to make sure 32 | # that including any public header works properly. Also, the 33 | # `header.header-name` target is made a dependency of the `headers` target. 34 | function(project_name_add_header_test header) 35 | string(REGEX REPLACE "/" "." _target "${header}") 36 | if (NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}/header/${header}.cpp") 37 | file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/header/${header}.cpp" " 38 | #include <${header}> 39 | int main() { return 0; } 40 | ") 41 | endif() 42 | add_executable(test.header.${_target} EXCLUDE_FROM_ALL 43 | "${CMAKE_CURRENT_BINARY_DIR}/header/${header}.cpp") 44 | project_name_add_test(test.header.${_target} 45 | ${CMAKE_CURRENT_BINARY_DIR}/test.header.${_target}) 46 | add_dependencies(test.headers test.header.${_target}) 47 | endfunction() 48 | 49 | # A list of all the test files 50 | file(GLOB_RECURSE PROJECT_NAME_TEST_SOURCES "${project_name_SOURCE_DIR}/test/*.cpp") 51 | 52 | # A list of all the public headers 53 | file(GLOB_RECURSE PROJECT_NAME_PUBLIC_HEADERS "${project_name_SOURCE_DIR}/include/*.hpp") 54 | 55 | 56 | ############################################################################## 57 | # Include directories 58 | ############################################################################## 59 | include_directories(${project_name_SOURCE_DIR}/include) 60 | include_directories(${CMAKE_CURRENT_LIST_DIR}/include) 61 | include_directories(${CMAKE_CURRENT_LIST_DIR}) 62 | 63 | ############################################################################## 64 | # Generate tests that include each public header 65 | ############################################################################## 66 | foreach(_header IN LISTS PROJECT_NAME_PUBLIC_HEADERS) 67 | file(RELATIVE_PATH _relative "${project_name_SOURCE_DIR}/include" "${_header}") 68 | project_name_add_header_test("${_relative}") 69 | endforeach() 70 | 71 | ############################################################################## 72 | # Add all the unit tests 73 | ############################################################################## 74 | foreach(_file IN LISTS PROJECT_NAME_TEST_SOURCES) 75 | file(READ "${_file}" _contents) 76 | project_name_target_name_for(_target "${_file}") 77 | 78 | add_executable(${_target} EXCLUDE_FROM_ALL "${_file}") 79 | project_name_add_unit_test(${_target} ${CMAKE_CURRENT_BINARY_DIR}/${_target}) 80 | endforeach() -------------------------------------------------------------------------------- /test/component/test_a.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace project_name; 4 | 5 | int main() { 6 | component::B b{0, 0}; 7 | if (component::bar(b) == 1) { 8 | return 0; 9 | } else { 10 | return 1; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /test/test_b.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace project_name; 4 | 5 | int main() { 6 | A a{0, 1}; 7 | 8 | if (foo(a) == 1) { 9 | return 0; 10 | } else { 11 | return 1; 12 | } 13 | } 14 | --------------------------------------------------------------------------------