From 6fb6f9dfc2858e3681aadbd178d13b38da043246 Mon Sep 17 00:00:00 2001 From: Kjell Ahlstedt Date: Wed, 20 Apr 2022 14:54:30 +0200 Subject: [PATCH 01/85] Add track_object(), deprecate track_obj() track_object() checks that the listed objects derive from sigc::trackable. Fixes #78 --- sigc++/adaptors/track_obj.h | 45 +++++++++++++++++---- tests/test_track_obj.cc | 80 ++++++++++++++++++++++--------------- 2 files changed, 85 insertions(+), 40 deletions(-) diff --git a/sigc++/adaptors/track_obj.h b/sigc++/adaptors/track_obj.h index 6f208f35..7f895b29 100644 --- a/sigc++/adaptors/track_obj.h +++ b/sigc++/adaptors/track_obj.h @@ -23,19 +23,24 @@ #include #include #include +#include +#include +#include namespace sigc { -/** @defgroup track_obj track_obj() - * sigc::track_obj() tracks trackable objects, referenced from a functor. +/** @defgroup track_obj track_obj(), track_object() + * sigc::track_object() tracks trackable objects, referenced from a functor. * It can be useful when you assign a C++11 lambda expression or a std::function<> * to a slot, or connect it to a signal, and the lambda expression or std::function<> * contains references to sigc::trackable derived objects. * - * The functor returned by sigc::track_obj() is formally an adaptor, but it does + * The functor returned by sigc::track_object() is formally an adaptor, but it does * not alter the signature, return type or behaviour of the supplied functor. * + * track_obj() is a deprecated alternative to track_object(). + * * @par Example: * @code * struct bar : public sigc::trackable {}; @@ -45,18 +50,18 @@ namespace sigc * bar some_bar; * some_signal.connect([&some_bar](){ foo(some_bar); }); * // NOT disconnected automatically when some_bar goes out of scope - * some_signal.connect(sigc::track_obj([&some_bar](){ foo(some_bar); }, some_bar); + * some_signal.connect(sigc::track_object([&some_bar](){ foo(some_bar); }, some_bar); * // disconnected automatically when some_bar goes out of scope * } * @endcode * - * @newin{2,4} - * * @ingroup adaptors */ -/** track_obj_functor wraps a functor and stores a reference to a trackable object. - * Use the convenience function track_obj() to create an instance of track_obj_functor. +/** %track_obj_functor wraps a functor and stores a reference to a trackable object. + * Use the convenience function track_object() to create an instance of %track_obj_functor. + * + * track_obj() is a deprecated alternative to track_object(). * * @tparam T_functor The type of functor to wrap. * @tparam T_obj The types of the trackable objects. @@ -124,12 +129,14 @@ struct visitor> }; #endif // DOXYGEN_SHOULD_SKIP_THIS +#ifndef SIGCXX_DISABLE_DEPRECATED /** Creates an adaptor of type sigc::track_obj_functor which wraps a functor. * @param func Functor that shall be wrapped. * @param obj Trackable objects. * @return Adaptor that executes func() on invocation. * * @newin{2,4} + * @deprecated Use sigc::track_object() instead. * * @ingroup track_obj */ @@ -139,6 +146,28 @@ track_obj(const T_functor& func, const T_obj&... obj) { return track_obj_functor(func, obj...); } +#endif // SIGCXX_DISABLE_DEPRECATED + +/** Creates an adaptor of type sigc::track_obj_functor which wraps a functor. + * @param func Functor that shall be wrapped. + * @param obj1 Trackable object, derived directly or indirectly from sigc::trackable. + * @param objs Zero or more trackable objects, derived directly or indirectly from sigc::trackable. + * @return Adaptor that executes func() on invocation. + * + * @newin{3,4} + * + * @ingroup track_obj + */ +template +inline decltype(auto) +track_object(const T_functor& func, const T_obj1& obj1, const T_objs&... objs) +{ + static_assert(std::min({std::is_base_of::value, + std::is_base_of::value...}), + "Each trackable object must be derived from sigc::trackable."); + + return track_obj_functor(func, obj1, objs...); +} } /* namespace sigc */ diff --git a/tests/test_track_obj.cc b/tests/test_track_obj.cc index aefdb078..54b44309 100644 --- a/tests/test_track_obj.cc +++ b/tests/test_track_obj.cc @@ -17,10 +17,10 @@ */ // The purpose of this test case is threefold. -// - Test sigc::track_obj(). +// - Test sigc::track_obj() and sigc::track_object(). // - Show that a slot with a C++11 lambda expression can be automatically // disconnected when an object derived from sigc::trackable is deleted, -// provided sigc::track_obj() is used. +// provided sigc::track_obj() or sigc::track_object() is used. // It shows that C++11 lambda expressions can replace the libsigc++ lambda // expressions, which have been removed. // See https://bugzilla.gnome.org/show_bug.cgi?id=672555 @@ -115,32 +115,38 @@ main(int argc, char* argv[]) return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; sigc::slot sl1; + sigc::slot sl2; { bar_group4 bar4; sl1 = sigc::track_obj(Functor1(bar4), bar4); - result_stream << sl1(-2); - util->check_result(result_stream, "negative"); + sl2 = sigc::track_object(Functor1(bar4), bar4); + result_stream << sl1(-2) << ", " << sl2(2); + util->check_result(result_stream, "negative, positive"); - } // auto-disconnect sl1 + } // auto-disconnect sl1 and sl2 - result_stream << sl1(-2); - util->check_result(result_stream, ""); + result_stream << sl1(-2) << ", " << sl2(2); + util->check_result(result_stream, ", "); // Allocate on the heap. valgrind can then find erroneous memory accesses. // (There should be none, of course.) - auto psl2 = new sigc::slot; + auto psl3 = new sigc::slot; + auto psl4 = new sigc::slot; auto pbar4 = new bar_group4; auto pbook4 = new book("A Book"); - *psl2 = sigc::track_obj(Functor2(*pbar4, *pbook4), *pbar4, *pbook4); - result_stream << (*psl2)(0, "Book title: "); - util->check_result(result_stream, "zero, Book title: A Book"); + *psl3 = sigc::track_obj(Functor2(*pbar4, *pbook4), *pbar4, *pbook4); + *psl4 = sigc::track_object(Functor2(*pbar4, *pbook4), *pbar4, *pbook4); + result_stream << (*psl3)(0, "Book title: ") << ", " << (*psl4)(1, "Title: "); + util->check_result(result_stream, "zero, Book title: A Book, positive, Title: A Book"); - delete pbook4; // auto-disconnect *psl2 + delete pbook4; // auto-disconnect *psl3 and *psl4 pbook4 = nullptr; - result_stream << (*psl2)(0, "Book title: "); - util->check_result(result_stream, ""); - delete psl2; - psl2 = nullptr; + result_stream << (*psl3)(0, "Book title: ") << ", " << (*psl4)(1, "Title: "); + util->check_result(result_stream, ", "); + delete psl3; + psl3 = nullptr; + delete psl4; + psl4 = nullptr; delete pbar4; pbar4 = nullptr; @@ -149,38 +155,47 @@ main(int argc, char* argv[]) // auto-disconnect // If you want to auto-disconnect a slot with a C++11 lambda expression // that contains references to sigc::trackable-derived objects, you must use - // sigc::track_obj(). - sigc::slot sl10; + // sigc::track_obj() or sigc::track_object(). + sigc::slot sl11; + sigc::slot sl12; { book guest_book("karl"); - // sl1 = [&guest_book](std::ostringstream& stream){ stream << guest_book << "\n"; }; // no - // auto-disconnect - sl10 = sigc::track_obj( + // no auto-disconnect + // sl1 = [&guest_book](std::ostringstream& stream){ stream << guest_book << "\n"; }; + sl11 = sigc::track_obj( + [&guest_book](std::ostringstream& stream) { stream << guest_book; }, guest_book); + sl12 = sigc::track_object( [&guest_book](std::ostringstream& stream) { stream << guest_book; }, guest_book); - sl10(result_stream); - util->check_result(result_stream, "karl"); + sl11(result_stream); + sl12(result_stream); + util->check_result(result_stream, "karlkarl"); - } // auto-disconnect sl10 + } // auto-disconnect sl11 and sl12 - sl10(result_stream); + sl11(result_stream); + sl12(result_stream); util->check_result(result_stream, ""); // auto-disconnect - sigc::slot sl20; + sigc::slot sl21; + sigc::slot sl22; { book guest_book("karl"); // sl2 = [&guest_book] () { egon(guest_book); }; // no auto-disconnect // sl2 = std::bind(&egon, std::ref(guest_book)); // does not compile (gcc 4.6.3) - sl20 = sigc::track_obj([&guest_book]() { egon(guest_book); }, guest_book); - sl20(); - util->check_result(result_stream, "egon(string 'karl')"); + sl21 = sigc::track_obj([&guest_book]() { egon(guest_book); }, guest_book); + sl22 = sigc::track_obj([&guest_book]() { egon(guest_book); }, guest_book); + sl21(); + sl22(); + util->check_result(result_stream, "egon(string 'karl')egon(string 'egon was here')"); result_stream << static_cast(guest_book); util->check_result(result_stream, "egon was here"); - } // auto-disconnect sl20 + } // auto-disconnect sl21 and sl22 - sl20(); + sl21(); + sl22(); util->check_result(result_stream, ""); // Code example in the documentation sigc++/adaptors/track_obj.h. @@ -194,8 +209,9 @@ main(int argc, char* argv[]) // some_signal.connect(sigc::bind(&foo_group4, std::ref(some_bar))); // auto-disconnects, // but we prefer C++11 lambda some_signal.connect(sigc::track_obj([&some_bar]() { foo_group4(some_bar); }, some_bar)); + some_signal.connect(sigc::track_object([&some_bar]() { foo_group4(some_bar); }, some_bar)); some_signal.emit(); - util->check_result(result_stream, "foo_group4(bar_group4&)"); + util->check_result(result_stream, "foo_group4(bar_group4&)foo_group4(bar_group4&)"); } // auto-disconnect the lambda expression From ef8435a8c8694283bbf905b8e53a83bf2144b751 Mon Sep 17 00:00:00 2001 From: Kjell Ahlstedt Date: Wed, 20 Apr 2022 15:54:19 +0200 Subject: [PATCH 02/85] Format source code to suit clang-format-12 Format sigc++/adaptors/track_obj.h. --- sigc++/adaptors/track_obj.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sigc++/adaptors/track_obj.h b/sigc++/adaptors/track_obj.h index 7f895b29..80cb3ff1 100644 --- a/sigc++/adaptors/track_obj.h +++ b/sigc++/adaptors/track_obj.h @@ -162,8 +162,8 @@ template inline decltype(auto) track_object(const T_functor& func, const T_obj1& obj1, const T_objs&... objs) { - static_assert(std::min({std::is_base_of::value, - std::is_base_of::value...}), + static_assert(std::min({ std::is_base_of::value, + std::is_base_of::value... }), "Each trackable object must be derived from sigc::trackable."); return track_obj_functor(func, obj1, objs...); From 4b829ece84c6dbaa4d89bf4fe6feebd4236b31d1 Mon Sep 17 00:00:00 2001 From: Kjell Ahlstedt Date: Wed, 27 Apr 2022 18:10:48 +0200 Subject: [PATCH 03/85] Fix some comments --- sigc++/adaptors/hide.h | 5 ++--- sigc++/functors/slot.h | 7 ++++++- sigc++/signal.h | 2 +- sigc++/tuple-utils/tuple_end.h | 2 +- sigc++/tuple-utils/tuple_start.h | 4 ++-- 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/sigc++/adaptors/hide.h b/sigc++/adaptors/hide.h index 46bc5d33..d8e95797 100644 --- a/sigc++/adaptors/hide.h +++ b/sigc++/adaptors/hide.h @@ -64,8 +64,8 @@ namespace sigc * @par Example: * @code * // multiple argument hiding ... - * sigc::hide(sigc::hide(&foo))(1,2,3,4); // adds two dummy parameters at the back and calls - foo(1,2) + * // adds two dummy parameters at the back and calls foo(1,2) + * sigc::hide(sigc::hide(&foo))(1,2,3,4); * @endcode * sigc::hide_return() alters an arbitrary functor by @@ -79,7 +79,6 @@ namespace sigc * * The following template arguments are used: * - @e I_location Zero-based position of the dummy parameter (@p -1 for the last parameter). - * - @e T_type Type of the dummy parameter. * - @e T_functor Type of the functor to wrap. * * @ingroup hide diff --git a/sigc++/functors/slot.h b/sigc++/functors/slot.h index e368e864..3f4b5108 100644 --- a/sigc++/functors/slot.h +++ b/sigc++/functors/slot.h @@ -24,7 +24,6 @@ #include #include #include - #include namespace sigc @@ -230,6 +229,12 @@ class slot : public slot_base inline slot() = default; + // If you're tempted to add + // template, int> = 0> + // to the constructor, see https://github.com/libsigcplusplus/libsigcplusplus/issues/79 + // It doesn't work well when sigc::slot is combined with sigc::hide(). + /** Constructs a slot from an arbitrary functor. * @param func The desired functor the new slot should be assigned to. */ diff --git a/sigc++/signal.h b/sigc++/signal.h index b8e0f26f..8f7dadcb 100644 --- a/sigc++/signal.h +++ b/sigc++/signal.h @@ -469,7 +469,7 @@ class signal_with_accumulator : public signal_base */ decltype(auto) make_slot() const { - // TODO: Instead use std::result_of<> on the static emitter_type::emit() + // TODO: Instead use std::invoke_result<> on the static emitter_type::emit() using result_type = typename internal::member_method_result::type; return bound_mem_functor...) diff --git a/sigc++/tuple-utils/tuple_end.h b/sigc++/tuple-utils/tuple_end.h index 966a6c87..e32d56b9 100644 --- a/sigc++/tuple-utils/tuple_end.h +++ b/sigc++/tuple-utils/tuple_end.h @@ -58,7 +58,7 @@ tuple_end(T&& t) { // We use std::decay_t<> because tuple_size is not defined for references. constexpr auto size = std::tuple_size>::value; - static_assert(len <= size, "The tuple size must be less than or equal to the length."); + static_assert(len <= size, "The tuple size must be greater than or equal to the length."); if constexpr (len == 0) { diff --git a/sigc++/tuple-utils/tuple_start.h b/sigc++/tuple-utils/tuple_start.h index 6c83030d..c75fda91 100644 --- a/sigc++/tuple-utils/tuple_start.h +++ b/sigc++/tuple-utils/tuple_start.h @@ -59,7 +59,7 @@ struct tuple_start_impl> { constexpr auto size = std::tuple_size>::value; constexpr auto len = sizeof...(I); - static_assert(len <= size, "The tuple size must be less than or equal to the length."); + static_assert(len <= size, "The tuple size must be greater than or equal to the length."); using start = typename tuple_type_start, len>::type; return start(std::get(std::forward(t))...); @@ -77,7 +77,7 @@ tuple_start(T&& t) { // We use std::decay_t<> because tuple_size is not defined for references. constexpr auto size = std::tuple_size>::value; - static_assert(len <= size, "The tuple size must be less than or equal to the length."); + static_assert(len <= size, "The tuple size must be greater than or equal to the length."); return detail::tuple_start_impl>::tuple_start( std::forward(t)); From 6952dddbcbab0daa61803b3d4b9b0719f326efba Mon Sep 17 00:00:00 2001 From: Kjell Ahlstedt Date: Wed, 27 Apr 2022 18:11:08 +0200 Subject: [PATCH 04/85] examples/member_method: Make on_print() non-virtual so it can be compiled with the -Wnon-virtual-dtor compiler option. --- examples/member_method.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/member_method.cc b/examples/member_method.cc index ab825258..5fc5b2cf 100644 --- a/examples/member_method.cc +++ b/examples/member_method.cc @@ -15,7 +15,7 @@ class Something : public sigc::trackable Something(); protected: - virtual void on_print(int a); + void on_print(int a); using type_signal_print = sigc::signal; type_signal_print signal_print; @@ -35,7 +35,7 @@ Something::Something() void Something::on_print(int a) { - std::cout << "on_print recieved: " << a << std::endl; + std::cout << "on_print received: " << a << std::endl; } int From f523c0cc076fe960b3f13112b3ea5359dd7e0e90 Mon Sep 17 00:00:00 2001 From: Kjell Ahlstedt Date: Tue, 17 May 2022 10:45:28 +0200 Subject: [PATCH 05/85] meson.build: Avoid configuration warnings --- meson.build | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/meson.build b/meson.build index ca49138e..376c9bd9 100644 --- a/meson.build +++ b/meson.build @@ -5,7 +5,7 @@ project('libsigc++', 'cpp', license: 'LGPLv2.1+', default_options: [ 'cpp_std=c++17', - 'warning_level=0', + 'warning_level=1', ], meson_version: '>= 0.55.0', # required for meson.add_dist_script(python3, ...) # and meson.add_install_script(python3, ...) @@ -70,10 +70,12 @@ maintainer_mode = maintainer_mode_opt == 'true' or \ if is_dist_check message('Looks like a tarball is being tested. ' + \ 'Option "dist-warnings" is used instead of "warnings".') - warning_level = get_option('dist-warnings') + cpp_warnings = get_option('dist-warnings') else - warning_level = get_option('warnings') + cpp_warnings = get_option('warnings') endif +warning_level = get_option('warning_level').to_int() +werror = get_option('werror') build_deprecated_api = get_option('build-deprecated-api') build_documentation_opt = get_option('build-documentation') build_documentation = build_documentation_opt == 'true' or \ @@ -159,25 +161,24 @@ if not (doc_perl_prop.returncode() == 0 and doc_perl_prop.stdout() == 'false') endif # Set compiler warnings. +# Meson warns if any of the /W1, /W2, /W3, /W4, /Wall, -Wall, -Wextra, -Werror +# compiler options are added with add_project_arguments(). +# Avoid such warnings, when possible. +# See _warn_about_builtin_args() in meson/mesonbuild/interpreter/interpreter.py. warning_flags = [] -if warning_level == 'min' - if is_msvc - warning_flags = ['/W3'] - else - warning_flags = ['-Wall'] +if cpp_warnings == 'min' + if warning_level == 0 + warning_flags = is_msvc ? ['/W2'] : ['-Wall'] + endif +elif cpp_warnings == 'max' or cpp_warnings == 'fatal' + if warning_level < 3 + warning_flags = is_msvc ? ['/W4'] : ['-pedantic', '-Wall', '-Wextra'] endif -elif warning_level == 'max' or warning_level == 'fatal' - if is_msvc - warning_flags = ['/W4'] - else - warning_flags = '-pedantic -Wall -Wextra -Wsuggest-override -Wshadow -Wzero-as-null-pointer-constant -Wformat-security'.split() + if not is_msvc + warning_flags += '-Wsuggest-override -Wshadow -Wzero-as-null-pointer-constant -Wformat-security'.split() endif - if warning_level == 'fatal' - if is_msvc - warning_flags += ['/WX'] - else - warning_flags += ['-Werror'] - endif + if cpp_warnings == 'fatal' and not werror + warning_flags += is_msvc ? ['/WX'] : ['-Werror'] endif endif @@ -307,7 +308,8 @@ summary = [ meson.project_name() + ' ' + meson.project_version(), '', ' Maintainer mode: @0@@1@'.format(maintainer_mode_opt, real_maintainer_mode), - ' Compiler warnings: @0@'.format(warning_level), + ' Compiler warnings: @0@ (warning_level: @1@, werror: @2@)'. \ + format(cpp_warnings, warning_level, werror), ' Build deprecated API: @0@'.format(build_deprecated_api), 'Build HTML documentation: @0@@1@'.format(build_documentation_opt, real_build_documentation), ' XML validation: @0@@1@'.format(validate, explain_val), From 196625df045cf7202da1b57acb39ee8b5a16a982 Mon Sep 17 00:00:00 2001 From: Kjell Ahlstedt Date: Tue, 17 May 2022 10:47:10 +0200 Subject: [PATCH 06/85] CI: Remove some tests with autotools Remove the tests with autotools build and clang 8, clang 9, gcc 8 and gcc 9. Test meson build with gcc 10 instead of gcc 9. --- .github/workflows/autotools-clang-8.yml | 25 ----------------- .github/workflows/autotools-clang-9.yml | 27 ------------------- .github/workflows/autotools-gcc-8.yml | 25 ----------------- .github/workflows/autotools-gcc-9.yml | 25 ----------------- .github/workflows/meson-clang-10.yml | 4 +-- .../{meson-gcc-9.yml => meson-gcc-10.yml} | 10 +++---- 6 files changed, 7 insertions(+), 109 deletions(-) delete mode 100644 .github/workflows/autotools-clang-8.yml delete mode 100644 .github/workflows/autotools-clang-9.yml delete mode 100644 .github/workflows/autotools-gcc-8.yml delete mode 100644 .github/workflows/autotools-gcc-9.yml rename .github/workflows/{meson-gcc-9.yml => meson-gcc-10.yml} (79%) diff --git a/.github/workflows/autotools-clang-8.yml b/.github/workflows/autotools-clang-8.yml deleted file mode 100644 index 908e2f83..00000000 --- a/.github/workflows/autotools-clang-8.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: "CI: autotools: clang 8" - -on: [push] - -jobs: - build: - - runs-on: ubuntu-18.04 - - steps: - - uses: actions/checkout@v1 - - name: Build - run: | - sudo apt update - sudo apt install mm-common clang-8 docbook-xsl - export CXX=clang++-8 - ./autogen.sh --enable-warnings=fatal - make - - name: Test - run: make check - - name: Distcheck - run: | - # distcheck runs configure again so we need to specify CXX again. - export CXX=clang++-8 - make distcheck diff --git a/.github/workflows/autotools-clang-9.yml b/.github/workflows/autotools-clang-9.yml deleted file mode 100644 index 9a0dae77..00000000 --- a/.github/workflows/autotools-clang-9.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: "CI: autotools: clang 9" - -on: [push] - -jobs: - build: - - runs-on: ubuntu-20.04 - - steps: - - uses: actions/checkout@v1 - - name: Build - run: | - # Prevent blocking apt install on a question during configuring of tzdata. - export ENV DEBIAN_FRONTEND=noninteractive - sudo apt update - sudo apt install mm-common clang-9 make docbook-xsl --yes - export CC=clang-9 CXX=clang++-9 - ./autogen.sh --enable-warnings=fatal - make - - name: Test - run: make check - - name: Distcheck - run: | - # distcheck runs configure again so we need to specify CC and CXX again. - export CC=clang-9 CXX=clang++-9 - make distcheck diff --git a/.github/workflows/autotools-gcc-8.yml b/.github/workflows/autotools-gcc-8.yml deleted file mode 100644 index 22c32d43..00000000 --- a/.github/workflows/autotools-gcc-8.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: "CI: autotools: gcc 8" - -on: [push] - -jobs: - build: - - runs-on: ubuntu-18.04 - - steps: - - uses: actions/checkout@v1 - - name: Build - run: | - sudo apt update - sudo apt install mm-common g++-8 docbook-xsl - export CXX=g++-8 - ./autogen.sh --enable-warnings=fatal - make - - name: Test - run: make check - - name: Distcheck - run: | - # distcheck runs configure again so we need to specify CXX again. - export CXX=g++-8 - make distcheck diff --git a/.github/workflows/autotools-gcc-9.yml b/.github/workflows/autotools-gcc-9.yml deleted file mode 100644 index 2ef20b49..00000000 --- a/.github/workflows/autotools-gcc-9.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: "CI: autotools: gcc 9" - -on: [push] - -jobs: - build: - - runs-on: ubuntu-20.04 - - steps: - - uses: actions/checkout@v1 - - name: Build - run: | - sudo apt update - sudo apt install mm-common g++-9 docbook-xsl - export CXX=g++-9 - ./autogen.sh --enable-warnings=fatal - make - - name: Test - run: make check - - name: Distcheck - run: | - # distcheck runs configure again so we need to specify CXX again. - export CXX=g++-9 - make distcheck diff --git a/.github/workflows/meson-clang-10.yml b/.github/workflows/meson-clang-10.yml index 13f611b7..adab1966 100644 --- a/.github/workflows/meson-clang-10.yml +++ b/.github/workflows/meson-clang-10.yml @@ -1,4 +1,4 @@ -name: "CI: meson: clang 10" +name: "meson: clang 10" on: [push] @@ -19,7 +19,7 @@ jobs: # Install it with pip3 instead of apt. sudo pip3 install "meson>=0.55.0" export CXX=clang++-10 - meson -Dwarnings=fatal _build + meson -Dwarnings=fatal -Dwarning_level=3 -Dwerror=true _build cd _build meson compile - name: Test diff --git a/.github/workflows/meson-gcc-9.yml b/.github/workflows/meson-gcc-10.yml similarity index 79% rename from .github/workflows/meson-gcc-9.yml rename to .github/workflows/meson-gcc-10.yml index 96b160f7..46cc6b51 100644 --- a/.github/workflows/meson-gcc-9.yml +++ b/.github/workflows/meson-gcc-10.yml @@ -1,4 +1,4 @@ -name: "CI: meson: gcc 9" +name: "meson: gcc 10" on: [push] @@ -14,12 +14,12 @@ jobs: # Prevent blocking apt install on a question during configuring of tzdata. export ENV DEBIAN_FRONTEND=noninteractive sudo apt update - sudo apt install libxml2-utils docbook5-xml docbook-xsl mm-common g++-9 ninja-build python3-setuptools python3-pip --yes + sudo apt install libxml2-utils docbook5-xml docbook-xsl mm-common g++-10 ninja-build python3-setuptools python3-pip --yes # Ubuntu 20.04 contains meson 0.53.2, but libsigc++ requires meson >= 0.55.0. # Install it with pip3 instead of apt. sudo pip3 install "meson>=0.55.0" - export CXX=g++-9 - meson -Dwarnings=fatal _build + export CXX=g++-10 + meson -Dwarnings=fatal -Dwarning_level=3 -Dwerror=true _build cd _build meson compile - name: Test @@ -30,6 +30,6 @@ jobs: run: | sudo apt install git --yes # dist runs setup again so we need to specify CXX again. - export CXX=g++-9 + export CXX=g++-10 cd _build meson dist From 5d8423cd2b05dc3d952abbe790d259699cbbaecf Mon Sep 17 00:00:00 2001 From: Kjell Ahlstedt Date: Thu, 19 May 2022 14:05:23 +0200 Subject: [PATCH 07/85] signal::make_slot() docs: Note that signal does not derive from trackable and therefore the made slot must be manually disconnected if the signal is deleted. See #80 --- sigc++/signal.h | 6 ++++++ sigc++/signal_base.h | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/sigc++/signal.h b/sigc++/signal.h index 8f7dadcb..9d6143c4 100644 --- a/sigc++/signal.h +++ b/sigc++/signal.h @@ -461,6 +461,12 @@ class signal_with_accumulator : public signal_base } /** Creates a functor that calls emit() on this signal. + * + * @note %sigc::signal does not derive from sigc::trackable in sigc++3. + * If you connect the returned functor (calling %emit() on signal1) to + * another signal (signal2) and then delete signal1, you must manually + * disconnect signal1 from signal2 before you delete signal1. + * * @code * sigc::mem_fun(mysignal, &sigc::signal_with_accumulator::emit) * @endcode diff --git a/sigc++/signal_base.h b/sigc++/signal_base.h index 3027c69f..aa27bc21 100644 --- a/sigc++/signal_base.h +++ b/sigc++/signal_base.h @@ -266,6 +266,11 @@ struct SIGC_API signal_impl_holder * @ref sigc::signal_with_accumulator::connect() "sigc::signal::connect()". */ +//TODO: When we can break ABI, let signal_base derive from trackable again. +// It does in sigc++2. Otherwise the slot returned from signal::make_slot() +// is not automatically disconnected when the signal is deleted. +// https://github.com/libsigcplusplus/libsigcplusplus/issues/80 + /** Base class for the @ref sigc::signal "sigc::signal" template. * %signal_base integrates most of the interface of the derived * @ref sigc::signal "sigc::signal" template. From 5ba2da6db90d20c0b75349b7cfb65391b51c180f Mon Sep 17 00:00:00 2001 From: Kjell Ahlstedt Date: Thu, 19 May 2022 14:46:03 +0200 Subject: [PATCH 08/85] Format source code to suit clang-format-12 Format sigc++/signal_base.h. --- sigc++/signal_base.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sigc++/signal_base.h b/sigc++/signal_base.h index aa27bc21..83917820 100644 --- a/sigc++/signal_base.h +++ b/sigc++/signal_base.h @@ -266,7 +266,7 @@ struct SIGC_API signal_impl_holder * @ref sigc::signal_with_accumulator::connect() "sigc::signal::connect()". */ -//TODO: When we can break ABI, let signal_base derive from trackable again. +// TODO: When we can break ABI, let signal_base derive from trackable again. // It does in sigc++2. Otherwise the slot returned from signal::make_slot() // is not automatically disconnected when the signal is deleted. // https://github.com/libsigcplusplus/libsigcplusplus/issues/80 From 10599993cc751a383feeacac61b4d1b2e3c50e79 Mon Sep 17 00:00:00 2001 From: Chun-wei Fan Date: Mon, 23 May 2022 18:56:50 +0800 Subject: [PATCH 09/85] Meson: Compensate for the lack of msvc_recommended_pragmas.h libsigc++ does not depend on GLib, so msvc_recommended_pragmas.h may not be available. If it isn't, disable warning C4244 to compensate for it. --- meson.build | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 376c9bd9..ed21e130 100644 --- a/meson.build +++ b/meson.build @@ -188,7 +188,16 @@ add_project_arguments(warning_flags, language: 'cpp') # MSVC: Ignore warnings that aren't really harmful, but make those # that should not be overlooked stand out. if is_msvc - foreach wd : ['/FImsvc_recommended_pragmas.h', '/EHsc', '/wd4267', '/utf-8'] + # Turn off harmless warnings but make potentially dangerous ones glaring, + # distributed with GLib, if available + use_recommended_pragmas = cpp_compiler.get_supported_arguments('/FImsvc_recommended_pragmas.h') + if use_recommended_pragmas.length() > 0 + add_project_arguments(use_recommended_pragmas, language: 'cpp') + else + disabled_warning = cpp_compiler.get_supported_arguments(['/wd4244']) + add_project_arguments(disabled_warning, language: 'cpp') + endif + foreach wd : ['/EHsc', '/wd4267'] disabled_warning = cpp_compiler.get_supported_arguments(wd) add_project_arguments(disabled_warning, language: 'cpp') endforeach From 8668c3f8e7e09a52d4f6b0c3a389799b2a98a904 Mon Sep 17 00:00:00 2001 From: Chun-wei Fan Date: Mon, 23 May 2022 19:02:03 +0800 Subject: [PATCH 10/85] Meson/MSVC: Re-organize warnings-related compiler flags Add a short description for each of the warnings-related compiler flags that we are using. Also, only apply '/wd4267' for 64-bit builds, since it is a warning that should only be related to 64-bit builds. --- meson.build | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/meson.build b/meson.build index ed21e130..bd1b7713 100644 --- a/meson.build +++ b/meson.build @@ -188,19 +188,28 @@ add_project_arguments(warning_flags, language: 'cpp') # MSVC: Ignore warnings that aren't really harmful, but make those # that should not be overlooked stand out. if is_msvc + disable_warnings_list = [ + '/EHsc', # avoid warnings caused by exception handling model used + ] + # Turn off harmless warnings but make potentially dangerous ones glaring, # distributed with GLib, if available use_recommended_pragmas = cpp_compiler.get_supported_arguments('/FImsvc_recommended_pragmas.h') if use_recommended_pragmas.length() > 0 add_project_arguments(use_recommended_pragmas, language: 'cpp') else - disabled_warning = cpp_compiler.get_supported_arguments(['/wd4244']) - add_project_arguments(disabled_warning, language: 'cpp') + disable_warnings_list += '/wd4244' # 'conversion' conversion from + # 'type1' to 'type2', possible loss of data + endif + + if host_machine.cpu_family() == 'x86_64' or host_machine.cpu_family() == 'aarch64' + # 'var' : conversion from 'size_t' to 'type', possible loss of data (applies on 64-bit builds) + disable_warnings_list += '/wd4267' endif - foreach wd : ['/EHsc', '/wd4267'] - disabled_warning = cpp_compiler.get_supported_arguments(wd) - add_project_arguments(disabled_warning, language: 'cpp') - endforeach + add_project_arguments( + cpp_compiler.get_supported_arguments(disable_warnings_list), + language: 'cpp' + ) endif # Configure files From 8fb78907ccf3c4425d23ba1555f365f22d376685 Mon Sep 17 00:00:00 2001 From: Kjell Ahlstedt Date: Mon, 30 May 2022 16:14:55 +0200 Subject: [PATCH 11/85] signal_with_accumulator derives from trackable A slot made with signal_with_accumulator::make_slot() is then automatically disconnected when the signal is deleted, as in sigc++2. Fixes #80 --- sigc++/signal.h | 32 ++++++++++++++++++++++---------- sigc++/signal_base.h | 7 ++++--- tests/test_signal.cc | 12 ++++++++++++ 3 files changed, 38 insertions(+), 13 deletions(-) diff --git a/sigc++/signal.h b/sigc++/signal.h index 9d6143c4..4a17e06f 100644 --- a/sigc++/signal.h +++ b/sigc++/signal.h @@ -371,8 +371,14 @@ struct signal_emit } /* namespace internal */ +// TODO: When we can break ABI, let signal_base instead of signal_with_accumulator +// derive from trackable, as in sigc++2. One of them must derive from trackable. +// Otherwise the slot returned from signal_with_accumulator::make_slot() is not +// automatically disconnected when the signal is deleted. +// https://github.com/libsigcplusplus/libsigcplusplus/issues/80 + /** Signal declaration. - * signal_with_accumulator can be used to connect() slots that are invoked + * %signal_with_accumulator can be used to connect() slots that are invoked * during subsequent calls to emit(). Any functor or slot * can be passed into connect(). It is converted into a slot * implicitly. @@ -396,7 +402,9 @@ struct signal_emit * @ingroup signal */ template -class signal_with_accumulator : public signal_base +class signal_with_accumulator +: public signal_base +, public trackable { public: using slot_type = slot; @@ -461,11 +469,6 @@ class signal_with_accumulator : public signal_base } /** Creates a functor that calls emit() on this signal. - * - * @note %sigc::signal does not derive from sigc::trackable in sigc++3. - * If you connect the returned functor (calling %emit() on signal1) to - * another signal (signal2) and then delete signal1, you must manually - * disconnect signal1 from signal2 before you delete signal1. * * @code * sigc::mem_fun(mysignal, &sigc::signal_with_accumulator::emit) @@ -485,19 +488,28 @@ class signal_with_accumulator : public signal_base signal_with_accumulator() = default; - signal_with_accumulator(const signal_with_accumulator& src) : signal_base(src) {} + signal_with_accumulator(const signal_with_accumulator& src) : signal_base(src), trackable(src) {} - signal_with_accumulator(signal_with_accumulator&& src) : signal_base(std::move(src)) {} + signal_with_accumulator(signal_with_accumulator&& src) + : signal_base(std::move(src)), trackable(std::move(src)) + { + } signal_with_accumulator& operator=(const signal_with_accumulator& src) { signal_base::operator=(src); + // Don't call trackable::operator=(src). + // It calls notify_callbacks(). This signal is not destroyed. return *this; } signal_with_accumulator& operator=(signal_with_accumulator&& src) { signal_base::operator=(std::move(src)); + if (src.impl_ != impl_) + src.notify_callbacks(); + // Don't call trackable::operator=(std::move(src)). + // It calls notify_callbacks(). This signal is not destroyed. return *this; } }; @@ -531,7 +543,7 @@ class signal_with_accumulator : public signal_base * @par Example: * @code * void foo(int) {} - * sigc::signal sig; + * sigc::signal sig; * sig.connect(sigc::ptr_fun(&foo)); * sig.emit(19); * @endcode diff --git a/sigc++/signal_base.h b/sigc++/signal_base.h index 83917820..a6da7d33 100644 --- a/sigc++/signal_base.h +++ b/sigc++/signal_base.h @@ -266,9 +266,10 @@ struct SIGC_API signal_impl_holder * @ref sigc::signal_with_accumulator::connect() "sigc::signal::connect()". */ -// TODO: When we can break ABI, let signal_base derive from trackable again. -// It does in sigc++2. Otherwise the slot returned from signal::make_slot() -// is not automatically disconnected when the signal is deleted. +// TODO: When we can break ABI, let signal_base instead of signal_with_accumulator +// derive from trackable, as in sigc++2. One of them must derive from trackable. +// Otherwise the slot returned from signal_with_accumulator::make_slot() is not +// automatically disconnected when the signal is deleted. // https://github.com/libsigcplusplus/libsigcplusplus/issues/80 /** Base class for the @ref sigc::signal "sigc::signal" template. diff --git a/tests/test_signal.cc b/tests/test_signal.cc index d050558b..34a8c7d6 100644 --- a/tests/test_signal.cc +++ b/tests/test_signal.cc @@ -5,6 +5,7 @@ #include "testutilities.h" #include #include +#include namespace { @@ -110,6 +111,17 @@ test_make_slot() sig2.connect(sig.make_slot()); sig2(3); util->check_result(result_stream, "foo(int 3) bar(float 3) foo(int 3) "); + + // Delete a signal that has been connected to sig2. + sig2.clear(); + sig2.connect(sigc::ptr_fun(&bar)); + auto sig3 = std::make_unique>(); + sig3->connect(sigc::ptr_fun(&foo)); + sig2.connect(sig3->make_slot()); + sig2(2); + sig3.reset(); + sig2(42); + util->check_result(result_stream, "bar(float 2) foo(int 2) bar(float 42) "); } void From d6271316157b6478aca068b6f972da7e839fe90a Mon Sep 17 00:00:00 2001 From: Kjell Ahlstedt Date: Mon, 30 May 2022 18:38:28 +0200 Subject: [PATCH 12/85] test_limit_reference.cc: Don't use auto where a slot is required The return values of sigc::bind() and sigc::bind_return() shall be converted to sigc::slot, otherwise automatic disconnection does not work. Fixes #44 --- tests/test_limit_reference.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/test_limit_reference.cc b/tests/test_limit_reference.cc index 8d1340d6..a115d6dc 100644 --- a/tests/test_limit_reference.cc +++ b/tests/test_limit_reference.cc @@ -14,6 +14,8 @@ class Base : virtual public sigc::trackable public: Base() {} + Base(const Base& src) = default; + Base& operator=(const Base& src) = default; Base(Base&& src) = delete; Base& operator=(Base&& src) = delete; }; @@ -47,11 +49,11 @@ main(int argc, char* argv[]) handler(); util->check_result(result_stream, "method()"); - auto param = sigc::bind(sigc::slot(), std::ref(*instance)); + sigc::slot param = sigc::bind(sigc::slot(), std::ref(*instance)); param(); util->check_result(result_stream, ""); - auto ret = sigc::bind_return(sigc::slot(), std::ref(*instance)); + sigc::slot ret = sigc::bind_return(sigc::slot(), std::ref(*instance)); ret(); util->check_result(result_stream, ""); From c07d75d47dd0374e437c8ba6f4c4816d4b7f89e1 Mon Sep 17 00:00:00 2001 From: Kjell Ahlstedt Date: Tue, 31 May 2022 15:30:15 +0200 Subject: [PATCH 13/85] Revert "signal_with_accumulator derives from trackable" This reverts commit 8fb78907ccf3c4425d23ba1555f365f22d376685. It's not safe. See #80 --- sigc++/signal.h | 32 ++++++++++---------------------- sigc++/signal_base.h | 7 +++---- tests/test_signal.cc | 12 ------------ 3 files changed, 13 insertions(+), 38 deletions(-) diff --git a/sigc++/signal.h b/sigc++/signal.h index 4a17e06f..9d6143c4 100644 --- a/sigc++/signal.h +++ b/sigc++/signal.h @@ -371,14 +371,8 @@ struct signal_emit } /* namespace internal */ -// TODO: When we can break ABI, let signal_base instead of signal_with_accumulator -// derive from trackable, as in sigc++2. One of them must derive from trackable. -// Otherwise the slot returned from signal_with_accumulator::make_slot() is not -// automatically disconnected when the signal is deleted. -// https://github.com/libsigcplusplus/libsigcplusplus/issues/80 - /** Signal declaration. - * %signal_with_accumulator can be used to connect() slots that are invoked + * signal_with_accumulator can be used to connect() slots that are invoked * during subsequent calls to emit(). Any functor or slot * can be passed into connect(). It is converted into a slot * implicitly. @@ -402,9 +396,7 @@ struct signal_emit * @ingroup signal */ template -class signal_with_accumulator -: public signal_base -, public trackable +class signal_with_accumulator : public signal_base { public: using slot_type = slot; @@ -469,6 +461,11 @@ class signal_with_accumulator } /** Creates a functor that calls emit() on this signal. + * + * @note %sigc::signal does not derive from sigc::trackable in sigc++3. + * If you connect the returned functor (calling %emit() on signal1) to + * another signal (signal2) and then delete signal1, you must manually + * disconnect signal1 from signal2 before you delete signal1. * * @code * sigc::mem_fun(mysignal, &sigc::signal_with_accumulator::emit) @@ -488,28 +485,19 @@ class signal_with_accumulator signal_with_accumulator() = default; - signal_with_accumulator(const signal_with_accumulator& src) : signal_base(src), trackable(src) {} + signal_with_accumulator(const signal_with_accumulator& src) : signal_base(src) {} - signal_with_accumulator(signal_with_accumulator&& src) - : signal_base(std::move(src)), trackable(std::move(src)) - { - } + signal_with_accumulator(signal_with_accumulator&& src) : signal_base(std::move(src)) {} signal_with_accumulator& operator=(const signal_with_accumulator& src) { signal_base::operator=(src); - // Don't call trackable::operator=(src). - // It calls notify_callbacks(). This signal is not destroyed. return *this; } signal_with_accumulator& operator=(signal_with_accumulator&& src) { signal_base::operator=(std::move(src)); - if (src.impl_ != impl_) - src.notify_callbacks(); - // Don't call trackable::operator=(std::move(src)). - // It calls notify_callbacks(). This signal is not destroyed. return *this; } }; @@ -543,7 +531,7 @@ class signal_with_accumulator * @par Example: * @code * void foo(int) {} - * sigc::signal sig; + * sigc::signal sig; * sig.connect(sigc::ptr_fun(&foo)); * sig.emit(19); * @endcode diff --git a/sigc++/signal_base.h b/sigc++/signal_base.h index a6da7d33..83917820 100644 --- a/sigc++/signal_base.h +++ b/sigc++/signal_base.h @@ -266,10 +266,9 @@ struct SIGC_API signal_impl_holder * @ref sigc::signal_with_accumulator::connect() "sigc::signal::connect()". */ -// TODO: When we can break ABI, let signal_base instead of signal_with_accumulator -// derive from trackable, as in sigc++2. One of them must derive from trackable. -// Otherwise the slot returned from signal_with_accumulator::make_slot() is not -// automatically disconnected when the signal is deleted. +// TODO: When we can break ABI, let signal_base derive from trackable again. +// It does in sigc++2. Otherwise the slot returned from signal::make_slot() +// is not automatically disconnected when the signal is deleted. // https://github.com/libsigcplusplus/libsigcplusplus/issues/80 /** Base class for the @ref sigc::signal "sigc::signal" template. diff --git a/tests/test_signal.cc b/tests/test_signal.cc index 34a8c7d6..d050558b 100644 --- a/tests/test_signal.cc +++ b/tests/test_signal.cc @@ -5,7 +5,6 @@ #include "testutilities.h" #include #include -#include namespace { @@ -111,17 +110,6 @@ test_make_slot() sig2.connect(sig.make_slot()); sig2(3); util->check_result(result_stream, "foo(int 3) bar(float 3) foo(int 3) "); - - // Delete a signal that has been connected to sig2. - sig2.clear(); - sig2.connect(sigc::ptr_fun(&bar)); - auto sig3 = std::make_unique>(); - sig3->connect(sigc::ptr_fun(&foo)); - sig2.connect(sig3->make_slot()); - sig2(2); - sig3.reset(); - sig2(42); - util->check_result(result_stream, "bar(float 2) foo(int 2) bar(float 42) "); } void From 560f800e45329ad55b1f5b0a05a80ad63164da48 Mon Sep 17 00:00:00 2001 From: Kjell Ahlstedt Date: Tue, 31 May 2022 16:57:50 +0200 Subject: [PATCH 14/85] Add trackable_signal_with_accumulator and trackable_signal trackable_signal_with_accumulator derives from trackable. A slot made with trackable_signal_with_accumulator::make_slot() is automatically disconnected when the signal is deleted, as in sigc++2. Fixes #80 --- sigc++/signal.h | 291 +++++++++++++++++++++++++++++++++++++- sigc++/signal_base.h | 5 +- tests/test_accumulated.cc | 6 +- tests/test_signal.cc | 18 ++- 4 files changed, 308 insertions(+), 12 deletions(-) diff --git a/sigc++/signal.h b/sigc++/signal.h index 9d6143c4..8cddf103 100644 --- a/sigc++/signal.h +++ b/sigc++/signal.h @@ -372,7 +372,7 @@ struct signal_emit } /* namespace internal */ /** Signal declaration. - * signal_with_accumulator can be used to connect() slots that are invoked + * %signal_with_accumulator can be used to connect() slots that are invoked * during subsequent calls to emit(). Any functor or slot * can be passed into connect(). It is converted into a slot * implicitly. @@ -462,10 +462,11 @@ class signal_with_accumulator : public signal_base /** Creates a functor that calls emit() on this signal. * - * @note %sigc::signal does not derive from sigc::trackable in sigc++3. - * If you connect the returned functor (calling %emit() on signal1) to - * another signal (signal2) and then delete signal1, you must manually + * @note %sigc::signal does not derive from sigc::trackable. + * If you connect the returned functor that calls %emit() on signal1, + * to another signal (signal2) and then delete signal1, you must manually * disconnect signal1 from signal2 before you delete signal1. + * Alternatively, make a slot of a sigc::trackable_signal. * * @code * sigc::mem_fun(mysignal, &sigc::signal_with_accumulator::emit) @@ -517,7 +518,8 @@ class signal_with_accumulator : public signal_base * * The template arguments determine the function signature of * the emit() function: - * - @e T_return The desired return type of the emit() function. * - @e T_arg Argument types used in + * - @e T_return The desired return type of the emit() function. + * - @e T_arg Argument types used in * the definition of emit(). * * For instance, to declare a signal whose connected slot returns void and takes @@ -531,7 +533,7 @@ class signal_with_accumulator : public signal_base * @par Example: * @code * void foo(int) {} - * sigc::signal sig; + * sigc::signal sig; * sig.connect(sigc::ptr_fun(&foo)); * sig.emit(19); * @endcode @@ -625,6 +627,283 @@ class signal : public signal_with_accumulator +class trackable_signal_with_accumulator +: public signal_base +, public trackable +{ +public: + using slot_type = slot; + + /** Add a slot to the list of slots. + * Any functor or slot may be passed into connect(). + * It will be converted into a slot implicitly. + * The returned connection may be stored for disconnection + * of the slot at some later point. It stays valid until + * the slot is disconnected from the signal. + * std::function<> and C++11 lambda expressions are functors. + * These are examples of functors that can be connected to a signal. + * + * %std::bind() creates a functor, but this functor typically has an + * %operator()() which is a variadic template. + * Our functor_trait can't deduce the result type + * of such a functor. If you first assign the return value of %std::bind() + * to a std::function, you can connect the std::function to a signal. + * + * @param slot_ The slot to add to the list of slots. + * @return A connection. + */ + connection connect(const slot_type& slot_) + { + auto iter = signal_base::connect(slot_); + auto& slot_base = *iter; + return connection(slot_base); + } + + /** Add a slot to the list of slots. + * @see connect(const slot_type& slot_). + */ + connection connect(slot_type&& slot_) + { + auto iter = signal_base::connect(std::move(slot_)); + auto& slot_base = *iter; + return connection(slot_base); + } + + /** Triggers the emission of the signal. + * During signal emission all slots that have been connected + * to the signal are invoked unless they are manually set into + * a blocking state. The parameters are passed on to the slots. + * If @e T_accumulated is not @p void, an accumulator of this type + * is used to process the return values of the slot invocations. + * Otherwise, the return value of the last slot invoked is returned. + * @param a Arguments to be passed on to the slots. + * @return The accumulated return values of the slot invocations. + */ + decltype(auto) emit(type_trait_take_t... a) const + { + using emitter_type = internal::signal_emit; + return emitter_type::emit(impl_, std::forward>(a)...); + } + + /** Triggers the emission of the signal (see emit()). */ + decltype(auto) operator()(type_trait_take_t... a) const + { + return emit(std::forward>(a)...); + } + + /** Creates a functor that calls emit() on this signal. + * + * @code + * sigc::mem_fun(mysignal, &sigc::trackable_signal_with_accumulator::emit) + * @endcode + * yields the same result. + * @return A functor that calls emit() on this signal. + */ + decltype(auto) make_slot() const + { + // TODO: Instead use std::invoke_result<> on the static emitter_type::emit() + using result_type = typename internal::member_method_result< + decltype(&trackable_signal_with_accumulator::emit)>::type; + return bound_mem_functor...) const, + type_trait_take_t...>(*this, &trackable_signal_with_accumulator::emit); + } + + trackable_signal_with_accumulator() = default; + + trackable_signal_with_accumulator(const trackable_signal_with_accumulator& src) + : signal_base(src), trackable(src) + { + } + + trackable_signal_with_accumulator(trackable_signal_with_accumulator&& src) + : signal_base(std::move(src)), trackable(std::move(src)) + { + } + + trackable_signal_with_accumulator& operator=(const trackable_signal_with_accumulator& src) + { + signal_base::operator=(src); + // Don't call trackable::operator=(src). + // It calls notify_callbacks(). This signal is not destroyed. + return *this; + } + + trackable_signal_with_accumulator& operator=(trackable_signal_with_accumulator&& src) + { + signal_base::operator=(std::move(src)); + if (src.impl_ != impl_) + src.notify_callbacks(); + // Don't call trackable::operator=(std::move(src)). + // It calls notify_callbacks(). This signal is not destroyed. + return *this; + } +}; + +/** %trackable_signal can be used to connect() slots that are invoked + * during subsequent calls to emit(). Any functor or slot + * can be passed into connect(). It is converted into a slot + * implicitly. + * + * If you want to connect one signal to another, use make_slot() + * to retrieve a functor that emits the signal when invoked. + * + * Be careful if you directly pass one signal into the connect() + * method of another: a shallow copy of the signal is made and + * the signal's slots are not disconnected until both the signal + * and its clone are destroyed, which is probably not what you want! + * + * The template arguments determine the function signature of + * the emit() function: + * - @e T_return The desired return type of the emit() function. + * - @e T_arg Argument types used in + * the definition of emit(). + * + * For instance, to declare a %trackable_signal whose connected slot returns void and takes + * two parameters of bool and int: + * @code + * sigc::trackable_signal some_signal; + * @endcode + * + * To specify an accumulator type the nested class trackable_signal::accumulated can be used. + * + * @par Example: + * @code + * void foo(int) {} + * sigc::trackable_signal sig; + * sig.connect(sigc::ptr_fun(&foo)); + * sig.emit(19); + * @endcode + * + * @newin{3,4} + * + * @ingroup signal + */ +#ifndef DOXYGEN_SHOULD_SKIP_THIS +template +class trackable_signal; +#endif // DOXYGEN_SHOULD_SKIP_THIS + +template +class trackable_signal +: public trackable_signal_with_accumulator +{ +public: + using accumulator_type = void; + + /** Like @ref sigc::trackable_signal "sigc::trackable_signal" + * but the additional template parameter @e T_accumulator defines the accumulator + * type that should be used. + * + * An accumulator is a functor that uses a pair of special iterators + * to step through a list of slots and calculate a return value + * from the results of the slot invocations. The iterators' operator*() + * executes the slot. The return value is buffered, so that in an expression + * like @code a = (*i) * (*i); @endcode the slot is executed only once. + * + * @par Example 1: + * This accumulator calculates the arithmetic mean value: + * @code + * struct arithmetic_mean_accumulator + * { + * template + * double operator()(T_iterator first, T_iterator last) const + * { + * double value_ = 0; + * int n_ = 0; + * for (; first != last; ++first, ++n_) + * value_ += *first; + * return value_ / n_; + * } + * }; + * @endcode + * + * @par Example 2: + * This accumulator stops signal emission when a slot returns zero: + * @code + * struct interruptable_accumulator + * { + * template + * bool operator()(T_iterator first, T_iterator last) const + * { + * for (; first != last; ++first, ++n_) + * if (!*first) return false; + * return true; + * } + * }; + * @endcode + * + * @newin{3,4} + * + * @ingroup signal + */ + template + class accumulated : public trackable_signal_with_accumulator + { + public: + accumulated() = default; + accumulated(const accumulated& src) + : trackable_signal_with_accumulator(src) + { + } + }; + + trackable_signal() = default; + + trackable_signal(const trackable_signal& src) + : trackable_signal_with_accumulator(src) + { + } + + trackable_signal(trackable_signal&& src) + : trackable_signal_with_accumulator(std::move(src)) + { + } + + trackable_signal& operator=(const trackable_signal& src) + { + trackable_signal_with_accumulator::operator=(src); + return *this; + } + + trackable_signal& operator=(trackable_signal&& src) + { + trackable_signal_with_accumulator::operator=( + std::move(src)); + return *this; + } +}; + } /* namespace sigc */ #endif /* SIGC_SIGNAL_H */ diff --git a/sigc++/signal_base.h b/sigc++/signal_base.h index 83917820..d21e4b3b 100644 --- a/sigc++/signal_base.h +++ b/sigc++/signal_base.h @@ -266,9 +266,10 @@ struct SIGC_API signal_impl_holder * @ref sigc::signal_with_accumulator::connect() "sigc::signal::connect()". */ -// TODO: When we can break ABI, let signal_base derive from trackable again. -// It does in sigc++2. Otherwise the slot returned from signal::make_slot() +// TODO: When we can break ABI, let signal_base derive from trackable again, +// as in sigc++2. Otherwise the slot returned from signal::make_slot() // is not automatically disconnected when the signal is deleted. +// And delete trackable_signal_with_accumulator and trackable_signal. // https://github.com/libsigcplusplus/libsigcplusplus/issues/80 /** Base class for the @ref sigc::signal "sigc::signal" template. diff --git a/tests/test_accumulated.cc b/tests/test_accumulated.cc index f010b1cd..39122b50 100644 --- a/tests/test_accumulated.cc +++ b/tests/test_accumulated.cc @@ -79,10 +79,11 @@ test_empty_signal() util->check_result(result_stream, "Vector result (empty slot list): empty"); } +template void test_mean() { - sigc::signal::accumulated sig; + typename T_signal::accumulated sig; A a; sig.connect(sigc::ptr_fun(&foo)); @@ -137,7 +138,8 @@ main(int argc, char* argv[]) return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; test_empty_signal(); - test_mean(); + test_mean>(); + test_mean>(); test_vector_accumulator(); return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; diff --git a/tests/test_signal.cc b/tests/test_signal.cc index d050558b..ff197a4d 100644 --- a/tests/test_signal.cc +++ b/tests/test_signal.cc @@ -5,6 +5,7 @@ #include "testutilities.h" #include #include +#include namespace { @@ -62,11 +63,12 @@ bar(float i) return 1; } +template void test_auto_disconnection() { // signal - sigc::signal sig; + T_signal sig; // connect some slots before emitting & test auto-disconnection { @@ -110,6 +112,17 @@ test_make_slot() sig2.connect(sig.make_slot()); sig2(3); util->check_result(result_stream, "foo(int 3) bar(float 3) foo(int 3) "); + + // Delete a trackable_signal that has been connected to sig2. + sig2.clear(); + sig2.connect(sigc::ptr_fun(&bar)); + auto sig3 = std::make_unique>(); + sig3->connect(sigc::ptr_fun(&foo)); + sig2.connect(sig3->make_slot()); + sig2(2); + sig3.reset(); + sig2(42); + util->check_result(result_stream, "bar(float 2) foo(int 2) bar(float 42) "); } void @@ -158,7 +171,8 @@ main(int argc, char* argv[]) test_empty_signal(); test_simple(); - test_auto_disconnection(); + test_auto_disconnection>(); + test_auto_disconnection>(); test_reference(); test_make_slot(); test_clear_called_in_signal_handler(); From 12cab9493107f8c65da1bccc1a4b3961b51c6fe3 Mon Sep 17 00:00:00 2001 From: Kjell Ahlstedt Date: Tue, 31 May 2022 17:24:51 +0200 Subject: [PATCH 15/85] test_accumulated.cc: clang++ requires another 'template' --- tests/test_accumulated.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_accumulated.cc b/tests/test_accumulated.cc index 39122b50..7fa81cc9 100644 --- a/tests/test_accumulated.cc +++ b/tests/test_accumulated.cc @@ -83,7 +83,7 @@ template void test_mean() { - typename T_signal::accumulated sig; + typename T_signal::template accumulated sig; A a; sig.connect(sigc::ptr_fun(&foo)); From 83422a7a5d60cbc7a575146e7fd99f4446df9426 Mon Sep 17 00:00:00 2001 From: Kjell Ahlstedt Date: Wed, 20 Jul 2022 21:53:12 +0200 Subject: [PATCH 16/85] Update README.md --- README.md | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index ecbb21f3..5ffed357 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,11 @@ allows you to define signals and to connect those signals to any callback function, either global or a member function, regardless of whether it is static or virtual. -libsigc++ is used by gtkmm to wrap the GTK+ signal system. It does not -depend on GTK+ or gtkmm. +libsigc++ is used by gtkmm to wrap the GTK signal system. It does not +depend on GTK or gtkmm. + +sigc++-2.0 and sigc++-3.0 are different parallel-installable ABIs. +This file describes sigc++-3.0. See the [libsigc++ web site](https://libsigcplusplus.github.io/libsigcplusplus/) @@ -31,7 +34,8 @@ packages. ## Building from a release tarball -Building from the [libsigc++ release tarball](https://github.com/libsigcplusplus/libsigcplusplus/releases) is easier than building from git. +Building from the [libsigc++ release tarball](https://github.com/libsigcplusplus/libsigcplusplus/releases) +is easier than building from git. It's easiest to build with Meson, if the tarball was made with Meson, and to build with Autotools, if the tarball was made with Autotools. @@ -50,10 +54,10 @@ For instance: ```sh # If the tarball was made with Autotools, and you want to rebuild the reference # documentation, you must enable maintainer-mode: -$ meson --prefix=/usr/local --libdir=lib -Dmaintainer-mode=true your_builddir . +$ meson --prefix=/some_directory --libdir=lib -Dmaintainer-mode=true your_builddir . # If the tarball was made with Meson, or you don't want to rebuild the docs: -$ meson --prefix=/usr/local --libdir=lib your_builddir . +$ meson --prefix=/some_directory --libdir=lib your_builddir . # then: $ cd your_builddir @@ -68,10 +72,10 @@ $ ninja test For instance: ```sh # If the tarball was made with Autotools: -$ ./configure --prefix=/usr/local +$ ./configure --prefix=/some_directory # If the tarball was made with Meson, you must enable maintainer-mode: -$ ./autogen.sh --prefix=/usr/local +$ ./autogen.sh --prefix=/some_directory # then: $ make @@ -85,8 +89,9 @@ $ make check Building from git can be difficult so you should prefer building from a release tarball unless you need to work on the libsigc++ code itself. -jhbuild can be a good help. See the [jhbuild repo](https://gitlab.gnome.org/GNOME/jhbuild) -and the [jhbuild wiki](https://wiki.gnome.org/Projects/Jhbuild). +jhbuild can be a good help. See the [jhbuild repo](https://gitlab.gnome.org/GNOME/jhbuild), +the [jhbuild wiki](https://wiki.gnome.org/Projects/Jhbuild) and +the [jhbuild manual](https://gnome.pages.gitlab.gnome.org/jhbuild). ### Building from git with Meson @@ -100,7 +105,7 @@ Don't call the builddir 'build'. There is a directory called 'build' with files used by Autotools. ```sh -$ meson --prefix=/usr/local --libdir=lib your_builddir . +$ meson --prefix=/some_directory --libdir=lib your_builddir . $ cd your_builddir $ ninja $ ninja install @@ -116,7 +121,7 @@ You must have Autotools properly installed (autoconf, automake, etc) and you will also need [mm-common](https://gitlab.gnome.org/GNOME/mm-common/). ```sh -$ ./autogen.sh --prefix=/usr/local +$ ./autogen.sh --prefix=/some_directory $ make $ make install # You can build the examples and tests, and run the tests, like so: From 10dd1c73b2bb86dcafb55c411707ebe2d68bf4df Mon Sep 17 00:00:00 2001 From: Kjell Ahlstedt Date: Mon, 15 Aug 2022 16:20:30 +0200 Subject: [PATCH 17/85] Fix build with -Dbuild-deprecated-api=false Fixes #82 --- examples/meson.build | 2 +- meson.build | 2 +- tests/test_cpp11_lambda.cc | 12 ++++++------ tests/test_track_obj.cc | 29 ++++++++++++++++++++++++++++- 4 files changed, 36 insertions(+), 9 deletions(-) diff --git a/examples/meson.build b/examples/meson.build index c55bfdd8..3c575aec 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -20,7 +20,7 @@ foreach ex : examples endforeach exe_file = executable(ex_name, ex_sources, - cpp_args: '-DSIGCXX_DISABLE_DEPRECATED', + cpp_args: '-DSIGCXX_DISABLE_DEPRECATED=1', dependencies: sigcxx_own_dep, implicit_include_directories: false, build_by_default: build_examples diff --git a/meson.build b/meson.build index bd1b7713..c1b0c906 100644 --- a/meson.build +++ b/meson.build @@ -225,7 +225,7 @@ pkg_conf_data.set('PACKAGE_VERSION', meson.project_version()) pkg_conf_data.set('SIGCXX_API_VERSION', sigcxx_api_version) if not build_deprecated_api - pkg_conf_data.set('SIGCXX_DISABLE_DEPRECATED', true) + pkg_conf_data.set('SIGCXX_DISABLE_DEPRECATED', 1) endif pkg_conf_data.set('SIGCXX_MAJOR_VERSION', sigcxx_major_version) pkg_conf_data.set('SIGCXX_MINOR_VERSION', sigcxx_minor_version) diff --git a/tests/test_cpp11_lambda.cc b/tests/test_cpp11_lambda.cc index ed125361..40534e25 100644 --- a/tests/test_cpp11_lambda.cc +++ b/tests/test_cpp11_lambda.cc @@ -32,7 +32,7 @@ // The only real disadvantage of the C++11 lambda expressions is that a slot that // contains an object derived from sigc::trackable is not automatically disconnected // when the object is deleted, if a reference to the object is stored in a C++11 -// lambda expression, connected to the slot. But if you use sigc::track_obj(), +// lambda expression, connected to the slot. But if you use sigc::track_object(), // the slot is automatically disconnected. Thus, the disadvantage is insignificant. // // To test the C++11 lambda expressions with gcc 4.6.3 (and probably some later @@ -270,14 +270,14 @@ main(int argc, char* argv[]) // Here's an area where the libsigc++ lambda expressions are advantageous. // If you want to auto-disconnect a slot with a C++11 lambda expression // that contains references to sigc::trackable-derived objects, you must use - // sigc::track_obj(). + // sigc::track_object(). sigc::slot sl1; { book guest_book("karl"); // sl1 = (sigc::var(std::cout) << std::ref(guest_book) << sigc::var("\n")); // sl1 = [&guest_book](std::ostringstream& stream){ stream << guest_book << "\n"; }; // no // auto-disconnect - sl1 = sigc::track_obj( + sl1 = sigc::track_object( [&guest_book](std::ostringstream& stream) { stream << guest_book << "\n"; }, guest_book); sl1(result_stream); util->check_result(result_stream, "karl\n"); @@ -332,7 +332,7 @@ main(int argc, char* argv[]) // sl2 = sigc::group(&egon, std::ref(guest_book)); // sl2 = [&guest_book] () { egon(guest_book); }; // no auto-disconnect // sl2 = std::bind(&egon, std::ref(guest_book)); // does not compile (gcc 4.6.3) - sl2 = sigc::track_obj([&guest_book]() { egon(guest_book); }, guest_book); + sl2 = sigc::track_object([&guest_book]() { egon(guest_book); }, guest_book); sl2(); util->check_result(result_stream, "egon(string 'karl')"); @@ -352,7 +352,7 @@ main(int argc, char* argv[]) // sl2 = std::bind(&egon, std::ref(guest_book)); // does not compile (gcc 4.6.3) auto fn2 = std::bind(&egon, std::ref(guest_book)); // sl2 = fn2; // no auto-disconnect - sl2 = sigc::track_obj(fn2, guest_book); + sl2 = sigc::track_object(fn2, guest_book); sl2(); util->check_result(result_stream, "egon(string 'charlie')"); @@ -502,7 +502,7 @@ main(int argc, char* argv[]) // some_signal.connect([&some_bar](){ foo_group4(some_bar); }); // no auto-disconnect // some_signal.connect(sigc::bind(&foo_group4, std::ref(some_bar))); // auto-disconnects, but // we prefer C++11 lambda - some_signal.connect(sigc::track_obj([&some_bar]() { foo_group4(some_bar); }, some_bar)); + some_signal.connect(sigc::track_object([&some_bar]() { foo_group4(some_bar); }, some_bar)); some_signal.emit(); util->check_result(result_stream, "foo_group4(bar_group4&)"); } diff --git a/tests/test_track_obj.cc b/tests/test_track_obj.cc index 54b44309..5d919534 100644 --- a/tests/test_track_obj.cc +++ b/tests/test_track_obj.cc @@ -28,6 +28,12 @@ // // If test_track_obj writes nothing and the return code is 0, the test has passed. +// sigc::track_obj() is deprecated, but let's keep the test if possible. +// If libsigc++ is configured with -Dbuild-deprecated-api=false +// (--disable-deprecated-api), SIGCXX_DISABLE_DEPRECATED is defined in +// sigc++config.h. An undef at the start of this file has no effect. +#undef SIGCXX_DISABLE_DEPRECATED + #include "testutilities.h" #include #include @@ -118,7 +124,11 @@ main(int argc, char* argv[]) sigc::slot sl2; { bar_group4 bar4; +#ifndef SIGCXX_DISABLE_DEPRECATED sl1 = sigc::track_obj(Functor1(bar4), bar4); +#else + sl1 = sigc::track_object(Functor1(bar4), bar4); +#endif sl2 = sigc::track_object(Functor1(bar4), bar4); result_stream << sl1(-2) << ", " << sl2(2); util->check_result(result_stream, "negative, positive"); @@ -134,7 +144,11 @@ main(int argc, char* argv[]) auto psl4 = new sigc::slot; auto pbar4 = new bar_group4; auto pbook4 = new book("A Book"); +#ifndef SIGCXX_DISABLE_DEPRECATED *psl3 = sigc::track_obj(Functor2(*pbar4, *pbook4), *pbar4, *pbook4); +#else + *psl3 = sigc::track_object(Functor2(*pbar4, *pbook4), *pbar4, *pbook4); +#endif *psl4 = sigc::track_object(Functor2(*pbar4, *pbook4), *pbar4, *pbook4); result_stream << (*psl3)(0, "Book title: ") << ", " << (*psl4)(1, "Title: "); util->check_result(result_stream, "zero, Book title: A Book, positive, Title: A Book"); @@ -162,8 +176,13 @@ main(int argc, char* argv[]) book guest_book("karl"); // no auto-disconnect // sl1 = [&guest_book](std::ostringstream& stream){ stream << guest_book << "\n"; }; +#ifndef SIGCXX_DISABLE_DEPRECATED sl11 = sigc::track_obj( [&guest_book](std::ostringstream& stream) { stream << guest_book; }, guest_book); +#else + sl11 = sigc::track_object( + [&guest_book](std::ostringstream& stream) { stream << guest_book; }, guest_book); +#endif sl12 = sigc::track_object( [&guest_book](std::ostringstream& stream) { stream << guest_book; }, guest_book); sl11(result_stream); @@ -183,8 +202,12 @@ main(int argc, char* argv[]) book guest_book("karl"); // sl2 = [&guest_book] () { egon(guest_book); }; // no auto-disconnect // sl2 = std::bind(&egon, std::ref(guest_book)); // does not compile (gcc 4.6.3) +#ifndef SIGCXX_DISABLE_DEPRECATED sl21 = sigc::track_obj([&guest_book]() { egon(guest_book); }, guest_book); - sl22 = sigc::track_obj([&guest_book]() { egon(guest_book); }, guest_book); +#else + sl21 = sigc::track_object([&guest_book]() { egon(guest_book); }, guest_book); +#endif + sl22 = sigc::track_object([&guest_book]() { egon(guest_book); }, guest_book); sl21(); sl22(); util->check_result(result_stream, "egon(string 'karl')egon(string 'egon was here')"); @@ -208,7 +231,11 @@ main(int argc, char* argv[]) // some_signal.connect([&some_bar](){ foo_group4(some_bar); }); // no auto-disconnect // some_signal.connect(sigc::bind(&foo_group4, std::ref(some_bar))); // auto-disconnects, // but we prefer C++11 lambda +#ifndef SIGCXX_DISABLE_DEPRECATED some_signal.connect(sigc::track_obj([&some_bar]() { foo_group4(some_bar); }, some_bar)); +#else + some_signal.connect(sigc::track_object([&some_bar]() { foo_group4(some_bar); }, some_bar)); +#endif some_signal.connect(sigc::track_object([&some_bar]() { foo_group4(some_bar); }, some_bar)); some_signal.emit(); util->check_result(result_stream, "foo_group4(bar_group4&)foo_group4(bar_group4&)"); From 6cd3c1b54973f2055187404ffabb36200253e9a6 Mon Sep 17 00:00:00 2001 From: Kjell Ahlstedt Date: Tue, 27 Sep 2022 09:44:27 +0200 Subject: [PATCH 18/85] meson.build: Detect if we build from a git subtree See https://gitlab.gnome.org/GNOME/gtkmm/-/merge_requests/72 (William Roy) --- meson.build | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/meson.build b/meson.build index c1b0c906..ee588f30 100644 --- a/meson.build +++ b/meson.build @@ -50,13 +50,15 @@ if not python_version.version_compare(python_version_req) endif # Do we build from a git repository? -# Suppose we do if and only if a '.git' directory or file exists. +# Suppose we do if and only if the meson.build file is tracked by git. cmd_py = ''' -import os -import sys -sys.exit(os.path.isdir("@0@") or os.path.isfile("@0@")) -'''.format(project_source_root / '.git') -is_git_build = run_command(python3, '-c', cmd_py, check: false).returncode() != 0 +import shutil, subprocess, sys +if not shutil.which('git'): + sys.exit(1) +cmd = [ 'git', 'ls-files', '--error-unmatch', 'meson.build' ] +sys.exit(subprocess.run(cmd, cwd="@0@", stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL).returncode) +'''.format(project_source_root) +is_git_build = run_command(python3, '-c', cmd_py, check: false).returncode() == 0 # Are we testing a dist tarball while it's being built? # There ought to be a better way. https://github.com/mesonbuild/meson/issues/6866 From b8260dd2a97a1775d5b7c23e080d2f0f32ed5fa4 Mon Sep 17 00:00:00 2001 From: Kjell Ahlstedt Date: Tue, 25 Oct 2022 15:41:25 +0200 Subject: [PATCH 19/85] docs/devel.md: Change libsigc-list to Discourse The libsigc-list will soon be closed for new contributions. --- docs/devel.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/docs/devel.md b/docs/devel.md index a049314f..060b8403 100644 --- a/docs/devel.md +++ b/docs/devel.md @@ -2,18 +2,20 @@ layout: default title: Development --- -## Mailing List +## Discussion -There is a mailing list, [libsigc-list@gnome.org](http://mail.gnome.org/mailman/listinfo/libsigc-list) for libsigc++. -To subscribe, use the web [page](http://mail.gnome.org/mailman/listinfo/libsigc-list). +You can discuss libsigc++ questions on GNOME's [Discourse](https://discourse.gnome.org) +instance, under the [Platform/Language bindings](https://discourse.gnome.org/c/platform/language-bindings) +category with a _cplusplus_ tag. -Members can post directly, but all other traffic is moderated. -There is an archive of messages, -[here](http://mail.gnome.org/archives/libsigc-list/). +There is an old mailing list, which is now closed for new posts. +There is an archive of messages [here](http://mail.gnome.org/archives/libsigc-list/). +Please do not email the developers directly. ## Contributing -Please report bugs as GitHub [issues](https://github.com/libsigcplusplus/libsigcplusplus/issues), or provide improvements as GitHub [pull requests](https://github.com/libsigcplusplus/libsigcplusplus/pulls). +Please report bugs as GitHub [issues](https://github.com/libsigcplusplus/libsigcplusplus/issues), +or provide improvements as GitHub [pull requests](https://github.com/libsigcplusplus/libsigcplusplus/pulls). ## Git From 9f1748e5fe6264e1da11fa334f6b73a7039b66f5 Mon Sep 17 00:00:00 2001 From: wael <40663@proton.me> Date: Fri, 4 Nov 2022 08:23:43 +0300 Subject: [PATCH 20/85] meson: simplify lookup of python command --- meson.build | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/meson.build b/meson.build index ee588f30..2fede19d 100644 --- a/meson.build +++ b/meson.build @@ -41,13 +41,7 @@ project_build_root = meson.current_build_dir() cpp_compiler = meson.get_compiler('cpp') is_msvc = cpp_compiler.get_id() == 'msvc' -python3 = import('python').find_installation() - -python_version = python3.language_version() -python_version_req = '>= 3.5' -if not python_version.version_compare(python_version_req) - error('Requires Python @0@, found @1@.'.format(python_version_req, python_version)) -endif +python3 = find_program('python3', version: '>=3.5') # Do we build from a git repository? # Suppose we do if and only if the meson.build file is tracked by git. From dc2f2f4e6daea26a8901cf86ebb0d4cd0b3b726e Mon Sep 17 00:00:00 2001 From: Fabrice Fontaine Date: Sat, 5 Nov 2022 15:04:36 +0100 Subject: [PATCH 21/85] add build_tests option Allow the user to disable build of test programs Signed-off-by: Fabrice Fontaine --- meson.build | 6 +++++- meson_options.txt | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 2fede19d..70be03be 100644 --- a/meson.build +++ b/meson.build @@ -77,6 +77,7 @@ build_documentation_opt = get_option('build-documentation') build_documentation = build_documentation_opt == 'true' or \ (build_documentation_opt == 'if-maintainer-mode' and maintainer_mode) build_examples = get_option('build-examples') +build_tests = get_option('build-tests') do_benchmark = get_option('benchmark') # Installation directories are relative to {prefix}. @@ -255,7 +256,9 @@ can_add_dist_script = not meson.is_subproject() or meson.version().version_compa subdir('MSVC_NMake') subdir('sigc++') subdir('examples') -subdir('tests') +if build_tests + subdir('tests') +endif subdir('docs/docs/reference') subdir('docs/docs/manual') @@ -329,6 +332,7 @@ summary = [ ' XML validation: @0@@1@'.format(validate, explain_val), ' Build PDF: @0@@1@'.format(build_pdf, explain_pdf), ' Build example programs: @0@'.format(build_examples), + ' Build test programs: @0@'.format(build_tests), ' Benchmark: @0@'.format(do_benchmark), 'Directories:', ' prefix: @0@'.format(install_prefix), diff --git a/meson_options.txt b/meson_options.txt index 138e302b..eea909a9 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -14,5 +14,7 @@ option('build-pdf', type: 'boolean', value: false, description: 'Build tutorial PDF file') option('build-examples', type: 'boolean', value: true, description: 'Build example programs') +option('build-tests', type: 'boolean', value: true, + description: 'Build test programs') option('benchmark', type: 'boolean', value: false, description: 'Build and test benchmark program') From 5711e2bc736d9a06fd19b838732568911baab6f1 Mon Sep 17 00:00:00 2001 From: Kjell Ahlstedt Date: Mon, 7 Nov 2022 13:20:13 +0100 Subject: [PATCH 22/85] Meson build: Always call subdir('tests') Make the build_tests check more like the check in cairomm and libxml++. Then it's possible to combine build-tests=false with benchmark=true. See PR#84 --- meson.build | 4 +--- tests/meson.build | 9 ++++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/meson.build b/meson.build index 70be03be..629e86e6 100644 --- a/meson.build +++ b/meson.build @@ -256,9 +256,7 @@ can_add_dist_script = not meson.is_subproject() or meson.version().version_compa subdir('MSVC_NMake') subdir('sigc++') subdir('examples') -if build_tests - subdir('tests') -endif +subdir('tests') subdir('docs/docs/reference') subdir('docs/docs/manual') diff --git a/tests/meson.build b/tests/meson.build index 87605a45..e0f57d72 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -1,6 +1,6 @@ # tests -# input: sigcxx_own_dep, do_benchmark, can_benchmark, benchmark_dep +# input: sigcxx_own_dep, build_tests, do_benchmark, can_benchmark, benchmark_dep benchmark_timeout = 100 @@ -67,10 +67,13 @@ foreach ex : test_programs exe_file = executable(ex_name, ex_sources, dependencies: sigcxx_own_dep, implicit_include_directories: false, - build_by_default: true + build_by_default: build_tests, ) - test(ex_name, exe_file) + # If exe_file is a test program, it is built by default unconditionally. + if build_tests + test(ex_name, exe_file) + endif endforeach if can_benchmark From ee0589cf5a5e4c2e95fc9302a8a193e4c3f43a2a Mon Sep 17 00:00:00 2001 From: Kjell Ahlstedt Date: Sun, 18 Dec 2022 18:31:00 +0100 Subject: [PATCH 23/85] CI: Add publish-docs.yml --- .github/workflows/publish-docs.yml | 76 ++++++++++++++++++++++++++++++ docs/_config.yml | 2 +- docs/doc.md | 17 ++++++- 3 files changed, 92 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/publish-docs.yml diff --git a/.github/workflows/publish-docs.yml b/.github/workflows/publish-docs.yml new file mode 100644 index 00000000..35434f8d --- /dev/null +++ b/.github/workflows/publish-docs.yml @@ -0,0 +1,76 @@ +# Sample workflow for building and deploying a Jekyll site to GitHub Pages + +# Copied from https://github.com/libsigcplusplus/libsigcplusplus/actions/new +# and changed. Actions -> New workflow -> Pages -> GitHub Pages Jekyll + +name: Deploy Jekyll with GitHub Pages dependencies preinstalled + +# 2022-12-17: ubuntu-latest = ubuntu-22.04 +on: + # Runs on pushes targeting the default branch + push: + branches: ["master"] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: read + pages: write + id-token: write + +# Allow one concurrent deployment +concurrency: + group: "pages" + cancel-in-progress: true + +jobs: + # Build job + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Build + run: | + # Prevent blocking apt install on a question during configuring of tzdata. + export ENV DEBIAN_FRONTEND=noninteractive + sudo apt update + sudo apt install libxml2-utils docbook5-xml docbook-xsl mm-common g++ meson ninja-build python3-setuptools python3-pip --yes + meson -Dbuild-documentation=true -Dbuild-examples=false -Dbuild-tests=false _build + meson compile -C _build + - name: Collect Documentation + # Collect all documentation to be published. + run: | + mkdir _publish _publish/_layouts _publish/pix _publish/manual _publish/reference + # Copy files from the git repository. + cp docs/_config.yml docs/*.md docs/style.css _publish + cp docs/_layouts/*.html _publish/_layouts + cp docs/pix/logo.gif _publish/pix + # Move generated documentation. + mv _build/docs/docs/manual/html _publish/manual + mv _build/docs/docs/reference/html _publish/reference + - name: Setup Pages + uses: actions/configure-pages@v2 + - name: Build with Jekyll + uses: actions/jekyll-build-pages@v1 + with: + source: ./_publish + destination: ./_site + - name: Upload artifact + uses: actions/upload-pages-artifact@v1 + + # Deployment job + # Publish documentation at https://libsigcplusplus.github.io/libsigcplusplus/ + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + needs: build + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v1 + diff --git a/docs/_config.yml b/docs/_config.yml index 966d1ac0..e59301ab 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -1 +1 @@ -name: libsigc++ +title: libsigc++ diff --git a/docs/doc.md b/docs/doc.md index eb8dfb51..7d5e6ede 100644 --- a/docs/doc.md +++ b/docs/doc.md @@ -3,8 +3,21 @@ layout: default title: Documentation --- -We have both [tutorial-style](http://developer.gnome.org/libsigc++-tutorial/stable/) -and [reference](http://developer.gnome.org/libsigc++/stable/) documentation. +## libsigc++-2.0 + +We have [tutorial-style](https://developer-old.gnome.org/libsigc++-tutorial/2.10/) +and [reference](https://developer-old.gnome.org/libsigc++/2.10/) documentation. + +This documentation is frozen on the web. It does not document the latest release. +If you want newer documentation, you can download a tarball from +[GitHub releases](https://github.com/libsigcplusplus/libsigcplusplus/releases/) +or the [GNOME download site](https://download.gnome.org/sources/libsigc++/), +extract it, and view the documentation at *untracked/docs/*. + +## libsigc++-3.0 + +The latest [tutorial-style](manual/html/index.html) and [reference](reference/html/index.html) +documentation is available on the web. ## Glossary of terms From d8d7c8c2e4065485208431815aba6bf22f4f2e9c Mon Sep 17 00:00:00 2001 From: Kjell Ahlstedt Date: Fri, 23 Dec 2022 11:16:17 +0100 Subject: [PATCH 24/85] meson.build: Don't distribute the .github directory --- meson.build | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/meson.build b/meson.build index 629e86e6..01c1f2e9 100644 --- a/meson.build +++ b/meson.build @@ -266,12 +266,17 @@ if can_add_dist_script python3, dist_changelog, project_source_root, ) + # Don't distribute these files and directories. + dont_distribute = [ + '.github', + ] # Add build scripts to the distribution directory, and delete .gitignore # files and an empty $MESON_PROJECT_DIST_ROOT/build/ directory. meson.add_dist_script( python3, dist_build_scripts, project_source_root, 'untracked' / 'build_scripts', + dont_distribute, ) endif From e88e319aa50df010320dd15e7c802f92752dc8dc Mon Sep 17 00:00:00 2001 From: Kjell Ahlstedt Date: Fri, 23 Dec 2022 11:17:22 +0100 Subject: [PATCH 25/85] 3.4.0 --- CMakeLists.txt | 2 +- NEWS | 33 +++++++++++++++++++++++++++++++++ configure.ac | 2 +- meson.build | 2 +- 4 files changed, 36 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e1b28fea..21513771 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ cmake_minimum_required (VERSION 3.2) set (SIGCXX_MAJOR_VERSION 3) -set (SIGCXX_MINOR_VERSION 2) +set (SIGCXX_MINOR_VERSION 4) set (SIGCXX_MICRO_VERSION 0) set (SIGCXX_API_VERSION 3.0) diff --git a/NEWS b/NEWS index 3cf92d69..19a16c32 100755 --- a/NEWS +++ b/NEWS @@ -1,3 +1,36 @@ +3.4.0 (stable) + +* Add track_object(), deprecate track_obj() + (Kjell Ahlstedt) Issue #78 (LordVolumeForm) +* Add trackable_signal_with_accumulator and trackable_signal + (Kjell Ahlstedt) Issue #80 (H2NCH2COOH) + +Examples, tests: +* examples/member_method: Make on_print() non-virtual +* test_accumulated.cc: clang++ requires another 'template' + (Kjell Ahlstedt) +* test_limit_reference.cc: Don't use auto where a slot is required + (Kjell Ahlstedt) Issue #44 (Murray Cumming) + +Documentation: +* signal::make_slot(): Note that signal does not derive from trackable + (Kjell Ahlstedt) Issue #80 (H2NCH2COOH) + +Build: +* Meson: Avoid configuration warnings + (Kjell Ahlstedt) +* Meson, MSVC: Compensate for the lack of msvc_recommended_pragmas.h + (Chun-wei Fan) +* Fix build with -Dbuild-deprecated-api=false + (Kjell Ahlstedt) Issue #82 (bbhtt) +* Meson: Detect if we build from a git subtree + (William Roy) Merge request gtkmm!72 +* Meson: Simplify lookup of python command + (wael444) Pull request #83 +* Meson: Add build_tests option + (Fabrice Fontaine) Pull request #84 + + 3.2.0 (stable) * Allow slots with rvalue reference parameters diff --git a/configure.ac b/configure.ac index 1307c2f9..2256657a 100644 --- a/configure.ac +++ b/configure.ac @@ -15,7 +15,7 @@ ## You should have received a copy of the GNU Lesser General Public License ## along with this library. If not, see . -AC_INIT([libsigc++], [3.2.0], +AC_INIT([libsigc++], [3.4.0], [https://github.com/libsigcplusplus/libsigcplusplus/issues/], [libsigc++], [https://libsigcplusplus.github.io/libsigcplusplus/]) AC_PREREQ([2.59]) diff --git a/meson.build b/meson.build index 01c1f2e9..c677697e 100644 --- a/meson.build +++ b/meson.build @@ -1,7 +1,7 @@ # This file is part of libsigc++. project('libsigc++', 'cpp', - version: '3.2.0', + version: '3.4.0', license: 'LGPLv2.1+', default_options: [ 'cpp_std=c++17', From b863edbe85b839ec14f468af4aebe5d6e51af380 Mon Sep 17 00:00:00 2001 From: Kjell Ahlstedt Date: Wed, 4 Jan 2023 10:53:56 +0100 Subject: [PATCH 26/85] Meson build: Don't copy files with configure_file() It's deprecated from Meson 0.64. The replacement, fs.copyfile(), is not useful here. It only copies from the source directory to the build directory. --- MSVC_NMake/meson.build | 8 ++++---- meson.build | 5 +++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/MSVC_NMake/meson.build b/MSVC_NMake/meson.build index 09078b37..f11412a0 100644 --- a/MSVC_NMake/meson.build +++ b/MSVC_NMake/meson.build @@ -1,6 +1,6 @@ # MSVC_NMake -# Input: pkg_conf_data, sigcxxconfig_h, project_build_root, python3, +# Input: pkg_conf_data, sigcxxconfig_h_meson, project_build_root, python3, # can_add_dist_script # Output: sigc_rc @@ -10,11 +10,11 @@ sigc_rc = configure_file( configuration: pkg_conf_data, ) -# Copy the generated configuration header into the MSVC project directory. +# Make a copy of the generated configuration header in the MSVC project directory. configure_file( - input: sigcxxconfig_h, + input: sigcxxconfig_h_meson, output: 'sigc++config.h', - copy: true, + configuration: pkg_conf_data, ) untracked_msvc_nmake = 'untracked' / 'MSVC_NMake' diff --git a/meson.build b/meson.build index c677697e..82920bf5 100644 --- a/meson.build +++ b/meson.build @@ -241,9 +241,10 @@ configure_file( configuration: pkg_conf_data, ) +sigcxxconfig_h_meson = files('sigc++config.h.meson') install_includeconfigdir = install_libdir / sigcxx_pcname / 'include' -sigcxxconfig_h = configure_file( - input: 'sigc++config.h.meson', +configure_file( + input: sigcxxconfig_h_meson, output: 'sigc++config.h', configuration: pkg_conf_data, install_dir: install_includeconfigdir, From 91441e49653721053c50e3dfadb591de8592cd93 Mon Sep 17 00:00:00 2001 From: Kjell Ahlstedt Date: Wed, 4 Jan 2023 10:56:31 +0100 Subject: [PATCH 27/85] meson.build: Fix the evaluation of is_git_build on Windows See gtkmm#131 --- meson.build | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/meson.build b/meson.build index 82920bf5..9f7627d2 100644 --- a/meson.build +++ b/meson.build @@ -47,12 +47,17 @@ python3 = find_program('python3', version: '>=3.5') # Suppose we do if and only if the meson.build file is tracked by git. cmd_py = ''' import shutil, subprocess, sys -if not shutil.which('git'): +git_exe = shutil.which('git') +if not git_exe: sys.exit(1) -cmd = [ 'git', 'ls-files', '--error-unmatch', 'meson.build' ] -sys.exit(subprocess.run(cmd, cwd="@0@", stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL).returncode) -'''.format(project_source_root) -is_git_build = run_command(python3, '-c', cmd_py, check: false).returncode() == 0 +cmd = [ git_exe, 'ls-files', '--error-unmatch', 'meson.build' ] +sys.exit(subprocess.run(cmd, cwd=sys.argv[1], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL).returncode) +''' +is_git_build = run_command( + python3, '-c', cmd_py, + project_source_root, + check: false, +).returncode() == 0 # Are we testing a dist tarball while it's being built? # There ought to be a better way. https://github.com/mesonbuild/meson/issues/6866 From 9fc3416a95abca28cb992e4607232a3287e847a1 Mon Sep 17 00:00:00 2001 From: Francesco Emanuele D'Agostino Date: Sun, 15 Jan 2023 00:46:51 +0100 Subject: [PATCH 28/85] introducing protection to prevent multiple target declaration for uninstall. --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 21513771..5741400b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,6 +65,7 @@ set (top_srcdir .) configure_file (sigc++.pc.in sigc++-${SIGCXX_API_VERSION}.pc @ONLY) configure_file (sigc++-uninstalled.pc.in sigc++-${SIGCXX_API_VERSION}-uninstalled.pc @ONLY) +if (NOT TARGET uninstall) configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" @@ -72,7 +73,7 @@ configure_file( add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) - +endif() install (FILES "${CMAKE_CURRENT_BINARY_DIR}/sigc++config.h" From 550e91d6c565deb5bf144f8d82f5dbdbeb75f412 Mon Sep 17 00:00:00 2001 From: Kjell Ahlstedt Date: Mon, 3 Apr 2023 11:17:59 +0200 Subject: [PATCH 29/85] meson.build: Simplify if-file-exists test --- meson.build | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/meson.build b/meson.build index 9f7627d2..e4630fe6 100644 --- a/meson.build +++ b/meson.build @@ -137,17 +137,9 @@ if maintainer_mode project_source_root / 'untracked' / 'docs' / 'docs', check: true, ) -else - cmd_py = ''' -import os -import sys -sys.exit(os.path.isfile("@0@")) -'''.format(doc_reference) - file_exists = run_command(python3, '-c', cmd_py, check: false).returncode() != 0 - if not file_exists - warning('Missing files in untracked/. ' + \ - 'Enable maintainer-mode if you want to build documentation or create a dist tarball.') - endif +elif not import('fs').is_file(doc_reference) + warning('Missing files in untracked/.\n ' + \ + 'Enable maintainer-mode if you want to build documentation or create a dist tarball.') endif # Check if perl is required and available. From 2ef3e5269f44c4664a90ec04f3c2c0a7382800c1 Mon Sep 17 00:00:00 2001 From: Kjell Ahlstedt Date: Mon, 3 Apr 2023 11:18:19 +0200 Subject: [PATCH 30/85] README.md, CI: meson -> meson setup --- .github/workflows/meson-clang-10.yml | 2 +- .github/workflows/meson-gcc-10.yml | 2 +- .github/workflows/publish-docs.yml | 2 +- README.md | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/meson-clang-10.yml b/.github/workflows/meson-clang-10.yml index adab1966..092c00ef 100644 --- a/.github/workflows/meson-clang-10.yml +++ b/.github/workflows/meson-clang-10.yml @@ -19,7 +19,7 @@ jobs: # Install it with pip3 instead of apt. sudo pip3 install "meson>=0.55.0" export CXX=clang++-10 - meson -Dwarnings=fatal -Dwarning_level=3 -Dwerror=true _build + meson setup -Dwarnings=fatal -Dwarning_level=3 -Dwerror=true _build cd _build meson compile - name: Test diff --git a/.github/workflows/meson-gcc-10.yml b/.github/workflows/meson-gcc-10.yml index 46cc6b51..d358d7fc 100644 --- a/.github/workflows/meson-gcc-10.yml +++ b/.github/workflows/meson-gcc-10.yml @@ -19,7 +19,7 @@ jobs: # Install it with pip3 instead of apt. sudo pip3 install "meson>=0.55.0" export CXX=g++-10 - meson -Dwarnings=fatal -Dwarning_level=3 -Dwerror=true _build + meson setup -Dwarnings=fatal -Dwarning_level=3 -Dwerror=true _build cd _build meson compile - name: Test diff --git a/.github/workflows/publish-docs.yml b/.github/workflows/publish-docs.yml index 35434f8d..95b0a6fa 100644 --- a/.github/workflows/publish-docs.yml +++ b/.github/workflows/publish-docs.yml @@ -38,7 +38,7 @@ jobs: export ENV DEBIAN_FRONTEND=noninteractive sudo apt update sudo apt install libxml2-utils docbook5-xml docbook-xsl mm-common g++ meson ninja-build python3-setuptools python3-pip --yes - meson -Dbuild-documentation=true -Dbuild-examples=false -Dbuild-tests=false _build + meson setup -Dbuild-documentation=true -Dbuild-examples=false -Dbuild-tests=false _build meson compile -C _build - name: Collect Documentation # Collect all documentation to be published. diff --git a/README.md b/README.md index 5ffed357..dfc32e9e 100644 --- a/README.md +++ b/README.md @@ -54,10 +54,10 @@ For instance: ```sh # If the tarball was made with Autotools, and you want to rebuild the reference # documentation, you must enable maintainer-mode: -$ meson --prefix=/some_directory --libdir=lib -Dmaintainer-mode=true your_builddir . +$ meson setup --prefix=/some_directory --libdir=lib -Dmaintainer-mode=true your_builddir . # If the tarball was made with Meson, or you don't want to rebuild the docs: -$ meson --prefix=/some_directory --libdir=lib your_builddir . +$ meson setup --prefix=/some_directory --libdir=lib your_builddir . # then: $ cd your_builddir @@ -105,7 +105,7 @@ Don't call the builddir 'build'. There is a directory called 'build' with files used by Autotools. ```sh -$ meson --prefix=/some_directory --libdir=lib your_builddir . +$ meson setup --prefix=/some_directory --libdir=lib your_builddir . $ cd your_builddir $ ninja $ ninja install From e82dc27ae6c42301695be5a2b2df10e4f544a1f4 Mon Sep 17 00:00:00 2001 From: Kjell Ahlstedt Date: Wed, 31 May 2023 18:35:45 +0200 Subject: [PATCH 31/85] sigc++.pc.in: Update htmlrefpub --- sigc++.pc.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sigc++.pc.in b/sigc++.pc.in index 05de3158..16a5514e 100644 --- a/sigc++.pc.in +++ b/sigc++.pc.in @@ -8,7 +8,7 @@ includedir=@includedir@ docdir=${datarootdir}/doc/libsigc++-@SIGCXX_API_VERSION@ doxytagfile=${docdir}/reference/libsigc++-@SIGCXX_API_VERSION@.tag htmlrefdir=${docdir}/reference/html -htmlrefpub=http://library.gnome.org/devel/libsigc++/unstable/ +htmlrefpub=https://libsigcplusplus.github.io/libsigcplusplus/reference/html/ Name: libsigc++ Description: Typesafe signal and callback system for C++ From 0e3724cd94ccd5da7c13c8169ce561bf02062d11 Mon Sep 17 00:00:00 2001 From: Kjell Ahlstedt Date: Wed, 31 May 2023 18:36:39 +0200 Subject: [PATCH 32/85] Doxyfile.in: Remove obsolete entries --- docs/docs/reference/Doxyfile.in | 4 ---- 1 file changed, 4 deletions(-) diff --git a/docs/docs/reference/Doxyfile.in b/docs/docs/reference/Doxyfile.in index c4cefda9..0ffb9eba 100644 --- a/docs/docs/reference/Doxyfile.in +++ b/docs/docs/reference/Doxyfile.in @@ -224,7 +224,6 @@ PDF_HYPERLINKS = YES USE_PDFLATEX = YES LATEX_BATCHMODE = NO LATEX_HIDE_INDICES = NO -LATEX_SOURCE_CODE = NO LATEX_BIB_STYLE = plain LATEX_TIMESTAMP = NO #--------------------------------------------------------------------------- @@ -236,7 +235,6 @@ COMPACT_RTF = NO RTF_HYPERLINKS = NO RTF_STYLESHEET_FILE = RTF_EXTENSIONS_FILE = -RTF_SOURCE_CODE = NO #--------------------------------------------------------------------------- # Configuration options related to the man page output #--------------------------------------------------------------------------- @@ -256,7 +254,6 @@ XML_PROGRAMLISTING = NO #--------------------------------------------------------------------------- GENERATE_DOCBOOK = NO DOCBOOK_OUTPUT = docbook -DOCBOOK_PROGRAMLISTING = NO #--------------------------------------------------------------------------- # Configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- @@ -297,7 +294,6 @@ EXTERNAL_PAGES = YES #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- -CLASS_DIAGRAMS = YES DIA_PATH = HIDE_UNDOC_RELATIONS = NO HAVE_DOT = YES From bc91a4f36ccece12c5e52e54f38e54f75b423c34 Mon Sep 17 00:00:00 2001 From: Kjell Ahlstedt Date: Wed, 31 May 2023 18:36:58 +0200 Subject: [PATCH 33/85] connection: Improve the class documentation Fixes #88 --- sigc++/connection.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sigc++/connection.h b/sigc++/connection.h index 4b4926e4..0e733760 100644 --- a/sigc++/connection.h +++ b/sigc++/connection.h @@ -25,7 +25,14 @@ namespace sigc { -/** This may be used to disconnect the referred slot at any time (disconnect()). +/** Convenience class for safe disconnection. + * + * This may be used to disconnect the referred slot at any time (disconnect()). + * @ref sigc::signal_with_accumulator::connect() "sigc::signal::connect()" + * returns a %sigc::connection. + * @code + * sigc::connection conn = sig.connect(sigc::mem_fun(a, &A::foo)); + * @endcode * If the slot has already been destroyed, disconnect() does nothing. empty() or * operator bool() can be used to test whether the connection is * still active. The connection can be blocked (block(), unblock()). From b0312f2397536c48f1f015aa1e7ee6f014206c48 Mon Sep 17 00:00:00 2001 From: Chun-wei Fan Date: Mon, 26 Jun 2023 15:20:53 +0800 Subject: [PATCH 34/85] meson: Disallow default_library == 'both' on Visual Studio We need different defines/cflags for building static and shared builds of libsigc++, so we can't really support default_library = 'both' for libsigc++ without much retinkering. So, just disallow such builds at least for now. Also, save up whether we are attempting a static build in the Visual Studio build. --- meson.build | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/meson.build b/meson.build index e4630fe6..3190d6eb 100644 --- a/meson.build +++ b/meson.build @@ -43,6 +43,18 @@ cpp_compiler = meson.get_compiler('cpp') is_msvc = cpp_compiler.get_id() == 'msvc' python3 = find_program('python3', version: '>=3.5') +# MSVC: We currently do not support shared and static builds at the, +# same time, since we need different defines/cflags for proper +# linking. +if is_msvc + if get_option('default_library') == 'both' + error('-Ddefault_library=both is currently not supported for Visual Studio') + endif + is_msvc_static = get_option('default_library') == 'static' +else + is_msvc_static = false +endif + # Do we build from a git repository? # Suppose we do if and only if the meson.build file is tracked by git. cmd_py = ''' From a23cdc45176979bc1f4dda2e09c72ad2d619e476 Mon Sep 17 00:00:00 2001 From: Chun-wei Fan Date: Mon, 26 Jun 2023 15:22:10 +0800 Subject: [PATCH 35/85] build: Drop _WINDLL from sigc++config.h.[in|meson|cmake] ...and add a new check macro LIBSIGCXX_STATIC, to use the appropriate macros to build and link against libsigc++. Drop this from the build files as well. --- MSVC_NMake/config-msvc.mak | 2 +- sigc++/meson.build | 2 +- sigc++config.h.cmake | 6 ++++-- sigc++config.h.in | 4 +++- sigc++config.h.meson | 4 +++- 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/MSVC_NMake/config-msvc.mak b/MSVC_NMake/config-msvc.mak index 86ee18b5..a8c5280a 100644 --- a/MSVC_NMake/config-msvc.mak +++ b/MSVC_NMake/config-msvc.mak @@ -14,7 +14,7 @@ DEBUG_SUFFIX = -d DEBUG_SUFFIX = !endif -LIBSIGCPP_DEFINES = /DSIGC_BUILD /D_WINDLL +LIBSIGCPP_DEFINES = /DSIGC_BUILD SIGCPP_BASE_CFLAGS = /I.. /I. /I..\untracked\MSVC_NMake /std:c++17 /EHsc $(CFLAGS) diff --git a/sigc++/meson.build b/sigc++/meson.build index 9d9561f7..3b3cfeb8 100644 --- a/sigc++/meson.build +++ b/sigc++/meson.build @@ -74,7 +74,7 @@ extra_sigc_objects = [] # Make sure we are exporting the symbols from the DLL if is_msvc - extra_sigc_cppflags += ['-DSIGC_BUILD', '-D_WINDLL'] + extra_sigc_cppflags += ['-DSIGC_BUILD'] endif # Build the .rc file for Windows builds and link to it diff --git a/sigc++config.h.cmake b/sigc++config.h.cmake index 74d348a0..2c7e943a 100644 --- a/sigc++config.h.cmake +++ b/sigc++config.h.cmake @@ -16,7 +16,9 @@ # if defined(_MSC_VER) # define SIGC_MSC 1 # define SIGC_WIN32 1 -# define SIGC_DLL 1 +# ifndef LIBSIGCXX_STATIC +# define SIGC_DLL 1 +# endif # elif defined(__CYGWIN__) # define SIGC_CONFIGURE 1 # elif defined(__MINGW32__) @@ -54,7 +56,7 @@ #endif /* !SIGC_MSC */ #ifdef SIGC_DLL -# if defined(SIGC_BUILD) && defined(_WINDLL) +# ifdef SIGC_BUILD # define SIGC_API __declspec(dllexport) # elif !defined(SIGC_BUILD) # define SIGC_API __declspec(dllimport) diff --git a/sigc++config.h.in b/sigc++config.h.in index a82a86b9..573bc36c 100644 --- a/sigc++config.h.in +++ b/sigc++config.h.in @@ -16,7 +16,9 @@ #if defined(_MSC_VER) #define SIGC_MSC 1 #define SIGC_WIN32 1 +#ifndef LIBSIGCXX_STATIC #define SIGC_DLL 1 +#endif #elif defined(__CYGWIN__) #define SIGC_CONFIGURE 1 #elif defined(__MINGW32__) @@ -54,7 +56,7 @@ #endif /* !SIGC_MSC */ #ifdef SIGC_DLL -#if defined(SIGC_BUILD) && defined(_WINDLL) +#ifdef SIGC_BUILD #define SIGC_API __declspec(dllexport) #elif !defined(SIGC_BUILD) #define SIGC_API __declspec(dllimport) diff --git a/sigc++config.h.meson b/sigc++config.h.meson index 47cbd80d..3027b26e 100644 --- a/sigc++config.h.meson +++ b/sigc++config.h.meson @@ -19,7 +19,9 @@ #if defined(_MSC_VER) #define SIGC_MSC 1 #define SIGC_WIN32 1 +#ifndef LIBSIGCXX_STATIC #define SIGC_DLL 1 +#endif #elif defined(__CYGWIN__) #define SIGC_CONFIGURE 1 #elif defined(__MINGW32__) @@ -57,7 +59,7 @@ #endif /* !SIGC_MSC */ #ifdef SIGC_DLL -#if defined(SIGC_BUILD) && defined(_WINDLL) +#ifdef SIGC_BUILD #define SIGC_API __declspec(dllexport) #elif !defined(SIGC_BUILD) #define SIGC_API __declspec(dllimport) From 41b7d33007b53098aec388a6b6bc5a896b1d7c76 Mon Sep 17 00:00:00 2001 From: Chun-wei Fan Date: Mon, 26 Jun 2023 11:25:42 +0800 Subject: [PATCH 36/85] build: Actually support MSVC static builds Apply -DLIBSIGCXX_STATIC as appropriate when we request a static build to be done for the Meson and NMake builds, and skip building the version .rc file if a static build is requested. For the NMake builds, separate the build artifacts from the static and shared builds. The CMake builds are not updated here as it always assumes a shared build, nor are the autotools builds since it is not used for Visual Studio builds at all. --- MSVC_NMake/build-rules-msvc.mak | 39 +++++++++++++++++++------------- MSVC_NMake/config-msvc.mak | 19 ++++++++++++++++ MSVC_NMake/create-lists-msvc.mak | 37 +++++++++++++++++++++++++----- MSVC_NMake/info-msvc.mak | 8 ++++++- meson.build | 3 +++ sigc++/meson.build | 6 +++-- 6 files changed, 87 insertions(+), 25 deletions(-) diff --git a/MSVC_NMake/build-rules-msvc.mak b/MSVC_NMake/build-rules-msvc.mak index fe5a587a..74e51d9d 100644 --- a/MSVC_NMake/build-rules-msvc.mak +++ b/MSVC_NMake/build-rules-msvc.mak @@ -13,25 +13,25 @@ # $(CC)|$(CXX) $(cflags) /Fo$(destdir) /c @<< # $< # << -{..\sigc++\}.cc{vs$(VSVER)\$(CFG)\$(PLAT)\sigc\}.obj: +{..\sigc++\}.cc{vs$(VSVER)\$(CFG)\$(PLAT)\$(LIBSIGC_INTDIR)\}.obj: @if not exist .\sigc++config.h if not exist ..\untracked\MSVC_NMake\sigc++config.h $(MAKE) /f Makefile.vc CFG=$(CFG) sigc++config.h @if not exist $(@D)\ md $(@D) $(CXX) $(LIBSIGCPP_CFLAGS) /Fo$(@D)\ /Fd$(@D)\ /c @<< $< << -{..\sigc++\functors\}.cc{vs$(VSVER)\$(CFG)\$(PLAT)\sigc\}.obj: +{..\sigc++\functors\}.cc{vs$(VSVER)\$(CFG)\$(PLAT)\$(LIBSIGC_INTDIR)\}.obj: @if not exist .\sigc++config.h if not exist ..\untracked\MSVC_NMake\sigc++config.h $(MAKE) /f Makefile.vc CFG=$(CFG) sigc++config.h @if not exist $(@D)\ md $(@D) $(CXX) $(LIBSIGCPP_CFLAGS) /Fo$(@D)\ /Fd$(@D)\ /c @<< $< << -{.}.rc{vs$(VSVER)\$(CFG)\$(PLAT)\sigc\}.res: +{.}.rc{vs$(VSVER)\$(CFG)\$(PLAT)\$(LIBSIGC_INTDIR)\}.res: @if not exist $(@D)\ md $(@D) rc /fo$@ $< -{..\untracked\MSVC_NMake\}.rc{vs$(VSVER)\$(CFG)\$(PLAT)\sigc\}.res: +{..\untracked\MSVC_NMake\}.rc{vs$(VSVER)\$(CFG)\$(PLAT)\$(LIBSIGC_INTDIR)\}.res: @if not exist $(@D)\ md $(@D) rc /fo$@ $< @@ -42,13 +42,20 @@ $< # $(dependent_objects) # << # @-if exist $@.manifest mt /manifest $@.manifest /outputresource:$@;2 +!ifdef STATIC +$(LIBSIGC_LIB): $(libsigc_OBJS) + lib $(ARFLAGS) -out:$@ @<< +$(libsigc_OBJS) +<< +!else $(LIBSIGC_LIB): $(LIBSIGC_DLL) -$(LIBSIGC_DLL): $(sigc_dll_OBJS) +$(LIBSIGC_DLL): $(libsigc_OBJS) link /DLL $(LDFLAGS) /implib:$(LIBSIGC_LIB) -out:$@ @<< -$(sigc_dll_OBJS) +$(libsigc_OBJS) << @-if exist $@.manifest mt /manifest $@.manifest /outputresource:$@;2 +!endif # Rules for linking Executables # Format is as follows (the mt command is needed for MSVC 2005/2008 builds): @@ -65,13 +72,13 @@ clean: @-del /f /q vs$(VSVER)\$(CFG)\$(PLAT)\*.ilk @-del /f /q vs$(VSVER)\$(CFG)\$(PLAT)\*.exp @-del /f /q vs$(VSVER)\$(CFG)\$(PLAT)\*.lib - @-if exist vs$(VSVER)\$(CFG)\$(PLAT)\sigc-tests del /f /q vs$(VSVER)\$(CFG)\$(PLAT)\sigc-tests\*.obj - @-if exist vs$(VSVER)\$(CFG)\$(PLAT)\sigc-tests del /f /q vs$(VSVER)\$(CFG)\$(PLAT)\sigc-tests\*.pdb - @-del /f /q vs$(VSVER)\$(CFG)\$(PLAT)\sigc-examples\*.obj - @-del /f /q vs$(VSVER)\$(CFG)\$(PLAT)\sigc-examples\*.pdb - @-del /f /q vs$(VSVER)\$(CFG)\$(PLAT)\sigc\*.res - @-del /f /q vs$(VSVER)\$(CFG)\$(PLAT)\sigc\*.obj - @-del /f /q vs$(VSVER)\$(CFG)\$(PLAT)\sigc\*.pdb - @-if exist vs$(VSVER)\$(CFG)\$(PLAT)\sigc-tests rd vs$(VSVER)\$(CFG)\$(PLAT)\sigc-tests - @-rd vs$(VSVER)\$(CFG)\$(PLAT)\sigc-examples - @-rd vs$(VSVER)\$(CFG)\$(PLAT)\sigc + @-if exist vs$(VSVER)\$(CFG)\$(PLAT)\$(SIGC_TESTS_INTDIR) del /f /q vs$(VSVER)\$(CFG)\$(PLAT)\$(SIGC_TESTS_INTDIR)\*.obj + @-if exist vs$(VSVER)\$(CFG)\$(PLAT)\$(SIGC_TESTS_INTDIR) del /f /q vs$(VSVER)\$(CFG)\$(PLAT)\$(SIGC_TESTS_INTDIR)\*.pdb + @-del /f /q vs$(VSVER)\$(CFG)\$(PLAT)\$(SIGC_EX_INTDIR)\*.obj + @-del /f /q vs$(VSVER)\$(CFG)\$(PLAT)\$(SIGC_EX_INTDIR)\*.pdb + @-del /f /q vs$(VSVER)\$(CFG)\$(PLAT)\$(LIBSIGC_INTDIR)\*.res + @-del /f /q vs$(VSVER)\$(CFG)\$(PLAT)\$(LIBSIGC_INTDIR)\*.obj + @-del /f /q vs$(VSVER)\$(CFG)\$(PLAT)\$(LIBSIGC_INTDIR)\*.pdb + @-if exist vs$(VSVER)\$(CFG)\$(PLAT)\$(SIGC_TESTS_INTDIR) rd vs$(VSVER)\$(CFG)\$(PLAT)\$(SIGC_TESTS_INTDIR) + @-rd vs$(VSVER)\$(CFG)\$(PLAT)\$(SIGC_EX_INTDIR) + @-rd vs$(VSVER)\$(CFG)\$(PLAT)\$(LIBSIGC_INTDIR) diff --git a/MSVC_NMake/config-msvc.mak b/MSVC_NMake/config-msvc.mak index a8c5280a..52c72a00 100644 --- a/MSVC_NMake/config-msvc.mak +++ b/MSVC_NMake/config-msvc.mak @@ -8,6 +8,16 @@ BASE_INCLUDES = /I$(PREFIX)\include LIBSIGC_MAJOR_VERSION = 3 LIBSIGC_MINOR_VERSION = 0 +!ifdef STATIC +LIBSIGC_INTDIR = sigc-static +SIGC_EX_INTDIR = sigc-examples-static +SIGC_TESTS_INTDIR = sigc-tests-static +!else +LIBSIGC_INTDIR = sigc +SIGC_EX_INTDIR = sigc-examples +SIGC_TESTS_INTDIR = sigc-tests +!endif + !if "$(CFG)" == "debug" || "$(CFG)" == "Debug" DEBUG_SUFFIX = -d !else @@ -18,6 +28,11 @@ LIBSIGCPP_DEFINES = /DSIGC_BUILD SIGCPP_BASE_CFLAGS = /I.. /I. /I..\untracked\MSVC_NMake /std:c++17 /EHsc $(CFLAGS) +# Define LIBSIGCXX_STATIC everywhere for static builds +!ifdef STATIC +SIGCPP_BASE_CFLAGS = $(SIGCPP_BASE_CFLAGS) /DLIBSIGCXX_STATIC +!endif + LIBSIGC_INT_SOURCES = $(sigc_sources_cc:/=\) LIBSIGC_INT_HDRS = $(sigc_public_h:/=\) @@ -35,8 +50,12 @@ LIBSIGC_LIBNAME = sigc-vc$(VSVER_LIB)$(DEBUG_SUFFIX)-$(LIBSIGC_MAJOR_VERSION)_$( LIBSIGC_DLLNAME = $(LIBSIGC_LIBNAME) !endif +!ifdef STATIC +LIBSIGC_LIB = vs$(VSVER)\$(CFG)\$(PLAT)\$(LIBSIGC_LIBNAME)-static.lib +!else LIBSIGC_DLL = vs$(VSVER)\$(CFG)\$(PLAT)\$(LIBSIGC_DLLNAME).dll LIBSIGC_LIB = vs$(VSVER)\$(CFG)\$(PLAT)\$(LIBSIGC_LIBNAME).lib +!endif # If your Boost libraries are built as DLLs, use BOOST_DLL=1 in your NMake command line !ifdef BOOST_DLL diff --git a/MSVC_NMake/create-lists-msvc.mak b/MSVC_NMake/create-lists-msvc.mak index 2691d886..0689c894 100644 --- a/MSVC_NMake/create-lists-msvc.mak +++ b/MSVC_NMake/create-lists-msvc.mak @@ -35,18 +35,40 @@ NULL= # For libsigc++ -!if [call create-lists.bat header sigc.mak sigc_dll_OBJS] +!if [call create-lists.bat header sigc.mak libsigc_OBJS] !endif -!if [for %c in ($(sigc_sources_cc)) do @if "%~xc" == ".cc" @call create-lists.bat file sigc.mak vs^$(VSVER)\^$(CFG)\^$(PLAT)\sigc\%~nc.obj] +!if [for %c in ($(sigc_sources_cc)) do @if "%~xc" == ".cc" @call create-lists.bat file sigc.mak vs^$(VSVER)\^$(CFG)\^$(PLAT)\$(LIBSIGC_INTDIR)\%~nc.obj] !endif -!if [@call create-lists.bat file sigc.mak vs^$(VSVER)\^$(CFG)\^$(PLAT)\sigc\sigc.res] +# No point linking in version resource for static builds +!ifndef STATIC +!if [@call create-lists.bat file sigc.mak vs^$(VSVER)\^$(CFG)\^$(PLAT)\$(LIBSIGC_INTDIR)\sigc.res] +!endif !endif !if [call create-lists.bat footer sigc.mak] !endif +!ifdef STATIC +# start of static executables +!if [for %d in (examples tests) do @call create-lists.bat header sigc.mak libsigc_%d & @(for %s in (..\%d\*.cc) do @if not "%~ns" == "testutilities" if not "%~ns" == "benchmark" call create-lists.bat file sigc.mak vs$(VSVER)\$(CFG)\$(PLAT)\%~ns-static.exe) & @call create-lists.bat footer sigc.mak] +!endif + +!if [call create-lists.bat header sigc.mak libsigc_benchmark & @for %s in (..\tests\benchmark.cc) do @(call create-lists.bat file sigc.mak vs$(VSVER)\$(CFG)\$(PLAT)\%~ns-static.exe) & @call create-lists.bat footer sigc.mak] +!endif + +!if [for %d in (examples tests) do @for %s in (..\%d\*.cc) do @if not "%~ns" == "benchmark" echo vs^$(VSVER)\^$(CFG)\^$(PLAT)\sigc-%d-static\%~ns.obj: %s>>sigc.mak & @echo. @if not exist ^$(@D)\ md ^$(@D)>>sigc.mak & @echo. ^$(CXX) ^$(SIGCPP_CFLAGS) /Fo^$(@D)\ /Fd^$(@D)\ ^$** /c>>sigc.mak & @echo.>>sigc.mak] +!endif + +!if [for %s in (..\examples\*.cc) do @echo vs^$(VSVER)\^$(CFG)\^$(PLAT)\%~ns-static.exe: ^$(LIBSIGC_LIB) vs^$(VSVER)\^$(CFG)\^$(PLAT)\$(SIGC_EX_INTDIR)\%~ns.obj>>sigc.mak & @echo. link ^$(LDFLAGS) ^$** /out:^$@>>sigc.mak & @echo.>>sigc.mak] +!endif + +!if [for %s in (..\tests\*.cc) do @if not "%~ns" == "testutilities" echo vs^$(VSVER)\^$(CFG)\^$(PLAT)\%~ns-static.exe: ^$(LIBSIGC_LIB) vs^$(VSVER)\^$(CFG)\^$(PLAT)\$(SIGC_TESTS_INTDIR)\%~ns.obj vs^$(VSVER)\^$(CFG)\^$(PLAT)\$(SIGC_TESTS_INTDIR)\testutilities.obj>>sigc.mak & @echo. link ^$(LDFLAGS) ^$** /out:^$@>>sigc.mak & @echo.>>sigc.mak] +!endif +# end of static executables +!else +# start of shared executables !if [for %d in (examples tests) do @call create-lists.bat header sigc.mak libsigc_%d & @(for %s in (..\%d\*.cc) do @if not "%~ns" == "testutilities" if not "%~ns" == "benchmark" call create-lists.bat file sigc.mak vs$(VSVER)\$(CFG)\$(PLAT)\%~ns.exe) & @call create-lists.bat footer sigc.mak] !endif @@ -56,13 +78,16 @@ NULL= !if [for %d in (examples tests) do @for %s in (..\%d\*.cc) do @if not "%~ns" == "benchmark" echo vs^$(VSVER)\^$(CFG)\^$(PLAT)\sigc-%d\%~ns.obj: %s>>sigc.mak & @echo. @if not exist ^$(@D)\ md ^$(@D)>>sigc.mak & @echo. ^$(CXX) ^$(SIGCPP_CFLAGS) /Fo^$(@D)\ /Fd^$(@D)\ ^$** /c>>sigc.mak & @echo.>>sigc.mak] !endif -!if [for %s in (..\tests\benchmark.cc) do @echo vs^$(VSVER)\^$(CFG)\^$(PLAT)\sigc-tests\%~ns.obj: %s>>sigc.mak & @echo. @if not exist ^$(@D)\ md ^$(@D)>>sigc.mak & @echo. ^$(CXX) ^$(SIGCPP_BENCHMARK_CFLAGS) /Fo^$(@D)\ /Fd^$(@D)\ ^$** /c>>sigc.mak & @echo.>>sigc.mak] +!if [for %s in (..\examples\*.cc) do @echo vs^$(VSVER)\^$(CFG)\^$(PLAT)\%~ns.exe: ^$(LIBSIGC_LIB) vs^$(VSVER)\^$(CFG)\^$(PLAT)\$(SIGC_EX_INTDIR)\%~ns.obj>>sigc.mak & @echo. link ^$(LDFLAGS) ^$** /out:^$@>>sigc.mak & @echo.>>sigc.mak] +!endif + +!if [for %s in (..\tests\*.cc) do @if not "%~ns" == "testutilities" echo vs^$(VSVER)\^$(CFG)\^$(PLAT)\%~ns.exe: ^$(LIBSIGC_LIB) vs^$(VSVER)\^$(CFG)\^$(PLAT)\$(SIGC_TESTS_INTDIR)\%~ns.obj vs^$(VSVER)\^$(CFG)\^$(PLAT)\$(SIGC_TESTS_INTDIR)\testutilities.obj>>sigc.mak & @echo. link ^$(LDFLAGS) ^$** /out:^$@>>sigc.mak & @echo.>>sigc.mak] !endif -!if [for %s in (..\examples\*.cc) do @echo vs^$(VSVER)\^$(CFG)\^$(PLAT)\%~ns.exe: ^$(LIBSIGC_LIB) vs^$(VSVER)\^$(CFG)\^$(PLAT)\sigc-examples\%~ns.obj>>sigc.mak & @echo. link ^$(LDFLAGS) ^$** /out:^$@>>sigc.mak & @echo.>>sigc.mak] +# end of shared executables !endif -!if [for %s in (..\tests\*.cc) do @if not "%~ns" == "testutilities" echo vs^$(VSVER)\^$(CFG)\^$(PLAT)\%~ns.exe: ^$(LIBSIGC_LIB) vs^$(VSVER)\^$(CFG)\^$(PLAT)\sigc-tests\%~ns.obj vs^$(VSVER)\^$(CFG)\^$(PLAT)\sigc-tests\testutilities.obj>>sigc.mak & @echo. link ^$(LDFLAGS) ^$** /out:^$@>>sigc.mak & @echo.>>sigc.mak] +!if [for %s in (..\tests\benchmark.cc) do @echo vs^$(VSVER)\^$(CFG)\^$(PLAT)\$(SIGC_TESTS_INTDIR)\%~ns.obj: %s>>sigc.mak & @echo. @if not exist ^$(@D)\ md ^$(@D)>>sigc.mak & @echo. ^$(CXX) ^$(SIGCPP_BENCHMARK_CFLAGS) /Fo^$(@D)\ /Fd^$(@D)\ ^$** /c>>sigc.mak & @echo.>>sigc.mak] !endif !include sigc.mak diff --git a/MSVC_NMake/info-msvc.mak b/MSVC_NMake/info-msvc.mak index 30d1dba9..76b2341e 100644 --- a/MSVC_NMake/info-msvc.mak +++ b/MSVC_NMake/info-msvc.mak @@ -6,13 +6,15 @@ all-build-info: @echo Build info @echo --------- @echo Build Type: $(CFG) + @if not "$(STATIC)" == "" echo Library Build Type: static + @if "$(STATIC)" == "" echo Library Build Type: DLL help: @echo. @echo ============================== @echo Building libsigc++ Using NMake @echo ============================== - @echo nmake /f Makefile.vc CFG=[release^|debug] ^ + @echo nmake /f Makefile.vc CFG=[release^|debug] ^ ^ @echo. @echo Where: @echo ------ @@ -24,6 +26,10 @@ help: @echo where ^$(short_vs_ver) is 15 for VS 2017 and so on; and @echo ^$(platform) is Win32 for 32-bit builds and x64 for x64 builds. @echo. + @echo STATIC: Optional, enable to build static libsigc++. Define + @echo LIBSIGCXX_STATIC in the compiler flags to use the static build of + @echo libsigc++. + @echo. @echo ====== @echo A 'clean' target is supported to remove all generated files, intermediate @echo object files and binaries for the specified configuration. diff --git a/meson.build b/meson.build index 3190d6eb..4777ed5e 100644 --- a/meson.build +++ b/meson.build @@ -216,6 +216,9 @@ if is_msvc cpp_compiler.get_supported_arguments(disable_warnings_list), language: 'cpp' ) + if is_msvc_static + add_project_arguments(['-DLIBSIGCXX_STATIC'], language: 'cpp') + endif endif # Configure files diff --git a/sigc++/meson.build b/sigc++/meson.build index 3b3cfeb8..d9c1231d 100644 --- a/sigc++/meson.build +++ b/sigc++/meson.build @@ -80,8 +80,10 @@ endif # Build the .rc file for Windows builds and link to it if host_machine.system() == 'windows' windows = import('windows') - sigc_res = windows.compile_resources(sigc_rc) - extra_sigc_objects += sigc_res + if get_option('default_library') == 'shared' + sigc_res = windows.compile_resources(sigc_rc) + extra_sigc_objects += sigc_res + endif endif extra_include_dirs = ['..'] From b94f8396c154dcc2e3de1950c8873002f9b651ac Mon Sep 17 00:00:00 2001 From: Chun-wei Fan Date: Mon, 26 Jun 2023 11:56:39 +0800 Subject: [PATCH 37/85] NMake Makefiles: Accomodate static builds during "install" Copy the built DLL and PDB only if building a shared build, and copy the appropriate .lib file according to the build type. --- MSVC_NMake/install.mak | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MSVC_NMake/install.mak b/MSVC_NMake/install.mak index f9f07e28..72b4402a 100644 --- a/MSVC_NMake/install.mak +++ b/MSVC_NMake/install.mak @@ -7,9 +7,9 @@ install: all @if not exist $(PREFIX)\include\sigc++-$(LIBSIGC_MAJOR_VERSION).$(LIBSIGC_MINOR_VERSION)\sigc++\adaptors\ @md $(PREFIX)\include\sigc++-$(LIBSIGC_MAJOR_VERSION).$(LIBSIGC_MINOR_VERSION)\sigc++\adaptors @if not exist $(PREFIX)\include\sigc++-$(LIBSIGC_MAJOR_VERSION).$(LIBSIGC_MINOR_VERSION)\sigc++\functors\ @md $(PREFIX)\include\sigc++-$(LIBSIGC_MAJOR_VERSION).$(LIBSIGC_MINOR_VERSION)\sigc++\functors @if not exist $(PREFIX)\include\sigc++-$(LIBSIGC_MAJOR_VERSION).$(LIBSIGC_MINOR_VERSION)\sigc++\tuple-utils\ @md $(PREFIX)\include\sigc++-$(LIBSIGC_MAJOR_VERSION).$(LIBSIGC_MINOR_VERSION)\sigc++\tuple-utils - @copy /b vs$(VSVER)\$(CFG)\$(PLAT)\$(LIBSIGC_LIBNAME).dll $(PREFIX)\bin - @copy /b vs$(VSVER)\$(CFG)\$(PLAT)\$(LIBSIGC_LIBNAME).pdb $(PREFIX)\bin - @copy /b vs$(VSVER)\$(CFG)\$(PLAT)\$(LIBSIGC_LIBNAME).lib $(PREFIX)\lib + @if "$(STATIC)" == "" copy /b $(LIBSIGC_DLL) $(PREFIX)\bin + @if "$(STATIC)" == "" copy /b $(LIBSIGC_DLL:.dll=.pdb) $(PREFIX)\bin + @copy /b $(LIBSIGC_LIB) $(PREFIX)\lib @copy "..\sigc++\sigc++.h" "$(PREFIX)\include\sigc++-$(LIBSIGC_MAJOR_VERSION).$(LIBSIGC_MINOR_VERSION)\sigc++\" @for %h in ($(LIBSIGC_INT_HDRS)) do @copy "..\sigc++\%h" "$(PREFIX)\include\sigc++-$(LIBSIGC_MAJOR_VERSION).$(LIBSIGC_MINOR_VERSION)\sigc++\%h" @if exist sigc++config.h copy "sigc++config.h" "$(PREFIX)\lib\sigc++-$(LIBSIGC_MAJOR_VERSION).$(LIBSIGC_MINOR_VERSION)\include\" From a9d8305a29724a2c596a823e46ecc0fe904d62db Mon Sep 17 00:00:00 2001 From: Chun-wei Fan Date: Mon, 26 Jun 2023 12:22:27 +0800 Subject: [PATCH 38/85] sigc++.pc.in: Set -DLIBSIGCXX_STATIC in cxxflags as needed Update the Meson build files to put in -DLIBSIGCXX_STATIC when we are building a static build of libsigc++. For the CMake and autotools build, this is not used. --- CMakeLists.txt | 1 + configure.ac | 2 ++ meson.build | 4 +++- sigc++.pc.in | 2 +- 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5741400b..c4b291c1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,7 @@ set (SIGCXX_MICRO_VERSION 0) set (SIGCXX_API_VERSION 3.0) set (PACKAGE_VERSION ${SIGCXX_MAJOR_VERSION}.${SIGCXX_MINOR_VERSION}.${SIGCXX_MICRO_VERSION}) set (LIBSIGCPP_SOVERSION 0) +set (MSVC_STATIC_CXXFLAG "") option (SIGCXX_DISABLE_DEPRECATED "Disable deprecated" OFF) diff --git a/configure.ac b/configure.ac index 2256657a..52237da4 100644 --- a/configure.ac +++ b/configure.ac @@ -73,6 +73,8 @@ AS_IF([test "x$enable_benchmark" = xyes],[ AX_BOOST_TIMER ]) +AC_SUBST(MSVC_STATIC_CXXFLAG, '') + AC_CONFIG_FILES([Makefile ${SIGCXX_MODULE_NAME}.pc:sigc++.pc.in ${SIGCXX_MODULE_NAME}-uninstalled.pc:sigc++-uninstalled.pc.in diff --git a/meson.build b/meson.build index 4777ed5e..4c975d44 100644 --- a/meson.build +++ b/meson.build @@ -193,6 +193,7 @@ add_project_arguments(warning_flags, language: 'cpp') # MSVC: Ignore warnings that aren't really harmful, but make those # that should not be overlooked stand out. +static_cxxflag = '-DLIBSIGCXX_STATIC' if is_msvc disable_warnings_list = [ '/EHsc', # avoid warnings caused by exception handling model used @@ -217,7 +218,7 @@ if is_msvc language: 'cpp' ) if is_msvc_static - add_project_arguments(['-DLIBSIGCXX_STATIC'], language: 'cpp') + add_project_arguments(static_cxxflag, language: 'cpp') endif endif @@ -239,6 +240,7 @@ endif pkg_conf_data.set('SIGCXX_MAJOR_VERSION', sigcxx_major_version) pkg_conf_data.set('SIGCXX_MINOR_VERSION', sigcxx_minor_version) pkg_conf_data.set('SIGCXX_MICRO_VERSION', sigcxx_micro_version) +pkg_conf_data.set('MSVC_STATIC_CXXFLAG', is_msvc_static ? static_cxxflag : '') configure_file( input: 'sigc++.pc.in', diff --git a/sigc++.pc.in b/sigc++.pc.in index 16a5514e..e162f2fc 100644 --- a/sigc++.pc.in +++ b/sigc++.pc.in @@ -15,4 +15,4 @@ Description: Typesafe signal and callback system for C++ Version: @PACKAGE_VERSION@ URL: https://libsigcplusplus.github.io/libsigcplusplus/ Libs: -L${libdir} -lsigc-@SIGCXX_API_VERSION@ -Cflags: -I${includedir}/sigc++-@SIGCXX_API_VERSION@ -I${libdir}/sigc++-@SIGCXX_API_VERSION@/include +Cflags: -I${includedir}/sigc++-@SIGCXX_API_VERSION@ -I${libdir}/sigc++-@SIGCXX_API_VERSION@/include @MSVC_STATIC_CXXFLAG@ From 9e7517a0c47c6e659cfd26384bcdb2a4311a6e12 Mon Sep 17 00:00:00 2001 From: Chun-wei Fan Date: Mon, 26 Jun 2023 12:26:48 +0800 Subject: [PATCH 39/85] MSVC_NMake/README.txt: Mention about static builds --- MSVC_NMake/README.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MSVC_NMake/README.txt b/MSVC_NMake/README.txt index d3ba16ff..54383350 100644 --- a/MSVC_NMake/README.txt +++ b/MSVC_NMake/README.txt @@ -45,6 +45,10 @@ PREFIX: Optional. Base directory of where the third-party headers, libraries $(X) is the short version of the Visual Studio used, as follows: 2017: 15 +STATIC: Optional. Set if building libsigc++ as a static library. Note that + for building items that use this static build, /DLIBSIGCXX_STATIC + must be passed into the compiler flags. + USE_COMPAT_LIBS: Build the sigc++ DLL and .lib with the filename 'sigc-vc150(d)-3_0' for all builds. This is for compatibility reasons, if re-building dependent code is not From d83dcfcf507356cc81dcb3e831d26b693b9c5397 Mon Sep 17 00:00:00 2001 From: Chun-wei Fan Date: Mon, 26 Jun 2023 12:26:48 +0800 Subject: [PATCH 40/85] Visual Studio builds: Convert build docs to MarkDown Convert the README.txt to MarkDown format so that it is easier on the eye in terms of formatting, and update some of the info: * ARM64 is actually supported * Move the part on static builds as appropriate * Some other minor tweaks --- MSVC_NMake/MSVC-Builds.md | 65 +++++++++++++++++++++++++++++++++++++++ MSVC_NMake/README.txt | 63 ------------------------------------- MSVC_NMake/filelist.am | 2 +- README.md | 2 +- 4 files changed, 67 insertions(+), 65 deletions(-) create mode 100644 MSVC_NMake/MSVC-Builds.md delete mode 100644 MSVC_NMake/README.txt diff --git a/MSVC_NMake/MSVC-Builds.md b/MSVC_NMake/MSVC-Builds.md new file mode 100644 index 00000000..4271176b --- /dev/null +++ b/MSVC_NMake/MSVC-Builds.md @@ -0,0 +1,65 @@ +Instructions for building libsigc++ on Visual Studio += + +Building libsigc++ on Windows is now supported using Visual Studio +versions 2017 or later in both 32-bit and 64-bit (x64 and ARM64) flavors, +via NMake Makefiles. Due to `C++17` usage, Visual Studio 2015 or +earlier is not supported, and any use of the headers installed with +this package will require the use of the `/std:c++17` compiler flag. + +libsigc++ itself has no external dependencies, but building the +benchmark test program will require an installation of the Boost +C++ libraries. + +Building with NMake +- +The following describes what items are built with the following +targets: + +* `all`, `examples`: (or no target specified): The libsigc++ DLL and the example programs. +* `tests`: The libsigc++ DLL and the test programs. +* `benchmark`: The libsigc++ DLL and the benchmark program, the Boost C++ headers should be found in one of the paths that are in`%INCLUDE%`. + +Building directly from a GIT checkout is now supported, provided that a `PERL` +installation is present (pass the `PERL` interpreter executable in your NMake +command line by using `nmake /f Makefile.vc ... PERL=` by using +the `prep-git-build` target. + +The following are instructions for performing such a build. A `clean` target is +provided-it is recommended that one cleans the build and redo the build if any +configuration option changed. An `install` target is also provided to copy the built +items in their appropriate +locations under `$(PREFIX)`, which is described below. + +Invoke the build by issuing the command: +`nmake /f Makefile.vc CFG=[release|debug] [PREFIX=...] ` +where: + +* `CFG`: Required. Choose from a `release` or `debug` build. Note that + all builds generate a `.pdb` file for each `.dll` and `.exe` built. + +* `PREFIX`: Optional. Base directory of where the third-party headers, libraries +and needed tools can be found, i.e. headers in `$(PREFIX)\include`, +libraries in `$(PREFIX)\lib` and tools and DLLs in `$(PREFIX)\bin`. If not +specified, `$(PREFIX)` is set as `$(srcroot)\..\vs$(X)\$(platform)`, where +`$(platform)` is `win32` for 32-bit builds or `x64` for 64-bit (Intel/AMD) +builds or `arm64` for 64-bit (ARM) builds, and `$(X)` is the short version of the +Visual Studio used, as follows: + * 2017: `15` + * 2019: `16` + * 2022: `17` + +* `USE_COMPAT_LIBS`: Build the libsigc++ DLL and .lib with the filename +`sigc-vc150(d)-3_0` for all builds. This is for compatibility reasons, +if re-building dependent code is not convenient, for instance + +* Options, set by `