Skip to content

Multipass cannot build on Ubuntu 25.10 #4427

@levkropp

Description

@levkropp

Describe the bug
Due to updates to the versions of Qt and GCC shipped with Ubuntu 25.10. There are 3 issues I have found, 2 related to a Qt update and 1 related to a GCC update, that are currently preventing the latest main from building on a fresh 25.10 install.

  1. Qt 6.9(?) changed the way that QDir::cleanPath works slightly, and now normalize_mount_target doesn't handle double slashes in paths the way it used to. The simplest solution is just running cleanPath again. The code snippet below fixes this issue:
QString mp::Utils::normalize_mount_target(QString target_mount_path) const
{
    if (QDir::isRelativePath(target_mount_path)) // rely on Qt to understand Linux paths on Windows
        target_mount_path.prepend('/').prepend(home_in_instance); // QString::prepend is fast

    auto cleaned = QDir::cleanPath(target_mount_path);
    
    // In Qt 6.9+, cleanPath may leave double slashes at the beginning when resolving paths
    // that go above root (e.g., "/home/ubuntu/../..//folder" -> "//folder")
    // Apply cleanPath again to normalize these cases
    if (cleaned.startsWith("//") && !cleaned.startsWith("///"))
        cleaned = QDir::cleanPath(cleaned);
    
    return cleaned;
}
  1. CreateBridgeTest Failures: Newer versions of Qt create warning messages when createReply() is called on a message that isn't a method call. The mock logger is set to screen out logs below warning level, but these Qt warnings are being logged and causing some tests to fail. Adding the EXPECT_CALL below resolves these errors
struct CreateBridgeTest : public Test
{
    void SetUp() override
    {
        logger_scope.mock_logger->screen_logs(mpl::Level::warning);

        // Allow Qt DBus warnings that occur in newer Qt versions when using createReply on default-constructed messages
        EXPECT_CALL(*logger_scope.mock_logger,
                    log(mpl::Level::warning, Eq("Qt"), HasSubstr("QDBusMessage: replying to a message that isn't a method call")))
            .Times(AnyNumber());

        // These will accept any number of calls (0..N) but they can still be shadowed
        EXPECT_CALL(*mock_dbus_provider, get_system_bus).WillRepeatedly(ReturnRef(mock_bus));
        EXPECT_CALL(*mock_nm_root, is_valid).WillRepeatedly(Return(true));
        EXPECT_CALL(*mock_nm_settings, is_valid).WillRepeatedly(Return(true));
        EXPECT_CALL(mock_bus, is_connected).WillRepeatedly(Return(true));
    }
  1. yaml-cpp needs cstdint include for GCC 14: The version of GCC now shipped in Ubuntu is more strict about headers and cstdint needs to be included in emitterutils.cpp. It already is included in the latest upstream of yaml-cpp, but we're actually still referencing our fork's commit. I have made a PR to fix this issue already

To Reproduce
Follow the Linux install instructions on a brand new (K)Ubuntu 25.10

Expected behavior
Multipass builds and run normally

Logs

CreateBridgeTest Logs

./bin/multipass_tests --gtest_filter=CreateBridge*
Note: Google Test filter = CreateBridge*
[==========] Running 14 tests from 3 test suites.
[----------] Global test environment set-up.
[----------] 6 tests from CreateBridgeTest
[ RUN      ] CreateBridgeTest.createsAndActivatesConnections
/home/frame/multipass/tests/mock_logger.cpp:68: Failure
Mock function called more times than expected - returning directly.
    Function call: log(4-byte object <01-00 00-00>, "Qt", "QDBusMessage: replying to a message that isn't a method call")
         Expected: to be never called
           Actual: called once - over-saturated and active

/home/frame/multipass/tests/mock_logger.cpp:68: Failure
Mock function called more times than expected - returning directly.
    Function call: log(4-byte object <01-00 00-00>, "Qt", "QDBusMessage: replying to a message that isn't a method call")
         Expected: to be never called
           Actual: called twice - over-saturated and active

/home/frame/multipass/tests/mock_logger.cpp:68: Failure
Mock function called more times than expected - returning directly.
    Function call: log(4-byte object <01-00 00-00>, "Qt", "QDBusMessage: replying to a message that isn't a method call")
         Expected: to be never called
           Actual: called 3 times - over-saturated and active

[  FAILED  ] CreateBridgeTest.createsAndActivatesConnections (2 ms)
[ RUN      ] CreateBridgeTest.throwsIfBusDisconnected
[       OK ] CreateBridgeTest.throwsIfBusDisconnected (0 ms)
[ RUN      ] CreateBridgeTest.throwsOnFailureToCreateFirstConnection
[       OK ] CreateBridgeTest.throwsOnFailureToCreateFirstConnection (0 ms)
[ RUN      ] CreateBridgeTest.throwsOnFailureToCreateSecondConnection
/home/frame/multipass/tests/mock_logger.cpp:68: Failure
Mock function called more times than expected - returning directly.
    Function call: log(4-byte object <01-00 00-00>, "Qt", "QDBusMessage: replying to a message that isn't a method call")
         Expected: to be never called
           Actual: called once - over-saturated and active

[  FAILED  ] CreateBridgeTest.throwsOnFailureToCreateSecondConnection (0 ms)
[ RUN      ] CreateBridgeTest.throwsOnFailureToActivateSecondConnection
/home/frame/multipass/tests/mock_logger.cpp:68: Failure
Mock function called more times than expected - returning directly.
    Function call: log(4-byte object <01-00 00-00>, "Qt", "QDBusMessage: replying to a message that isn't a method call")
         Expected: to be never called
           Actual: called once - over-saturated and active

/home/frame/multipass/tests/mock_logger.cpp:68: Failure
Mock function called more times than expected - returning directly.
    Function call: log(4-byte object <01-00 00-00>, "Qt", "QDBusMessage: replying to a message that isn't a method call")
         Expected: to be never called
           Actual: called twice - over-saturated and active

[  FAILED  ] CreateBridgeTest.throwsOnFailureToActivateSecondConnection (0 ms)
[ RUN      ] CreateBridgeTest.logsOnFailureToRollback
/home/frame/multipass/tests/mock_logger.cpp:68: Failure
Mock function called more times than expected - returning directly.
    Function call: log(4-byte object <01-00 00-00>, "Qt", "QDBusMessage: replying to a message that isn't a method call")
         Expected: to be never called
           Actual: called once - over-saturated and active

/home/frame/multipass/tests/mock_logger.cpp:68: Failure
Mock function called more times than expected - returning directly.
    Function call: log(4-byte object <01-00 00-00>, "Qt", "QDBusMessage: replying to a message that isn't a method call")
         Expected: to be never called
           Actual: called twice - over-saturated and active

[  FAILED  ] CreateBridgeTest.logsOnFailureToRollback (0 ms)
[----------] 6 tests from CreateBridgeTest (4 ms total)

[----------] 2 tests from CreateBridgeTest/CreateBridgeInvalidInterfaceTest
[ RUN      ] CreateBridgeTest/CreateBridgeInvalidInterfaceTest.throwsIfInterfaceInvalid/0
[       OK ] CreateBridgeTest/CreateBridgeInvalidInterfaceTest.throwsIfInterfaceInvalid/0 (0 ms)
[ RUN      ] CreateBridgeTest/CreateBridgeInvalidInterfaceTest.throwsIfInterfaceInvalid/1
[       OK ] CreateBridgeTest/CreateBridgeInvalidInterfaceTest.throwsIfInterfaceInvalid/1 (0 ms)
[----------] 2 tests from CreateBridgeTest/CreateBridgeInvalidInterfaceTest (0 ms total)

[----------] 6 tests from CreateBridgeTest/CreateBridgeExceptionTest
[ RUN      ] CreateBridgeTest/CreateBridgeExceptionTest.createBridgeExceptionInfo/0
[       OK ] CreateBridgeTest/CreateBridgeExceptionTest.createBridgeExceptionInfo/0 (0 ms)
[ RUN      ] CreateBridgeTest/CreateBridgeExceptionTest.createBridgeExceptionInfo/1
[       OK ] CreateBridgeTest/CreateBridgeExceptionTest.createBridgeExceptionInfo/1 (0 ms)
[ RUN      ] CreateBridgeTest/CreateBridgeExceptionTest.createBridgeExceptionIncludesDbusCauseWhenAvailable/0
[       OK ] CreateBridgeTest/CreateBridgeExceptionTest.createBridgeExceptionIncludesDbusCauseWhenAvailable/0 (0 ms)
[ RUN      ] CreateBridgeTest/CreateBridgeExceptionTest.createBridgeExceptionIncludesDbusCauseWhenAvailable/1
[       OK ] CreateBridgeTest/CreateBridgeExceptionTest.createBridgeExceptionIncludesDbusCauseWhenAvailable/1 (0 ms)
[ RUN      ] CreateBridgeTest/CreateBridgeExceptionTest.createBridgeExceptionMentionsUnknownCauseWhenUnavailable/0
[       OK ] CreateBridgeTest/CreateBridgeExceptionTest.createBridgeExceptionMentionsUnknownCauseWhenUnavailable/0 (0 ms)
[ RUN      ] CreateBridgeTest/CreateBridgeExceptionTest.createBridgeExceptionMentionsUnknownCauseWhenUnavailable/1
[       OK ] CreateBridgeTest/CreateBridgeExceptionTest.createBridgeExceptionMentionsUnknownCauseWhenUnavailable/1 (0 ms)
[----------] 6 tests from CreateBridgeTest/CreateBridgeExceptionTest (0 ms total)

[----------] Global test environment tear-down
[==========] 14 tests from 3 test suites ran. (6 ms total)
[  PASSED  ] 10 tests.
[  FAILED  ] 4 tests, listed below:
[  FAILED  ] CreateBridgeTest.createsAndActivatesConnections
[  FAILED  ] CreateBridgeTest.throwsOnFailureToCreateSecondConnection
[  FAILED  ] CreateBridgeTest.throwsOnFailureToActivateSecondConnection
[  FAILED  ] CreateBridgeTest.logsOnFailureToRollback

 4 FAILED TESTS

Additional info

  • OS: Ubuntu 25.10
  • CPU architecture or model: 11th Series Intel i5 x86_64

Additional context
PR for the yaml-cpp update: #4425

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions