diff --git a/.github/workflows/windows_meson.yml b/.github/workflows/windows_meson.yml new file mode 100644 index 000000000000..6be2af7e5e4e --- /dev/null +++ b/.github/workflows/windows_meson.yml @@ -0,0 +1,86 @@ +name: Test Meson build (Windows) + +on: + push: + branches: + - main + - maintenance/** + pull_request: + branches: + - main + - maintenance/** + +env: + PYTHON_VERSION: 3.11 + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +permissions: + contents: read # to fetch code (actions/checkout) + +jobs: + meson: + name: Meson windows build/test + runs-on: windows-2019 + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + submodules: recursive + fetch-depth: 0 + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: ${{ env.PYTHON_VERSION }} + + - name: Install dependencies + run: | + pip install -r build_requirements.txt + - name: openblas-libs + run: | + # Download and install pre-built OpenBLAS library + # with 32-bit interfaces + # Unpack it in the pkg-config hardcoded path + choco install unzip -y + choco install wget -y + choco install -y --checksum 6004DF17818F5A6DBF19CB335CC92702 pkgconfiglite + wget https://anaconda.org/multibuild-wheels-staging/openblas-libs/v0.3.21/download/openblas-v0.3.21-win_amd64-gcc_10_3_0.zip + unzip -d c:\opt openblas-v0.3.21-win_amd64-gcc_10_3_0.zip + echo "PKG_CONFIG_PATH=c:\opt\64\lib\pkgconfig;" >> $env:GITHUB_ENV + - name: meson-configure + run: | + meson setup build --prefix=$PWD\build-install -Ddebug=false --optimization 2 --vsenv + - name: meson-build + run: | + meson compile -C build -v + + - name: meson-install + run: | + cd build + meson install --no-rebuild + - name: build-path + run: | + echo "installed_path=$PWD\build-install\Lib\site-packages" >> $env:GITHUB_ENV + - name: post-install + run: | + $numpy_path = "${env:installed_path}\numpy" + $libs_path = "${numpy_path}\.libs" + mkdir ${libs_path} + $ob_path = "C:/opt/64/bin/" + cp $ob_path/*.dll $libs_path + # Write _distributor_init.py to load .libs DLLs. + python tools\openblas_support.py --write-init $numpy_path + + - name: prep-test + run: | + echo "PYTHONPATH=${env:installed_path}" >> $env:GITHUB_ENV + python -m pip install -r test_requirements.txt + python -m pip install threadpoolctl + - name: test + run: | + mkdir tmp + cd tmp + python -c"import numpy; print(numpy.show_runtime())" + python -c "import numpy; numpy.test(verbose=3)" diff --git a/numpy/core/meson.build b/numpy/core/meson.build index e094f9dabf66..651f7a00a775 100644 --- a/numpy/core/meson.build +++ b/numpy/core/meson.build @@ -589,11 +589,17 @@ c_args_common = [ ] # Same as NPY_CXX_FLAGS (TODO: extend for what ccompiler_opt adds) -cpp_args_common = c_args_common + [ - '-D__STDC_VERSION__=0', # for compatibility with C headers - '-fno-exceptions', # no exception support - '-fno-rtti', # no runtime type information -] +if cc.get_id() == 'msvc' + cpp_args_common = c_args_common + [ + '-D__STDC_VERSION__=0', # for compatibility with C headers + ] +else + cpp_args_common = c_args_common + [ + '-D__STDC_VERSION__=0', # for compatibility with C headers + '-fno-exceptions', # no exception support + '-fno-rtti', # no runtime type information + ] +endif # Other submodules depend on generated headers and include directories from # core, wrap those up into a reusable dependency. Also useful for some test diff --git a/numpy/meson.build b/numpy/meson.build index 0bb37f8c2ae2..76f3ee8bd3cd 100644 --- a/numpy/meson.build +++ b/numpy/meson.build @@ -30,6 +30,9 @@ if is_windows endif endif endif +if is_msvc + add_project_arguments('-DNDEBUG', language: ['c', 'cpp']) +endif # Enable UNIX large file support on 32-bit systems (64 bit off_t, # lseek -> lseek64, etc.) @@ -77,6 +80,9 @@ dependency_map = { # TODO: add ILP64 support have_blas = blas.found() # TODO: and blas.has_cblas() have_lapack = lapack.found() +if have_blas + add_project_arguments('-DHAVE_CBLAS', language: ['c', 'cpp']) +endif # Copy the main __init__.py|pxd files to the build dir (needed for Cython) __init__py = fs.copyfile('__init__.py') diff --git a/numpy/random/meson.build b/numpy/random/meson.build index cc61c66dd7fc..036cd81b9a2e 100644 --- a/numpy/random/meson.build +++ b/numpy/random/meson.build @@ -66,7 +66,7 @@ random_pyx_sources = [ fs.copyfile('mtrand.pyx'), 'src/distributions/distributions.c', 'src/legacy/legacy-distributions.c' - ], ['-DNPY_RANDOM_LEGACY=1'], npymath_lib, + ], ['-DNP_RANDOM_LEGACY=1'], npymath_lib, ], ] foreach gen: random_pyx_sources diff --git a/tools/openblas_support.py b/tools/openblas_support.py index bc81c5f68737..84567fffe0f5 100644 --- a/tools/openblas_support.py +++ b/tools/openblas_support.py @@ -232,36 +232,13 @@ def make_init(dirname): with open(os.path.join(dirname, '_distributor_init.py'), 'wt') as fid: fid.write(textwrap.dedent(""" ''' - Helper to preload windows dlls to prevent dll not found errors. - Once a DLL is preloaded, its namespace is made available to any - subsequent DLL. This file originated in the numpy-wheels repo, - and is created as part of the scripts that build the wheel. + Helper to add the path to the openblas dll to the dll search space ''' import os - import glob - if os.name == 'nt': - # convention for storing / loading the DLL from - # numpy/.libs/, if present - try: - from ctypes import WinDLL - basedir = os.path.dirname(__file__) - except: - pass - else: - libs_dir = os.path.abspath(os.path.join(basedir, '.libs')) - DLL_filenames = [] - if os.path.isdir(libs_dir): - for filename in glob.glob(os.path.join(libs_dir, - '*openblas*dll')): - # NOTE: would it change behavior to load ALL - # DLLs at this path vs. the name restriction? - WinDLL(os.path.abspath(filename)) - DLL_filenames.append(filename) - if len(DLL_filenames) > 1: - import warnings - warnings.warn("loaded more than 1 DLL from .libs:" - "\\n%s" % "\\n".join(DLL_filenames), - stacklevel=1) + import sys + extra_dll_dir = os.path.join(os.path.dirname(__file__), '.libs') + if sys.platform == 'win32' and os.path.isdir(extra_dll_dir): + os.add_dll_directory(extra_dll_dir) """)) @@ -343,9 +320,14 @@ def test_version(expected_version=None): parser.add_argument('--check_version', nargs='?', default='', help='Check provided OpenBLAS version string ' 'against available OpenBLAS') + parser.add_argument('--write-init', nargs=1, + metavar='OUT_SCIPY_DIR', + help='Write distribution init to named dir') args = parser.parse_args() if args.check_version != '': test_version(args.check_version) + elif args.write_init: + make_init(args.write_init[0]) elif args.test is None: print(setup_openblas()) else: