scons,stdlib: Remove deprecated 'distutils' module

The Python module 'distutils' will be removed in Python 3.12:
https://docs.python.org/3/library/distutils.html

This patch removed usage of 'distutils' in the gem5 code base.

Change-Id: I1e3a944446149f3cd6cbf4211a1565b5f74c85a0
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71679
Tested-by: kokoro <noreply+kokoro@google.com>
Maintainer: Jason Lowe-Power <power.jg@gmail.com>
Reviewed-by: Jason Lowe-Power <power.jg@gmail.com>
diff --git a/src/SConscript b/src/SConscript
index d26bf49..1b44303 100644
--- a/src/SConscript
+++ b/src/SConscript
@@ -39,7 +39,7 @@
 
 import collections
 import copy
-import distutils.spawn
+from shutil import which
 import itertools
 import os
 import os.path
@@ -269,7 +269,7 @@
     '''Add a Protocol Buffer to build'''
     Source(source, tags, add_tags, append={'CXXFLAGS': '-Wno-array-bounds'})
 
-env['PROTOC_GRPC'] = distutils.spawn.find_executable('grpc_cpp_plugin')
+env['PROTOC_GRPC'] = which('grpc_cpp_plugin')
 if env['PROTOC_GRPC']:
     with Configure(env) as conf:
         if (not env['HAVE_PKG_CONFIG'] or
diff --git a/src/python/gem5/resources/client_api/client_wrapper.py b/src/python/gem5/resources/client_api/client_wrapper.py
index ebf1b8e..d2baabc 100644
--- a/src/python/gem5/resources/client_api/client_wrapper.py
+++ b/src/python/gem5/resources/client_api/client_wrapper.py
@@ -27,8 +27,7 @@
 from .jsonclient import JSONClient
 from .atlasclient import AtlasClient
 from _m5 import core
-from typing import Optional, Dict, List
-from distutils.version import StrictVersion
+from typing import Optional, Dict, List, Tuple
 import itertools
 from m5.util import warn
 
@@ -247,12 +246,27 @@
         :param resources: A list of resources to sort.
         :return: A list of sorted resources.
         """
+
+        def sort_tuple(resource: Dict) -> Tuple:
+            """This is used for sorting resources by ID and version. First
+            the ID is sorted, then the version. In cases where the version
+            contains periods, it's assumed this is to separate a
+            "major.minor.hotfix" style versioning system. In which case, the
+            value separated in the most-significant position is sorted before
+            those less significant. If the value is a digit it is cast as an
+            int, otherwise, it is cast as a string, to lower-case.
+            """
+            to_return = (resource["id"].lower(),)
+            for val in resource["resource_version"].split("."):
+                if val.isdigit():
+                    to_return += (int(val),)
+                else:
+                    to_return += (str(val).lower(),)
+            return to_return
+
         return sorted(
             resources,
-            key=lambda resource: (
-                resource["id"].lower(),
-                StrictVersion(resource["resource_version"]),
-            ),
+            key=lambda resource: sort_tuple(resource),
             reverse=True,
         )