# Buggy code
def sanitize_dir_option_value(self, prefix, option, value):
    """
    If the option is an installation directory option and the value is an
    absolute path, check that it resides within prefix and return the value
    as a path relative to the prefix.

    This way everyone can do f.ex, get_option('libdir') and be sure to get
    the library directory relative to prefix.
    """
    if (
        option.endswith("dir")
        and os.path.isabs(value)
        and option not in builtin_dir_noprefix_options
    ):
        # Value must be a subdir of the prefix
        # commonpath will always return a path in the native format, so we
        # must use pathlib.PurePath to do the same conversion before
        # comparing.
        if os.path.commonpath([value, prefix]) != str(PurePath(prefix)):
            m = (
                "The value of the {!r} option is {!r} which must be a "
                "subdir of the prefix {!r}.\nNote that if you pass a "
                "relative path, it is assumed to be a subdir of prefix."
            )
            raise MesonException(m.format(option, value, prefix))
        # Convert path to be relative to prefix
        skip = len(prefix) + 1
        value = value[skip:]
    return value


# Traceback (ValueError)
$ meson setup build --libdir=E:/Documents/Coding/C/lib
The Meson build system
Version: 0.52.1
Source dir: E:\Documents\Coding\C\meson_test
Build dir: E:\Documents\Coding\C\meson_test\build
Build type: native build
Traceback (most recent call last):
File "C:\Users\<user>\AppData\Roaming\Python\Python38\site-packages\mesonbuild\mesonmain.py", line 129, in run
return options.run_func(options)
File "C:\Users\<user>\AppData\Roaming\Python\Python38\site-packages\mesonbuild\msetup.py", line 245, in run
app.generate()
File "C:\Users\<user>\AppData\Roaming\Python\Python38\site-packages\mesonbuild\msetup.py", line 159, in generate
self._generate(env)
File "C:\Users\<user>\AppData\Roaming\Python\Python38\site-packages\mesonbuild\msetup.py", line 176, in _generate
intr = interpreter.Interpreter(b)
File "C:\Users\<user>\AppData\Roaming\Python\Python38\site-packages\mesonbuild\interpreter.py", line 2110, in __init__
self.parse_project()
File "C:\Users\<user>\AppData\Roaming\Python\Python38\site-packages\mesonbuild\interpreterbase.py", line 397, in parse_project
self.evaluate_codeblock(self.ast, end=1)
File "C:\Users\<user>\AppData\Roaming\Python\Python38\site-packages\mesonbuild\interpreterbase.py", line 436, in evaluate_codeblock
raise e
File "C:\Users\<user>\AppData\Roaming\Python\Python38\site-packages\mesonbuild\interpreterbase.py", line 430, in evaluate_codeblock
self.evaluate_statement(cur)
File "C:\Users\<user>\AppData\Roaming\Python\Python38\site-packages\mesonbuild\interpreterbase.py", line 441, in evaluate_statement
return self.function_call(cur)
File "C:\Users\<user>\AppData\Roaming\Python\Python38\site-packages\mesonbuild\interpreterbase.py", line 776, in function_call
return func(node, posargs, kwargs)
File "C:\Users\<user>\AppData\Roaming\Python\Python38\site-packages\mesonbuild\interpreterbase.py", line 143, in wrapped
return f(*wrapped_args, **wrapped_kwargs)
File "C:\Users\<user>\AppData\Roaming\Python\Python38\site-packages\mesonbuild\interpreterbase.py", line 174, in wrapped
return f(*wrapped_args, **wrapped_kwargs)
File "C:\Users\<user>\AppData\Roaming\Python\Python38\site-packages\mesonbuild\interpreter.py", line 2723, in func_project
self.coredata.set_default_options(default_options, self.subproject, self.environment)
File "C:\Users\<user>\AppData\Roaming\Python\Python38\site-packages\mesonbuild\coredata.py", line 742, in set_default_options
self.set_options(options, subproject=subproject)
File "C:\Users\<user>\AppData\Roaming\Python\Python38\site-packages\mesonbuild\coredata.py", line 674, in set_options
if self._try_set_builtin_option(k, v):
File "C:\Users\<user>\AppData\Roaming\Python\Python38\site-packages\mesonbuild\coredata.py", line 531, in _try_set_builtin_option
value = self.sanitize_dir_option_value(prefix, optname, value)
File "C:\Users\<user>\AppData\Roaming\Python\Python38\site-packages\mesonbuild\coredata.py", line 479, in sanitize_dir_option_value
if os.path.commonpath([value, prefix]) != str(PurePath(prefix)):
File "c:\users\liz\appdata\local\programs\python\python38\lib\ntpath.py", line 763, in commonpath
raise ValueError("Paths don't have the same drive")
ValueError: Paths don't have the same drive

# Fixed code
def sanitize_dir_option_value(self, prefix: str, option: str, value: Any) -> Any:
    """
    If the option is an installation directory option and the value is an
    absolute path, check that it resides within prefix and return the value
    as a path relative to the prefix.

    This way everyone can do f.ex, get_option('libdir') and be sure to get
    the library directory relative to prefix.

    .as_posix() keeps the posix-like file seperators Meson uses.
    """
    try:
        value = PurePath(value)
    except TypeError:
        return value
    if (
        option.endswith("dir")
        and value.is_absolute()
        and option not in builtin_dir_noprefix_options
    ):
        # Value must be a subdir of the prefix
        # commonpath will always return a path in the native format, so we
        # must use pathlib.PurePath to do the same conversion before
        # comparing.
        msg = (
            "The value of the {!r} option is {!r} which must be a "
            "subdir of the prefix {!r}.\nNote that if you pass a "
            "relative path, it is assumed to be a subdir of prefix."
        )
        # os.path.commonpath doesn't understand case-insensitive filesystems,
        # but PurePath().relative_to() does.
        try:
            value = value.relative_to(prefix)
        except ValueError:
            raise MesonException(msg.format(option, value, prefix))
        if ".." in str(value):
            raise MesonException(msg.format(option, value, prefix))
    return value.as_posix()