mesonbuild / meson

The Meson Build System
http://mesonbuild.com
Apache License 2.0
5.51k stars 1.6k forks source link

cmake module: AttributeError: 'NoneType' object has no attribute 'resolve' #13551

Closed ethindp closed 2 weeks ago

ethindp commented 3 weeks ago

Describe the bug When trying to integrate Poco as a dependency via the cmake module, this exception is thrown. At first I thought it was unable to find a CMake target, but I don't believe this is the case.

To Reproduce First, add this wrap:

[wrap-file]
directory=poco-1.13.3-all
source_url=https://pocoproject.org/releases/poco-1.13.3/poco-1.13.3-all.zip
source_filename=poco-1.13.3-all.zip
source_hash=03279d93fb2f5172edbe1b5a1c5d85c1da53cba3fdd60e3403ce193748ee1134

Then, use a meson.build like the following (a standard meson init without any changes other than dependencies will cause this bug):

project(
    'test',
    'c',
    'cpp',
    version: '0.1',
    default_options: ['warning_level=3'],
)

cmake = import('cmake')

if meson.project_source_root() == meson.project_build_root()
    error(
        'In-source builds are not allowed. Please run Meson from a build directory.',
    )
endif

cpp = meson.get_compiler('cpp')

poco_opts = cmake.subproject_options()
poco_opts.add_cmake_defines(
    {
        'ENABLE_FOUNDATION': true,
        'ENABLE_ENCODINGS': true,
        'ENABLE_ENCODINGS_COMPILER': false,
        'ENABLE_XML': true,
        'ENABLE_JSON': true,
        'ENABLE_MONGODB': true,
        'ENABLE_DATA_SQLITE': true,
        'ENABLE_DATA_ODBC': false,
        'ENABLE_REDIS': true,
        'ENABLE_DNSSD': true,
        'ENABLE_DNSSD_DEFAULT': true,
        'ENABLE_DNSSD_AVAHI': true,
        'ENABLE_DNSSD_BONJOUR': true,
        'ENABLE_PROMETHEUS': true,
        'ENABLE_PDF': false,
        'ENABLE_UTIL': true,
        'ENABLE_NET': true,
        'ENABLE_SEVENZIP': true,
        'ENABLE_ZIP': true,
        'ENABLE_CPPPARSER': false,
        'ENABLE_POCODOC': false,
        'ENABLE_PAGECOMPILER': false,
        'ENABLE_PAGECOMPILER_FILE2PAGE': false,
        'ENABLE_ACTIVERECORD': true,
        'ENABLE_ACTIVERECORD_COMPILER': true,
        'ENABLE_TESTS': false,
        'ENABLE_TEST_DEPRECATED': false,
        'ENABLE_COMPILER_WARNINGS': false,
        'ENABLE_SAMPLES': false,
        'POCO_UNBUNDLED': false,
        'POCO_DISABLE_INTERNAL_OPENSSL': false,
    },
)
poco_proj = cmake.subproject('poco', options: poco_opts)
poco = declare_dependency(
    dependencies: [
        poco_proj.dependency('Poco::Foundation'),
        poco_proj.dependency('Poco::Data'),
        poco_proj.dependency('Poco::DataSQLite'),
        poco_proj.dependency('Poco::Encodings'),
        poco_proj.dependency('Poco::ActiveRecord'),
        poco_proj.dependency('Poco::Crypto'),
        poco_proj.dependency('Poco::DNSSD'),
        poco_proj.dependency('Pocoo::JSON'),
        poco_proj.dependency('Poco::JWT'),
        poco_proj.dependency('Poco::Mongodb'),
        poco_proj.dependency('Poco::Net'),
        poco_proj.dependency('Poco::NetSSL'),
        poco_proj.dependency('Poco::Prometheus'),
        poco_proj.dependency('Poco::Redis'),
        poco_proj.dependency('Poco::Util'),
        poco_proj.dependency('Pocoo::XML'),
        poco_proj.dependency('Poco::SevenZip'),
        poco_proj.dependency('Poco::Zip'),
    ],
)

exe = executable(
    'test',
    'test.c',
    install: true,
    dependencies: [
        poco,
    ],
)

test('basic', exe)

Expected behavior This should work fine. I don't think Poco is necessarily doing anything special.

system parameters

dcbaker commented 3 weeks ago

I can't reproduce this on Linux, could you provide the actual backtrace?

ethindp commented 3 weeks ago

@dcbaker Sure, it's odd it can't be reproduced on Linux but here you go:

...\build>meson setup --reconfigure --wipe
The Meson build system
Version: 1.5.1
...
poco| CMake configuration: SUCCEEDED
Traceback (most recent call last):
  File "...\mesonbuild\mesonmain.py", line 188, in run
    return options.run_func(options)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "...\mesonbuild\msetup.py", line 364, in run
    app.generate()
  File "...\mesonbuild\msetup.py", line 187, in generate
    return self._generate(env, capture, vslite_ctx)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "...\mesonbuild\msetup.py", line 226, in _generate
    intr.run()
  File "...\mesonbuild\interpreter\interpreter.py", line 3032, in run
    super().run()
  File "...\mesonbuild\interpreterbase\interpreterbase.py", line 169, in run
    self.evaluate_codeblock(self.ast, start=1)
  File "...\mesonbuild\interpreterbase\interpreterbase.py", line 195, in evaluate_codeblock
    raise e
  File "...\mesonbuild\interpreterbase\interpreterbase.py", line 187, in evaluate_codeblock
    self.evaluate_statement(cur)
  File "...\mesonbuild\interpreterbase\interpreterbase.py", line 205, in evaluate_statement
    self.assignment(cur)
  File "...\mesonbuild\interpreterbase\interpreterbase.py", line 642, in assignment
    value = self.evaluate_statement(node.value)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "...\mesonbuild\interpreterbase\interpreterbase.py", line 207, in evaluate_statement
    return self.method_call(cur)
           ^^^^^^^^^^^^^^^^^^^^^
  File "...\mesonbuild\interpreterbase\interpreterbase.py", line 557, in method_call
    res = obj.method_call(method_name, args, kwargs)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "...\mesonbuild\interpreter\interpreterobjects.py", line 854, in method_call
    ret = method(state, args, kwargs)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "...\mesonbuild\interpreterbase\decorators.py", line 663, in wrapped
    return f(*wrapped_args, **wrapped_kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "...\mesonbuild\interpreterbase\decorators.py", line 250, in wrapper
    return f(*nargs, **wrapped_kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "...\mesonbuild\interpreterbase\decorators.py", line 569, in wrapper
    return f(*wrapped_args, **wrapped_kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "...\mesonbuild\modules\cmake.py", line 429, in subproject
    subp = self.interpreter.do_subproject(dirname, kw, force_method='cmake')
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "...\mesonbuild\interpreter\interpreter.py", line 948, in do_subproject
    raise e
  File "...\mesonbuild\interpreter\interpreter.py", line 936, in do_subproject
    return methods_map[method](subp_name, subdir, default_options, kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "...\mesonbuild\interpreter\interpreter.py", line 1023, in _do_subproject_cmake
    cm_int.analyse()
  File "...\mesonbuild\cmake\interpreter.py", line 948, in analyse
    tgt.postprocess(self.output_target_map, self.src_dir, self.subdir, self.install_prefix, self.trace)
  File "...\mesonbuild\cmake\interpreter.py", line 425, in postprocess
    ctgt = output_target_map.generated(gen_file)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "...\mesonbuild\cmake\interpreter.py", line 181, in generated
    res = self._return_first_valid_key([self._rel_generated_file_key(name), self._base_generated_file_key(name)])
                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "...\mesonbuild\cmake\interpreter.py", line 197, in _rel_generated_file_key
    path = self._rel_path(fname)
           ^^^^^^^^^^^^^^^^^^^^^
  File "...\mesonbuild\cmake\interpreter.py", line 188, in _rel_path
    return fname.resolve().relative_to(self.build_dir)
           ^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'resolve'

..\meson.build:57:18: ERROR: Unhandled python exception

    This is a Meson bug and should be reported!
dcbaker commented 3 weeks ago

Out of curiosity, what version of CMake do you have?

ethindp commented 3 weeks ago

@dcbaker I'm on CMake 3.28.3 right now. It might change with VS upgrades though. I have yet to test it with absolute latest CMake (3.30+).

dcbaker commented 3 weeks ago

Okay, I have 3.29.2, so it's not like we have wildly different versions... hmmm. There's a lot of lose handling of None in the CMake convertor in Meson. unfortunately the actual place that the None is getting inserted is not in the stack trace, but I can look at the typing a bit more, it might pop out at me

dcbaker commented 3 weeks ago

I found some places were we can put an Optional[Path] into the sources that we shouldn't, and it looks relevant. Could you try with https://github.com/mesonbuild/meson/pull/13579 and see if that fixes the issue?

ethindp commented 3 weeks ago

@dcbaker Is there any more things I can do to give more data? I tried looking into it myself but it didn't really make much sense to me when I was trying to dig into it. Hopefully you'll have more luck than I did. It doesn't help that I'm not overly proficient with understanding Meson's source code so... Lol

dcbaker commented 3 weeks ago

@ethindp, yeah, and the CMake handling code is some of the most complicated code in Meson. Could you try the PR I mentioned?

ethindp commented 3 weeks ago

@dcbaker I can confirm that this did solve the problem. Hopefully it doesn't break things on other platforms.

dcbaker commented 3 weeks ago

It shouldn't, this is really an internal variable type issue.

ethindp commented 3 weeks ago

Ah, okay. It fixed it for me when I tried it.