Calculator: Alternative compilers

Created on 6 Mar 2019  Â·  10Comments  Â·  Source: microsoft/calculator

Support Clang and/or GCC

approved tooling

Most helpful comment

We use many features of MSVC and Visual Studio (like C++/CX, for example) which would make it difficult to support other toolchains for the whole app.

However, it would be great to make the calculator _engine_ code more portable so it can be reused in other projects. I'd also love to use tools from other ecosystems, like afl-fuzz or clang-format, to improve that code. We would accept PRs which make improvements along those lines.

All 10 comments

This is your friendly Microsoft Issue Bot. I've seen this issue come in and have gone to tell a human about it.

We use many features of MSVC and Visual Studio (like C++/CX, for example) which would make it difficult to support other toolchains for the whole app.

However, it would be great to make the calculator _engine_ code more portable so it can be reused in other projects. I'd also love to use tools from other ecosystems, like afl-fuzz or clang-format, to improve that code. We would accept PRs which make improvements along those lines.

@mcooley I think this project should use C++/WinRT to refactoring because C++/WinRT don't use MSVC compiler extension and may help you achieve this goal.

Mouri

@MouriNaruto yep, as mentioned in the contributing guidelines we'd like to use C++/WinRT where possible, especially in new code. Unfortunately using C++/WinRT with XAML is still a bit cumbersome (you have to write idl), which is the main reason we haven't adopted it in more places in the codebase. Ideally the calc _engine_ wouldn't have any Windows-specific API calls, so the choice of WinRT projection wouldn't be relevant in that part of the code.

@mcooley

Unfortunately using C++/WinRT with XAML is still a bit cumbersome (you have to write idl), which is the main reason we haven't adopted it in more places in the codebase.

You are right. I have created an open source UWP app project (https://github.com/Project-Nagisa/Nagisa) which is mainly developed in C++ STL and C++/WinRT. So I can understand your said. Also, there are some blocking bugs in Windows 10 17763 SDK's Modern IDL compiler and I have to use both 17763 and 17134 sdk. (But 19H1 SDK has fixed them.)

Ideally the calc engine wouldn't have any Windows-specific API calls, so the choice of WinRT projection wouldn't be relevant in that part of the code.

I think C Runtime and C++ STL are good choice for them.

Mouri

There's currently a bug in Clang that prevents using a lot C++/WinRT features with it. I've filled it here: https://bugs.llvm.org/show_bug.cgi?id=38490

Not to mention asynchronous methods (coroutines) using C++/WinRT are not working OOB on Clang. While I did get it to work, I've had to do compromises, like dropping x86 support (because Clang cannot convert a capture-less lambda to a function pointer with a certain calling convention, which C++/WinRT assumes the compiler can do, on x64/arm/arm64 there is only one calling convention so it just isn't a problem) and carrying along a libc++ header around to implement std::experimental::coroutine_traits<void> because the Microsoft STL implementation of that only works on MSVC due to usage of compiler-specific intrinsics (even if Clang has nearly the same ones under a different name). I believe the second issue will be fixed soon-ish since coroutines are now standardized for C++20, and I've read somewhere that the 3 major compiler vendors are working on all using the same intrinsics, but can't find the source of that claim anymore.

Oh, and catching an exception in a coroutine results in a really nasty ICE in Clang.

Here's the coroutine ICE (clang -std=c++17 -fcoroutines-ts):

#define _RESUMABLE_FUNCTIONS_SUPPORTED
#include <winrt/Windows.ApplicationModel.h>

using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::ApplicationModel;

IAsyncOperation<StartupTask> GetApplicationStartupTask()
{
    static auto task = (co_await StartupTask::GetForCurrentPackageAsync()).GetAt(0);
    co_return task;
}

IAsyncOperation<StartupTaskState> GetStartupState()
{
    try
    {
        co_return (co_await GetApplicationStartupTask()).State();
    }
    catch (const winrt::hresult_error &err)
    {
        co_return StartupTaskState::Disabled;
    }
}

Note that I did not even get to the point where linking fails because of the missing intrinsics.

Instruction does not dominate all uses!
  %116 = getelementptr inbounds %"\01?GetStartupState@@YA?AU?$IAsyncOperation@W4StartupTaskState@ApplicationModel@Windows@winrt@@@Foundation@Windows@winrt@@XZ.Frame", %"\01?GetStartupState@@YA?AU?$IAsyncOperation@W4StartupTaskState@ApplicationModel@Windows@winrt@@@Foundation@Windows@winrt@@XZ.Frame"* %15, i32 0, i32 13
  %114 = catchpad within %112 [%rtti.TypeDescriptor25* @"\01??_R0?AUhresult_error@winrt@@@8", i32 8, %"struct.winrt::hresult_error"** %116]
fatal error: error in backend: Broken function found, compilation aborted!

That ICE is not triggered by not naming the catched exception (catch (const winrt::hresult_error &) or just doing catch (…), but then you can't do anything useful with the exception.

I haven't filled an issue for this one, because coroutines are still very experimental, and such a bug will probably not be present in their final release.

There's also another bug, where control flow guard doesn't works when using a string stream.

#include <iostream>
#include <sstream>

int main()
{
    std::wostringstream str;
    str << L"Lorem ipsum dolor sit amet"; // crash here. Investigation lead me to xsputn not being registered somehow in the list of valid function pointers

    std::wcout << str.str();
}
clang-cl /c file.cpp -m32 /guard:cf /MDd
lld-link /guard:cf file.obj

Running the executable will cause a crash because of a control flow guard violation. I did fill an issue for this one: https://bugs.llvm.org/show_bug.cgi?id=39517

The PR #211 largely resolves this issue by porting the engine to Clang. The question whether the UI can be built using other compilers remains however, so it might be worth reopening the issue then.

I would prefer to have everything ported to .NET Standard and C#/F# 😅

Catching up on this since it's been over a year since this issue was first opened. Unfortunately, we haven't had time to focus on this issue and it doesn't look like that will change anytime soon. Because we're focused on the Windows app, we don't think we can support infrastructure like linux builds which would be needed to keep cross-platform targets in a state of good repair.

We're still happy to make the calculator engine more portable and PRs which make portability improvements are still welcome! But they need to be small enough that we can review them easily, and it's vital that they're well-tested in our primary environment (Visual Studio on Windows).

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Diggsey picture Diggsey  Â·  20Comments

InfoLibre picture InfoLibre  Â·  17Comments

MicrosoftIssueBot picture MicrosoftIssueBot  Â·  16Comments

patrick-compass picture patrick-compass  Â·  22Comments

grochocki picture grochocki  Â·  25Comments