├── .clang-format ├── .clang-tidy ├── .github ├── ISSUE_TEMPLATE │ └── bug-report.md ├── pull_request_template.md └── workflows │ ├── ci.yml │ ├── conventional-commits.yml │ └── signed-commits.yml ├── .gitignore ├── .gitmodules ├── 01-cmake-basic-use ├── README.md ├── hello_world │ ├── CMakeLists.txt │ ├── hello │ │ ├── CMakeLists.txt │ │ └── main.cpp │ └── main.cpp ├── object │ ├── CMakeLists.txt │ ├── include │ │ └── my_lib.h │ └── src │ │ ├── main.cpp │ │ └── my_lib.cpp └── thread │ ├── CMakeLists.txt │ └── main.cpp ├── 02-static-dynamic-library ├── CMakeLists.txt ├── README.md ├── hello │ ├── CMakeLists.txt │ ├── hello.cpp │ └── hello.h ├── main │ ├── CMakeLists.txt │ └── main.cpp └── world │ ├── CMakeLists.txt │ ├── world.cpp │ └── world.h ├── 03-import-external-project ├── CMakeLists.txt ├── README.md ├── cmake │ └── spdlog.cmake └── spdlog_test.cpp ├── 05-testing ├── CMakeLists.txt ├── README.md ├── src │ ├── CMakeLists.txt │ └── main.cpp └── test │ ├── CMakeLists.txt │ ├── gtest_test.cpp │ └── gtest_test2.cpp ├── 06-optimize ├── CMakeLists.txt ├── README.md ├── hello.cpp └── world.h ├── ImportThirdParty.md ├── LICENSE ├── README.md ├── README_bak.md ├── README_bak_2.md ├── add_custom_command ├── CMakeLists.txt ├── Makefile ├── README.md └── main.cpp ├── add_dependencies ├── CMakeLists.txt ├── README.md └── main.cpp ├── c_cpp_combine ├── CMakeLists.txt ├── README.md ├── b.cpp ├── b.h └── main.c ├── cmake_advanced ├── CMakeLists.txt ├── define_test.cpp ├── fetch_content │ ├── CMakeLists.txt │ └── main.cpp ├── find_package │ ├── CMakeLists.txt │ ├── cmake │ │ └── Findleveldb.cmake │ └── main.cpp └── hello.cpp ├── find_package ├── CMakeLists.txt ├── README.md ├── main.cpp ├── main2.cpp └── main3.cpp ├── gtest ├── CMakeLists.txt ├── README.md ├── a_contain_b_test.cpp ├── cs │ └── client_server_test.cpp ├── gtest_test.cpp ├── inner_test.cpp └── non_virtual_method_test.cpp ├── target_compile_definitions ├── CMakeLists.txt ├── README.md ├── lib │ ├── CMakeLists.txt │ ├── mylib.cpp │ └── mylib.h └── main.cpp └── vcpkg ├── CMakeLists.txt ├── README.md ├── src └── main.cpp └── vcpkg.json /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: LLVM 2 | TabWidth: 4 3 | IndentWidth: 4 4 | UseTab: ForIndentation 5 | DerivePointerAlignment: false 6 | PointerAlignment: Right 7 | AlignConsecutiveMacros: true 8 | AlignTrailingComments: true 9 | AllowAllArgumentsOnNextLine: true 10 | AllowAllConstructorInitializersOnNextLine: true 11 | AllowAllParametersOfDeclarationOnNextLine: true 12 | AlignAfterOpenBracket: Align 13 | SpaceBeforeCpp11BracedList: true 14 | SpaceBeforeCtorInitializerColon: true 15 | SpaceBeforeInheritanceColon: true 16 | SpacesInAngles: false 17 | SpacesInCStyleCastParentheses: false 18 | SpacesInConditionalStatement: false 19 | AllowShortFunctionsOnASingleLine: false 20 | AllowShortLambdasOnASingleLine: Inline 21 | AllowShortLoopsOnASingleLine: false 22 | AlwaysBreakTemplateDeclarations: Yes 23 | ColumnLimit: 120 24 | IncludeBlocks: Regroup 25 | Language: Cpp 26 | AccessModifierOffset: -4 27 | -------------------------------------------------------------------------------- /.clang-tidy: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | # 18 | # Modified from the Apache Arrow project for the Terrier project. 19 | # 20 | --- 21 | Checks: ' 22 | bugprone-*, 23 | clang-analyzer-*, 24 | google-*, 25 | modernize-*, 26 | performance-*, 27 | portability-*, 28 | readability-*, 29 | -bugprone-easily-swappable-parameters, 30 | -bugprone-implicit-widening-of-multiplication-result, 31 | -bugprone-narrowing-conversions, 32 | -bugprone-reserved-identifier, 33 | -bugprone-signed-char-misuse, 34 | -bugprone-suspicious-include, 35 | -bugprone-unhandled-self-assignment, 36 | -clang-analyzer-cplusplus.NewDelete, 37 | -clang-analyzer-cplusplus.NewDeleteLeaks, 38 | -clang-analyzer-security.insecureAPI.rand, 39 | -clang-diagnostic-implicit-int-float-conversion, 40 | -google-readability-avoid-underscore-in-googletest-name, 41 | -modernize-avoid-c-arrays, 42 | -modernize-use-nodiscard, 43 | -readability-convert-member-functions-to-static, 44 | -readability-identifier-length, 45 | -readability-function-cognitive-complexity, 46 | -readability-magic-numbers, 47 | -readability-make-member-function-const, 48 | -readability-qualified-auto, 49 | -readability-redundant-access-specifiers, 50 | -bugprone-exception-escape, 51 | ' 52 | CheckOptions: 53 | - { key: readability-identifier-naming.ClassCase, value: CamelCase } 54 | - { key: readability-identifier-naming.EnumCase, value: CamelCase } 55 | - { key: readability-identifier-naming.FunctionCase, value: CamelCase } 56 | - { key: readability-identifier-naming.GlobalConstantCase, value: UPPER_CASE } 57 | - { key: readability-identifier-naming.MemberCase, value: lower_case } 58 | - { key: readability-identifier-naming.MemberSuffix, value: _ } 59 | - { key: readability-identifier-naming.NamespaceCase, value: lower_case } 60 | - { key: readability-identifier-naming.StructCase, value: CamelCase } 61 | - { key: readability-identifier-naming.UnionCase, value: CamelCase } 62 | - { key: readability-identifier-naming.VariableCase, value: lower_case } 63 | WarningsAsErrors: '*' 64 | HeaderFilterRegex: '/(src|test)/include' 65 | AnalyzeTemporaryDtors: true 66 | 67 | #### Disabled checks and why: ##### 68 | # 69 | # -readability-convert-member-functions-to-static, 70 | # This check started going off in the upgrade from clang-tidy-8 to clang-tidy-12. It is not always correct because 71 | # we hide the reference implementation in another repository. 72 | # -clang-analyzer-security.insecureAPI.rand, -clang-analyzer-security.insecureAPI.rand, -bugprone-unhandled-self-assignment, 73 | # -bugprone-implicit-widening-of-multiplication-result 74 | # These have not been investigated yet. 75 | # -bugprone-reserved-identifier, 76 | # Fails due to use of some __SHORT_FILE__ symbol, originating from very old code. 77 | # -bugprone-suspicious-include, 78 | # False positive due to GTest code. 79 | # -bugprone-too-small-loop-variable, 80 | # Complains about uint8_t or uint16_t when the limit on the loop is a container's .size() (size_t). 81 | # We usually do this when we know the maximum size of the container though, so propose leaving disabled. 82 | # -clang-analyzer-cplusplus.NewDelete, 83 | # Seems to generate false positives. Suggest relying on ASAN and valgrind for memory stuff. 84 | # -clang-analyzer-cplusplus.NewDeleteLeaks, 85 | # Seems to generate false positives. Suggest relying on ASAN and valgrind for memory stuff. 86 | # -modernize-use-nodiscard, 87 | # New C++17 feature, slightly polarizing. Would clutter codebase. 88 | # -modernize-avoid-c-arrays, 89 | # We use C-style arrays in page.h, type.h and logger.h. They're a little more ergonomic than std::array. Thoughts? 90 | # -readability-magic-numbers, 91 | # Let's not deal with people doing ridiculous things to hack around this. If it bites them, it bites them. 92 | # -bugprone-signed-char-misuse, -clang-diagnostic-implicit-int-float-conversion, -readability-make-member-function-const, 93 | # -readability-qualified-auto, -readability-redundant-access-specifiers 94 | # These were previously disabled for not being available in clang-tidy-8. They are now available on our clang-tidy-12, 95 | # and potentially worth investigating/fixing. 96 | # -bugprone-exception-escape 97 | # Weird. No idea how to resolve. 98 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "\U0001F41B Bug Report" 3 | about: Bug report 4 | --- 5 | 6 | ## Bug Report 7 | 8 | ### Minimal reproduce step 9 | 10 | 11 | 12 | ### Expected result 13 | 14 | ### Actual result 15 | 16 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## What's changed and how does it work? 4 | 5 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | pull_request: 7 | branches: [ "main" ] 8 | 9 | jobs: 10 | ut_coverage: 11 | runs-on: ubuntu-24.04 12 | name: Unit Tests - Coverage 13 | steps: 14 | 15 | - name: Check out repository 16 | uses: actions/checkout@v3 17 | 18 | - name: Install dependencies 19 | run: | 20 | cat /etc/lsb-release; 21 | sudo apt update; 22 | sudo apt install -y build-essential git cmake make gcc-13 g++-13; 23 | sudo apt install -y libaio-dev python3-pip cppcheck ninja-build; 24 | sudo apt install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu; 25 | sudo apt install -y curl zip unzip tar pkg-config; 26 | sudo apt install -y autoconf libtool; 27 | sudo ln -sf /usr/bin/cpp-13 /usr/bin/cpp; 28 | sudo ln -sf /usr/bin/g++-13 /usr/bin/g++; 29 | sudo ln -sf /usr/bin/gcc-13 /usr/bin/gcc; 30 | sudo ln -sf /usr/bin/gcc-ar-13 /usr/bin/gcc-ar; 31 | sudo ln -sf /usr/bin/gcc-nm-13 /usr/bin/gcc-nm; 32 | sudo ln -sf /usr/bin/gcc-ranlib-13 /usr/bin/gcc-ranlib; 33 | sudo ln -sf /usr/bin/gcov-13 /usr/bin/gcov; 34 | sudo ln -sf /usr/bin/gcov-dump-13 /usr/bin/gcov-dump; 35 | sudo ln -sf /usr/bin/gcov-tool-13 /usr/bin/gcov-tool; 36 | sudo ln -sf /usr/bin/lto-dump-13 /usr/bin/lto-dump; 37 | sudo ln -sf /usr/bin/g++-13 /usr/bin/c++; 38 | sudo ln -sf /usr/bin/gcc-13 /usr/bin/cc; 39 | pip3 install gcovr==6.0 --break-system-packages; 40 | sudo git clone https://github.com/Microsoft/vcpkg.git /opt/vcpkg; 41 | echo 'export VCPKG_ROOT=/opt/vcpkg' >> ~/.bashrc; 42 | echo 'export PATH=$VCPKG_ROOT:$PATH' >> ~/.bashrc; 43 | echo 'export VCPKG_FORCE_SYSTEM_BINARIES=1' >> ~/.bashrc; 44 | sudo rm -rf /var/lib/apt/lists/*; 45 | 46 | - name: Config project 47 | run: | 48 | export VCPKG_ROOT=/opt/vcpkg; 49 | export PATH=$VCPKG_ROOT:$PATH; 50 | export VCPKG_FORCE_SYSTEM_BINARIES=1; 51 | which vcpkg; 52 | cmake --preset debug_tsan; 53 | 54 | - name: Cppcheck 55 | run: cppcheck --project=build/debug_tsan/compile_commands.json -i tests --error-exitcode=1 56 | 57 | - name: Build project 58 | run: cmake --build build/debug_tsan -j `nproc` 59 | 60 | - name: Unit test with tsan 61 | run: TSAN_OPTIONS="suppressions=$(pwd)/tests/tsan.supp" ctest --test-dir build/debug_tsan --output-on-failure -j 2 62 | 63 | - name: Generate coverage file 64 | run: gcovr -v -r . --xml-pretty --xml=coverage.xml --exclude 'build/*' --exclude 'tests/*' --exclude 'benchmarks/*' --verbose 65 | 66 | - name: Upload coverage reports to Codecov 67 | uses: codecov/codecov-action@v3 68 | env: 69 | CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} 70 | with: 71 | files: coverage.xml 72 | verbose: true 73 | -------------------------------------------------------------------------------- /.github/workflows/conventional-commits.yml: -------------------------------------------------------------------------------- 1 | name: PR Check 2 | 3 | on: 4 | pull_request: 5 | types: [opened, synchronize, reopened, edited] 6 | 7 | jobs: 8 | build: 9 | name: Conventional Commits 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Conventional Commits Validation 13 | uses: ytanikin/PRConventionalCommits@1.1.0 14 | with: 15 | task_types: '["feat","fix","perf","chore","revert"]' 16 | add_label: 'false' -------------------------------------------------------------------------------- /.github/workflows/signed-commits.yml: -------------------------------------------------------------------------------- 1 | name: PR Check 2 | 3 | on: 4 | pull_request: 5 | types: [opened, synchronize, reopened, edited] 6 | 7 | jobs: 8 | check-signed-commits: 9 | name: Signed Commits 10 | runs-on: ubuntu-latest 11 | permissions: 12 | contents: read 13 | pull-requests: write 14 | steps: 15 | - name: Signed Commits Validation 16 | uses: 1Password/check-signed-commits-action@v1 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | */build/* 2 | .idea/* 3 | .vscode/* 4 | */cmake-build-debug/* 5 | */*/build -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | 2 | [submodule "gtest/googletest"] 3 | path = gtest/googletest 4 | url = https://gitee.com/mirrors/googletest.git 5 | -------------------------------------------------------------------------------- /01-cmake-basic-use/README.md: -------------------------------------------------------------------------------- 1 | # 第一章:CMake简单使用 2 | 3 | ## 目录结构 4 | ``` 5 | ├── CMakeLists.txt 6 | └── main.cpp 7 | ``` 8 | ## 内置函数 9 | - 生成可执行文件 10 | ``` 11 | add_executable(main main.cpp) 12 | ``` 13 | ## 内置宏 14 | - 设置编译类型 15 | ``` 16 | CMAKE_BUILD_TYPE "Release" 17 | ``` -------------------------------------------------------------------------------- /01-cmake-basic-use/hello_world/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | project(main) 3 | set(CMAKE_CXX_STANDARD 17) 4 | 5 | add_subdirectory(hello) 6 | 7 | add_executable(main main.cpp) -------------------------------------------------------------------------------- /01-cmake-basic-use/hello_world/hello/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | project(cmake_study) 3 | set(CMAKE_CXX_STANDARD 14) 4 | set(CMAKE_BUILD_TYPE Debug) 5 | add_executable(main main.cpp) -------------------------------------------------------------------------------- /01-cmake-basic-use/hello_world/hello/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | int main(){ 3 | std::cout<<"hello world!"< 2 | 3 | int main() { 4 | 5 | std::cout<<"hello world!"<) 10 | 11 | add_library(my_shared_lib SHARED $) 12 | 13 | add_executable(my_executable src/main.cpp $) 14 | 15 | -------------------------------------------------------------------------------- /01-cmake-basic-use/object/include/my_lib.h: -------------------------------------------------------------------------------- 1 | #ifndef MY_LIB_H 2 | #define MY_LIB_H 3 | 4 | void myFunction(); 5 | 6 | #endif // MY_LIB_H 7 | -------------------------------------------------------------------------------- /01-cmake-basic-use/object/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "my_lib.h" 2 | 3 | int main() { 4 | myFunction(); 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /01-cmake-basic-use/object/src/my_lib.cpp: -------------------------------------------------------------------------------- 1 | #include "my_lib.h" 2 | #include 3 | 4 | void myFunction() { 5 | std::cout << "Hello from myFunction in my_lib!" << std::endl; 6 | } 7 | -------------------------------------------------------------------------------- /01-cmake-basic-use/thread/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | project(main) 3 | set(CMAKE_CXX_STANDARD 17) 4 | 5 | find_package(Threads) 6 | add_executable(main main.cpp) 7 | target_link_libraries(main Threads::Threads) -------------------------------------------------------------------------------- /01-cmake-basic-use/thread/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | 5 | std::cout<<"hello world!"< 2 | 3 | void hello(); -------------------------------------------------------------------------------- /02-static-dynamic-library/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(main main.cpp) 2 | target_link_libraries( 3 | main 4 | hello 5 | world 6 | ) -------------------------------------------------------------------------------- /02-static-dynamic-library/main/main.cpp: -------------------------------------------------------------------------------- 1 | #include "../hello/hello.h" 2 | #include "../world/world.h" 3 | int main() { 4 | hello(); 5 | world(); 6 | return 0; 7 | } -------------------------------------------------------------------------------- /02-static-dynamic-library/world/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(world STATIC world.h world.cpp) -------------------------------------------------------------------------------- /02-static-dynamic-library/world/world.cpp: -------------------------------------------------------------------------------- 1 | #include "world.h" 2 | void world() { 3 | std::cout<<"world"< 2 | 3 | void world(); -------------------------------------------------------------------------------- /03-import-external-project/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | project(spdlog_test) 3 | set(CMAKE_CXX_STANDARD 17) 4 | 5 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake") 6 | include(spdlog) 7 | include_directories(${SPDLOG_INCLUDE_DIR}) 8 | add_executable(spdlog_test spdlog_test.cpp) 9 | add_dependencies(spdlog_test spdlog) 10 | target_link_libraries(spdlog_test PRIVATE ${SPDLOG_LIBRARIES}) -------------------------------------------------------------------------------- /03-import-external-project/README.md: -------------------------------------------------------------------------------- 1 | # 第三章:引入外部项目 2 | 3 | ## 1\. submodule 4 | 5 | - 把一个已有的仓库作为子模块添加到主项目中,如果子模块也有依赖,需要递归地拉取代码到本地。 6 | - 直接源码编译。 7 | 8 | ``` 9 | git submodule add git@gitee.com:roberchen/spdlog.git 10 | git submodule init 11 | git submodule update --init --recursive 12 | ``` 13 | 14 | - 移除子模块 15 | 16 | ``` 17 | git submodule deinit -f path/to/submodule 18 | git rm -f path/to/submodule 19 | rm -rf .git/modules/path/to/submodule 20 | ``` 21 | 22 | ## 2\. external_project 23 | 24 | - 在编译时下载项目并引入到主项目中 25 | 26 | ``` 27 | include(ExternalProject) 28 | ExternalProject_Add(SPDLOG 29 | PREFIX ${SPDLOG_ROOT} 30 | GIT_REPOSITORY ${SPDLOG_GIT_URL} 31 | GIT_TAG ${SPDLOG_GIT_TAG} 32 | CONFIGURE_COMMAND ${SPDLOG_CONFIGURE} 33 | BUILD_COMMAND ${SPDLOG_MAKE} 34 | INSTALL_COMMAND ${SPDLOG_INSTALL} 35 | ) 36 | ``` 37 | 38 | ## 3\. FetchContent 39 | 40 | ``` 41 | cmake_minimum_required(VERSION 3.16) 42 | project(gtest_test) 43 | set(CMAKE_CXX_STANDARD 17) 44 | include(FetchContent) 45 | FetchContent_Declare( 46 | googletest 47 | GIT_REPOSITORY https://github.com/google/googletest.git 48 | GIT_TAG v1.14.0 49 | ) 50 | FetchContent_MakeAvailable(googletest) 51 | 52 | add_executable(gtest_test gtest_test.cpp) 53 | target_link_libraries(gtest_test gtest_main) 54 | ``` 55 | 56 | ## 4\. find_package 57 | 58 | - 查找系统中安装好的三方包 59 | 60 | ``` 61 | find_package(GTest REQUIRED) 62 | target_link_libraries(gtest_test GTest::gtest GTest::gtest_main) 63 | ``` 64 | 65 | ## 5\. find_library 66 | 67 | - 给定路径查找 68 | 69 | ``` 70 | find_library(DB_LIBS 71 | NAMES duckdb 72 | PATHS /Users/yaojun/MyInstall/duckdb_install/usr/local/lib 73 | REQUIRED) 74 | include_directories(/Users/yaojun/MyInstall/duckdb_install/usr/local/include) 75 | target_link_libraries(duckdb_test ${DB_LIBS}) 76 | ``` 77 | 78 | ## 参考文档 79 | 80 | [CMakeTutorial](https://github.com/BrightXiaoHan/CMakeTutorial/blob/master/ImportExternalProject/README.md) 81 | -------------------------------------------------------------------------------- /03-import-external-project/cmake/spdlog.cmake: -------------------------------------------------------------------------------- 1 | include(ExternalProject) 2 | set(SPDLOG_ROOT ${CMAKE_BINARY_DIR}/third_party/extern_spdlog) 3 | ExternalProject_Add( 4 | extern_spdlog 5 | PREFIX ${CMAKE_BINARY_DIR}/third_party/extern_spdlog 6 | GIT_REPOSITORY https://gitee.com/roberchen/spdlog.git 7 | GIT_TAG v1.6.0 8 | CONFIGURE_COMMAND cd ${SPDLOG_ROOT}/src/extern_spdlog && cmake -B build 9 | -DCMAKE_INSTALL_PREFIX=${SPDLOG_ROOT} 10 | BUILD_COMMAND cd ${SPDLOG_ROOT}/src/extern_spdlog && cmake --build build -j 8 11 | INSTALL_COMMAND cd ${SPDLOG_ROOT}/src/extern_spdlog && cmake --install build 12 | BUILD_BYPRODUCTS ${SPDLOG_ROOT}/lib/libspdlog.a 13 | ) 14 | # 指定编译好的静态库文件的路径 find_library(SPDLOG_LIBRARIES spdlog ${SPDLOG_ROOT}/lib/) # 15 | # 指定头文件所在的目录 16 | set(SPDLOG_INCLUDE_DIR ${SPDLOG_ROOT}/include) 17 | set(SPDLOG_LIBRARIES ${SPDLOG_ROOT}/lib/libspdlog.a) 18 | add_library(spdlog STATIC IMPORTED GLOBAL) 19 | add_dependencies(spdlog extern_spdlog) 20 | set_target_properties( 21 | spdlog PROPERTIES IMPORTED_LOCATION ${SPDLOG_LIBRARIES} 22 | INTERFACE_INCLUDE_DIRECTORIES ${SPDLOG_INCLUDE_DIR}) 23 | -------------------------------------------------------------------------------- /03-import-external-project/spdlog_test.cpp: -------------------------------------------------------------------------------- 1 | #include "spdlog/spdlog.h" 2 | 3 | // Use the default logger (stdout, multi-threaded, colored) 4 | int main() { spdlog::info("Hello, {}!", "World"); } -------------------------------------------------------------------------------- /05-testing/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | project(main) 3 | set(CMAKE_CXX_STANDARD 17) 4 | include(CTest) 5 | enable_testing() 6 | add_subdirectory(src) 7 | 8 | if(BUILD_TESTING) 9 | add_subdirectory(test) 10 | endif() -------------------------------------------------------------------------------- /05-testing/README.md: -------------------------------------------------------------------------------- 1 | # 第五章:单元测试 2 | ``` 3 | include(CTest) 4 | enable_testing() 5 | add_test() 6 | ``` 7 | ## 编译运行 8 | ``` 9 | ctest --test-dir build 10 | # 或者只测试cs开头的数据 11 | ctest --test-dir build -R "^cs." 12 | ``` 13 | ## 宏macro 14 | - ${ARGN}是所有传入的可变参数 15 | ```cmake 16 | macro(my_add_test TEST_NAME) 17 | add_executable(${TEST_NAME} ${ARGN}) 18 | add_test(NAME cs.${TEST_NAME} COMMAND ${TEST_NAME}) 19 | target_link_libraries(${TEST_NAME} PRIVATE gtest gtest_main) 20 | endmacro() 21 | ``` 22 | 23 | ## 函数function 24 | ```cmake 25 | function(add_thirdparty) 26 | cmake_parse_arguments(DORIS_THIRDPARTY 27 | "NOTADD;LIB64" 28 | "LIBNAME;WHOLELIBPATH" 29 | "" 30 | ${ARGN}) 31 | set(DORIS_THIRDPARTY_NAME ${DORIS_THIRDPARTY_UNPARSED_ARGUMENTS}) 32 | add_library(${DORIS_THIRDPARTY_NAME} STATIC IMPORTED) 33 | endfunction() 34 | ``` 35 | -------------------------------------------------------------------------------- /05-testing/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(main main.cpp) -------------------------------------------------------------------------------- /05-testing/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | 5 | std::cout<<"hello world!"< PRIVATE my_pch.h) 21 | ``` 22 | ## 性能优化 23 | - 将debug模式改为release 24 | -------------------------------------------------------------------------------- /06-optimize/hello.cpp: -------------------------------------------------------------------------------- 1 | #include "world.h" 2 | int main() { 3 | world(); 4 | std::cout<<"main"< 4 | 5 | int world(){ 6 | std::cout<<"world"< 2 | int main(){ 3 | std::cout << "Hello World!" << std::endl; 4 | } -------------------------------------------------------------------------------- /add_dependencies/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | project(add_custom_target_test) 3 | set(CMAKE_CXX_STANDARD 17) 4 | 5 | add_executable(add_custom_target_test main.cpp) 6 | add_custom_target(run_test COMMAND cp ../README.md README.md.bak) 7 | add_dependencies(run_test add_custom_target_test) -------------------------------------------------------------------------------- /add_dependencies/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SYaoJun/CMake/1ec3e601d94403409f1e384f47d594d4863f8900/add_dependencies/README.md -------------------------------------------------------------------------------- /add_dependencies/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | int main(){ 3 | std::cout << "Hello World!" << std::endl; 4 | } -------------------------------------------------------------------------------- /c_cpp_combine/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | project(gtest_test) 3 | set(CMAKE_CXX_STANDARD 17) 4 | 5 | add_library(b SHARED b.cpp) 6 | add_executable(my_test main.c) 7 | target_link_libraries(my_test b) 8 | 9 | -------------------------------------------------------------------------------- /c_cpp_combine/README.md: -------------------------------------------------------------------------------- 1 | # C和C++混合使用 2 | ## 目标:C代码中调用C++的动态库 3 | ```bash 4 | ├── CMakeLists.txt 5 | ├── b.cpp 6 | ├── b.h 7 | └── main.c 8 | ``` 9 | ## C代码中引用C++的动态库 10 | 必须保证C++的动态库的头文件中,添加过extern关键字。 11 | ```c 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | int add(int a, int b); 17 | #ifdef __cplusplus 18 | } 19 | #endif 20 | ``` 21 | - C代码中不能使用C++提供的std::string和std::vector,无法编译通过。 22 | - C++提供给C的接口也必须改造为C的接口,否则C代码无法调用。 -------------------------------------------------------------------------------- /c_cpp_combine/b.cpp: -------------------------------------------------------------------------------- 1 | #include "b.h" 2 | 3 | int add(int a, int b){ 4 | return a + b; 5 | } -------------------------------------------------------------------------------- /c_cpp_combine/b.h: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | extern "C" { 3 | #endif 4 | 5 | int add(int a, int b); 6 | #ifdef __cplusplus 7 | } 8 | #endif -------------------------------------------------------------------------------- /c_cpp_combine/main.c: -------------------------------------------------------------------------------- 1 | // main.c 2 | #include "b.h" 3 | #include 4 | int main() { 5 | printf("add result = %d\n", add(1, 2)); 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /cmake_advanced/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | project(advanced) 3 | set(CMAKE_CXX_STANDARD 14) 4 | 5 | add_executable(my_app define_test.cpp) 6 | # 宏定义开关 7 | target_compile_definitions(my_app PRIVATE ENABLE_FEATURE_A) -------------------------------------------------------------------------------- /cmake_advanced/define_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef ENABLE_FEATURE_A 4 | void featureA() { 5 | std::cout << "Feature A is enabled." << std::endl; 6 | } 7 | #endif 8 | 9 | int main() { 10 | #ifdef ENABLE_FEATURE_A 11 | featureA(); 12 | #else 13 | std::cout << "Feature A is disabled." << std::endl; 14 | #endif 15 | 16 | return 0; 17 | } -------------------------------------------------------------------------------- /cmake_advanced/fetch_content/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.17) 2 | project(fetch) 3 | set(CMAKE_CXX_STANDARD 17) 4 | 5 | add_executable(fetch main.cpp) 6 | 7 | # step1 8 | include(FetchContent) 9 | # step2 FetchContent_Declare 10 | 11 | FetchContent_Declare(json 12 | GIT_REPOSITORY https://github.com/nlohmann/json.git 13 | GIT_TAG v3.7.3) 14 | # step3 15 | # FetchContent_MakeAvailable 16 | FetchContent_MakeAvailable(json) 17 | # target_link_libraries 18 | 19 | target_link_libraries(fetch PRIVATE nlohmann_json::nlohmann_json) 20 | 21 | FetchContent_Declare(spdlog 22 | GIT_REPOSITORY https://github.com/gabime/spdlog.git 23 | GIT_TAG v1.4.1) 24 | FetchContent_MakeAvailable(spdlog) 25 | target_link_libraries(fetch PRIVATE spdlog::spdlog) -------------------------------------------------------------------------------- /cmake_advanced/fetch_content/main.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | using json = nlohmann::json; 7 | int main(){ 8 | // create JSON values 9 | json object = {{"one", 1}, {"two", 2}}; 10 | json null; 11 | 12 | // print values 13 | std::cout << object << '\n'; 14 | std::cout << null << '\n'; 15 | 16 | // add values 17 | auto res1 = object.emplace("three", 3); 18 | null.emplace("A", "a"); 19 | null.emplace("B", "b"); 20 | 21 | // the following call will not add an object, because there is already 22 | // a value stored at key "B" 23 | auto res2 = null.emplace("B", "c"); 24 | 25 | // print values 26 | std::cout << object << '\n'; 27 | std::cout << *res1.first << " " << std::boolalpha << res1.second << '\n'; 28 | 29 | std::cout << null << '\n'; 30 | std::cout << *res2.first << " " << std::boolalpha << res2.second << '\n'; 31 | 32 | spdlog::info("i love c++"); 33 | return 0; 34 | } -------------------------------------------------------------------------------- /cmake_advanced/find_package/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | project(leveldb_test) 4 | set(CMAKE_CXX_STANDARD 17) 5 | SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake") 6 | find_package(leveldb REQUIRED) 7 | add_executable(test main.cpp) 8 | 9 | if(LEVELDB_FOUND_) 10 | target_include_directories(test PRIVATE ${LEVELDB_INCLUDES_}) 11 | target_link_libraries(test ${LEVELDB_LIBRARY_} pthread) 12 | else(LEVELDB_FOUND_) 13 | message(FATAL_ERROR "library not found") 14 | endif(LEVELDB_FOUND_) 15 | -------------------------------------------------------------------------------- /cmake_advanced/find_package/cmake/Findleveldb.cmake: -------------------------------------------------------------------------------- 1 | 2 | find_library(LEVELDB_LIBRARY_ 3 | leveldb 4 | /Users/yaojun/MyInstall/leveldb_install/lib) 5 | 6 | find_path(LEVELDB_INCLUDES_ 7 | leveldb/db.h 8 | /Users/yaojun/MyInstall/leveldb_install/include) 9 | 10 | if (LEVELDB_INCLUDES_ AND LEVELDB_LIBRARY_) 11 | set(LEVELDB_FOUND_ TRUE) 12 | endif (LEVELDB_INCLUDES_ AND LEVELDB_LIBRARY_) -------------------------------------------------------------------------------- /cmake_advanced/find_package/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "leveldb/db.h" 4 | #include "leveldb/write_batch.h" 5 | int main() 6 | { 7 | // Open a database. 8 | leveldb::DB* db; 9 | leveldb::Options opts; 10 | opts.create_if_missing = true; 11 | leveldb::Status status = leveldb::DB::Open(opts, "testdb", &db); 12 | assert(status.ok()); 13 | 14 | // Write data. 15 | status = db->Put(leveldb::WriteOptions(), "name", "yaojun"); 16 | assert(status.ok()); 17 | 18 | // Read data. 19 | std::string val; 20 | status = db->Get(leveldb::ReadOptions(), "name", &val); 21 | assert(status.ok()); 22 | std::cout << val << std::endl; 23 | } 24 | -------------------------------------------------------------------------------- /cmake_advanced/hello.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(){ 4 | std::cout<<"hello yaojun"< 2 | 3 | void memoryLeakExample() { 4 | int* leak = new int[10]; // 分配了10个int的数组,但没有释放 5 | leak[0] = 1; // 使用分配的内存 6 | // 未调用 delete[] leak; 7 | } 8 | 9 | int main() { 10 | memoryLeakExample(); 11 | std::cout << "Program finished." << std::endl; 12 | return 0; 13 | } -------------------------------------------------------------------------------- /gtest/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | project(gtest_test) 3 | set(CMAKE_CXX_STANDARD 17) 4 | add_subdirectory(googletest) 5 | #add_executable(inner_test inner_test.cpp) 6 | #target_link_libraries(inner_test GTest::gtest_main GTest::gtest GTest::gmock) 7 | 8 | # add_executable(client_server_test cs/client_server_test.cpp) 9 | # target_link_libraries(client_server_test GTest::gtest_main GTest::gtest GTest::gmock) 10 | 11 | add_executable(a_contain_b_test a_contain_b_test.cpp) 12 | target_link_libraries(a_contain_b_test GTest::gtest_main GTest::gtest GTest::gmock) -------------------------------------------------------------------------------- /gtest/README.md: -------------------------------------------------------------------------------- 1 | # gtest 2 | 把gtest的代码下载到本地 3 | ``` 4 | git submodule update --init 5 | ``` -------------------------------------------------------------------------------- /gtest/a_contain_b_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class B { 5 | public: 6 | virtual ~B() = default; 7 | virtual void stop() = 0; 8 | }; 9 | 10 | class A { 11 | public: 12 | A(B* b) : b_(b) {} 13 | virtual ~A() = default; 14 | 15 | virtual void stop() { 16 | if (b_) { 17 | b_->stop(); 18 | } 19 | } 20 | 21 | private: 22 | B* b_; 23 | }; 24 | 25 | 26 | class MockB : public B { 27 | public: 28 | MOCK_METHOD(void, stop, (), (override)); 29 | }; 30 | 31 | class MockA : public A { 32 | public: 33 | MockA(B* b) : A(b) {} 34 | MOCK_METHOD(void, stop, (), (override)); 35 | }; 36 | 37 | 38 | using ::testing::_; 39 | using ::testing::Return; 40 | using ::testing::Invoke; 41 | 42 | class ATest : public ::testing::Test { 43 | protected: 44 | MockB mockB; 45 | A a{&mockB}; 46 | }; 47 | 48 | TEST_F(ATest, StopCallsBStop) { 49 | // 设置期望:当调用 a.stop() 时,期望调用 mockB.stop() 50 | EXPECT_CALL(mockB, stop()).Times(1); 51 | 52 | // 调用 A 的 stop 方法,应该调用 B 的 stop 方法 53 | a.stop(); 54 | } 55 | -------------------------------------------------------------------------------- /gtest/cs/client_server_test.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | class ServerInterface { 5 | public: 6 | virtual ~ServerInterface() = default; 7 | virtual std::string HandleRequest(const std::string& request) = 0; 8 | }; 9 | 10 | // MockServer.h 11 | 12 | #include 13 | 14 | 15 | class MockServer : public ServerInterface { 16 | public: 17 | MOCK_METHOD1(HandleRequest, std::string(const std::string& request)); 18 | }; 19 | // Client.h 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #define SERV_IP "127.0.0.1" 26 | class Client { 27 | public: 28 | Client(const std::string& server_ip, int server_port); 29 | ~Client(); 30 | std::string SendMessage(const std::string& message); 31 | 32 | private: 33 | int sockfd; 34 | sockaddr_in server_addr; 35 | }; 36 | // Client.cpp 37 | 38 | #include 39 | #include 40 | #include 41 | 42 | Client::Client(const std::string& server_ip, int server_port) { 43 | std::cout<<"client start"< 59 | #include 60 | 61 | 62 | using ::testing::Return; 63 | 64 | class MockSocketServer { 65 | public: 66 | MockSocketServer(MockServer& mock_server) : mock_server_(mock_server) {} 67 | 68 | void Start() { 69 | // 模拟服务端的行为 70 | std::string request = "Hello"; 71 | 72 | std::string response = mock_server_.HandleRequest(request); 73 | // 处理客户端请求并返回响应 74 | // 在实际应用中,这里会涉及到 socket 监听、接收和发送数据 75 | // 在测试中,我们使用 Mock 对象来模拟这些操作 76 | } 77 | 78 | private: 79 | MockServer& mock_server_; 80 | }; 81 | 82 | TEST(ClientTest, SendMessage) { 83 | MockServer mock_server; 84 | std::string expected_response = "World"; 85 | 86 | // 设置期望并指定返回值 87 | EXPECT_CALL(mock_server, HandleRequest("Hello")) 88 | .WillOnce(Return(expected_response)); 89 | 90 | MockSocketServer mock_socket_server(mock_server); 91 | mock_socket_server.Start(); 92 | 93 | // 创建客户端并发送消息 94 | Client client("127.0.0.1", 8080); 95 | std::string response = client.SendMessage("Hello"); 96 | 97 | EXPECT_EQ(response, expected_response); 98 | } 99 | -------------------------------------------------------------------------------- /gtest/gtest_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "gmock/gmock.h" 3 | 4 | namespace gmock_ { 5 | 6 | class Foo { 7 | public: 8 | // Must be virtual as we'll inherit from Foo. 9 | virtual ~Foo() {} 10 | 11 | virtual bool SetName(const std::string& name) = 0; 12 | virtual std::string GetName() const = 0; 13 | }; 14 | 15 | class MockFoo : public Foo { 16 | public: 17 | //! 1. first argument is return type 18 | //! 2. second argument is the name of the method 19 | //! 3. third argument is the arguments 20 | //! 4. fourth argument is the confined type 21 | MOCK_METHOD(bool, SetName, (const std::string&), (override)); // the last argument is the convention for a mock method. 22 | MOCK_METHOD(std::string, GetName, (), (const, override)); 23 | }; 24 | 25 | class Area { 26 | public: 27 | virtual ~Area() {} 28 | virtual int area() = 0; 29 | }; 30 | 31 | int GetValue(Area* p) { return p->area() / 2; } 32 | 33 | class MockArea : public Area { 34 | public: 35 | MOCK_METHOD(int, area, (), (override)); 36 | }; 37 | 38 | } // namespace gmock_ 39 | 40 | TEST(gmock, name) { 41 | using namespace gmock_; 42 | using ::testing::AtLeast; 43 | using ::testing::Return; 44 | 45 | MockFoo foo; 46 | EXPECT_CALL(foo, SetName("Mike")) 47 | .Times(AtLeast(2)) 48 | .WillOnce(Return(1)) 49 | .WillOnce(Return(0)); 50 | EXPECT_TRUE(foo.SetName("Mike")); 51 | EXPECT_FALSE(foo.SetName("Mike")); 52 | 53 | EXPECT_CALL(foo, GetName()) 54 | .Times(AtLeast(1)) 55 | .WillRepeatedly(Return("Mike")); 56 | EXPECT_EQ("Mike", foo.GetName()); 57 | } 58 | 59 | TEST(gmock, area) { 60 | using namespace gmock_; 61 | using ::testing::Return; 62 | 63 | MockArea m; 64 | EXPECT_CALL(m, area()).WillRepeatedly(Return(10)); 65 | EXPECT_EQ(5, GetValue(&m)); 66 | } 67 | 68 | -------------------------------------------------------------------------------- /gtest/inner_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "gmock/gmock.h" 3 | 4 | namespace gmock_ { 5 | 6 | class Foo { 7 | 8 | public: 9 | int value = 0; 10 | // Must be virtual as we'll inherit from Foo. 11 | virtual ~Foo() {} 12 | 13 | virtual bool SetName(const std::string& name) = 0; 14 | virtual std::string GetName() const = 0; 15 | virtual std::string GenerateString(int x) = 0; 16 | virtual int GetValue() = 0; 17 | }; 18 | 19 | class MockFoo : public Foo { 20 | public: 21 | //! 1. first argument is return type 22 | //! 2. second argument is the name of the method 23 | //! 3. third argument is the arguments 24 | //! 4. fourth argument is the confined type 25 | MOCK_METHOD(bool, SetName, (const std::string&), (override)); // the last argument is the convention for a mock method. 26 | MOCK_METHOD(std::string, GetName, (), (const, override)); 27 | MOCK_METHOD(std::string, GenerateString, (int x), (override)); 28 | MOCK_METHOD(int, GetValue, (), (override)); 29 | }; 30 | 31 | 32 | 33 | } // namespace gmock_ 34 | 35 | TEST(gmock, name) { 36 | using namespace gmock_; 37 | using ::testing::AtLeast; 38 | using ::testing::Return; 39 | using ::testing::Invoke; 40 | MockFoo foo; 41 | EXPECT_CALL(foo, GenerateString(1)) 42 | .Times(AtLeast(2)) 43 | .WillOnce([](int x) { 44 | 45 | return "world1"; 46 | }).WillOnce(Invoke([&foo]() { 47 | foo.value++; 48 | return "world2"; 49 | })); 50 | 51 | EXPECT_EQ("world1", foo.GenerateString(1)); 52 | EXPECT_EQ("world2", foo.GenerateString(1)); 53 | 54 | EXPECT_CALL(foo, GetValue()).Times(AtLeast(1)).WillOnce(Return(1)); 55 | EXPECT_EQ(1, foo.GetValue()); 56 | } 57 | 58 | 59 | -------------------------------------------------------------------------------- /gtest/non_virtual_method_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using ::testing::_; 6 | using ::testing::Invoke; 7 | 8 | // 实际类 9 | class MyClass { 10 | public: 11 | void NonVirtualMethod() { 12 | std::cout << "NonVirtualMethod called" << std::endl; 13 | } 14 | }; 15 | 16 | // 接口定义 17 | class MyClassInterface { 18 | public: 19 | virtual ~MyClassInterface() = default; 20 | virtual void NonVirtualMethod() = 0; 21 | }; 22 | 23 | // 代理类 24 | class MyClassProxy : public MyClassInterface { 25 | public: 26 | explicit MyClassProxy(MyClass* my_class) : my_class_(my_class) {} 27 | void NonVirtualMethod() override { 28 | my_class_->NonVirtualMethod(); 29 | } 30 | 31 | private: 32 | MyClass* my_class_; 33 | }; 34 | 35 | // Mock 类 36 | class MockMyClass : public MyClassInterface { 37 | public: 38 | MOCK_METHOD(void, NonVirtualMethod, (), (override)); 39 | }; 40 | 41 | // 测试实际类 42 | TEST(MyClassTest, ActualNonVirtualMethodTest) { 43 | MyClass my_class; 44 | MyClassProxy proxy(&my_class); 45 | proxy.NonVirtualMethod(); 46 | } 47 | 48 | // 测试 Mock 类 49 | TEST(MyClassTest, NonVirtualMethodTest) { 50 | MockMyClass mock_my_class; 51 | EXPECT_CALL(mock_my_class, NonVirtualMethod()).Times(1); 52 | 53 | MyClassInterface* interface = &mock_my_class; 54 | interface->NonVirtualMethod(); 55 | } 56 | 57 | int main(int argc, char** argv) { 58 | ::testing::InitGoogleTest(&argc, argv); 59 | return RUN_ALL_TESTS(); 60 | } 61 | -------------------------------------------------------------------------------- /target_compile_definitions/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13) 2 | project(MyProject) 3 | 4 | 5 | add_subdirectory(lib) 6 | add_executable(test_executable main.cpp) 7 | 8 | 9 | target_link_libraries(test_executable PRIVATE mylib) 10 | -------------------------------------------------------------------------------- /target_compile_definitions/README.md: -------------------------------------------------------------------------------- 1 | # target_compile_definitions 2 | 用于给目标添加编译参数,比如定义宏。 3 | 不管是使用private还是interface还是public对外部的调用者都没影响,一般建议使用private。 4 | ```cmake 5 | target_compile_definitions(mylib PRIVATE USE_A) 6 | ``` 7 | -------------------------------------------------------------------------------- /target_compile_definitions/lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library(mylib SHARED mylib.cpp) 3 | 4 | target_compile_definitions(mylib PRIVATE USE_A) 5 | # make sure that the header file can be found by the other targets 6 | target_include_directories(mylib INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) 7 | -------------------------------------------------------------------------------- /target_compile_definitions/lib/mylib.cpp: -------------------------------------------------------------------------------- 1 | #include "mylib.h" 2 | #include 3 | 4 | #ifndef USE_A 5 | void featureXFunction() { 6 | std::cout << "Not Use Feature X" << std::endl; 7 | } 8 | #endif 9 | 10 | #ifdef USE_A 11 | void featureXFunction() { 12 | std::cout << "Feature X is enabled" << std::endl; 13 | } 14 | #endif -------------------------------------------------------------------------------- /target_compile_definitions/lib/mylib.h: -------------------------------------------------------------------------------- 1 | #ifndef MYLIB_H 2 | #define MYLIB_H 3 | 4 | 5 | void featureXFunction(); 6 | 7 | #endif // MYLIB_H 8 | -------------------------------------------------------------------------------- /target_compile_definitions/main.cpp: -------------------------------------------------------------------------------- 1 | #include "mylib.h" 2 | #include 3 | int main() { 4 | featureXFunction(); 5 | std::cout <<"main hello"< 2 | #include 3 | #include 4 | 5 | int main() { 6 | std::cout << "ZLIB version: " << zlibVersion() << std::endl; 7 | fmt::print("Hello, {}!\n", "world"); 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /vcpkg/vcpkg.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "abc", 3 | "version": "1.0.0", 4 | "dependencies": [ 5 | "zlib", 6 | "fmt" 7 | ] 8 | } 9 | --------------------------------------------------------------------------------