mesonbuild / meson-python

Meson PEP 517 Python build backend
https://mesonbuild.com/meson-python/
MIT License
125 stars 65 forks source link

pip install failing on windows due to FileNotFoundError for simple build file #578

Closed peppedilillo closed 7 months ago

peppedilillo commented 7 months ago

Hello,

I have successfully pip install-ed a package comprising C code on MacOs, using mesonpy. Trying pip install for the same package fails on Windows with a FileNotFoundError relative to the location of a shared library I'm attempting to build. I can replicate the problem within my mwe test repository, which again builds just fine on MacOs.

For convenience, the build file for the test repository is:

project('PkgName', 'c')
add_global_arguments(language : 'c')

py = import('python').find_installation()

# installs the package, which only contains the ctypes wrapper
py.install_sources(
  [
    'pkgname/__init__.py',
    'pkgname/wrapper.py',
  ],
  subdir: 'pkgname'
)

# compiles the shared library and puts it in the package installation folder
incdir = include_directories('pkgname/c/include')
sources = ['pkgname/c/mylib.c']
shared_library('sharedlibname',
    sources,
    include_directories : incdir,
    install: true,
    install_dir: py.get_install_dir() / 'pkgname/.sharedlibs'
)

I tried changing the path specification to use meson's path separator, e.g. transforming 'pkgname/init.py' into 'pkgname' / 'init.py', and similiarly for the other files, with no luck.

The full error log is:

Processing c:\users\utente\desktop\meson-ctypes-test
  Installing build dependencies ... done
  Getting requirements to build wheel ... done
  Installing backend dependencies ... done
  Preparing metadata (pyproject.toml) ... error
  error: subprocess-exited-with-error

  × Preparing metadata (pyproject.toml) did not run successfully.
  │ exit code: 1
  ╰─> [60 lines of output]
      + meson setup C:\Users\Utente\Desktop\meson-ctypes-test C:\Users\Utente\Desktop\meson-ctypes-test\.mesonpy-tht_yopx -Dbuildtype=release -Db_ndebug=if-release -Db_vscrt=md --native-file=C:\Users\Utente\Desktop\meson-ctypes-test\.mesonpy-tht_yopx\meson-python-native-file.ini
      The Meson build system
      Version: 1.3.2
      Source dir: C:\Users\Utente\Desktop\meson-ctypes-test
      Build dir: C:\Users\Utente\Desktop\meson-ctypes-test\.mesonpy-tht_yopx
      Build type: native build
      Project name: PkgName
      Project version: undefined
      Activating VS 17.3.3
      C compiler for the host machine: cl (msvc 19.33.31629 "Microsoft (R) C/C++ Optimizing Compiler versione 19.33.31629 per x64")
      C linker for the host machine: link link 14.33.31629.0
      Host machine cpu family: x86_64
      Host machine cpu: x86_64
      Program python found: YES (C:\Users\Utente\Desktop\meson-ctypes-test\.venv\Scripts\python.exe)
      Build targets in project: 1

      PkgName undefined

        User defined options
          Native files: C:\Users\Utente\Desktop\meson-ctypes-test\.mesonpy-tht_yopx\meson-python-native-file.ini
          buildtype   : release
          b_ndebug    : if-release
          b_vscrt     : md

      Found ninja.EXE-1.11.1.git.kitware.jobserver-1 at C:\Users\Utente\AppData\Local\Temp\pip-build-env-doizkxdm\normal\Scripts\ninja.EXE
      + meson compile
      [1/2] Compiling C object sharedlibname.dll.p/pkgname_c_mylib.c.obj
      [2/2] Linking target sharedlibname.dll
      Activating VS 17.3.3
      INFO: automatically activated MSVC compiler environment
      INFO: autodetecting backend as ninja
      INFO: calculating backend command to run: C:\Users\Utente\AppData\Local\Temp\pip-build-env-doizkxdm\normal\Scripts\ninja.EXE
      [1/4] C:\Users\Utente\Desktop\meson-ctypes-test\.mesonpy-tht_yopx\sharedlibname.dll
      [2/4] C:\Users\Utente\Desktop\meson-ctypes-test\.mesonpy-tht_yopx\sharedlibname.lib
      Traceback (most recent call last):
        File "C:\Users\Utente\Desktop\meson-ctypes-test\.venv\Lib\site-packages\pip\_vendor\pyproject_hooks\_in_process\_in_process.py", line 353, in <module>
          main()
        File "C:\Users\Utente\Desktop\meson-ctypes-test\.venv\Lib\site-packages\pip\_vendor\pyproject_hooks\_in_process\_in_process.py", line 335, in main
          json_out['return_val'] = hook(**hook_input['kwargs'])
                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "C:\Users\Utente\Desktop\meson-ctypes-test\.venv\Lib\site-packages\pip\_vendor\pyproject_hooks\_in_process\_in_process.py", line 152, in prepare_metadata_for_build_wheel
          whl_basename = backend.build_wheel(metadata_directory, config_settings)
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "C:\Users\Utente\AppData\Local\Temp\pip-build-env-doizkxdm\overlay\Lib\site-packages\mesonpy\__init__.py", line 985, in wrapper
          return func(*args, **kwargs)
                 ^^^^^^^^^^^^^^^^^^^^^
        File "C:\Users\Utente\AppData\Local\Temp\pip-build-env-doizkxdm\overlay\Lib\site-packages\mesonpy\__init__.py", line 1039, in build_wheel
          return project.wheel(out).name
                 ^^^^^^^^^^^^^^^^^^
        File "C:\Users\Utente\AppData\Local\Temp\pip-build-env-doizkxdm\overlay\Lib\site-packages\mesonpy\__init__.py", line 890, in wheel
          return builder.build(directory)
                 ^^^^^^^^^^^^^^^^^^^^^^^^
        File "C:\Users\Utente\AppData\Local\Temp\pip-build-env-doizkxdm\overlay\Lib\site-packages\mesonpy\__init__.py", line 455, in build
          self._install_path(whl, src, dst)
        File "C:\Users\Utente\AppData\Local\Temp\pip-build-env-doizkxdm\overlay\Lib\site-packages\mesonpy\__init__.py", line 417, in _install_path
          wheel_file.write(origin, destination.as_posix())
        File "C:\Users\Utente\AppData\Local\Temp\pip-build-env-doizkxdm\overlay\Lib\site-packages\mesonpy\_wheelfile.py", line 97, in write
          with open(filename, 'rb') as f:
               ^^^^^^^^^^^^^^^^^^^^
      FileNotFoundError: [Errno 2] No such file or directory: 'C:\\Users\\Utente\\Desktop\\meson-ctypes-test\\.mesonpy-tht_yopx\\sharedlibname.lib'
      [end of output]

  note: This error originates from a subprocess, and is likely not a problem with pip.
error: metadata-generation-faile
eli-schwartz commented 7 months ago

I believe your issue is because on Windows, you must annotate which symbols are public/private using __declspec dllimport/dllexport. Instead, right now, Unix compilers export all symbols by default and Microsoft compilers export no symbols.

No symbols equals no functional library, but the Microsoft compiler won't warn you that that is the case, even when silently refusing to create the implib.

peppedilillo commented 7 months ago

This seems to indeed be the case, changing the header to the following seems to solve the problem. My bad (and goddamn windows). Thank you.

#ifndef _TEST_CTYPES_H_
#define _TEST_CTYPES_H_
#include <stdint.h>

#if defined(_WIN32)
#  define DLL00_EXPORT_API __declspec(dllexport)
#else
#  define DLL00_EXPORT_API
#endif

enum errors {
    NO_ERRORS,
    EMPTY_ARRAY
};

struct Result {
    double mean;
};

DLL00_EXPORT_API enum errors calculateMean(struct Result *result, const int32_t *array, size_t length);

#endif //_TEST_CTYPES_H_
rgommers commented 7 months ago

Great, problem solved! Thanks @eli-schwartz and @peppedilillo