ubuntu@ubuntu-cpp:~/code/cpp/doctest/doctest-01$ tree -a
.
├── CMakeLists.txt
├── cm.py
├── cmake
│ └── khl_common_set_project_debug.cmake
├── include
│ └── khl_math
│ ├── calc.h
│ ├── khl_math.h
│ └── khl_math_config.h
├── src
│ ├── CMakeLists.txt
│ ├── khl_math
│ │ ├── CMakeLists.txt
│ │ └── calc.cpp
│ └── main
│ ├── CMakeLists.txt
│ └── main.cpp
├── test
│ ├── CMakeLists.txt
│ └── maintest.cpp
└── third
└── doctest
└── doctest.h
9 directories, 14 files
ubuntu@ubuntu-cpp:~/code/cpp/doctest/doctest-01$
#ifndef _CALC_H_
#define _CALC_H_
#include "khl_math_config.h"
class DllExport Calc
{
public:
Calc();
~Calc();
public:
int add(int x, int y);
};
#endif // _CALC_H_
#ifndef _KHL_MATH_H_
#define _KHL_MATH_H_
#include "khl_math/calc.h"
// C/C++ 跨平台时预处理判断平台环境
// 参考: https://www.cnblogs.com/Forgenvueory/p/12757271.html
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
#ifdef _WIN64
#ifdef _DEBUG
#pragma comment(lib,__FILE__"\\..\\..\\..\\lib\\khl_mathd.lib")
#else
#pragma comment(lib,__FILE__"\\..\\..\\..\\lib\\khl_math.lib")
#endif
#else
//define something for Windows (32-bit only)
#endif
#elif __APPLE__
#include <TargetConditionals.h>
#if TARGET_IPHONE_SIMULATOR
// iOS Simulator
#elif TARGET_OS_IPHONE
// iOS device
#elif TARGET_OS_MAC
// Other kinds of Mac OS
#else
# error "Unknown Apple platform"
#endif
#elif __linux__
// linux
#elif __unix__ // all unices not caught above
// Unix
#elif defined(_POSIX_VERSION)
// POSIX
#else
# error "Unknown compiler"
#endif
#endif // _KHL_MATH_H_
#ifndef _KHL_MATH_CONFIG_H_
#define _KHL_MATH_CONFIG_H_
// C/C++ 跨平台时预处理判断平台环境
// 参考: https://www.cnblogs.com/Forgenvueory/p/12757271.html
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
//define something for Windows (32-bit and 64-bit, this part is common)
#ifdef _WIN64
#define DllExport __declspec(dllexport)
#else
//define something for Windows (32-bit only)
#endif
#elif __APPLE__
#include <TargetConditionals.h>
#if TARGET_IPHONE_SIMULATOR
// iOS Simulator
#elif TARGET_OS_IPHONE
// iOS device
#elif TARGET_OS_MAC
// Other kinds of Mac OS
#else
# error "Unknown Apple platform"
#endif
#elif __linux__
// linux
#define DllExport
#elif __unix__ // all unices not caught above
// Unix
#elif defined(_POSIX_VERSION)
// POSIX
#else
# error "Unknown compiler"
#endif
#endif // _KHL_MATH_CONFIG_H_
#include "khl_math/calc.h"
Calc::Calc()
{
}
Calc::~Calc()
{
}
int Calc::add(int x, int y)
{
return x + y;
}
#include <iostream>
#include <memory>
#include "khl_math/khl_math.h"
int main()
{
auto calc = std::make_unique<Calc>();
std::cout << "1 + 2 = " << calc->add(1,2) << std::endl;
std::cout << "Hello World!" << std::endl;
return 0;
}
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest/doctest.h"
#include "khl_math/khl_math.h"
TEST_CASE("test khl_math")
{
// MESSAGE("message - test khl_math calc add");
int a = 1;
INFO("info - test khl_math calc add ", a);
auto calc = std::make_unique<Calc>();
CHECK(3 == calc->add(1,2));
}
# 该项目所需 cmake 的最小版本, 如果 cmake 版本小于设置的版本, cmake 将停止处理并报错
cmake_minimum_required(VERSION 3.25)
project(hello CXX)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
include(khl_common_set_project_debug)
# 编译模式是否为 debug
cmake_language(CALL khl_common_set_project_debug)
message(STATUS "====> project_debug : ${project_debug}")
message(STATUS "====> CMAKE_BUILD_TYPE : ${CMAKE_BUILD_TYPE}")
# 设置 debug 库后缀
if(${project_debug})
set(CMAKE_DEBUG_POSTFIX d)
endif()
# 消除警告 warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
# 参考: https://blog.csdn.net/five_east_west/article/details/125382251
if(${CMAKE_HOST_WIN32})
add_compile_options("$<$<C_COMPILER_ID:MSVC>:/utf-8>")
add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>")
endif()
set(khl_math_lib_name khl_math${CMAKE_DEBUG_POSTFIX})
# 添加预处理器定义, 主要用于 windows
if(${project_debug})
add_compile_definitions(_DEBUG)
endif()
# windows 平台
# 把 .dll 和 .lib 复制到 lib 目录
function(copy_dll_to_lib dll_name)
if(${CMAKE_HOST_WIN32})
set(dll_full_name ${CMAKE_SHARED_LIBRARY_PREFIX}${dll_name}${CMAKE_DEBUG_POSTFIX}${CMAKE_SHARED_LIBRARY_SUFFIX})
set(dll_lib_name ${CMAKE_SHARED_LIBRARY_PREFIX}${dll_name}${CMAKE_DEBUG_POSTFIX}.lib)
add_custom_command(TARGET ${dll_name} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/build/src/${dll_name}/${CMAKE_BUILD_TYPE}/${dll_full_name} ${CMAKE_SOURCE_DIR}/lib/${dll_full_name})
add_custom_command(TARGET ${dll_name} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/build/src/${dll_name}/${CMAKE_BUILD_TYPE}/${dll_lib_name} ${CMAKE_SOURCE_DIR}/lib/${dll_lib_name})
endif()
endfunction()
# windows 平台
# 把 .dll 复制到 bin 目录
function(copy_dll_to_exe dll_name)
if(${CMAKE_HOST_WIN32})
set(dll_full_name ${CMAKE_SHARED_LIBRARY_PREFIX}${dll_name}${CMAKE_DEBUG_POSTFIX}${CMAKE_SHARED_LIBRARY_SUFFIX})
add_custom_command(TARGET ${PROJECT_NAME} PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/build/src/${dll_name}/${CMAKE_BUILD_TYPE}/${dll_full_name} ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE})
endif()
endfunction()
add_subdirectory(src)
# 添加测试项目所在目录
add_subdirectory(test)
# 必须添加这两行, 而且必须在顶层 CMakeLists.txt 添加
enable_testing()
add_test(NAME hello_test COMMAND hello_test)
add_subdirectory(main)
add_subdirectory(khl_math)
# 头文件目录
include_directories(${CMAKE_SOURCE_DIR}/include)
# 源文件列表
aux_source_directory(. CALC_SRCS)
# 设置生成目录
if(${CMAKE_HOST_LINUX})
message(STATUS "====> linux lib dir")
set(LIBRARY_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/lib)
endif()
# 生成动态库, 默认生成的是静态库
add_library(${khl_math_lib_name} SHARED ${CALC_SRCS})
# 指定动态库版本
# VERSION 动态库版本
# SOVERSION API版本
set_target_properties(${khl_math_lib_name} PROPERTIES VERSION 1.0 SOVERSION 1)
cmake_language(CALL copy_dll_to_lib ${khl_math_lib_name})
# 头文件目录
include_directories(${CMAKE_SOURCE_DIR}/include)
# 源文件列表
aux_source_directory(. MAIN_SRCS)
# 可执行文件目录
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin)
# 使用指定的源文件向项目添加可执行文件
add_executable(${PROJECT_NAME} ${MAIN_SRCS})
if(${CMAKE_HOST_LINUX})
target_link_directories(${PROJECT_NAME} PUBLIC ${CMAKE_SOURCE_DIR}/lib)
target_link_libraries(${PROJECT_NAME} ${khl_math_lib_name})
endif()
add_dependencies(${PROJECT_NAME} ${khl_math_lib_name})
cmake_language(CALL copy_dll_to_exe ${khl_math_lib_name})
# 该项目所需 cmake 的最小版本, 如果 cmake 版本小于设置的版本, cmake 将停止处理并报错
cmake_minimum_required(VERSION 3.0)
# 设置项目名称和语言
project(hello_test CXX)
# 指定 c++ 14
set (CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
include(khl_common_set_project_debug)
message(STATUS "====> project_debug : ${project_debug}")
message(STATUS "====> CMAKE_BUILD_TYPE : ${CMAKE_BUILD_TYPE}")
# 设置 debug 库后缀
if(${project_debug})
set(CMAKE_DEBUG_POSTFIX d)
endif()
# 消除警告 warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
# 参考: https://blog.csdn.net/five_east_west/article/details/125382251
if(${CMAKE_HOST_WIN32})
add_compile_options("$<$<C_COMPILER_ID:MSVC>:/utf-8>")
add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>")
endif()
# 添加预处理器定义, 主要用于 windows
if(${project_debug})
add_compile_definitions(_DEBUG)
endif()
include_directories(${CMAKE_SOURCE_DIR}/third)
include_directories(${CMAKE_SOURCE_DIR}/include)
aux_source_directory(. TEST_SRCS)
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin)
add_executable(${PROJECT_NAME} ${TEST_SRCS})
if(${CMAKE_HOST_LINUX})
target_link_directories(${PROJECT_NAME} PUBLIC ${CMAKE_SOURCE_DIR}/lib)
target_link_libraries(${PROJECT_NAME} ${khl_math_lib_name})
endif()
避免重复繁琐的命令行操作, 默认是构建并运行测试
ubuntu@ubuntu-cpp:~/code/cpp/doctest/doctest-01$ python3 cm.py --help
usage: cm.py [-h] {build,rebuild,run,test,clean} ...
positional arguments:
{build,rebuild,run,test,clean}
build 构建
rebuild 重新构建
run 运行
test 测试
clean 清理
options:
-h, --help show this help message and exit
ubuntu@ubuntu-cpp:~/code/cpp/doctest/doctest-01$
# -*- coding: utf-8 -*-
import argparse
import os
import platform
import os.path
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
KEY_CM_ACTION = 'cm_action'
ARG_PREFIX = '--'
SUB_COMMAND_BUILD = 'build'
SUB_COMMAND_RE_BUILD = 'rebuild'
SUB_COMMAND_RUN = 'run'
SUB_COMMAND_TEST = 'test'
SUB_COMMAND_CLEAN = 'clean'
def register_build_args():
build_parsers = subparsers.add_parser(SUB_COMMAND_BUILD, help='构建')
build_parsers.add_argument(ARG_PREFIX + KEY_CM_ACTION, help='动作类型', default=SUB_COMMAND_BUILD)
def register_re_build_args():
rebuild_parsers = subparsers.add_parser(SUB_COMMAND_RE_BUILD, help='重新构建')
rebuild_parsers.add_argument(ARG_PREFIX + KEY_CM_ACTION, help='动作类型', default=SUB_COMMAND_RE_BUILD)
def register_run_args():
run_parsers = subparsers.add_parser(SUB_COMMAND_RUN, help='运行')
run_parsers.add_argument(ARG_PREFIX + KEY_CM_ACTION, help='动作类型', default=SUB_COMMAND_RUN)
def register_test_args():
test_parsers = subparsers.add_parser(SUB_COMMAND_TEST, help='测试')
test_parsers.add_argument(ARG_PREFIX + KEY_CM_ACTION, help='动作类型', default=SUB_COMMAND_TEST)
def register_clean_args():
test_parsers = subparsers.add_parser(SUB_COMMAND_CLEAN, help='清理')
test_parsers.add_argument(ARG_PREFIX + KEY_CM_ACTION, help='动作类型', default=SUB_COMMAND_CLEAN)
def is_windows():
return 'Windows' == platform.system()
def get_build_dir():
return os.getcwd() + os.path.sep + 'build'
def get_bin_dir():
return os.getcwd() + os.path.sep + 'bin'
def get_lib_dir():
return os.getcwd() + os.path.sep + 'lib'
def execute_build():
if is_windows():
os.system('cmake -S . -B build -DCMAKE_CONFIGURATION_TYPES=Release && cmake --build build --config=release')
else:
os.system('cmake -S . -B build -DCMAKE_BUILD_TYPE=Release && cmake --build build --config=release')
def execute_re_build():
execute_clean()
if is_windows():
os.system('cmake -S . -B build -DCMAKE_CONFIGURATION_TYPES=Release && cmake --build build --config=release')
else:
os.system('cmake -S . -B build -DCMAKE_BUILD_TYPE=Release && cmake --build build --config=release')
def execute_run():
execute_build()
if is_windows():
os.system(".\\bin\\Release\\hello.exe")
else:
os.system('./bin/hello')
def execute_test():
execute_build()
if is_windows():
os.system(".\\bin\\Release\\hello_test.exe")
else:
os.system('./bin/hello_test')
def execute_clean():
if is_windows():
if os.path.exists(get_build_dir()):
os.system('rd /q/s build')
if os.path.exists(get_bin_dir()):
os.system('rd /q/s bin')
if os.path.exists(get_lib_dir()):
os.system('rd /q/s lib')
else:
if os.path.exists(get_build_dir()):
os.system('rm -rf build')
if os.path.exists(get_bin_dir()):
os.system('rm -rf bin')
if os.path.exists(get_lib_dir()):
os.system('rm -rf lib')
if __name__ == '__main__':
register_build_args()
register_re_build_args()
register_run_args()
register_test_args()
register_clean_args()
args = parser.parse_args()
if 0 == len(args.__dict__):
execute_test()
else:
if SUB_COMMAND_BUILD == args.__dict__[KEY_CM_ACTION]:
execute_build()
if SUB_COMMAND_RE_BUILD == args.__dict__[KEY_CM_ACTION]:
execute_re_build()
if SUB_COMMAND_RUN == args.__dict__[KEY_CM_ACTION]:
execute_run()
if SUB_COMMAND_TEST == args.__dict__[KEY_CM_ACTION]:
execute_test()
if SUB_COMMAND_CLEAN == args.__dict__[KEY_CM_ACTION]:
execute_clean()
F:\2023\code\cpp\vscode\doctest\doctest-01>cm.py
-- Building for: Visual Studio 17 2022
-- Selecting Windows SDK version 10.0.22000.0 to target Windows 10.0.19045.
-- The CXX compiler identification is MSVC 19.34.31937.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: D:/program/microsoft/vs2022/community/VC/Tools/MSVC/14.34.31933/bin/Hostx64/x64/cl.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- ====> khl_common_set_project_debug : 判断是否为 debug 模式
-- ====> khl_common_set_project_debug : 编译模式: release
-- ====> project_debug : 0
-- ====> CMAKE_BUILD_TYPE : Release
-- ====> project_debug : 0
-- ====> CMAKE_BUILD_TYPE : Release
-- Configuring done
-- Generating done
-- Build files have been written to: F:/2023/code/cpp/vscode/doctest/doctest-01/build
MSBuild version 17.4.1+9a89d02ff for .NET Framework
Checking Build System
Building Custom Rule F:/2023/code/cpp/vscode/doctest/doctest-01/src/khl_math/CMakeLists.txt
calc.cpp
正在创建库 F:/2023/code/cpp/vscode/doctest/doctest-01/build/src/khl_math/Release/khl_math.lib 和对象 F:/2023/code/cpp/vscode/doctest/doctest-01/build/src/khl_math/Release/khl_math.exp
khl_math.vcxproj -> F:\2023\code\cpp\vscode\doctest\doctest-01\build\src\khl_math\Release\khl_math.dll
Building Custom Rule F:/2023/code/cpp/vscode/doctest/doctest-01/src/main/CMakeLists.txt
main.cpp
正在创建库 F:/2023/code/cpp/vscode/doctest/doctest-01/bin/Release/hello.lib 和对象 F:/2023/code/cpp/vscode/doctest/doctest-01/bin/Release/hello.exp
hello.vcxproj -> F:\2023\code\cpp\vscode\doctest\doctest-01\bin\Release\hello.exe
Building Custom Rule F:/2023/code/cpp/vscode/doctest/doctest-01/test/CMakeLists.txt
maintest.cpp
正在创建库 F:/2023/code/cpp/vscode/doctest/doctest-01/bin/Release/hello_test.lib 和对象 F:/2023/code/cpp/vscode/doctest/doctest-01/bin/Release/hello_test.exp
hello_test.vcxproj -> F:\2023\code\cpp\vscode\doctest\doctest-01\bin\Release\hello_test.exe
Building Custom Rule F:/2023/code/cpp/vscode/doctest/doctest-01/CMakeLists.txt
[doctest] doctest version is "2.4.9"
[doctest] run with "--help" for options
===============================================================================
[doctest] test cases: 2 | 2 passed | 0 failed | 0 skipped
[doctest] assertions: 2 | 2 passed | 0 failed |
[doctest] Status: SUCCESS!
F:\2023\code\cpp\vscode\doctest\doctest-01>rd /q/s build
F:\2023\code\cpp\vscode\doctest\doctest-01>tree /f
Folder PATH listing for volume dox
Volume serial number is 34D2-6BE8
F:.
│ cm.py
│ CMakeLists.txt
│
├───bin
│ └───Release
│ hello.exe
│ hello.exp
│ hello.lib
│ hello_test.exe
│ hello_test.exp
│ hello_test.lib
│ khl_math.dll
│
├───cmake
│ khl_common_set_project_debug.cmake
│
├───include
│ └───khl_math
│ calc.h
│ khl_math.h
│ khl_math_config.h
│
├───lib
│ khl_math.dll
│ khl_math.lib
│
├───src
│ │ CMakeLists.txt
│ │
│ ├───khl_math
│ │ calc.cpp
│ │ CMakeLists.txt
│ │
│ └───main
│ CMakeLists.txt
│ main.cpp
│
├───test
│ CMakeLists.txt
│ maintest.cpp
│
└───third
└───doctest
doctest.h
F:\2023\code\cpp\vscode\doctest\doctest-01>
ubuntu@ubuntu-cpp:~/code/cpp/doctest/doctest-01$ python3 cm.py test
-- The CXX compiler identification is GNU 11.3.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- ====> khl_common_set_project_debug : 判断是否为 debug 模式
-- ====> khl_common_set_project_debug : 编译模式: release
-- ====> project_debug : 0
-- ====> CMAKE_BUILD_TYPE : Release
-- ====> linux lib dir
-- ====> project_debug : 0
-- ====> CMAKE_BUILD_TYPE : Release
-- Configuring done
-- Generating done
-- Build files have been written to: /home/ubuntu/code/cpp/doctest/doctest-01/build
[ 16%] Building CXX object src/khl_math/CMakeFiles/khl_math.dir/calc.cpp.o
[ 33%] Linking CXX shared library /home/ubuntu/code/cpp/doctest/doctest-01/lib/libkhl_math.so
[ 33%] Built target khl_math
[ 50%] Building CXX object src/main/CMakeFiles/hello.dir/main.cpp.o
[ 66%] Linking CXX executable /home/ubuntu/code/cpp/doctest/doctest-01/bin/hello
[ 66%] Built target hello
[ 83%] Building CXX object test/CMakeFiles/hello_test.dir/maintest.cpp.o
[100%] Linking CXX executable /home/ubuntu/code/cpp/doctest/doctest-01/bin/hello_test
[100%] Built target hello_test
[doctest] doctest version is "2.4.9"
[doctest] run with "--help" for options
===============================================================================
[doctest] test cases: 2 | 2 passed | 0 failed | 0 skipped
[doctest] assertions: 2 | 2 passed | 0 failed |
[doctest] Status: SUCCESS!
ubuntu@ubuntu-cpp:~/code/cpp/doctest/doctest-01$ rm -rf build/
ubuntu@ubuntu-cpp:~/code/cpp/doctest/doctest-01$ tree -a
.
├── CMakeLists.txt
├── bin
│ ├── hello
│ └── hello_test
├── cm.py
├── cmake
│ └── khl_common_set_project_debug.cmake
├── include
│ └── khl_math
│ ├── calc.h
│ ├── khl_math.h
│ └── khl_math_config.h
├── lib
│ ├── libkhl_math.so -> libkhl_math.so.1
│ ├── libkhl_math.so.1 -> libkhl_math.so.1.0
│ └── libkhl_math.so.1.0
├── src
│ ├── CMakeLists.txt
│ ├── khl_math
│ │ ├── CMakeLists.txt
│ │ └── calc.cpp
│ └── main
│ ├── CMakeLists.txt
│ └── main.cpp
├── test
│ ├── CMakeLists.txt
│ └── maintest.cpp
└── third
└── doctest
└── doctest.h
11 directories, 19 files
ubuntu@ubuntu-cpp:~/code/cpp/doctest/doctest-01$
可以有多个文件引入doctest.h
, 只要保证只有一个文件有 #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
即可.