From 0cd95827572ca79d069f71e45f2d6db584550d09 Mon Sep 17 00:00:00 2001 From: yyc12345 Date: Sun, 3 Nov 2024 14:51:18 +0800 Subject: [PATCH] refactor: refactor project layout - move header files into an individual directory to prevent the possibility that file name is conflict in Linux include directory. - update build script generator. use jinja2 template engine to get better view, rather than python code written by hand. - add version number and version comparation macros in core library. --- script/.gitignore | 1 + script/gen_build_script.py | 108 +++++++++++ script/gen_win_build.py | 170 ------------------ ...linux_build.sh => linux_build.template.sh} | 11 +- script/win_build.old.bat | 57 ------ script/win_build.template.bat | 85 +++++++++ script/win_msvc_build.old.bat | 52 ------ src/CMakeLists.txt | 59 +++--- src/{ => YYCC}/ArgParser.cpp | 0 src/{ => YYCC}/ArgParser.hpp | 0 src/{ => YYCC}/COMHelper.cpp | 0 src/{ => YYCC}/COMHelper.hpp | 0 src/{ => YYCC}/ConfigManager.cpp | 0 src/{ => YYCC}/ConfigManager.hpp | 0 src/{ => YYCC}/ConsoleHelper.cpp | 0 src/{ => YYCC}/ConsoleHelper.hpp | 0 src/{ => YYCC}/Constraints.hpp | 0 src/{ => YYCC}/DialogHelper.cpp | 0 src/{ => YYCC}/DialogHelper.hpp | 0 src/{ => YYCC}/EncodingHelper.cpp | 0 src/{ => YYCC}/EncodingHelper.hpp | 0 src/{ => YYCC}/EnumHelper.hpp | 0 src/{ => YYCC}/ExceptionHelper.cpp | 0 src/{ => YYCC}/ExceptionHelper.hpp | 0 src/{ => YYCC}/IOHelper.cpp | 0 src/{ => YYCC}/IOHelper.hpp | 0 src/{ => YYCC}/ParserHelper.hpp | 0 src/{ => YYCC}/StdPatch.cpp | 0 src/{ => YYCC}/StdPatch.hpp | 0 src/{ => YYCC}/StringHelper.cpp | 0 src/{ => YYCC}/StringHelper.hpp | 0 src/{ => YYCC}/WinFctHelper.cpp | 0 src/{ => YYCC}/WinFctHelper.hpp | 0 src/{ => YYCC}/WinImportPrefix.hpp | 0 src/{ => YYCC}/WinImportSuffix.hpp | 0 src/{ => YYCC}/YYCCInternal.hpp | 33 ++++ src/YYCCommonplace.hpp | 28 +-- testbench/main.cpp | 18 ++ 38 files changed, 293 insertions(+), 329 deletions(-) create mode 100644 script/gen_build_script.py delete mode 100644 script/gen_win_build.py rename script/{linux_build.sh => linux_build.template.sh} (53%) delete mode 100644 script/win_build.old.bat create mode 100644 script/win_build.template.bat delete mode 100644 script/win_msvc_build.old.bat rename src/{ => YYCC}/ArgParser.cpp (100%) rename src/{ => YYCC}/ArgParser.hpp (100%) rename src/{ => YYCC}/COMHelper.cpp (100%) rename src/{ => YYCC}/COMHelper.hpp (100%) rename src/{ => YYCC}/ConfigManager.cpp (100%) rename src/{ => YYCC}/ConfigManager.hpp (100%) rename src/{ => YYCC}/ConsoleHelper.cpp (100%) rename src/{ => YYCC}/ConsoleHelper.hpp (100%) rename src/{ => YYCC}/Constraints.hpp (100%) rename src/{ => YYCC}/DialogHelper.cpp (100%) rename src/{ => YYCC}/DialogHelper.hpp (100%) rename src/{ => YYCC}/EncodingHelper.cpp (100%) rename src/{ => YYCC}/EncodingHelper.hpp (100%) rename src/{ => YYCC}/EnumHelper.hpp (100%) rename src/{ => YYCC}/ExceptionHelper.cpp (100%) rename src/{ => YYCC}/ExceptionHelper.hpp (100%) rename src/{ => YYCC}/IOHelper.cpp (100%) rename src/{ => YYCC}/IOHelper.hpp (100%) rename src/{ => YYCC}/ParserHelper.hpp (100%) rename src/{ => YYCC}/StdPatch.cpp (100%) rename src/{ => YYCC}/StdPatch.hpp (100%) rename src/{ => YYCC}/StringHelper.cpp (100%) rename src/{ => YYCC}/StringHelper.hpp (100%) rename src/{ => YYCC}/WinFctHelper.cpp (100%) rename src/{ => YYCC}/WinFctHelper.hpp (100%) rename src/{ => YYCC}/WinImportPrefix.hpp (100%) rename src/{ => YYCC}/WinImportSuffix.hpp (100%) rename src/{ => YYCC}/YYCCInternal.hpp (62%) diff --git a/script/.gitignore b/script/.gitignore index ab184df..dabf011 100644 --- a/script/.gitignore +++ b/script/.gitignore @@ -1,2 +1,3 @@ # -------------------- Output -------------------- win_build.bat +linux_build.sh diff --git a/script/gen_build_script.py b/script/gen_build_script.py new file mode 100644 index 0000000..a61a620 --- /dev/null +++ b/script/gen_build_script.py @@ -0,0 +1,108 @@ +import jinja2 +import argparse +import os +import io +import re +import shlex + +def validate_cpp_ver(ver: str) -> str: + if re.match(r'^[0-9]+$', ver) is not None: return ver + else: raise argparse.ArgumentTypeError('invalid version of C++ standard.') + +def write_line(f: io.TextIOWrapper, val: str) -> None: + f.write(val) + f.write('\n') + +# Reference: https://stackoverflow.com/questions/29213106/how-to-securely-escape-command-line-arguments-for-the-cmd-exe-shell-on-windows +def escape_for_cmd_exe(arg): + meta_re = re.compile(r'([()%!^"<>&|])') + return meta_re.sub('^\1', arg) +def escape_cmd_argument(arg): + if not arg or re.search(r'(["\s])', arg): + arg = '"' + arg.replace('"', r'\"') + '"' + return escape_for_cmd_exe(arg) +def escape_sh_argument(arg): + return shlex.quote(arg) + +class ScriptSettings: + m_CppVersion: str + m_BuildDoc: bool + m_PIC: bool + + def __init__(self, cpp_ver: str, build_doc: bool, pic: bool): + self.m_CppVersion = cpp_ver + self.m_BuildDoc = build_doc + self.m_PIC = pic + +class TemplateRender: + m_Loader: jinja2.BaseLoader + m_Environment: jinja2.Environment + + m_WinTemplate: jinja2.Template + m_LinuxTemplate: jinja2.Template + + m_Settings: ScriptSettings + + def __init__(self, settings: ScriptSettings) -> None: + self.m_Loader = jinja2.FileSystemLoader(self.__get_dir()) + self.m_Environment = jinja2.Environment(loader=self.m_Loader) + + self.m_WinTemplate = self.m_Environment.get_template('win_build.template.bat') + self.m_LinuxTemplate = self.m_Environment.get_template('linux_build.template.sh') + + self.m_Settings = settings + + def __get_dir(self) -> str: + return os.path.dirname(__file__) + + def __escape_path(self, val: str, is_win: bool) -> str: + if is_win: return escape_cmd_argument(val) + else: return escape_sh_argument(val) + + def __render(self, template: jinja2.Template, dest_file: str, is_win: bool) -> None: + with open(os.path.join(self.__get_dir(), dest_file), 'w', encoding='utf-8') as f: + f.write(template.render( + repo_root_dir = self.__escape_path(os.path.dirname(self.__get_dir()), is_win), + cpp_version = self.m_Settings.m_CppVersion, + build_doc = self.m_Settings.m_BuildDoc, + pic = settings.m_PIC + )) + + def render_win_script(self) -> None: + self.__render(self.m_WinTemplate, 'win_build.bat', True) + + def render_linux_script(self) -> None: + self.__render(self.m_LinuxTemplate, 'linux_build.sh', False) + + +if __name__ == '__main__': + # parse argument + parser = argparse.ArgumentParser( + prog='YYCC Windows Build Script Generator', + description='YYCC Windows Build Script Generator' + ) + parser.add_argument( + '-c', '--cpp', + action='store', default='17', dest='cpp', type=validate_cpp_ver, + help='The version of C++ standard used when building.' + ) + parser.add_argument( + '-d', '--build-doc', + action='store_true', dest='build_doc', + help='Build YYCC without documentation.' + ) + parser.add_argument( + '-p', '--pic', + action='store_true', dest='pic', + help='Enable Position Independent Code flag on non-Windows platform. This is crucial for compiling dynamic library using this library.' + ) + args = parser.parse_args() + + # build settings + settings = ScriptSettings(args.cpp, args.build_doc, args.pic) + # build template render and render result + render = TemplateRender(settings) + render.render_win_script() + render.render_linux_script() + + diff --git a/script/gen_win_build.py b/script/gen_win_build.py deleted file mode 100644 index f57cfe1..0000000 --- a/script/gen_win_build.py +++ /dev/null @@ -1,170 +0,0 @@ -import argparse -import os -import io -import re - -def validate_cpp_ver(ver: str) -> str: - if re.match(r'^[0-9]+$', ver) is not None: return ver - else: raise argparse.ArgumentTypeError('invalid version of C++ standard.') - -def write_line(f: io.TextIOWrapper, val: str) -> None: - f.write(val) - f.write('\n') - -# Reference: https://stackoverflow.com/questions/29213106/how-to-securely-escape-command-line-arguments-for-the-cmd-exe-shell-on-windows -def escape_argument(arg): - if not arg or re.search(r'(["\s])', arg): - arg = '"' + arg.replace('"', r'\"') + '"' - return escape_for_cmd_exe(arg) -def escape_for_cmd_exe(arg): - meta_re = re.compile(r'([()%!^"<>&|])') - return meta_re.sub('^\1', arg) - -class ScriptSettings: - m_CppVersion: str - m_NoDoc: bool - - def __init__(self, cpp_ver: str, no_doc: bool): - self.m_CppVersion = cpp_ver - self.m_NoDoc = no_doc - -def script_head(f: io.TextIOWrapper, s: ScriptSettings) -> None: - # change directory to root folder - write_line(f, ':: Navigate to project root directory') - root_dir: str = os.path.dirname(os.path.dirname(__file__)) - write_line(f, f'CD /d {escape_argument(root_dir)}') - # create build directory and enter - write_line(f, ':: Create build directory and enter it') - write_line(f, 'MKDIR bin') - write_line(f, 'CD bin') - cpp_dir: str = f'cpp{s.m_CppVersion}' - write_line(f, f'MKDIR {cpp_dir}') - write_line(f, f'CD {cpp_dir}') - # blank line - write_line(f, '') - -def script_tail(f: io.TextIOWrapper, s: ScriptSettings) -> None: - # leave build directory and report success - write_line(f, ':: Leave build directory and report') - write_line(f, 'CD ..\\..') - write_line(f, 'ECHO Windows CMake Build Done') - -def create_directory(f: io.TextIOWrapper, s: ScriptSettings) -> None: - # create build directory - write_line(f, ':: Create internal build directory') - write_line(f, 'MKDIR Win32') - write_line(f, 'MKDIR x64') - write_line(f, 'MKDIR documentation') - # create install directory - write_line(f, ':: Create internal install directory') - write_line(f, 'MKDIR install') - write_line(f, 'CD install') - write_line(f, 'MKDIR Win32_Debug') - write_line(f, 'MKDIR Win32_Release') - write_line(f, 'MKDIR x64_Debug') - write_line(f, 'MKDIR x64_Release') - write_line(f, 'CD ..') - # create msvc install directory - write_line(f, ':: Create internal MSVC specific install directory') - write_line(f, 'MKDIR msvc_install') - write_line(f, 'CD msvc_install') - write_line(f, 'MKDIR bin') - write_line(f, 'MKDIR include') - write_line(f, 'MKDIR lib') - write_line(f, 'MKDIR share') - write_line(f, 'CD bin') - write_line(f, 'MKDIR Win32') - write_line(f, 'MKDIR x64') - write_line(f, 'CD ..') - write_line(f, 'CD lib') - write_line(f, 'MKDIR Win32\\Debug') - write_line(f, 'MKDIR Win32\\Release') - write_line(f, 'MKDIR x64\\Debug') - write_line(f, 'MKDIR x64\\Release') - write_line(f, 'CD ..') - write_line(f, 'CD ..') - # blank line - write_line(f, '') - -def cmake_build(f: io.TextIOWrapper, s: ScriptSettings) -> None: - # build for Win32 - write_line(f, ':: Build for Win32') - write_line(f, 'CD Win32') - write_line(f, f'cmake -G "Visual Studio 16 2019" -A Win32 -DCMAKE_CXX_STANDARD={s.m_CppVersion} -DYYCC_BUILD_TESTBENCH=ON ../../..') - write_line(f, 'cmake --build . --config Debug') - write_line(f, 'cmake --install . --prefix=../install/Win32_Debug --config Debug') - write_line(f, 'cmake --build . --config Release') - write_line(f, 'cmake --install . --prefix=../install/Win32_Release --config Release') - write_line(f, 'CD ..') - # build for x64 - write_line(f, ':: Build for x64') - write_line(f, 'CD x64') - write_line(f, f'cmake -G "Visual Studio 16 2019" -A x64 -DCMAKE_CXX_STANDARD={s.m_CppVersion} -DYYCC_BUILD_TESTBENCH=ON ../../..') - write_line(f, 'cmake --build . --config Debug') - write_line(f, 'cmake --install . --prefix=../install/x64_Debug --config Debug') - write_line(f, 'cmake --build . --config Release') - write_line(f, 'cmake --install . --prefix=../install/x64_Release --config Release') - write_line(f, 'CD ..') - # build for documentation - if not s.m_NoDoc: - write_line(f, ':: Build for documentation') - write_line(f, 'CD documentation') - write_line(f, f'cmake -G "Visual Studio 16 2019" -A x64 -DCMAKE_CXX_STANDARD={s.m_CppVersion} -DYYCC_BUILD_DOC=ON ../../..') - write_line(f, 'cmake --build . --config Release') - write_line(f, 'cmake --build . --target YYCCDocumentation') - write_line(f, 'cmake --install . --prefix=../install/x64_Release --config Release') - write_line(f, 'CD ..') - # blank line - write_line(f, '') - -def msvc_build(f: io.TextIOWrapper, s: ScriptSettings) -> None: - # copy include from x64_Release build - write_line(f, ':: Copy header files') - write_line(f, 'XCOPY install\\x64_Release\\include msvc_install\\include\\ /E /Y') - # copy binary testbench - write_line(f, ':: Copy binary files') - write_line(f, 'COPY install\\Win32_Release\\bin\\YYCCTestbench.exe msvc_install\\bin\\Win32\\YYCCTestbench.exe /Y') - write_line(f, 'COPY install\\x64_Release\\bin\\YYCCTestbench.exe msvc_install\\bin\\x64\\YYCCTestbench.exe /Y') - # copy static library - write_line(f, ':: Copy library files') - write_line(f, 'COPY install\\Win32_Debug\\lib\\YYCCommonplace.lib msvc_install\\lib\\Win32\\Debug\\YYCCommonplace.lib /Y') - write_line(f, 'COPY install\\Win32_Release\\lib\\YYCCommonplace.lib msvc_install\\lib\\Win32\\Release\\YYCCommonplace.lib /Y') - write_line(f, 'COPY install\\x64_Debug\\lib\\YYCCommonplace.lib msvc_install\\lib\\x64\\Debug\\YYCCommonplace.lib /Y') - write_line(f, 'COPY install\\x64_Release\\lib\\YYCCommonplace.lib msvc_install\\lib\\x64\\Release\\YYCCommonplace.lib /Y') - # Copy document from x64_Release build - if not s.m_NoDoc: - write_line(f, ':: Copy documentation files') - write_line(f, 'XCOPY install\\x64_Release\\share msvc_install\\share\\ /E /Y') - # blank line - write_line(f, '') - -if __name__ == '__main__': - # parse argument - parser = argparse.ArgumentParser( - prog='YYCC Windows Build Script Generator', - description='YYCC Windows Build Script Generator' - ) - parser.add_argument( - '-c', '--cpp', - action='store', default='17', dest='cpp', type=validate_cpp_ver, - help='The version of C++ standard used when building.' - ) - parser.add_argument( - '-d', '--no-doc', - action='store_true', dest='no_doc', - help='Build YYCC without documentation.' - ) - args = parser.parse_args() - - # build settings - settings = ScriptSettings(args.cpp, args.no_doc) - # write result - filepath = os.path.join(os.path.dirname(__file__), 'win_build.bat') - with open(filepath, 'w') as f: - write_line(f, '@ECHO OFF') - script_head(f, settings) - create_directory(f, settings) - cmake_build(f, settings) - msvc_build(f, settings) - script_tail(f, settings) - diff --git a/script/linux_build.sh b/script/linux_build.template.sh similarity index 53% rename from script/linux_build.sh rename to script/linux_build.template.sh index 98fa32d..0c23c74 100644 --- a/script/linux_build.sh +++ b/script/linux_build.template.sh @@ -1,9 +1,6 @@ #!/bin/bash -README_PATH=$(pwd)/README.md -if [ ! -f "$README_PATH" ]; then - echo "Error: You must run this script at the root folder of this project!" - exit -fi +# Navigate to project root directory +cd {{ repo_root_dir }} # Create main binary directory mkdir bin @@ -19,10 +16,10 @@ cd .. # Build current system debug and release version cd build -cmake -DCMAKE_BUILD_TYPE=Debug ../.. --fresh +cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_STANDARD={{ cpp_version }} {{ '-DCMAKE_POSITION_INDEPENDENT_CODE=True' if pic else '' }} ../.. --fresh cmake --build . cmake --install . --prefix ../install/Debug -cmake -DCMAKE_BUILD_TYPE=Release -DYYCC_BUILD_TESTBENCH=ON ../.. --fresh +cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD={{ cpp_version }} {{ '-DCMAKE_POSITION_INDEPENDENT_CODE=True' if pic else '' }} -DYYCC_BUILD_TESTBENCH=ON ../.. --fresh cmake --build . cmake --install . --prefix ../install/Release cd .. diff --git a/script/win_build.old.bat b/script/win_build.old.bat deleted file mode 100644 index 5333c57..0000000 --- a/script/win_build.old.bat +++ /dev/null @@ -1,57 +0,0 @@ -@ECHO OFF -:: Check environment -SET README_PATH=%CD%\README.md -IF EXIST %README_PATH% ( - REM DO NOTHING -) ELSE ( - ECHO Error: You must run this script at the root folder of this project! - EXIT /b -) - -:: Create main binary directory -MKDIR bin -CD bin -:: Create build folder -MKDIR Win32 -MKDIR x64 -MKDIR documentation -:: Create install folder -MKDIR install -CD install -MKDIR Win32_Debug -MKDIR Win32_Release -MKDIR x64_Debug -MKDIR x64_Release -CD .. - -:: Build for Win32 -CD Win32 -cmake -G "Visual Studio 16 2019" -A Win32 -DYYCC_BUILD_TESTBENCH=ON ../.. -cmake --build . --config Debug -cmake --install . --prefix=../install/Win32_Debug --config Debug -cmake --build . --config Release -cmake --install . --prefix=../install/Win32_Release --config Release -CD .. - -:: Build for x64 -CD x64 -cmake -G "Visual Studio 16 2019" -A x64 -DYYCC_BUILD_TESTBENCH=ON ../.. -cmake --build . --config Debug -cmake --install . --prefix=../install/x64_Debug --config Debug -cmake --build . --config Release -cmake --install . --prefix=../install/x64_Release --config Release -CD .. - -:: Build for documentation -IF NOT "%1"=="NODOC" ( - CD documentation - cmake -G "Visual Studio 16 2019" -A x64 -DYYCC_BUILD_DOC=ON ../.. - cmake --build . --config Release - cmake --build . --target YYCCDocumentation - cmake --install . --prefix=../install/x64_Release --config Release - CD .. -) - -:: Exit to original path -CD .. -ECHO Windows CMake Build Done diff --git a/script/win_build.template.bat b/script/win_build.template.bat new file mode 100644 index 0000000..9e207af --- /dev/null +++ b/script/win_build.template.bat @@ -0,0 +1,85 @@ +@ECHO OFF +:: Navigate to project root directory +CD /d {{ repo_root_dir }} +:: Create build directory and enter it +MKDIR bin +CD bin +MKDIR cpp{{ cpp_version }} +CD cpp{{ cpp_version }} + +:: Create internal build directory +MKDIR Win32 +MKDIR x64 +MKDIR documentation +:: Create internal install directory +MKDIR install +CD install +MKDIR Win32_Debug +MKDIR Win32_Release +MKDIR x64_Debug +MKDIR x64_Release +CD .. +:: Create internal MSVC specific install directory +MKDIR msvc_install +CD msvc_install +MKDIR bin +MKDIR include +MKDIR lib +MKDIR share +CD bin +MKDIR Win32 +MKDIR x64 +CD .. +CD lib +MKDIR Win32\Debug +MKDIR Win32\Release +MKDIR x64\Debug +MKDIR x64\Release +CD .. +CD .. + +:: Build for Win32 +CD Win32 +cmake -G "Visual Studio 16 2019" -A Win32 -DCMAKE_CXX_STANDARD={{ cpp_version }} -DYYCC_BUILD_TESTBENCH=ON ../../.. +cmake --build . --config Debug +cmake --install . --prefix=../install/Win32_Debug --config Debug +cmake --build . --config Release +cmake --install . --prefix=../install/Win32_Release --config Release +CD .. +:: Build for x64 +CD x64 +cmake -G "Visual Studio 16 2019" -A x64 -DCMAKE_CXX_STANDARD={{ cpp_version }} -DYYCC_BUILD_TESTBENCH=ON ../../.. +cmake --build . --config Debug +cmake --install . --prefix=../install/x64_Debug --config Debug +cmake --build . --config Release +cmake --install . --prefix=../install/x64_Release --config Release +CD .. + +{% if build_doc %} +:: Build for documentation +CD documentation +'cmake -G "Visual Studio 16 2019" -A x64 -DCMAKE_CXX_STANDARD={{ cpp_version }} -DYYCC_BUILD_DOC=ON ../../.. +cmake --build . --config Release +cmake --build . --target YYCCDocumentation +cmake --install . --prefix=../install/x64_Release --config Release +CD .. +{% endif %} + +:: Copy header files +XCOPY install\x64_Release\include msvc_install\include\ /E /Y +:: Copy binary files +COPY install\Win32_Release\bin\YYCCTestbench.exe msvc_install\bin\Win32\YYCCTestbench.exe /Y +COPY install\x64_Release\bin\YYCCTestbench.exe msvc_install\bin\x64\YYCCTestbench.exe /Y +:: Copy library files +COPY install\Win32_Debug\lib\YYCCommonplace.lib msvc_install\lib\Win32\Debug\YYCCommonplace.lib /Y +COPY install\Win32_Release\lib\YYCCommonplace.lib msvc_install\lib\Win32\Release\YYCCommonplace.lib /Y +COPY install\x64_Debug\lib\YYCCommonplace.lib msvc_install\lib\x64\Debug\YYCCommonplace.lib /Y +COPY install\x64_Release\lib\YYCCommonplace.lib msvc_install\lib\x64\Release\YYCCommonplace.lib /Y +{% if build_doc %} +:: Copy documentation files +XCOPY install\x64_Release\share msvc_install\share\ /E /Y +{% endif %} + +:: Leave build directory and report +CD ..\.. +ECHO Windows CMake Build Done diff --git a/script/win_msvc_build.old.bat b/script/win_msvc_build.old.bat deleted file mode 100644 index 50fe0b4..0000000 --- a/script/win_msvc_build.old.bat +++ /dev/null @@ -1,52 +0,0 @@ -@ECHO OFF -SET README_PATH=%CD%\README.md -IF EXIST %README_PATH% ( - REM DO NOTHING -) ELSE ( - ECHO Error: You must run this script at the root folder of this project! - EXIT /b -) - -:: Enter main binary directory -CD bin - -:: Create MSVC binary directory -MKDIR msvc_install -CD msvc_install -:: Create direcotries tree -MKDIR bin -MKDIR include -MKDIR lib -MKDIR share -CD bin -MKDIR Win32 -MKDIR x64 -CD .. -CD lib -MKDIR Win32\Debug -MKDIR Win32\Release -MKDIR x64\Debug -MKDIR x64\Release -CD .. -:: Exit MSVC binary directory -CD .. - -:: Copy result -:: Copy include from x64_Release build -XCOPY install\x64_Release\include msvc_install\include\ /E /Y -:: Copy document from x64_Release build -IF NOT "%1"=="NODOC" ( - XCOPY install\x64_Release\share msvc_install\share\ /E /Y -) -:: Copy binary testbench -COPY install\Win32_Release\bin\YYCCTestbench.exe msvc_install\bin\Win32\YYCCTestbench.exe /Y -COPY install\x64_Release\bin\YYCCTestbench.exe msvc_install\bin\x64\YYCCTestbench.exe /Y -:: Copy static library -COPY install\Win32_Debug\lib\YYCCommonplace.lib msvc_install\lib\Win32\Debug\YYCCommonplace.lib /Y -COPY install\Win32_Release\lib\YYCCommonplace.lib msvc_install\lib\Win32\Release\YYCCommonplace.lib /Y -COPY install\x64_Debug\lib\YYCCommonplace.lib msvc_install\lib\x64\Debug\YYCCommonplace.lib /Y -COPY install\x64_Release\lib\YYCCommonplace.lib msvc_install\lib\x64\Release\YYCCommonplace.lib /Y - -:: Exit to original path -CD .. -ECHO Windows MSVC Build Done diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 11097eb..a0931b8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,17 +4,17 @@ add_library(YYCCommonplace STATIC "") target_sources(YYCCommonplace PRIVATE # Sources - COMHelper.cpp - ArgParser.cpp - ConfigManager.cpp - ConsoleHelper.cpp - DialogHelper.cpp - EncodingHelper.cpp - ExceptionHelper.cpp - StdPatch.cpp - IOHelper.cpp - StringHelper.cpp - WinFctHelper.cpp + YYCC/COMHelper.cpp + YYCC/ArgParser.cpp + YYCC/ConfigManager.cpp + YYCC/ConsoleHelper.cpp + YYCC/DialogHelper.cpp + YYCC/EncodingHelper.cpp + YYCC/ExceptionHelper.cpp + YYCC/StdPatch.cpp + YYCC/IOHelper.cpp + YYCC/StringHelper.cpp + YYCC/WinFctHelper.cpp # Natvis (only for MSVC) $<$:YYCC.natvis> ) @@ -24,25 +24,26 @@ FILE_SET HEADERS FILES # Headers # Common headers - Constraints.hpp - COMHelper.hpp - ArgParser.hpp - ConfigManager.hpp - ConsoleHelper.hpp - DialogHelper.hpp - EncodingHelper.hpp - EnumHelper.hpp - ExceptionHelper.hpp - StdPatch.hpp - IOHelper.hpp - ParserHelper.hpp - StringHelper.hpp - WinFctHelper.hpp + YYCC/Constraints.hpp + YYCC/COMHelper.hpp + YYCC/ArgParser.hpp + YYCC/ConfigManager.hpp + YYCC/ConsoleHelper.hpp + YYCC/DialogHelper.hpp + YYCC/EncodingHelper.hpp + YYCC/EnumHelper.hpp + YYCC/ExceptionHelper.hpp + YYCC/StdPatch.hpp + YYCC/IOHelper.hpp + YYCC/ParserHelper.hpp + YYCC/StringHelper.hpp + YYCC/WinFctHelper.hpp # Windows including guard pair - WinImportPrefix.hpp - WinImportSuffix.hpp - # Misc - YYCCInternal.hpp + YYCC/WinImportPrefix.hpp + YYCC/WinImportSuffix.hpp + # Internal + YYCC/YYCCInternal.hpp + # Exposed YYCCommonplace.hpp ) # Setup header infomations diff --git a/src/ArgParser.cpp b/src/YYCC/ArgParser.cpp similarity index 100% rename from src/ArgParser.cpp rename to src/YYCC/ArgParser.cpp diff --git a/src/ArgParser.hpp b/src/YYCC/ArgParser.hpp similarity index 100% rename from src/ArgParser.hpp rename to src/YYCC/ArgParser.hpp diff --git a/src/COMHelper.cpp b/src/YYCC/COMHelper.cpp similarity index 100% rename from src/COMHelper.cpp rename to src/YYCC/COMHelper.cpp diff --git a/src/COMHelper.hpp b/src/YYCC/COMHelper.hpp similarity index 100% rename from src/COMHelper.hpp rename to src/YYCC/COMHelper.hpp diff --git a/src/ConfigManager.cpp b/src/YYCC/ConfigManager.cpp similarity index 100% rename from src/ConfigManager.cpp rename to src/YYCC/ConfigManager.cpp diff --git a/src/ConfigManager.hpp b/src/YYCC/ConfigManager.hpp similarity index 100% rename from src/ConfigManager.hpp rename to src/YYCC/ConfigManager.hpp diff --git a/src/ConsoleHelper.cpp b/src/YYCC/ConsoleHelper.cpp similarity index 100% rename from src/ConsoleHelper.cpp rename to src/YYCC/ConsoleHelper.cpp diff --git a/src/ConsoleHelper.hpp b/src/YYCC/ConsoleHelper.hpp similarity index 100% rename from src/ConsoleHelper.hpp rename to src/YYCC/ConsoleHelper.hpp diff --git a/src/Constraints.hpp b/src/YYCC/Constraints.hpp similarity index 100% rename from src/Constraints.hpp rename to src/YYCC/Constraints.hpp diff --git a/src/DialogHelper.cpp b/src/YYCC/DialogHelper.cpp similarity index 100% rename from src/DialogHelper.cpp rename to src/YYCC/DialogHelper.cpp diff --git a/src/DialogHelper.hpp b/src/YYCC/DialogHelper.hpp similarity index 100% rename from src/DialogHelper.hpp rename to src/YYCC/DialogHelper.hpp diff --git a/src/EncodingHelper.cpp b/src/YYCC/EncodingHelper.cpp similarity index 100% rename from src/EncodingHelper.cpp rename to src/YYCC/EncodingHelper.cpp diff --git a/src/EncodingHelper.hpp b/src/YYCC/EncodingHelper.hpp similarity index 100% rename from src/EncodingHelper.hpp rename to src/YYCC/EncodingHelper.hpp diff --git a/src/EnumHelper.hpp b/src/YYCC/EnumHelper.hpp similarity index 100% rename from src/EnumHelper.hpp rename to src/YYCC/EnumHelper.hpp diff --git a/src/ExceptionHelper.cpp b/src/YYCC/ExceptionHelper.cpp similarity index 100% rename from src/ExceptionHelper.cpp rename to src/YYCC/ExceptionHelper.cpp diff --git a/src/ExceptionHelper.hpp b/src/YYCC/ExceptionHelper.hpp similarity index 100% rename from src/ExceptionHelper.hpp rename to src/YYCC/ExceptionHelper.hpp diff --git a/src/IOHelper.cpp b/src/YYCC/IOHelper.cpp similarity index 100% rename from src/IOHelper.cpp rename to src/YYCC/IOHelper.cpp diff --git a/src/IOHelper.hpp b/src/YYCC/IOHelper.hpp similarity index 100% rename from src/IOHelper.hpp rename to src/YYCC/IOHelper.hpp diff --git a/src/ParserHelper.hpp b/src/YYCC/ParserHelper.hpp similarity index 100% rename from src/ParserHelper.hpp rename to src/YYCC/ParserHelper.hpp diff --git a/src/StdPatch.cpp b/src/YYCC/StdPatch.cpp similarity index 100% rename from src/StdPatch.cpp rename to src/YYCC/StdPatch.cpp diff --git a/src/StdPatch.hpp b/src/YYCC/StdPatch.hpp similarity index 100% rename from src/StdPatch.hpp rename to src/YYCC/StdPatch.hpp diff --git a/src/StringHelper.cpp b/src/YYCC/StringHelper.cpp similarity index 100% rename from src/StringHelper.cpp rename to src/YYCC/StringHelper.cpp diff --git a/src/StringHelper.hpp b/src/YYCC/StringHelper.hpp similarity index 100% rename from src/StringHelper.hpp rename to src/YYCC/StringHelper.hpp diff --git a/src/WinFctHelper.cpp b/src/YYCC/WinFctHelper.cpp similarity index 100% rename from src/WinFctHelper.cpp rename to src/YYCC/WinFctHelper.cpp diff --git a/src/WinFctHelper.hpp b/src/YYCC/WinFctHelper.hpp similarity index 100% rename from src/WinFctHelper.hpp rename to src/YYCC/WinFctHelper.hpp diff --git a/src/WinImportPrefix.hpp b/src/YYCC/WinImportPrefix.hpp similarity index 100% rename from src/WinImportPrefix.hpp rename to src/YYCC/WinImportPrefix.hpp diff --git a/src/WinImportSuffix.hpp b/src/YYCC/WinImportSuffix.hpp similarity index 100% rename from src/WinImportSuffix.hpp rename to src/YYCC/WinImportSuffix.hpp diff --git a/src/YYCCInternal.hpp b/src/YYCC/YYCCInternal.hpp similarity index 62% rename from src/YYCCInternal.hpp rename to src/YYCC/YYCCInternal.hpp index 0b901d3..3aaac7b 100644 --- a/src/YYCCInternal.hpp +++ b/src/YYCC/YYCCInternal.hpp @@ -1,5 +1,38 @@ #pragma once +#pragma region Library Version and Comparation Macros + +#define YYCC_VER_MAJOR 1 +#define YYCC_VER_MINOR 3 +#define YYCC_VER_PATCH 0 + +/// @brief Return true if left version number is equal to right version number, otherwise false. +#define YYCC_VERCMP_E(av1, av2, av3, bv1, bv2, bv3) ((av1) == (bv1) && (av2) == (bv2) && (av3) == (bv3)) +/// @brief Return true if left version number is not equal to right version number, otherwise false. +#define YYCC_VERCMP_NE(av1, av2, av3, bv1, bv2, bv3) (!YYCC_VERCMP_E(av1, av2, av3, bv1, bv2, bv3)) +/// @brief Return true if left version number is greater than right version number, otherwise false. +#define YYCC_VERCMP_G(av1, av2, av3, bv1, bv2, bv3) ( \ + ((av1) > (bv1)) || \ + ((av1) == (bv1) && (av2) > (bv2)) || \ + ((av1) == (bv1) && (av2) == (bv2) && (av3) > (bv3)) \ +) +/// @brief Return true if left version number is greater than or equal to right version number, otherwise false. +#define YYCC_VERCMP_GE(av1, av2, av3, bv1, bv2, bv3) (YYCC_VERCMP_G(av1, av2, av3, bv1, bv2, bv3) || YYCC_VERCMP_E(av1, av2, av3, bv1, bv2, bv3)) +/// @brief Return true if left version number is not lower than right version number, otherwise false. +#define YYCC_VERCMP_NL(av1, av2, av3, bv1, bv2, bv3) YYCC_VERCMP_GE(av1, av2, av3, bv1, bv2, bv3) +/// @brief Return true if left version number is lower than right version number, otherwise false. +#define YYCC_VERCMP_L(av1, av2, av3, bv1, bv2, bv3) ( \ + ((av1) < (bv1)) || \ + ((av1) == (bv1) && (av2) < (bv2)) || \ + ((av1) == (bv1) && (av2) == (bv2) && (av3) < (bv3)) \ +) +/// @brief Return true if left version number is lower than or equal to right version number, otherwise false. +#define YYCC_VERCMP_LE(av1, av2, av3, bv1, bv2, bv3) (YYCC_VERCMP_L(av1, av2, av3, bv1, bv2, bv3) || YYCC_VERCMP_E(av1, av2, av3, bv1, bv2, bv3)) +/// @brief Return true if left version number is not greater than right version number, otherwise false. +#define YYCC_VERCMP_NG(av1, av2, av3, bv1, bv2, bv3) YYCC_VERCMP_LE(av1, av2, av3, bv1, bv2, bv3) + +#pragma endregion + #pragma region Operating System Identifier Macros // Define operating system macros diff --git a/src/YYCCommonplace.hpp b/src/YYCCommonplace.hpp index 05b355a..7f7e51b 100644 --- a/src/YYCCommonplace.hpp +++ b/src/YYCCommonplace.hpp @@ -1,18 +1,18 @@ #pragma once -#include "YYCCInternal.hpp" +#include "YYCC/YYCCInternal.hpp" -#include "EncodingHelper.hpp" -#include "StringHelper.hpp" -#include "ConsoleHelper.hpp" -#include "COMHelper.hpp" -#include "DialogHelper.hpp" -#include "ParserHelper.hpp" -#include "IOHelper.hpp" -#include "WinFctHelper.hpp" -#include "StdPatch.hpp" -#include "EnumHelper.hpp" -#include "ExceptionHelper.hpp" +#include "YYCC/EncodingHelper.hpp" +#include "YYCC/StringHelper.hpp" +#include "YYCC/ConsoleHelper.hpp" +#include "YYCC/COMHelper.hpp" +#include "YYCC/DialogHelper.hpp" +#include "YYCC/ParserHelper.hpp" +#include "YYCC/IOHelper.hpp" +#include "YYCC/WinFctHelper.hpp" +#include "YYCC/StdPatch.hpp" +#include "YYCC/EnumHelper.hpp" +#include "YYCC/ExceptionHelper.hpp" -#include "ConfigManager.hpp" -#include "ArgParser.hpp" +#include "YYCC/ConfigManager.hpp" +#include "YYCC/ArgParser.hpp" diff --git a/testbench/main.cpp b/testbench/main.cpp index 791473d..3041158 100644 --- a/testbench/main.cpp +++ b/testbench/main.cpp @@ -484,6 +484,17 @@ namespace YYCCTestbench { } + static void VersionMacroTestbench() { + Assert(YYCC_VERCMP_E(1, 2, 3, 1, 2, 3), YYCC_U8("YYCC_VERCMP_E")); + Assert(!YYCC_VERCMP_NE(1, 2, 3, 1, 2, 3), YYCC_U8("YYCC_VERCMP_NE")); + Assert(YYCC_VERCMP_G(1, 2, 3, 0, 2, 5), YYCC_U8("YYCC_VERCMP_G")); + Assert(YYCC_VERCMP_GE(1, 2, 3, 1, 2, 3), YYCC_U8("YYCC_VERCMP_GE")); + Assert(YYCC_VERCMP_NL(1, 2, 3, 1, 2, 3), YYCC_U8("YYCC_VERCMP_NL")); + Assert(YYCC_VERCMP_L(0, 2, 5, 1, 2, 3), YYCC_U8("YYCC_VERCMP_L")); + Assert(YYCC_VERCMP_LE(1, 2, 3, 1, 2, 3), YYCC_U8("YYCC_VERCMP_LE")); + Assert(YYCC_VERCMP_NG(1, 2, 3, 1, 2, 3), YYCC_U8("YYCC_VERCMP_NG")); + } + enum class TestEnum : int8_t { Test1, Test2, Test3 }; @@ -698,6 +709,12 @@ auto al = YYCC::ArgParser::ArgumentList::CreateFromStd(sizeof(test_argv) / sizeo } int main(int argc, char* argv[]) { + +#if YYCC_VERCMP_NE(YYCC_VER_MAJOR, YYCC_VER_MINOR, YYCC_VER_PATCH, 1, 3 ,0) +#error "The YYCC library used when compiling is not match code expected, this may cause build error." +#error "If you trust it, please annotate these preprocessor statement, otherwise please contact developer." +#endif + // common testbench // normal YYCCTestbench::EncodingTestbench(); @@ -706,6 +723,7 @@ int main(int argc, char* argv[]) { YYCCTestbench::WinFctTestbench(); YYCCTestbench::StdPatchTestbench(); YYCCTestbench::EnumHelperTestbench(); + YYCCTestbench::VersionMacroTestbench(); // advanced YYCCTestbench::ConfigManagerTestbench(); YYCCTestbench::ArgParserTestbench(argc, argv);