diff --git a/.circleci/config.yml b/.circleci/config.yml index 871dac4..06266a6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -24,7 +24,7 @@ jobs: - run: name: Building and testing with clang 9 command: | - CXX=clang++-9 meson build --buildtype=debug -DGENERATE_CMAKE_CONFIG=disabled -DBUILD_EXAMPLES=disabled + CXX=clang++-9 meson build --buildtype=debug -Dpedantic=true -Dbuild_tests=true -Dbuild_examples=true -Dgenerate_cmake_config=false cd build && ninja -v -j 4 && ninja test release_clang9: @@ -49,7 +49,7 @@ jobs: - run: name: Building and testing with clang 9 command: | - CXX=clang++-9 meson build --buildtype=release -DGENERATE_CMAKE_CONFIG=disabled -DBUILD_EXAMPLES=disabled + CXX=clang++-9 meson build --buildtype=release -Dpedantic=true -Dbuild_tests=true -Dbuild_examples=true -Dgenerate_cmake_config=false cd build && ninja -v -j 4 && ninja test debug_gcc9: @@ -70,7 +70,7 @@ jobs: - run: name: Building and testing with gcc9 command: | - CXX=g++-9 meson build --buildtype=debug -DGENERATE_CMAKE_CONFIG=disabled -DBUILD_EXAMPLES=disabled + CXX=g++-9 meson build --buildtype=debug -Dpedantic=true -Dbuild_tests=true -Dbuild_examples=true -Dgenerate_cmake_config=false cd build && ninja -v -j 4 && ninja test release_gcc9: @@ -91,7 +91,7 @@ jobs: - run: name: Building and testing with gcc9 command: | - CXX=g++-9 meson build --buildtype=release -DGENERATE_CMAKE_CONFIG=disabled -DBUILD_EXAMPLES=disabled + CXX=g++-9 meson build --buildtype=release -Dpedantic=true -Dbuild_tests=true -Dbuild_examples=true -Dgenerate_cmake_config=false cd build && ninja -v -j 4 && ninja test generate_dox: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 13defa0..9b55cdb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -39,27 +39,27 @@ If test discovery fails you can usually fix it by enabling # install ninja, meson, locales (first time only) sudo apt update && sudo apt install -y locales python3 python3-pip ninja-build sudo pip3 install meson -sudo locale-gen 'en_US.utf8' \ - 'ja_JP.utf8' \ - 'de_DE.utf8' \ - 'it_IT.utf8' \ - 'tr_TR.utf8' \ - 'fi_FI.utf8' \ - 'fr_FR.utf8' \ - 'zh_CN.utf8' +sudo locale-gen 'en_US.utf8' \ + 'ja_JP.utf8' \ + 'de_DE.utf8' \ + 'it_IT.utf8' \ + 'tr_TR.utf8' \ + 'fi_FI.utf8' \ + 'fr_FR.utf8' \ + 'zh_CN.utf8' # create the build configs (first time only) -CXX=g++ meson build-gcc-debug -DGENERATE_CMAKE_CONFIG=disabled -DALL_WARNINGS=true -CXX=clang++ meson build-clang-debug -DGENERATE_CMAKE_CONFIG=disabled -DALL_WARNINGS=true -CXX=g++ meson build-gcc-release -DGENERATE_CMAKE_CONFIG=disabled -DALL_WARNINGS=true --buildtype=release -CXX=clang++ meson build-clang-release -DGENERATE_CMAKE_CONFIG=disabled -DALL_WARNINGS=true --buildtype=release +CXX=g++ meson build-gcc-debug --buildtype=debug -Dpedantic=true -Dbuild_tests=true -Dgenerate_cmake_config=false +CXX=clang++ meson build-clang-debug --buildtype=debug -Dpedantic=true -Dbuild_tests=true -Dgenerate_cmake_config=false +CXX=g++ meson build-gcc-release --buildtype=release -Dpedantic=true -Dbuild_tests=true -Dgenerate_cmake_config=false +CXX=clang++ meson build-clang-release --buildtype=release -Dpedantic=true -Dbuild_tests=true -Dgenerate_cmake_config=false # run the tests -cd build-gcc-debug && ninja && ninja test \ - && cd ../build-clang-debug && ninja && ninja test \ - && cd ../build-gcc-release && ninja && ninja test \ - && cd ../build-clang-release && ninja && ninja test \ - && cd .. +cd build-gcc-debug && ninja && ninja test \ + && cd ../build-clang-debug && ninja && ninja test \ + && cd ../build-gcc-release && ninja && ninja test \ + && cd ../build-clang-release && ninja && ninja test \ + && cd .. ``` diff --git a/examples/meson.build b/examples/meson.build index 28eced0..1b67114 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -1,33 +1,22 @@ -args = [] - -if compiler.get_id() == 'gcc' or compiler.get_id() == 'clang' - args += [ '-Wno-switch', '-Wno-switch-default', '-Wno-switch-enum' ] +example_args = [] +example_args += additional_arguments +if is_gcc or is_clang + example_args += [ '-Wno-switch', '-Wno-switch-default', '-Wno-switch-enum' ] endif -simple_parser = executable( +examples = [ 'simple_parser', - [ 'simple_parser.cpp' ], - include_directories : inc, - cpp_args : args -) - -toml_to_json_transcoder = executable( 'toml_to_json_transcoder', - [ 'toml_to_json_transcoder.cpp' ], - include_directories : inc, - cpp_args : args -) - -toml_generator = executable( 'toml_generator', - [ 'toml_generator.cpp' ], - include_directories : inc, - cpp_args : args -) + 'error_printer' +] -error_printer = executable( - 'error_printer', - [ 'error_printer.cpp' ], - include_directories : inc, - cpp_args : args -) +foreach example : examples + executable( + example, + [ example+'.cpp' ], + include_directories : include_dirs, + cpp_args : example_args, + override_options: overrides + ) +endforeach diff --git a/meson.build b/meson.build index 77cbd94..c2ad0bc 100644 --- a/meson.build +++ b/meson.build @@ -2,182 +2,482 @@ project( 'tomlplusplus', 'cpp', version : '2.1.0', + meson_version : '>=0.53.0', license : 'MIT', default_options : [ - 'cpp_std=c++17', + # core options + 'buildtype=release', 'warning_level=3', 'werror=true', - 'cpp_eh=default', - 'b_ndebug=if-release' + 'layout=flat', + + # base options + 'b_lto=true', + 'b_ndebug=if-release', + + # compiler options + 'cpp_std=c++17' ] ) +####################################################################################################################### +# compiler management +####################################################################################################################### + +compiler = meson.get_compiler('cpp') +message(['target cpu_family', host_machine.cpu_family()]) +message(['target cpu', host_machine.cpu()]) +message(['target system', host_machine.system()]) +message(['target endian', host_machine.endian()]) + +is_gcc = compiler.get_id() == 'gcc' +is_clang = compiler.get_id() == 'clang' +is_msvc = compiler.get_id() == 'msvc' +is_icc_cl = compiler.get_id() == 'intel-cl' +is_icc = is_icc_cl or compiler.get_id() == 'intel' +is_debug = get_option('debug') +is_release = not is_debug +is_pedantic = get_option('pedantic') +is_windows = host_machine.system() == 'windows' +is_x64 = host_machine.cpu_family() == 'x86_64' +is_subproject = meson.is_subproject() +has_exceptions = get_option('cpp_eh') != 'none' +include_dirs = include_directories('include', 'extern') +overrides = [] +additional_arguments = [] + +message(['is_release', is_release]) +message(['is_windows', is_windows]) +message(['is_x64', is_x64]) + +# compiler argument references: +# msvc: https://docs.microsoft.com/en-us/cpp/build/reference/compiler-options-listed-alphabetically?view=vs-2019 +# intel and intel-cl: https://software.intel.com/content/www/us/en/develop/documentation/cpp-compiler-oneapi-dev-guide-and-reference/top/compiler-reference/compiler-options/alphabetical-list-of-compiler-options.html +# gcc: +# clang: + +# GCC or Clang +if is_gcc or is_clang + add_project_arguments( + '-march=native', + language : 'cpp' + ) + if is_release + add_project_arguments( + '-fdata-sections', + '-ffunction-sections', + '-Wl,--gc-sections', + '-Wl,-s', + language : 'cpp' + ) + endif +endif + +# GCC +if is_gcc + add_project_arguments( + '-fmax-errors=5', + '-Wno-init-list-lifetime', + language : 'cpp' + ) + if is_pedantic + add_project_arguments([ + '-Wcast-align', + '-Wcast-qual', + '-Wctor-dtor-privacy', + '-Wdisabled-optimization', + '-Wextra', + '-Wfloat-equal', + '-Wimport', + '-Winit-self', + '-Wlogical-op', + '-Wmissing-declarations', + '-Wmissing-field-initializers', + '-Wmissing-format-attribute', + '-Wmissing-include-dirs', + '-Wmissing-noreturn', + '-Wnoexcept', + '-Wold-style-cast', + '-Woverloaded-virtual', + '-Wpacked', + '-Wpadded', + '-Wpedantic', + '-Wpointer-arith', + '-Wredundant-decls', + '-Wshadow', + '-Wsign-conversion', + '-Wsign-promo', + '-Wstack-protector', + '-Wstrict-null-sentinel', + '-Wswitch-default', + '-Wswitch-enum', + '-Wundef', + '-Wunreachable-code', + '-Wunused', + '-Wunused-parameter', + '-Wvariadic-macros', + '-Wwrite-strings', + '-Wmissing-noreturn', + '-Wsuggest-attribute=const', + '-Wsuggest-attribute=pure' + ], + language : 'cpp' + ) + endif + if is_release + add_project_arguments('-fmerge-constants', language : 'cpp') + endif +endif + +# Clang +if is_clang + if is_pedantic + add_project_arguments('-Weverything', language : 'cpp') + endif + add_project_arguments( + '-ferror-limit=5', + '-Wno-unused-command-line-argument', + + # flags from here down are disabling stupidly pedantic warnings that only appear with -Weverything + '-Wno-c++98-compat', + '-Wno-c++98-compat-pedantic', + '-Wno-documentation', + '-Wno-documentation-unknown-command', + '-Wno-switch-enum', + '-Wno-covered-switch-default', + language : 'cpp' + ) + if get_option('time_trace') + add_project_arguments('-ftime-trace', language : 'cpp') + endif + if is_release + add_project_arguments('-Oz', '-fmerge-all-constants', language : 'cpp') + endif +endif + +# MSVC or icc-cl +if is_msvc or is_icc_cl + add_project_arguments( + '/bigobj', + '/fp:except-', # disable floating-point exceptions + '/Gy', # function-level linking + '/GF', # string pooling + '/openmp-', + '/permissive-', + '/sdl-', + '/utf-8', + '/volatile:iso', + '/Zc:__cplusplus', + '/Zc:inline', + '/Zc:throwingNew', + '/Zi', # generate debug info (doesn't affect optimization) + language : 'cpp' + ) + add_project_link_arguments('/DEBUG', language : 'cpp') # generate PDB (doesn't affect optimization) + if is_release + add_project_arguments( + '/GL', # whole program optimization + '/Gw', # Optimize Global Data + '/Ob3', # aggressive inlining + '/Oy', # omit frame pointers + '/Oi', # generate intrinsics + language : 'cpp' + ) + add_project_link_arguments('/ltcg', language : 'cpp') + endif + if is_pedantic + add_project_arguments('/W4', language : 'cpp') + endif + if is_x64 + add_project_arguments('/arch:AVX', language : 'cpp') + endif +endif + +# icc-cl +if is_icc_cl + add_project_arguments( + '/wd82', # storage class is not first + '/wd177', # unreferenced var + '/wd280', # selector expression is constant (why the fuck is that a warning?) + '/wd411', # class provides no constructor (duh, it's an aggregate) + '/wd869', # parameter "blah" was never referenced + '/wd1011', # missing return statement (false negative) + '/wd1628', # function marked [[noreturn]] returns (false positive) + '/wd2261', # assume with side effects discarded + '/wd2557', # mismatched sign compare + '/wd3280', # declaration hides member (triggered in Catch2) + language : 'cpp' + ) +endif + +# icc (any) +if is_icc + add_project_arguments( + '/Qdiag-error-limit:5', + '/Qoption,cpp,--unicode_source_kind,UTF-8', + '/D__builtin_bit_cast(T, v)=([&]()noexcept{ T val; memcpy(&val, &v, sizeof(T)); return val; })()', # __builtin_bit_cast workaround + language : 'cpp' + ) +endif + +# windows stuff +if is_windows + add_project_arguments( + '-D_ITERATOR_DEBUG_LEVEL=0', + '-D_WINSOCK_DEPRECATED_NO_WARNINGS', + '-D_SCL_SECURE_NO_WARNINGS', + '-D_CRT_SECURE_NO_WARNINGS', + language : 'cpp' + ) + add_project_arguments(has_exceptions ? '-D_HAS_EXCEPTIONS=1' : '-D_HAS_EXCEPTIONS=0', language : 'cpp') +elif is_release + overrides += 'strip=true' +endif + +####################################################################################################################### +# c++ 20 check +# (used by tests) +####################################################################################################################### + +compiler_supports_cpp20_args = [] +if is_gcc or is_clang + compiler_supports_cpp20_args += '-std=c++2a' +elif is_icc + compiler_supports_cpp20_args += '/Qstd=c++2a' +elif is_msvc + compiler_supports_cpp20_args += '/std:c++latest' +endif +compiler_supports_cpp20 = compiler_supports_cpp20_args.length() > 0 and compiler.links(''' + #include + #include + #include + + int main() + { + std::string s = "kek"; + std::cout << s << std::endl; + return 0; + } + ''', + name : 'supports c++20', + args : compiler_supports_cpp20_args +) + +####################################################################################################################### +# char8_t check +# (used by tests) +####################################################################################################################### + +compiler_supports_char8_args = [] +if is_gcc or is_clang + compiler_supports_char8_args += '-fchar8_t' +endif +compiler_supports_char8_args_private = [] +compiler_supports_char8_args_private += compiler_supports_cpp20_args +compiler_supports_char8_args_private += compiler_supports_char8_args +compiler_supports_char8 = compiler_supports_cpp20 and compiler.links(''' + #include + #include + #include + #include + using namespace std::string_view_literals; + + #ifndef __cpp_lib_char8_t + #error oh noes + #endif + + static_assert(!std::is_same_v); + static_assert(!std::is_same_v); + + std::u8string func() + { + return std::u8string{ u8"this is a test."sv }; + } + + int main() + { + return 0; + } + ''', + name : 'supports char8_t', + args : compiler_supports_char8_args_private +) + +####################################################################################################################### +# consteval check +# (this doesn't inform the build in any way; it's just so i can see who supports it) +####################################################################################################################### + +compiler_supports_consteval = compiler_supports_cpp20 and compiler.compiles(''' + + consteval int kek() noexcept + { + return 42; + } + + int main() + { + return kek(); + } + ''', + name : 'supports consteval', + args : compiler_supports_cpp20_args +) + +####################################################################################################################### +# __fp16 and _Float16 checks +####################################################################################################################### + +float_16_preprocessor_single_check_template = ''' + #ifndef @0@ + #error @0@ wasn't defined! + #else + #pragma message("@0@: " MAKE_STRING(@0@)) + #endif + #if @0@ != @1@ + #error @0@ was not @1@! + #endif +''' +float_16_preprocessor_checks = ''' + #define MAKE_STRING(s) MAKE_STRING_1(s) + #define MAKE_STRING_1(s) #s + ''' + float_16_preprocessor_single_check_template.format('__FLT_RADIX__', '2') \ + + float_16_preprocessor_single_check_template.format('__FLT16_MANT_DIG__', '11') \ + + float_16_preprocessor_single_check_template.format('__FLT16_DIG__', '3') \ + + float_16_preprocessor_single_check_template.format('__FLT16_MIN_EXP__', '-13') \ + + float_16_preprocessor_single_check_template.format('__FLT16_MIN_10_EXP__', '-4') \ + + float_16_preprocessor_single_check_template.format('__FLT16_MAX_EXP__', '16') \ + + float_16_preprocessor_single_check_template.format('__FLT16_MAX_10_EXP__', '4') + +compiler_supports_float16_args = [] +if is_gcc + compiler_supports_float16_args += '-mfp16-format=ieee' +endif +compiler_supports_fp16 = compiler.links(''' + @0@ + + int main() + { + static_assert(sizeof(__fp16) == 2); + __fp16 f = static_cast<__fp16>(1); + const auto f2 = static_cast(f); + const auto f3 = static_cast<__fp16>(0.2L); + return 0; + } + '''.format(float_16_preprocessor_checks), + name : 'supports __fp16', + args : compiler_supports_float16_args +) +compiler_supports_float16 = compiler.links(''' + @0@ + + int main() + { + static_assert(sizeof(_Float16) == 2); + _Float16 f = static_cast<_Float16>(1); + const auto f2 = static_cast(f); + const auto f3 = static_cast<_Float16>(0.2L); + return 0; + } + '''.format(float_16_preprocessor_checks), + name : 'supports _Float16', + args : compiler_supports_float16_args +) +if compiler_supports_fp16 or compiler_supports_float16 + additional_arguments += compiler_supports_float16_args +endif + +####################################################################################################################### +# int128 check +####################################################################################################################### + +compiler_supports_int128 = compiler.links(''' + #ifndef __SIZEOF_INT128__ + #error __SIZEOF_INT128__ wasn't defined! + #endif + + #include + + int main() + { + static_assert(__SIZEOF_INT128__ == 16); + static_assert(sizeof(__int128_t) == 16); + static_assert(sizeof(__uint128_t) == 16); + __int128_t i = static_cast<__int128_t>(1); + const auto i2 = static_cast(i); + const auto i3 = static_cast(i); + return 0; + } + ''', + name : 'supports __int128_t' +) + +####################################################################################################################### +# float128 check +####################################################################################################################### + +compiler_supports_float128 = compiler.links(''' + #ifndef __SIZEOF_FLOAT128__ + #error __SIZEOF_FLOAT128__ wasn't defined! + #endif + #ifndef __FLT128_MANT_DIG__ + #error __FLT128_MANT_DIG__ wasn't defined! + #endif + #ifndef __LDBL_MANT_DIG__ + #error __LDBL_MANT_DIG__ wasn't defined! + #endif + #if __FLT128_MANT_DIG__ <= __LDBL_MANT_DIG__ + #error __FLT128_MANT_DIG__ was <= __LDBL_MANT_DIG__ + #endif + int main() + { + static_assert(__SIZEOF_FLOAT128__ == 16); + static_assert(sizeof(__float128) == 16); + __float128 f = static_cast<__float128>(1); + const auto f2 = static_cast(f); + const auto f3 = static_cast(f); + return 0; + } + ''', + name : 'supports __float128' +) + +if compiler_supports_float16 or compiler_supports_int128 or compiler_supports_float128 + if is_gcc + additional_arguments += '-fext-numeric-literals' + endif +endif + +####################################################################################################################### +# subdirectories +####################################################################################################################### + +build_tests = get_option('build_tests') and not is_subproject +if build_tests + run_command('git', 'submodule', 'update', '--init', 'extern/Catch2') + run_command('git', 'submodule', 'update', '--init', 'extern/tloptional') + subdir('tests') +endif + +build_examples = get_option('build_examples') and not is_subproject +if build_examples + subdir('examples') +endif + +install_subdir('include/toml++', + strip_directory: true, + install_dir: 'include/toml++' +) + +####################################################################################################################### +# dependencies, cmake etc. +####################################################################################################################### + tomlplusplus_dep = declare_dependency( include_directories : include_directories('include'), version : meson.project_version(), ) -build_tests = get_option('BUILD_TESTS').enabled() or (get_option('BUILD_TESTS').auto() and not meson.is_subproject()) -build_examples = get_option('BUILD_EXAMPLES').enabled() or (get_option('BUILD_EXAMPLES').auto() and not meson.is_subproject()) - -if build_tests or build_examples - - compiler = meson.get_compiler('cpp') - message(['compiler ID: ', compiler.get_id()]) - message(['compiler version: ', compiler.version()]) - - # intel-cl __builtin_bit_cast workaround - if compiler.get_id() == 'intel-cl' - add_project_arguments([ - '/D__builtin_bit_cast(x,y)=x{}' - ], - language : 'cpp' - ) - endif - - # GCC or Clang - if compiler.get_id() == 'gcc' or compiler.get_id() == 'clang' - add_project_arguments([ - '-march=native', - '-fno-rtti', - ], - language : 'cpp' - ) - if get_option('SMALL_BINARIES') - add_project_arguments([ '-fdata-sections', '-ffunction-sections', '-Wl,--gc-sections', '-Wl,-s' ], language : 'cpp') - endif - endif - - # GCC - if compiler.get_id() == 'gcc' - add_project_arguments([ - '-fmax-errors=5', - '-Wno-init-list-lifetime' - ], - language : 'cpp' - ) - if get_option('ALL_WARNINGS') - add_project_arguments([ - '-Wcast-align', - '-Wcast-qual', - '-Wctor-dtor-privacy', - '-Wdisabled-optimization', - '-Wextra', - '-Wfloat-equal', - '-Wimport', - '-Winit-self', - '-Wlogical-op', - '-Wmissing-declarations', - '-Wmissing-field-initializers', - '-Wmissing-format-attribute', - '-Wmissing-include-dirs', - '-Wmissing-noreturn', - '-Wnoexcept', - '-Wold-style-cast', - '-Woverloaded-virtual', - '-Wpacked', - '-Wpadded', - '-Wpedantic', - '-Wpointer-arith', - '-Wredundant-decls', - '-Wshadow', - '-Wsign-conversion', - '-Wsign-promo', - '-Wstack-protector', - '-Wstrict-null-sentinel', - '-Wswitch-default', - '-Wswitch-enum', - '-Wundef', - '-Wunreachable-code', - '-Wunused', - '-Wunused-parameter', - '-Wvariadic-macros', - '-Wwrite-strings', - '-Wmissing-noreturn', - '-Wsuggest-attribute=const', - '-Wsuggest-attribute=pure' - ], - language : 'cpp' - ) - endif - if get_option('SMALL_BINARIES') - add_project_arguments([ '-fmerge-constants' ], language : 'cpp') - endif - endif - - # Clang - if compiler.get_id() == 'clang' - - if get_option('ALL_WARNINGS') - add_project_arguments([ '-Weverything' ], language : 'cpp') - endif - add_project_arguments([ - '-ferror-limit=5', - '-Wno-unused-command-line-argument', - - # flags from here down are disabling stupidly pedantic warnings that only appear with -Weverything - '-Wno-c++98-compat', - '-Wno-c++98-compat-pedantic', - '-Wno-documentation', - '-Wno-documentation-unknown-command', - '-Wno-switch-enum', - '-Wno-covered-switch-default' - ], - language : 'cpp' - ) - if get_option('TIME_TRACE') - add_project_arguments([ '-ftime-trace' ], language : 'cpp') - endif - if get_option('SMALL_BINARIES') - add_project_arguments([ '-Oz', '-fmerge-all-constants', '-Wl,--build-id' ], language : 'cpp') - endif - endif - - # msvc - if compiler.get_id() == 'msvc' - add_project_arguments([ - '/utf-8' - ], - language : 'cpp' - ) - endif - - # ICC's visual studio frontend, ICL - if compiler.get_id() == 'intel-cl' - add_project_arguments([ - '/Qoption,cpp,--unicode_source_kind,UTF-8', - '/wd82', # storage class is not first - '/wd280', # selector expression is constant (why the fuck is that a warning?) - '/wd411', # class provides no constructor (duh, it's an aggregate) - '/wd1011', # missing return statement (false negative) - '/wd1628', # function marked [[noreturn]] returns (false positive) - '/wd3280' # declaration hides member (triggered in Catch2) - ], - language : 'cpp' - ) - endif - - inc = include_directories('include', 'extern') - - if build_tests - subdir('tests') - else - message('Not building tests') - endif - - if build_examples - subdir('examples') - else - message('Not building examples') - endif - -endif - -install_subdir('include/toml++/', - strip_directory: true, - install_dir: 'include/toml++' -) - pkgc = import('pkgconfig') pkgc.generate ( name: meson.project_name(), @@ -185,20 +485,18 @@ pkgc.generate ( description: 'Header-only TOML config file parser and serializer for modern C++' ) -# meson cmake stuff requires at least 0.50 -if meson.version().version_compare('>= 0.50') - if get_option('GENERATE_CMAKE_CONFIG').enabled() or (get_option('GENERATE_CMAKE_CONFIG').auto() and not meson.is_subproject()) - cmake = import('cmake') - cmake.write_basic_package_version_file( - name: meson.project_name(), - version: meson.project_version() - ) +# cmake +if get_option('generate_cmake_config') and not is_subproject + cmake = import('cmake') + cmake.write_basic_package_version_file( + name: meson.project_name(), + version: meson.project_version() + ) - cmake_conf = configuration_data() - cmake.configure_package_config_file( - name: meson.project_name(), - input: 'cmake/tomlplusplus.cmake.in', - configuration: cmake_conf, - ) - endif + cmake_conf = configuration_data() + cmake.configure_package_config_file( + name: meson.project_name(), + input: 'cmake/tomlplusplus.cmake.in', + configuration: cmake_conf, + ) endif diff --git a/meson_options.txt b/meson_options.txt index 06eec30..d9893ad 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1,6 +1,5 @@ -option('BUILD_TESTS', type : 'feature', value : 'auto', description : 'Build tests (default: auto - only if not a subproject)') -option('BUILD_EXAMPLES', type : 'feature', value : 'auto', description : 'Build examples (default: auto - only if not a subproject)') -option('GENERATE_CMAKE_CONFIG', type : 'feature', value : 'auto', description : 'Generate a cmake package config file (default: auto - only if not a subproject)') -option('ALL_WARNINGS', type : 'boolean', value : false, description : 'Enable all the extra super-extremely-pedantic compiler warnings') -option('TIME_TRACE', type : 'boolean', value : false, description : 'Enable the -ftime-trace option (Clang only)') -option('SMALL_BINARIES', type : 'boolean', value : false, description : 'Add some flags to try to generate the smallest binary possible') +option('build_tests', type: 'boolean', value: false, description: 'Build tests (default: false - no effect when included as a subproject)') +option('build_examples', type: 'boolean', value: false, description: 'Build examples (default: false - no effect when included as a subproject)') +option('generate_cmake_config', type: 'boolean', value: true, description: 'Generate a cmake package config file (default: true - no effect when included as a subproject)') +option('pedantic', type: 'boolean', value: false, description: 'Enable as many compiler warnings as possible (default: false)') +option('time_trace', type: 'boolean', value: false, description: 'Enable the -ftime-trace option (Clang only)') diff --git a/tests/meson.build b/tests/meson.build index 1df30ec..5115788 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -24,225 +24,6 @@ test_sources = [ 'windows_compat.cpp' ] -# compiler argument references: -# msvc: https://docs.microsoft.com/en-us/cpp/build/reference/compiler-options-listed-alphabetically?view=vs-2019 -# intel and intel-cl: https://software.intel.com/content/www/us/en/develop/documentation/cpp-compiler-oneapi-dev-guide-and-reference/top/compiler-reference/compiler-options/alphabetical-list-of-compiler-options.html -# gcc: -# clang: - -####################################################################################################################### -# c++ 20 check -####################################################################################################################### - -compiler_supports_cpp20_args = [] -if compiler.get_id() == 'gcc' or compiler.get_id() == 'clang' - compiler_supports_cpp20_args += '-std=c++2a' -elif compiler.get_id() == 'intel-cl' - compiler_supports_cpp20_args += '/Qstd=c++2a' -elif compiler.get_id() == 'msvc' - compiler_supports_cpp20_args += '/std=c++latest' -endif -compiler_supports_cpp20 = compiler.links(''' - #include - #include - #include - - int main() - { - std::string s = "kek"; - std::cout << s << "\n"; - return 0; - } - ''', - name : 'supports c++20', - args : compiler_supports_cpp20_args -) - -####################################################################################################################### -# char8_t check -####################################################################################################################### - -compiler_supports_char8_args = [] -compiler_supports_char8_args += compiler_supports_cpp20_args -if compiler.get_id() == 'gcc' or compiler.get_id() == 'clang' - compiler_supports_char8_args += '-fchar8_t' -endif -compiler_supports_char8 = compiler_supports_cpp20 and compiler.links(''' - #include - #include - #include - #include - using namespace std::string_view_literals; - - #ifndef __cpp_lib_char8_t - #error oh noes - #endif - - static_assert(!std::is_same_v); - static_assert(!std::is_same_v); - - std::u8string func() - { - return std::u8string{ u8"this is a test."sv }; - } - - int main() - { - return 0; - } - ''', - name : 'supports char8_t', - args : compiler_supports_char8_args -) - -####################################################################################################################### -# consteval check -####################################################################################################################### - -compiler_supports_consteval = compiler_supports_cpp20 and compiler.compiles(''' - - consteval int kek() noexcept - { - return 42; - } - - int main() - { - return kek(); - } - ''', - name : 'supports consteval', - args : compiler_supports_cpp20_args -) - -####################################################################################################################### -# __fp16 and _Float16 checks -####################################################################################################################### - -float_16_preprocessor_single_check_template = ''' - #ifndef @0@ - #error @0@ wasn't defined! - #else - #pragma message("@0@: " MAKE_STRING(@0@)) - #endif - #if @0@ != @1@ - #error @0@ was not @1@! - #endif - -''' -float_16_preprocessor_checks = ''' - #define MAKE_STRING(s) MAKE_STRING_1(s) - #define MAKE_STRING_1(s) #s - ''' + float_16_preprocessor_single_check_template.format('__FLT_RADIX__', '2') \ - + float_16_preprocessor_single_check_template.format('__FLT16_MANT_DIG__', '11') \ - + float_16_preprocessor_single_check_template.format('__FLT16_DIG__', '3') \ - + float_16_preprocessor_single_check_template.format('__FLT16_MIN_EXP__', '-13') \ - + float_16_preprocessor_single_check_template.format('__FLT16_MIN_10_EXP__', '-4') \ - + float_16_preprocessor_single_check_template.format('__FLT16_MAX_EXP__', '16') \ - + float_16_preprocessor_single_check_template.format('__FLT16_MAX_10_EXP__', '4') - -compiler_disable_optimizations = '' -if compiler.get_id() == 'gcc' or compiler.get_id() == 'clang' - compiler_disable_optimizations = '-O0' -elif compiler.get_id() == 'msvc' or compiler.get_id() == 'intel-cl' - compiler_disable_optimizations = '/Od' -endif - -compiler_supports_float16_args = [ compiler_disable_optimizations ] -if compiler.get_id() == 'gcc' - compiler_supports_float16_args += '-mfp16-format=ieee' - compiler_supports_float16_args += '-fmax-errors=1' -elif compiler.get_id() == 'clang' - compiler_supports_float16_args += '-ferror-limit=1' -endif -compiler_supports_fp16 = compiler.links(''' - @0@ - - int main() - { - static_assert(sizeof(__fp16) == 2); - __fp16 f = static_cast<__fp16>(1); - const auto f2 = static_cast(f); - const auto f3 = static_cast<__fp16>(0.2L); - return 0; - } - '''.format(float_16_preprocessor_checks), - name : 'supports __fp16', - args : compiler_supports_float16_args -) -compiler_supports_float16 = compiler.links(''' - @0@ - - int main() - { - static_assert(sizeof(_Float16) == 2); - _Float16 f = static_cast<_Float16>(1); - const auto f2 = static_cast(f); - const auto f3 = static_cast<_Float16>(0.2L); - return 0; - } - '''.format(float_16_preprocessor_checks), - name : 'supports _Float16', - args : compiler_supports_float16_args -) - -####################################################################################################################### -# int128 check -####################################################################################################################### - -compiler_supports_int128 = compiler.links(''' - #ifndef __SIZEOF_INT128__ - #error __SIZEOF_INT128__ wasn't defined! - #endif - - #include - - int main() - { - static_assert(__SIZEOF_INT128__ == 16); - static_assert(sizeof(__int128_t) == 16); - static_assert(sizeof(__uint128_t) == 16); - __int128_t i = static_cast<__int128_t>(1); - const auto i2 = static_cast(i); - const auto i3 = static_cast(i); - return 0; - } - ''', - name : 'supports __int128_t', - args : [ compiler_disable_optimizations ] -) - -####################################################################################################################### -# float128 check -####################################################################################################################### - -compiler_supports_float128 = compiler.links(''' - #ifndef __SIZEOF_FLOAT128__ - #error __SIZEOF_FLOAT128__ wasn't defined! - #endif - #ifndef __FLT128_MANT_DIG__ - #error __FLT128_MANT_DIG__ wasn't defined! - #endif - #ifndef __LDBL_MANT_DIG__ - #error __LDBL_MANT_DIG__ wasn't defined! - #endif - #if __FLT128_MANT_DIG__ <= __LDBL_MANT_DIG__ - #error __FLT128_MANT_DIG__ was <= __LDBL_MANT_DIG__ - #endif - int main() - { - static_assert(__SIZEOF_FLOAT128__ == 16); - static_assert(sizeof(__float128) == 16); - __float128 f = static_cast<__float128>(1); - const auto f2 = static_cast(f); - const auto f3 = static_cast(f); - return 0; - } - ''', - name : 'supports __float128', - args : [ compiler_disable_optimizations ] -) - ####################################################################################################################### # fast math check ####################################################################################################################### @@ -275,7 +56,7 @@ fast_math_modes = [ false, true ] exception_modes = [ true, false ] unreleased_feature_modes = [ false, true ] cpp20_modes = [ false, true ] -executables = [] +test_executables = [] counter = 0 foreach cpp20 : cpp20_modes @@ -289,94 +70,88 @@ foreach cpp20 : cpp20_modes endif foreach exceptions : exception_modes - name = '' - overrides = [] - args = [] + test_name = '' + test_overrides = [] + test_overrides += overrides + test_args = [] + test_args += additional_arguments - if cpp20 - name = 'cpp20' - overrides += 'cpp_std=none' - args += '-std=c++2a' + if cpp20 + test_name = 'cpp20' + test_overrides += 'cpp_std=none' + test_args += compiler_supports_cpp20_args + if compiler_supports_char8 + test_args += compiler_supports_char8_args + endif + else + test_name = 'cpp17' + endif - if compiler_supports_char8 - args += '-fchar8_t' - endif - else - name = 'cpp17' + if exceptions + test_overrides += 'cpp_eh=default' + test_args += '-DSHOULD_HAVE_EXCEPTIONS=1' + if is_windows + test_args += '-D_HAS_EXCEPTIONS=1' endif + else + test_name = test_name + '_noexcept' + test_overrides += 'cpp_eh=none' + test_args += '-DSHOULD_HAVE_EXCEPTIONS=0' + if is_windows + test_args += '-D_HAS_EXCEPTIONS=0' + endif + endif - if exceptions - args += '-DSHOULD_HAVE_EXCEPTIONS=1' - else - name = name + '_noexcept' - overrides += 'cpp_eh=none' - args += '-DSHOULD_HAVE_EXCEPTIONS=0' - endif + if fast_math + test_name = test_name + '_fastmath' + test_args += compiler_supports_fast_math_args + endif - if fast_math - name = name + '_fastmath' - if compiler.get_id() == 'gcc' or compiler.get_id() == 'clang' - args += '-ffast-math' - args += '-ffp-contract=fast' - endif + if compiler_supports_float16 or compiler_supports_fp16 + if compiler_supports_fp16 + test_args += '-DSHOULD_HAVE_FP16=1' endif + if compiler_supports_float16 + test_args += '-DSHOULD_HAVE_FLOAT16=1' + endif + endif + if compiler_supports_int128 + test_args += '-DSHOULD_HAVE_INT128=1' + endif + if compiler_supports_float128 + test_args += '-DSHOULD_HAVE_FLOAT128=1' + endif - if compiler_supports_float16 or compiler_supports_fp16 - if compiler.get_id() == 'gcc' - args += '-mfp16-format=ieee' - endif - if compiler_supports_fp16 - args += '-DSHOULD_HAVE_FP16=1' - endif - if compiler_supports_float16 - args += '-DSHOULD_HAVE_FLOAT16=1' - endif - endif + if unrel + test_name = test_name + '_unrel' + test_args += '-DTOML_UNRELEASED_FEATURES=1' + else + test_args += '-DTOML_UNRELEASED_FEATURES=0' + endif - if compiler_supports_int128 - args += '-DSHOULD_HAVE_INT128=1' - endif - - if compiler_supports_float128 - args += '-DSHOULD_HAVE_FLOAT128=1' - endif + if counter % 6 == 3 + test_args += '-DTOML_HEADER_ONLY=1' + endif + if counter % 2 == 1 + test_args += '-DUSE_SINGLE_HEADER=1' + endif + if counter % 4 == 2 and exceptions + test_args += '-DUSE_TARTANLLAMA_OPTIONAL=1' + test_name = test_name + '_tlopt' + endif + + test_executables += [[ + test_name, + executable( + test_name, + test_sources, + include_directories : include_dirs, + cpp_args : test_args, + override_options : test_overrides + ) + ]] - if compiler_supports_float16 or compiler_supports_int128 or compiler_supports_float128 - if compiler.get_id() == 'gcc' - args += '-fext-numeric-literals' - endif - endif - - if unrel - name = name + '_unrel' - args += '-DTOML_UNRELEASED_FEATURES=1' - else - args += '-DTOML_UNRELEASED_FEATURES=0' - endif - - if counter % 6 == 3 - args += '-DTOML_HEADER_ONLY=1' - endif - if counter % 2 == 1 - args += '-DUSE_SINGLE_HEADER=1' - endif - if counter % 4 == 2 and exceptions - args += '-DUSE_TARTANLLAMA_OPTIONAL=1' - name = name + '_tlopt' - endif - - executables += [[ - name, - executable( - name, - test_sources, - include_directories : inc, - cpp_args : args, - override_options : overrides - ) - ]] - - counter = counter + 1 + counter = counter + 1 endforeach # exceptions endforeach # fast_math @@ -395,7 +170,7 @@ locales = [ 'de_DE.utf8' ] -foreach executable : executables +foreach executable : test_executables foreach locale : locales test( executable[0] + ' (' + locale + ')', executable[1],