diff --git a/README.md b/README.md index 7f042c7..2a41bfa 100644 --- a/README.md +++ b/README.md @@ -228,7 +228,7 @@ UTF-8 decoding is performed using a state machine based on Bjoern Hoehrmann's '[ - **[@sneves](https://github.com/sneves)** - Helped fix a number of parser bugs - **[@sobczyk](https://github.com/sobczyk)** - Reported some bugs - **[@std-any-emplace](https://github.com/std-any-emplace)** - Reported some bugs -- **[@Tachi107](https://github.com/Tachi107)** - Made some tweaks to meson.build +- **[@Tachi107](https://github.com/Tachi107)** - Made some tweaks to meson.build, added compile_library build option - **[@traversaro](https://github.com/traversaro)** - Added vcpkg support and reported a bunch of bugs - **[@whiterabbit963](https://github.com/whiterabbit963)** - Fixed a bug with value_or conversions - **[@ximion](https://github.com/ximion)** - Added support for installation with meson diff --git a/cmake/tomlplusplus.cmake.in b/cmake/tomlplusplus.cmake.in deleted file mode 100644 index ef36b9f..0000000 --- a/cmake/tomlplusplus.cmake.in +++ /dev/null @@ -1,14 +0,0 @@ -@PACKAGE_INIT@ - -# If tomlplusplus::tomlplusplus target is not defined it will be included -if(NOT TARGET tomlplusplus::tomlplusplus) - - # Import tomlplusplus interface library - add_library(tomlplusplus::tomlplusplus INTERFACE IMPORTED) - set_target_properties(tomlplusplus::tomlplusplus PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "${PACKAGE_PREFIX_DIR}/@includedir@") - - # Require C++17 - target_compile_features(tomlplusplus::tomlplusplus INTERFACE cxx_std_17) - -endif() diff --git a/cmake/tomlplusplusConfig.cmake.meson.in b/cmake/tomlplusplusConfig.cmake.meson.in new file mode 100644 index 0000000..b007b68 --- /dev/null +++ b/cmake/tomlplusplusConfig.cmake.meson.in @@ -0,0 +1,29 @@ +@PACKAGE_INIT@ + +# If tomlplusplus::tomlplusplus target is not defined it will be included +if(NOT TARGET tomlplusplus::tomlplusplus) + + if (@compile_library@) + set(imported_type UNKNOWN) + else() + set(imported_type INTERFACE) + endif() + + # Import tomlplusplus interface library + add_library(tomlplusplus::tomlplusplus ${imported_type} IMPORTED) + set_target_properties(tomlplusplus::tomlplusplus PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${PACKAGE_PREFIX_DIR}/@includedir@") + + # Require C++17 + target_compile_features(tomlplusplus::tomlplusplus INTERFACE cxx_std_17) + + # Set the path to the installed library so that users can link to it + if (@compile_library@) + set_target_properties(tomlplusplus::tomlplusplus PROPERTIES + IMPORTED_LOCATION "${PACKAGE_PREFIX_DIR}/@libdir@/@lib_name@" + ) + # compile_options not quoted on purpose + target_compile_options(tomlplusplus::tomlplusplus INTERFACE @compile_options@) + endif() + +endif() diff --git a/cmake/tomlplusplusConfigVersion.cmake.in b/cmake/tomlplusplusConfigVersion.cmake.meson.in similarity index 100% rename from cmake/tomlplusplusConfigVersion.cmake.in rename to cmake/tomlplusplusConfigVersion.cmake.meson.in diff --git a/examples/error_printer.cpp b/examples/error_printer.cpp index 1a56bb2..a0ee735 100644 --- a/examples/error_printer.cpp +++ b/examples/error_printer.cpp @@ -7,9 +7,6 @@ // failures and printing their results. #include "examples.h" - -#define TOML_EXCEPTIONS 0 -#define TOML_ENABLE_UNRELEASED_FEATURES 0 #include using namespace std::string_view_literals; @@ -110,6 +107,24 @@ namespace int main() { + const auto parse_and_print_if_error = [](std::string_view str) + { +#if TOML_EXCEPTIONS + try + { + auto result = toml::parse(str); + static_cast(result); + } + catch (const toml::parse_error& err) + { + std::cout << err << "\n\n"sv; + } +#else + if (auto result = toml::parse(str); !result) + std::cout << result.error() << "\n\n"sv; +#endif + }; + for (auto str : invalid_parses) { if (str.empty()) @@ -133,13 +148,10 @@ int main() std::string s(1000u, '['); constexpr auto start = "array = "sv; memcpy(s.data(), start.data(), start.length()); - result = toml::parse(s); + parse_and_print_if_error(s); } else - result = toml::parse(str); - - if (!result) - std::cout << result.error() << "\n\n"sv; + parse_and_print_if_error(str); } } return 0; diff --git a/examples/examples.h b/examples/examples.h index 34a6bc3..b3d75be 100644 --- a/examples/examples.h +++ b/examples/examples.h @@ -25,6 +25,7 @@ #include #include #include +#include #ifdef _WIN32 #ifdef _MSC_VER extern "C" __declspec(dllimport) int __stdcall SetConsoleOutputCP(unsigned int); diff --git a/examples/meson.build b/examples/meson.build index bc078c8..b002b0a 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -1,5 +1,5 @@ example_args = [] -example_args += additional_arguments +example_args += devel_args example_overrides = [] example_overrides += overrides if is_gcc or is_clang @@ -25,8 +25,8 @@ foreach example : examples executable( example, [ example+'.cpp' ], - include_directories: include_dirs, cpp_args: example_args, + dependencies: tomlplusplus_dep, override_options: example_overrides ) ]] diff --git a/examples/simple_parser.cpp b/examples/simple_parser.cpp index 1e369ef..ec77111 100644 --- a/examples/simple_parser.cpp +++ b/examples/simple_parser.cpp @@ -6,8 +6,6 @@ // This example demonstrates how to parse TOML from a file or stdin and re-serialize it (print it out) to stdout. #include "examples.h" - -#define TOML_ENABLE_UNRELEASED_FEATURES 1 #include using namespace std::string_view_literals; diff --git a/examples/toml_generator.cpp b/examples/toml_generator.cpp index 2825ce8..43bbcfe 100644 --- a/examples/toml_generator.cpp +++ b/examples/toml_generator.cpp @@ -6,8 +6,6 @@ // This example demonstrates the use of some more advanced features to generate a tree of random TOML data. #include "examples.h" - -#define TOML_ENABLE_PARSER 0 #include using namespace std::string_view_literals; diff --git a/examples/toml_to_json_transcoder.cpp b/examples/toml_to_json_transcoder.cpp index d785344..881bcd5 100644 --- a/examples/toml_to_json_transcoder.cpp +++ b/examples/toml_to_json_transcoder.cpp @@ -6,8 +6,6 @@ // This example demonstrates how to use the toml::json_formatter to re-serialize TOML data as JSON. #include "examples.h" - -#define TOML_ENABLE_UNRELEASED_FEATURES 1 #include using namespace std::string_view_literals; diff --git a/include/meson.build b/include/meson.build new file mode 100644 index 0000000..1bfc624 --- /dev/null +++ b/include/meson.build @@ -0,0 +1,39 @@ +# Header-only + +tomlplusplus_dep = declare_dependency(include_directories: include_dir) + +if not is_subproject + import('pkgconfig').generate( + name: meson.project_name(), + description: 'Header-only TOML config file parser and serializer for C++', + install_dir: get_option('datadir')/'pkgconfig', + url: 'https://marzer.github.io/tomlplusplus' + ) +endif + +# cmake +if get_option('generate_cmake_config') and not is_subproject + cmake = import('cmake') + # Can't use until Meson 0.62.0, see https://github.com/mesonbuild/meson/pull/9916 + # and https://github.com/marzer/tomlplusplus/issues/140 + #cmake.write_basic_package_version_file( + # name: meson.project_name(), + # version: meson.project_version(), + # install_dir: get_option('datadir')/'cmake'/meson.project_name(), + # arch_independent: true + #) + # In the meantime, install a pre-generated Package Version file + configure_file( + configuration: {'version': meson.project_version()}, + input: '..'/'cmake'/'tomlplusplusConfigVersion.cmake.meson.in', + output: 'tomlplusplusConfigVersion.cmake', + install_dir: get_option('datadir')/'cmake'/meson.project_name() + ) + + cmake.configure_package_config_file( + name: meson.project_name(), + input: '..'/'cmake'/'tomlplusplusConfig.cmake.meson.in', + configuration: configuration_data({'includedir': get_option('includedir')}), + install_dir: get_option('datadir')/'cmake'/meson.project_name(), + ) +endif diff --git a/include/toml++/impl/preprocessor.h b/include/toml++/impl/preprocessor.h index b797955..9a5bcc9 100644 --- a/include/toml++/impl/preprocessor.h +++ b/include/toml++/impl/preprocessor.h @@ -88,6 +88,7 @@ _Pragma("clang diagnostic ignored \"-Wchar-subscripts\"") \ _Pragma("clang diagnostic ignored \"-Wmissing-field-initializers\"") \ _Pragma("clang diagnostic ignored \"-Wpadded\"") \ + _Pragma("clang diagnostic ignored \"-Wsuggest-destructor-override\"") \ static_assert(true) #define TOML_POP_WARNINGS \ @@ -366,6 +367,11 @@ #ifdef TOML_CONFIG_HEADER #include TOML_CONFIG_HEADER #endif + +// is the library being built as a shared lib/dll using meson and friends? +#ifndef TOML_SHARED_LIB + #define TOML_SHARED_LIB 0 +#endif // header-only mode #if !defined(TOML_HEADER_ONLY) && defined(TOML_ALL_INLINE) // was TOML_ALL_INLINE pre-2.0 @@ -375,7 +381,7 @@ #undef TOML_HEADER_ONLY #define TOML_HEADER_ONLY 1 #endif -#ifdef DOXYGEN +#if defined(DOXYGEN) || TOML_SHARED_LIB #undef TOML_HEADER_ONLY #define TOML_HEADER_ONLY 0 #endif @@ -398,6 +404,28 @@ #define TOML_EXPORTED_FREE_FUNCTION TOML_API #endif +// dll/shared lib exports +#if TOML_SHARED_LIB + #undef TOML_API + #undef TOML_EXPORTED_CLASS + #undef TOML_EXPORTED_MEMBER_FUNCTION + #undef TOML_EXPORTED_STATIC_FUNCTION + #undef TOML_EXPORTED_FREE_FUNCTION + #if defined(_WIN32) || defined(__CYGWIN__) + #if TOML_IMPLEMENTATION + #define TOML_EXPORTED_CLASS __declspec(dllexport) + #define TOML_EXPORTED_FREE_FUNCTION __declspec(dllexport) + #else + #define TOML_EXPORTED_CLASS __declspec(dllimport) + #define TOML_EXPORTED_FREE_FUNCTION __declspec(dllimport) + #endif + #elif defined(__GNUC__) && __GNUC__ >= 4 + #define TOML_EXPORTED_CLASS __attribute__((visibility("default"))) + #define TOML_EXPORTED_MEMBER_FUNCTION __attribute__((visibility("default"))) + #define TOML_EXPORTED_STATIC_FUNCTION __attribute__((visibility("default"))) + #define TOML_EXPORTED_FREE_FUNCTION __attribute__((visibility("default"))) + #endif +#endif #ifndef TOML_EXPORTED_CLASS #define TOML_EXPORTED_CLASS #endif diff --git a/include/toml++/toml.h b/include/toml++/toml.h index 197b7e7..ec5dd05 100644 --- a/include/toml++/toml.h +++ b/include/toml++/toml.h @@ -20,6 +20,9 @@ TOML_DISABLE_SUGGEST_ATTR_WARNINGS; // misc warning false-positives #if TOML_MSVC #pragma warning(disable : 5031) // #pragma warning(pop): likely mismatch +#if TOML_SHARED_LIB +#pragma warning(disable : 4251) // dll exports for std lib types +#endif #elif TOML_CLANG #pragma clang diagnostic ignored "-Wheader-hygiene" #if TOML_CLANG >= 12 diff --git a/meson.build b/meson.build index 97bba7d..632f901 100644 --- a/meson.build +++ b/meson.build @@ -44,7 +44,8 @@ is_subproject = meson.is_subproject() has_exceptions = get_option('cpp_eh') != 'none' include_dirs = include_directories('include', 'external') overrides = [] -additional_arguments = [] +universal_args = [] # args used in tests, examples, lib, everything +devel_args = [] # args used in everything *but* the lib message('is_release: @0@'.format(is_release)) message('is_windows: @0@'.format(is_windows)) @@ -59,34 +60,17 @@ message('has_exceptions: @0@'.format(has_exceptions)) # GCC or Clang if is_gcc or is_clang - add_project_arguments( - '-march=native', - '-fvisibility=hidden', - '-fvisibility-inlines-hidden', - language: 'cpp' - ) - if is_release - add_project_arguments( - '-fdata-sections', - '-ffunction-sections', - '-Wl,--gc-sections', - '-Wl,-s', - '-mfma', - language: 'cpp' - ) - endif + devel_args += '-march=native' endif - # GCC if is_gcc - add_project_arguments( + universal_args += [ '-fmax-errors=5', '-Wno-init-list-lifetime', - language: 'cpp' - ) + ] if is_pedantic - add_project_arguments( + universal_args += [ '-Wcast-align', '-Wcast-qual', '-Wctor-dtor-privacy', @@ -122,25 +106,22 @@ if is_gcc '-Wvariadic-macros', '-Wwrite-strings', '-Wmissing-noreturn', - language: 'cpp' - ) + ] endif - if is_release - add_project_arguments( - '-fmerge-constants', + if is_release and is_pedantic + universal_args += [ '-Wsuggest-attribute=const', '-Wsuggest-attribute=pure', - language: 'cpp' - ) + ] endif endif # Clang if is_clang if is_pedantic - add_project_arguments('-Weverything', language: 'cpp') + universal_args += '-Weverything' endif - add_project_arguments( + universal_args += [ '-ferror-limit=5', '-Wno-unused-command-line-argument', @@ -151,54 +132,45 @@ if is_clang '-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') + universal_args += ['-ftime-trace'] endif endif # MSVC or icc-cl if is_msvc or is_icc_cl - add_project_arguments( + universal_args += [ '/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) + '/Zc:inline' + ] + if has_exceptions + universal_args += '/Zc:throwingNew' + endif if is_release - add_project_arguments( + universal_args += [ '/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') + universal_args += '/W4' endif endif # icc-cl if is_icc_cl - add_project_arguments( + universal_args += [ '/wd82', # storage class is not first '/wd177', # unreferenced var '/wd280', # selector expression is constant (why the fuck is that a warning?) @@ -209,37 +181,27 @@ if is_icc_cl '/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( + universal_args += [ '/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') + universal_args += has_exceptions ? '-D_HAS_EXCEPTIONS=1' : '-D_HAS_EXCEPTIONS=0' elif is_release overrides += 'strip=true' endif - # LTO -if is_lld or is_debug +if is_lld or is_debug or (is_windows and is_clang) overrides += 'b_lto=false' endif @@ -418,7 +380,7 @@ compiler_supports_float16 = compiler.links(''' args: compiler_supports_float16_args ) if compiler_supports_fp16 or compiler_supports_float16 - additional_arguments += compiler_supports_float16_args + devel_args += compiler_supports_float16_args endif ####################################################################################################################### @@ -484,6 +446,17 @@ endif # subdirectories ####################################################################################################################### +include_dir = include_directories('include') + +# Empty dependency that will be filled either in src/ or include/ +tomlplusplus_dep = dependency('', required: false) + +if get_option('compile_library') + subdir('src') +else + subdir('include') +endif + build_tests = get_option('build_tests') and not is_subproject if build_tests run_command('git', 'submodule', 'update', '--init', '--depth', '1', 'external/Catch2') @@ -502,51 +475,8 @@ if build_tt endif if not is_subproject - install_subdir('include'/'toml++', - strip_directory: true, - install_dir: get_option('includedir')/'toml++' - ) + install_subdir('include'/'toml++', install_dir: get_option('includedir')) endif -####################################################################################################################### -# dependencies, cmake etc. -####################################################################################################################### - -tomlplusplus_dep = declare_dependency(include_directories: 'include') - +# Allow subproject usage meson.override_dependency(meson.project_name(), tomlplusplus_dep) - -if not is_subproject - import('pkgconfig').generate( - name: meson.project_name(), - description: 'Header-only TOML config file parser and serializer for C++', - install_dir: get_option('datadir')/'pkgconfig', - ) -endif - -# cmake -if get_option('generate_cmake_config') and not is_subproject - cmake = import('cmake') - # Can't use until Meson 0.62.0, see https://github.com/mesonbuild/meson/pull/9916 - # and https://github.com/marzer/tomlplusplus/issues/140 - #cmake.write_basic_package_version_file( - # name: meson.project_name(), - # version: meson.project_version(), - # install_dir: get_option('datadir')/'cmake'/meson.project_name(), - # arch_independent: true - #) - # In the meantime, install a pre-generated Package Version file - configure_file( - configuration: {'version': meson.project_version()}, - input: 'cmake'/'tomlplusplusConfigVersion.cmake.in', - output: 'tomlplusplusConfigVersion.cmake', - install_dir: get_option('datadir')/'cmake'/meson.project_name() - ) - - cmake.configure_package_config_file( - name: meson.project_name(), - input: 'cmake'/'tomlplusplus.cmake.in', - configuration: configuration_data({'includedir': get_option('includedir')}), - install_dir: get_option('datadir')/'cmake'/meson.project_name(), - ) -endif diff --git a/meson_options.txt b/meson_options.txt index 380bf62..b604540 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1,4 +1,4 @@ -option('build_tests', type: 'boolean', value: false, description: 'Build tests (default: false - no effect when included as a subproject)') +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)') @@ -7,4 +7,4 @@ option('asan_examples', type: 'boolean', value: false) option('asan_tests', type: 'boolean', value: false) option('build_tt_encoder', type: 'boolean', value: false, description: 'Enable to build the toml-test encoder.') option('build_tt_decoder', type: 'boolean', value: false, description: 'Enable to build the toml-test decoder.') - +option('compile_library', type: 'boolean', value: false, description: 'Compile as a library') diff --git a/src/meson.build b/src/meson.build new file mode 100644 index 0000000..a49cb1f --- /dev/null +++ b/src/meson.build @@ -0,0 +1,72 @@ +# Compiled library + +# These are the arguments needed to compile and consume the library, and +# are exposed to users with the `compile_args` kwarg of declare_dependency() +lib_args = ['-DTOML_HEADER_ONLY=0'] +if get_option('default_library') != 'static' + lib_args += '-DTOML_SHARED_LIB=1' +endif + +lib = library( + meson.project_name(), + 'toml++'/'toml.cpp', + cpp_args: [universal_args, lib_args], + gnu_symbol_visibility: 'hidden', + include_directories: include_dir, + install: not is_subproject, + version: meson.project_version(), + override_options: overrides +) + +tomlplusplus_dep = declare_dependency( + compile_args: lib_args, + include_directories: include_dir, + link_with: lib +) + +if not is_subproject + import('pkgconfig').generate( + lib, + description: 'TOML config file parser and serializer for C++', + extra_cflags: lib_args, + url: 'https://marzer.github.io/tomlplusplus' + ) +endif + +# 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(), + ) + + # This gets the full path of the library, then considers just the last + # component (i.e. the actual file name), and finally removes the + # version suffix from it, because users _should_ link against the .so + # file, as opposed to the .so.x.y.z one. This last step is only doable + # with str.replace(), introduced in Meson 0.58.0, but it isn't essential + lib_name = lib.full_path().split('/')[-1] + if meson.version().version_compare('>=0.58.0') + lib_name = lib_name.replace('.' + meson.project_version(), '') + endif + + # CMake needs space-separated values since it doesn't have types + cmake_compile_options = '' + foreach arg : lib_args + cmake_compile_options += arg + ' ' + endforeach + cmake_compile_options = cmake_compile_options.strip() + + cmake.configure_package_config_file( + name: meson.project_name(), + input: '..'/'cmake'/'tomlplusplusConfig.cmake.meson.in', + configuration: configuration_data({ + 'compile_library': true, + 'compile_options': cmake_compile_options, + 'includedir': get_option('includedir'), + 'libdir': get_option('libdir'), + 'lib_name': lib_name + }) + ) +endif diff --git a/src/toml++/toml.cpp b/src/toml++/toml.cpp new file mode 100644 index 0000000..f880eaa --- /dev/null +++ b/src/toml++/toml.cpp @@ -0,0 +1,5 @@ +#ifndef TOML_IMPLEMENTATION +#define TOML_IMPLEMENTATION +#endif + +#include diff --git a/tests/impl_toml.cpp b/tests/impl_toml.cpp index 69cb0d8..2c55075 100644 --- a/tests/impl_toml.cpp +++ b/tests/impl_toml.cpp @@ -4,7 +4,7 @@ // SPDX-License-Identifier: MIT #include "settings.h" -#if !TOML_HEADER_ONLY +#if !TOML_HEADER_ONLY && !TOML_SHARED_LIB #define TOML_IMPLEMENTATION #endif diff --git a/tests/meson.build b/tests/meson.build index 0758f6d..ca7b64d 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -60,26 +60,34 @@ unreleased_feature_modes = [ false, true ] cpp20_modes = [ false, true ] test_executables = [] counter = 0 +test_base_args = [] +test_base_args += universal_args +test_base_args += devel_args foreach cpp20 : cpp20_modes - if cpp20 and not compiler_supports_cpp20 + if cpp20 and (not compiler_supports_cpp20 or get_option('compile_library')) continue endif foreach unrel : unreleased_feature_modes + if unrel and get_option('compile_library') + continue + endif foreach fast_math : fast_math_modes - if fast_math and not compiler_supports_fast_math + if fast_math and (not compiler_supports_fast_math or get_option('compile_library')) continue endif foreach exceptions : exception_modes - + if (not exceptions) and get_option('compile_library') + continue + endif test_name = '' test_overrides = [] test_overrides += overrides test_args = [] - test_args += additional_arguments + test_args += test_base_args single_header = (counter % 2 == 1) - tl_optional = (counter % 4 == 2 and exceptions) + tl_optional = (counter % 4 == 2 and exceptions and not get_option('compile_library')) address_sanitizer = (is_clang and not (single_header or tl_optional or fast_math)) and get_option('asan_tests') if cpp20 @@ -155,6 +163,7 @@ foreach cpp20 : cpp20_modes test_sources, include_directories: include_dirs, cpp_args: test_args, + dependencies: tomlplusplus_dep, override_options: test_overrides ) ]] @@ -195,6 +204,6 @@ executable( 'odr_test', [ 'odr_test_1.cpp', 'odr_test_2.cpp' ], include_directories: include_dirs, - cpp_args: additional_arguments, + cpp_args: test_base_args, override_options: overrides ) diff --git a/tests/odr_test_1.cpp b/tests/odr_test_1.cpp index 06e4263..27befe1 100644 --- a/tests/odr_test_1.cpp +++ b/tests/odr_test_1.cpp @@ -1,6 +1,4 @@ -#define TOML_ENABLE_UNRELEASED_FEATURES 1 -#define TOML_HEADER_ONLY 1 -#define TOML_UNDEF_MACROS 0 +#define TOML_UNDEF_MACROS 0 #include "../toml.hpp" TOML_DISABLE_WARNINGS; diff --git a/tests/odr_test_2.cpp b/tests/odr_test_2.cpp index 4920690..763c0c9 100644 --- a/tests/odr_test_2.cpp +++ b/tests/odr_test_2.cpp @@ -1,3 +1,2 @@ -#define TOML_ENABLE_UNRELEASED_FEATURES 1 -#define TOML_HEADER_ONLY 1 #include "../toml.hpp" +#include "../toml.hpp" // make sure it behaves if included more than once diff --git a/tests/settings.h b/tests/settings.h index 017a5a5..948d516 100644 --- a/tests/settings.h +++ b/tests/settings.h @@ -6,7 +6,12 @@ // toml++ config #define TOML_UNDEF_MACROS 0 -#define TOML_HEADER_ONLY 0 +#ifndef TOML_HEADER_ONLY +#define TOML_HEADER_ONLY 0 +#endif +#ifndef TOML_SHARED_LIB +#define TOML_SHARED_LIB 0 +#endif #ifndef USE_SINGLE_HEADER #define USE_SINGLE_HEADER 0 #endif diff --git a/toml++.vcxproj b/toml++.vcxproj index 223f149..e330bbc 100644 --- a/toml++.vcxproj +++ b/toml++.vcxproj @@ -94,6 +94,7 @@ + @@ -108,6 +109,7 @@ + diff --git a/toml++.vcxproj.filters b/toml++.vcxproj.filters index 5543a4e..294c0cf 100644 --- a/toml++.vcxproj.filters +++ b/toml++.vcxproj.filters @@ -112,18 +112,9 @@ include\impl - - include\impl - - - include\impl - include\impl - - include\impl - include\impl @@ -195,9 +186,6 @@ tools - - include\impl - .github @@ -226,6 +214,12 @@ include\impl + + src + + + include + @@ -252,6 +246,9 @@ {e3ab5e86-e053-48a6-9fee-f6442a63aaa6} + + {5ae94dae-1dce-4522-a33a-230bdb075921} + diff --git a/toml-test/meson.build b/toml-test/meson.build index 92f51e0..949b6c2 100644 --- a/toml-test/meson.build +++ b/toml-test/meson.build @@ -2,6 +2,7 @@ if get_option('build_tt_encoder') executable( 'tt_encoder', 'tt_encoder.cpp', + cpp_args: devel_args, include_directories: include_dirs ) endif @@ -10,6 +11,7 @@ if get_option('build_tt_decoder') executable( 'tt_decoder', 'tt_decoder.cpp', + cpp_args: devel_args, include_directories: include_dirs ) endif diff --git a/toml.hpp b/toml.hpp index d23ece1..b4dd836 100644 --- a/toml.hpp +++ b/toml.hpp @@ -124,6 +124,7 @@ _Pragma("clang diagnostic ignored \"-Wchar-subscripts\"") \ _Pragma("clang diagnostic ignored \"-Wmissing-field-initializers\"") \ _Pragma("clang diagnostic ignored \"-Wpadded\"") \ + _Pragma("clang diagnostic ignored \"-Wsuggest-destructor-override\"") \ static_assert(true) #define TOML_POP_WARNINGS \ @@ -382,6 +383,11 @@ #include TOML_CONFIG_HEADER #endif +// is the library being built as a shared lib/dll using meson and friends? +#ifndef TOML_SHARED_LIB + #define TOML_SHARED_LIB 0 +#endif + // header-only mode #if !defined(TOML_HEADER_ONLY) && defined(TOML_ALL_INLINE) // was TOML_ALL_INLINE pre-2.0 #define TOML_HEADER_ONLY TOML_ALL_INLINE @@ -390,20 +396,11 @@ #undef TOML_HEADER_ONLY #define TOML_HEADER_ONLY 1 #endif -#ifdef DOXYGEN +#if defined(DOXYGEN) || TOML_SHARED_LIB #undef TOML_HEADER_ONLY #define TOML_HEADER_ONLY 0 #endif -// extern templates (for !TOML_HEADER_ONLY) -#ifndef TOML_EXTERN_TEMPLATES - #define TOML_EXTERN_TEMPLATES 1 -#endif -#if (defined(DOXYGEN) || TOML_HEADER_ONLY) - #undef TOML_EXTERN_TEMPLATES - #define TOML_EXTERN_TEMPLATES 0 -#endif - // internal implementation switch #if defined(TOML_IMPLEMENTATION) || TOML_HEADER_ONLY #undef TOML_IMPLEMENTATION @@ -412,9 +409,49 @@ #define TOML_IMPLEMENTATION 0 #endif -// dllexport etc -#ifndef TOML_API - #define TOML_API +// dll/shared lib function exports (legacy - TOML_API was the old name for this setting) +#if !defined(TOML_EXPORTED_MEMBER_FUNCTION) \ + && !defined(TOML_EXPORTED_STATIC_FUNCTION) \ + && !defined(TOML_EXPORTED_FREE_FUNCTION) \ + && defined(TOML_API) + #define TOML_EXPORTED_MEMBER_FUNCTION TOML_API + #define TOML_EXPORTED_STATIC_FUNCTION TOML_API + #define TOML_EXPORTED_FREE_FUNCTION TOML_API +#endif + +// dll/shared lib exports +#if TOML_SHARED_LIB + #undef TOML_API + #undef TOML_EXPORTED_CLASS + #undef TOML_EXPORTED_MEMBER_FUNCTION + #undef TOML_EXPORTED_STATIC_FUNCTION + #undef TOML_EXPORTED_FREE_FUNCTION + #if defined(_WIN32) || defined(__CYGWIN__) + #if TOML_IMPLEMENTATION + #define TOML_EXPORTED_CLASS __declspec(dllexport) + #define TOML_EXPORTED_FREE_FUNCTION __declspec(dllexport) + #else + #define TOML_EXPORTED_CLASS __declspec(dllimport) + #define TOML_EXPORTED_FREE_FUNCTION __declspec(dllimport) + #endif + #elif defined(__GNUC__) && __GNUC__ >= 4 + #define TOML_EXPORTED_CLASS __attribute__((visibility("default"))) + #define TOML_EXPORTED_MEMBER_FUNCTION __attribute__((visibility("default"))) + #define TOML_EXPORTED_STATIC_FUNCTION __attribute__((visibility("default"))) + #define TOML_EXPORTED_FREE_FUNCTION __attribute__((visibility("default"))) + #endif +#endif +#ifndef TOML_EXPORTED_CLASS + #define TOML_EXPORTED_CLASS +#endif +#ifndef TOML_EXPORTED_MEMBER_FUNCTION + #define TOML_EXPORTED_MEMBER_FUNCTION +#endif +#ifndef TOML_EXPORTED_STATIC_FUNCTION + #define TOML_EXPORTED_STATIC_FUNCTION +#endif +#ifndef TOML_EXPORTED_FREE_FUNCTION + #define TOML_EXPORTED_FREE_FUNCTION #endif // experimental language features @@ -738,17 +775,6 @@ #define POXY_IMPLEMENTATION_DETAIL(...) __VA_ARGS__ #endif -#if TOML_IMPLEMENTATION - #define TOML_EXTERN -#else - #define TOML_EXTERN extern -#endif -#if TOML_CLANG - #define TOML_EXTERN_NOEXCEPT(...) -#else - #define TOML_EXTERN_NOEXCEPT(...) noexcept(__VA_ARGS__) -#endif - #ifdef NDEBUG #define TOML_PURE_GETTER TOML_NODISCARD TOML_ATTR(pure) #define TOML_CONST_GETTER TOML_NODISCARD TOML_ATTR(const) @@ -955,6 +981,9 @@ TOML_DISABLE_SUGGEST_ATTR_WARNINGS; // misc warning false-positives #if TOML_MSVC #pragma warning(disable : 5031) // #pragma warning(pop): likely mismatch +#if TOML_SHARED_LIB +#pragma warning(disable : 4251) // dll exports for std lib types +#endif #elif TOML_CLANG #pragma clang diagnostic ignored "-Wheader-hygiene" #if TOML_CLANG >= 12 @@ -1005,17 +1034,17 @@ namespace toml // non-abi namespace; this is not an error TOML_IMPL_NAMESPACE_START { TOML_NODISCARD - TOML_API + TOML_EXPORTED_FREE_FUNCTION std::string narrow(std::wstring_view); TOML_NODISCARD - TOML_API + TOML_EXPORTED_FREE_FUNCTION std::wstring widen(std::string_view); #if TOML_HAS_CHAR8 TOML_NODISCARD - TOML_API + TOML_EXPORTED_FREE_FUNCTION std::wstring widen(std::u8string_view); #endif @@ -2002,97 +2031,97 @@ TOML_IMPL_NAMESPACE_START // - I can (potentially) avoid forcing users to drag in and . // - Strings in C++. Honestly. - TOML_API + TOML_EXPORTED_FREE_FUNCTION TOML_ATTR(nonnull) void print_to_stream(std::ostream&, const char*, size_t); - TOML_API + TOML_EXPORTED_FREE_FUNCTION void print_to_stream(std::ostream&, std::string_view); - TOML_API + TOML_EXPORTED_FREE_FUNCTION void print_to_stream(std::ostream&, const std::string&); - TOML_API + TOML_EXPORTED_FREE_FUNCTION void print_to_stream(std::ostream&, char); - TOML_API + TOML_EXPORTED_FREE_FUNCTION void print_to_stream(std::ostream&, int8_t, value_flags = {}, size_t min_digits = 0); - TOML_API + TOML_EXPORTED_FREE_FUNCTION void print_to_stream(std::ostream&, int16_t, value_flags = {}, size_t min_digits = 0); - TOML_API + TOML_EXPORTED_FREE_FUNCTION void print_to_stream(std::ostream&, int32_t, value_flags = {}, size_t min_digits = 0); - TOML_API + TOML_EXPORTED_FREE_FUNCTION void print_to_stream(std::ostream&, int64_t, value_flags = {}, size_t min_digits = 0); - TOML_API + TOML_EXPORTED_FREE_FUNCTION void print_to_stream(std::ostream&, uint8_t, value_flags = {}, size_t min_digits = 0); - TOML_API + TOML_EXPORTED_FREE_FUNCTION void print_to_stream(std::ostream&, uint16_t, value_flags = {}, size_t min_digits = 0); - TOML_API + TOML_EXPORTED_FREE_FUNCTION void print_to_stream(std::ostream&, uint32_t, value_flags = {}, size_t min_digits = 0); - TOML_API + TOML_EXPORTED_FREE_FUNCTION void print_to_stream(std::ostream&, uint64_t, value_flags = {}, size_t min_digits = 0); - TOML_API + TOML_EXPORTED_FREE_FUNCTION void print_to_stream(std::ostream&, float, value_flags = {}, bool relaxed_precision = false); - TOML_API + TOML_EXPORTED_FREE_FUNCTION void print_to_stream(std::ostream&, double, value_flags = {}, bool relaxed_precision = false); - TOML_API + TOML_EXPORTED_FREE_FUNCTION void print_to_stream(std::ostream&, bool); - TOML_API + TOML_EXPORTED_FREE_FUNCTION void print_to_stream(std::ostream&, const toml::date&); - TOML_API + TOML_EXPORTED_FREE_FUNCTION void print_to_stream(std::ostream&, const toml::time&); - TOML_API + TOML_EXPORTED_FREE_FUNCTION void print_to_stream(std::ostream&, const toml::time_offset&); - TOML_API + TOML_EXPORTED_FREE_FUNCTION void print_to_stream(std::ostream&, const toml::date_time&); - TOML_API + TOML_EXPORTED_FREE_FUNCTION void print_to_stream(std::ostream&, const source_position&); - TOML_API + TOML_EXPORTED_FREE_FUNCTION void print_to_stream(std::ostream&, const source_region&); #if TOML_ENABLE_FORMATTERS - TOML_API + TOML_EXPORTED_FREE_FUNCTION void print_to_stream(std::ostream&, const array&); - TOML_API + TOML_EXPORTED_FREE_FUNCTION void print_to_stream(std::ostream&, const table&); - TOML_API + TOML_EXPORTED_FREE_FUNCTION void print_to_stream(std::ostream&, const value&); - TOML_API + TOML_EXPORTED_FREE_FUNCTION void print_to_stream(std::ostream&, const value&); - TOML_API + TOML_EXPORTED_FREE_FUNCTION void print_to_stream(std::ostream&, const value&); - TOML_API + TOML_EXPORTED_FREE_FUNCTION void print_to_stream(std::ostream&, const value&); - TOML_API + TOML_EXPORTED_FREE_FUNCTION void print_to_stream(std::ostream&, const value&); - TOML_API + TOML_EXPORTED_FREE_FUNCTION void print_to_stream(std::ostream&, const value