runtime: [ppc64le][.net7] Unhandled Exception: System.PlatformNotSupportedException: System.Data.ODBC is not supported on this platform

Description

Support for ppc64le architecture was added in .NET7. Using this, we were trying some sample code which uses System.Data.Odbc package.

The sample code works on x86 machine with .NET7 but fails on ppc64le. We are not sure about the root cause of the problem but suspect it is because there is no enablement for ppc64le in https://github.com/dotnet/msbuild/blob/main/eng/common/cross

dotnet build shows the MSBuild Version as MSBuild version 17.4.0+18d5aef85 for .NET

The .csproj has the following:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net7.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="System.Data.Odbc" Version="7.0.0" />
  </ItemGroup>

</Project>

Project was created as follows:

# dotnet new console -o odbc_sample
The template "Console App" was created successfully.

Processing post-creation actions...
Restoring /root/samples/odbc_sample/odbc_sample.csproj:
 Determining projects to restore...
 Restored /root/samples/odbc_sample/odbc_sample.csproj (in 230 ms).
Restore succeeded.

# cd odbc_sample/
# dotnet add package System.Data.Odbc
 Determining projects to restore...
 Writing /tmp/tmp5D3gRy.tmp
info : X.509 certificate chain validation will use the system certificate bundle at '/etc/pki/ca-trust/extracted/pem/objsign-ca-bundle.pem'.
info : X.509 certificate chain validation will use the fallback certificate bundle at '/usr/lib64/dotnet/sdk/7.0.100/trustedroots/timestampctl.pem'.
info : Adding PackageReference for package 'System.Data.Odbc' into project '/root/samples/odbc_sample/odbc_sample.csproj'.
info :  GET https://api.nuget.org/v3/registration5-gz-semver2/system.data.odbc/index.json
info :  OK https://api.nuget.org/v3/registration5-gz-semver2/system.data.odbc/index.json 43ms
info : Restoring packages for /root/samples/odbc_sample/odbc_sample.csproj...
info :  GET https://api.nuget.org/v3-flatcontainer/system.data.odbc/index.json
info :  OK https://api.nuget.org/v3-flatcontainer/system.data.odbc/index.json 117ms
info :  GET https://api.nuget.org/v3-flatcontainer/system.data.odbc/7.0.0/system.data.odbc.7.0.0.nupkg
info :  OK https://api.nuget.org/v3-flatcontainer/system.data.odbc/7.0.0/system.data.odbc.7.0.0.nupkg 17ms
info :  GET https://api.nuget.org/v3-flatcontainer/system.text.encoding.codepages/index.json
info :  OK https://api.nuget.org/v3-flatcontainer/system.text.encoding.codepages/index.json 116ms
info :  GET https://api.nuget.org/v3-flatcontainer/system.text.encoding.codepages/7.0.0/system.text.encoding.codepages.7.0.0.nupkg
info :  OK https://api.nuget.org/v3-flatcontainer/system.text.encoding.codepages/7.0.0/system.text.encoding.codepages.7.0.0.nupkg 17ms
info : Installed System.Text.Encoding.CodePages 7.0.0 from https://api.nuget.org/v3/index.json with content hash LSyCblMpvOe0N3E+8e0skHcrIhgV2huaNcjUUEa8hRtgEAm36aGkRoC8Jxlb6Ra6GSfF29ftduPNywin8XolzQ==.
info : Installed System.Data.Odbc 7.0.0 from https://api.nuget.org/v3/index.json with content hash siwu7NoCsfHa9bfw2a2wSeTt2c/rhk3X8I28nJln1dlxdW3KqhRp0aW87yH1XkCo9h8zO1qcIfdTHO7YvvWLEA==.
info : Package 'System.Data.Odbc' is compatible with all the specified frameworks in project '/root/samples/odbc_sample/odbc_sample.csproj'.
info : PackageReference for package 'System.Data.Odbc' version '7.0.0' added to file '/root/samples/odbc_sample/odbc_sample.csproj'.
info : Writing assets file to disk. Path: /root/samples/odbc_sample/obj/project.assets.json
log : Restored /root/samples/odbc_sample/odbc_sample.csproj (in 1.21 sec).

Sample code ( note: we are able to connect to the database using cli )

using System;
using System.Collections.Generic;
using System.Text;
using System.Data.Odbc;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string MyConString = "DRIVER={Free Sybase & MS SQL Driver}; " +
            "SERVER=(local); " +
            "DATABASE=TestDB; " +
            "UID=sa; " +
            "PWD=password@123; " +
            "TrustServerCertificate=yes; ";

            OdbcConnection DbConnection = new OdbcConnection(MyConString);
            //OdbcConnection DbConnection = new OdbcConnection("driver={ODBC Driver 18 for SQL Server};Server=(local);TrustServerCertificate=yes;Database=TestDB;UID=sa;PWD=password@123;");

            DbConnection.Open();

            OdbcCommand DbCommand = DbConnection.CreateCommand();

            DbCommand.CommandText = "SELECT * FROM Persons";
            OdbcDataReader DbReader = DbCommand.ExecuteReader();

            int fCount = DbReader.FieldCount;

            Console.Write( ":" );
            for ( int i = 0; i < fCount; i ++ )
            {
                String fName = DbReader.GetName(i);
                Console.Write( fName + ":" );
            }
            Console.WriteLine();

            while( DbReader.Read())
            {
                Console.Write( ":" );
                for (int i = 0; i < fCount; i++)
                {
                    String col = DbReader.GetString(i);
                    Console.Write(col + ":");
                }
                Console.WriteLine();
            }

            DbReader.Close();
            DbCommand.Dispose();
            DbConnection.Close();
        }
    }
}

But on Power ppc64le machine we are getting below error

# dotnet build
MSBuild version 17.4.0+18d5aef85 for .NET
  Determining projects to restore...
  Restored /root/samples/odbc_sample/odbc_sample.csproj (in 527 ms).
  odbc_sample -> /root/samples/odbc_sample/bin/Debug/net7.0/odbc_sample.dll

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:04.13

# dotnet run 
Unhandled Exception:
 System.PlatformNotSupportedException: 
System.Data.ODBC is not supported on this platform. at System.Data.Odbc.OdbcConnection..ctor(String connectionString)   at ConsoleApplication1.Program.Main(String[] args) in /root/samples/odbc_sample/Program.cs:line 19 

[ERROR] FATAL UNHANDLED EXCEPTION: 
System.PlatformNotSupportedException: System.Data.ODBC is not supported on this platform. 
at System.Data.Odbc.OdbcConnection..ctor(String connectionString) at ConsoleApplication1.Program.Main(String[] args) in /root/samples/odbc_sample/Program.cs:line 19

During debugging what we found MSBuild::GetTargetPlatformIdentifier () may be returning empty string and this (https://github.com/dotnet/runtime/blob/main/src/libraries/System.Data.Odbc/src/System.Data.Odbc.csproj#L27) code throwing error. When we check the MSBuild repo https://github.com/dotnet/msbuild we don’t see ppc64le changes in eng/common/cross folder.

https://github.com/dotnet/msbuild/blob/main/eng/common/README.md says “The files in this directory are shared by all Arcade repos and managed by automation. If you need to make changes to these files, open an issue or submit a pull request to https://github.com/dotnet/arcade first.” –

Question @akoeplinger : Since the https://github.com/dotnet/arcade/tree/main/eng/common/cross has support for ppc64le, does it also need to get propagated to msbuild?

Note: We opened the same issue in the arcade repo ( see https://github.com/dotnet/arcade/issues/11675 ) but since we don’t know if our analysis of root cause is right, opening it in the runtime repo also

Tagging @omajid / @Sapana-Khemkar / @uweigand for awareness.

Reproduction Steps

On a ppc64le machine

  • Install .net7 SDK

  • Install mysql, created database and table, add sample data in table. Verify that you can connect to database and retrieve data using command line

  • Create a sample C# program that uses System.Data.Odbc to connect to the backend mysql database

# dotnet new console -o odbc_sample
The template "Console App" was created successfully.

Processing post-creation actions...
Restoring /root/samples/odbc_sample/odbc_sample.csproj:
 Determining projects to restore...
 Restored /root/samples/odbc_sample/odbc_sample.csproj (in 230 ms).
Restore succeeded.

# cd odbc_sample/
# dotnet add package System.Data.Odbc
  • Run the program using dotnet run

Expected behavior

Be able to connect to the database and retrieve data

Actual behavior

# dotnet run 
Unhandled Exception:
 System.PlatformNotSupportedException: 
System.Data.ODBC is not supported on this platform. at System.Data.Odbc.OdbcConnection..ctor(String connectionString)   at ConsoleApplication1.Program.Main(String[] args) in /root/samples/odbc_sample/Program.cs:line 19 

[ERROR] FATAL UNHANDLED EXCEPTION: 
System.PlatformNotSupportedException: System.Data.ODBC is not supported on this platform. 
at System.Data.Odbc.OdbcConnection..ctor(String connectionString) at ConsoleApplication1.Program.Main(String[] args) in /root/samples/odbc_sample/Program.cs:line 19

Regression?

No response

Known Workarounds

No response

Configuration

# uname -a
Linux dotnet-validator-ghatwala 4.18.0-348.2.1.el8_5.ppc64le #1 SMP Mon Nov 8 12:14:56 EST 2021 ppc64le ppc64le ppc64le GNU/Linux
# cat /etc/redhat-release 
Red Hat Enterprise Linux release 8.6 (Ootpa)
[root@dotnet-validator-ghatwala ~]# dotnet --info
.NET SDK:
 Version:   7.0.100
 Commit:    e12b7af219

Runtime Environment:
 OS Name:     rhel
 OS Version:  8
 OS Platform: Linux
 RID:         rhel.8-ppc64le
 Base Path:   /usr/lib64/dotnet/sdk/7.0.100/

Host:
  Version:      7.0.0
  Architecture: ppc64le
  Commit:       d099f075e4

.NET SDKs installed:
  7.0.100 [/usr/lib64/dotnet/sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.App 7.0.0 [/usr/lib64/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 7.0.0 [/usr/lib64/dotnet/shared/Microsoft.NETCore.App]

Other architectures found:
  None

Environment variables:
  DOTNET_ROOT       [/usr/lib64/dotnet]

global.json file:
  Not found

Learn more:
  https://aka.ms/dotnet/info

Download .NET:
  https://aka.ms/dotnet/download

Other information

No response

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 22 (21 by maintainers)

Commits related to this issue

Most upvoted comments

You need the complete set of patches which is the list here: https://github.com/dotnet/installer/pull/14549#issuecomment-1291757350. All of these have been backported to 7.0 for the next release.

And two PRs for installer which have not been backported yet to 7.0: https://github.com/dotnet/installer/pull/14549 and https://github.com/dotnet/installer/pull/14938.

Hmm. I can reproduce this on my Ubuntu system when building upstream runtime as well.

However, on the same system, when I build the source-build tree (which also uses the non-portable RID), I get instead:

uweigand@m8345019:~/source-build-tarball$ tail -20 ./src/runtime/artifacts/source-build/self/src/artifacts/obj/Microsoft.NETCore.App.Runtime/Release/net7.0/ubuntu.20.04-s390x/Microsoft.NETCore.App.deps.json 
      "sha512": "",
      "path": "microsoft.netcore.app.runtime.ubuntu.20.04-s390x/7.0.0-rtm.22507.1"
    }
  },
  "runtimes": {
    "ubuntu.20.04-s390x": [
      "ubuntu.20.04",
      "ubuntu-s390x",
      "ubuntu",
      "debian-s390x",
      "debian",
      "linux-s390x",
      "linux",
      "unix-s390x",
      "unix",
      "any",
      "base"
    ]
  }
}

It appears to me the difference is which input RID fallback graph is being used to generate the deps.json file. This happens in Microsoft.DotNet.SharedFramework.Sdk here:

    <GenerateSharedFrameworkDepsFile TargetFrameworkMoniker="$(TargetFrameworkMoniker)"
                                     RuntimeIdentifier="$(RuntimeIdentifier)"
                                     SharedFrameworkName="$(SharedFrameworkName)"
                                     SharedFrameworkPackName="$(PackageId)"
                                     Version="$(Version)"
                                     Files="@(_FilesForDepsFile)"
                                     IntermediateOutputPath="$(IntermediateOutputPath)"
                                     SharedFrameworkDepsNameOverride="$(SharedFrameworkHostFileNameOverride)"
                                     RuntimeIdentifierGraph="$(BundledRuntimeIdentifierGraphFile)"
                                     IncludeFallbacksInDepsFile="$(IncludeFallbacksInDepsFile)">

where BundledRuntimeIdentifierGraphFile seems to be set in the runtime in eng/liveBuilds.target:

  <PropertyGroup>
    <!-- Keep in sync with outputs defined in Microsoft.NETCore.Platforms.csproj. -->
    <BundledRuntimeIdentifierGraphFile>$([MSBuild]::NormalizePath('$(ArtifactsBinDir)', 'Microsoft.NETCore.Platforms', 'runtime.json'))</BundledRuntimeIdentifierGraphFile>
    <BundledRuntimeIdentifierGraphFile Condition="!Exists('$(BundledRuntimeIdentifierGraphFile)')">$([MSBuild]::NormalizePath('$(LibrariesProjectRoot)', 'Microsoft.NETCore.Platforms', 'src', 'runtime.json'))</BundledRuntimeIdentifierGraphFile>
  </PropertyGroup>

Now, when building runtime by itself, the above code uses the file src/libraries/Microsoft.NETCore.Platforms/src/runtime.json, which does not mention ubuntu20.04-s390x (or rhel.8-s390x for that matter) at all, only linux-s390x. However, during source-build, the file artifacts/bin/Microsoft.NETCore.Platforms/runtime.json is used, which does contain ubuntu20.04-s390x (but not rhel.8-s390x – which is presumably because it only adds the relevant RIDs for the host system).

This is turn seems to be because of this line in src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj:

    <!-- When building from source, ensure the RID we're building for is part of the RID graph -->
    <AdditionalRuntimeIdentifiers Condition="'$(DotNetBuildFromSource)' == 'true'">$(AdditionalRuntimeIdentifiers);$(OutputRID)</AdditionalRuntimeIdentifiers>

which causes the runtime.json file to be rebuilt only in source-build mode.

Now, this makes me wonder if this is correct condition: maybe instead of checking for source-build mode, we should add the identifier whenever building in non-portable mode here?

However, even so, this still doesn’t explain why this does not work correctly in the RHEL RPM build, which does use source-build …