CIL icon indicating copy to clipboard operation
CIL copied to clipboard

ctests fail on Windows due to module problem

Open KrisThielemans opened this issue 8 months ago • 21 comments

I'm building CIL on Windows (!) with the SIRF-SuperBuild and conda according to https://github.com/SyneRBI/SIRF/wiki/Building-SIRF-and-CIL-with-conda.

After https://github.com/SyneRBI/SIRF-SuperBuild/pull/950 , it succesfully builds and installs, and imports (yay!). However, ctest fails for all tests with always the same error:

======================================================================
ERROR: test_TranslateFunction (unittest.loader._FailedTest.test_TranslateFunction)
----------------------------------------------------------------------
ImportError: Failed to import test module: test_TranslateFunction
Traceback (most recent call last):
  File "C:\Users\krisf\miniconda3\envs\cilsirfbuild\Lib\unittest\loader.py", line 396, in _find_test_path
    module = self._get_module_from_name(name)
  File "C:\Users\krisf\miniconda3\envs\cilsirfbuild\Lib\unittest\loader.py", line 339, in _get_module_from_name
    __import__(name)
    ~~~~~~~~~~^^^^^^
  File "C:\Users\krisf\Documents\devel\buildConda2\sources\CIL\Wrappers\Python\test\test_TranslateFunction.py", line 20, in <module>
    from utils import initialise_tests
  File "C:\Users\krisf\Documents\devel\buildConda2\sources\CIL\Wrappers\Python\test\utils.py", line 95, in <module>
    from cil.framework import cilacc
  File "C:\Users\krisf\miniconda3\envs\cilsirfbuild\Lib\site-packages\cil\framework\__init__.py", line 19, in <module>
    from .cilacc import cilacc
  File "C:\Users\krisf\miniconda3\envs\cilsirfbuild\Lib\site-packages\cil\framework\cilacc.py", line 33, in <module>
    cilacc = ctypes.cdll.LoadLibrary(dll)
  File "C:\Users\krisf\miniconda3\envs\cilsirfbuild\Lib\ctypes\__init__.py", line 471, in LoadLibrary
    return self._dlltype(name)
           ~~~~~~~~~~~~~^^^^^^
  File "C:\Users\krisf\miniconda3\envs\cilsirfbuild\Lib\ctypes\__init__.py", line 380, in __init__
    if '/' in name or '\\' in name:
       ^^^^^^^^^^^
TypeError: argument of type 'NoneType' is not iterable

We're currently using 4f6e3cfb0648d08071974eba35c1369a892d4924 by default, but the same problem occurs with master.

KrisThielemans avatar Apr 13 '25 23:04 KrisThielemans

It's imported from here:

https://github.com/TomographicImaging/CIL/blob/c10f3de6a8d2cea7f2bdbfc6b6f05ce70b31ebdb/Wrappers/Python/cil/framework/cilacc.py#L25-L27

I'm not sure if find_library is looking in the wrong place, or your build is putting the dll in the wrong place, or not setting PATH.

gfardell avatar Apr 22 '25 09:04 gfardell

This is a python runtime error, so nothing to do with cmake's find_library. Could be that the dll is not found, but AFAIK, we're just using CIL's install procedure, not our own.

Maybe had to do with python on Windows only importing DLLs from "approved" places.

KrisThielemans avatar Apr 23 '25 07:04 KrisThielemans

It's Python's ctypes.util.find_library (not CMake's find_library) failing to find the dll. Presumably SuperBuild/External_CIL.cmake is installing it in the wrong place.

Alternatively, if it's not super urgent, you could wait for CIL to implement #1875 first :)

casperdcl avatar Apr 23 '25 08:04 casperdcl

FYI @KrisThielemans - #2145 will make pip install cil possible in the SuperBuild; thus avoiding not only #2141 but also some dependency conflicts like https://github.com/SyneRBI/SIRF-SuperBuild/issues/935

casperdcl avatar Apr 23 '25 12:04 casperdcl

As indicated on the wiki page, I used

cmake -S ../SIRF-SuperBuild/ -B . -DCMAKE_INSTALL_PREFIX:PATH=$Env:CONDA_PREFIX/Library -DPYTHON_DEST_DIR:PATH=$Env:CONDA_PREFIX/lib/site-packages` -DCMAKE_PREFIX_PATH:PATH=$Env:CONDA_PREFIX <copy options from above>

Turns out that cilacc.dll is installed in $Env:CONDA_PREFIX\Library\Library\bin. Note the double Library\Library. It's the only file that is installed there.

Moving the DLL to $Env:CONDA_PREFIX/Library/bin resolves the import problem. If I then conda install -c conda-forge olefile dxchange, most tests worked (!), except CIL_FRAMEWORK_TESTS_3, 4 and 12 which say

Ran 0 tests in 0.000s

NO TESTS RAN

I also see

TEST SYSTEM CONFIGURATION
CIL version:  24.1.1.dev105+g4f6e3cfb.d20250413
{'has_astra': False,
 'has_ccpi_regularisation': True,
 'has_cvxpy': False,
 'has_ipp': False,
 'has_numba': True,
 'has_nvidia': False,
 'has_tigre': False,
 'has_tomophantom': True}

Maybe those tests depend on other stuff (which I'm not interested in).

Of course, I'm happy to wait for #2145.

KrisThielemans avatar May 02 '25 10:05 KrisThielemans

@KrisThielemans the wiki suggests to pass -DCMAKE_INSTALL_PREFIX:PATH="$CONDA_PREFIX".

But you seem to have passed -DCMAKE_INSTALL_PREFIX:PATH=$Env:CONDA_PREFIX/Library which may be the origin of the repeated Library?

paskino avatar May 02 '25 13:05 paskino

I've checked all of @TomographicImaging and can't find any reference to CONDA_PREFIX[/\\]Library (apart from perhaps CCPi-Regularisation-Toolkit#109/471509913 which doth not exist anymore).

You shouldn't need the /Library bit afaik @KrisThielemans

casperdcl avatar May 02 '25 15:05 casperdcl

I do need $Env:CONDA_PREFIX/Library on Windows, otherwise everything else gets installed in $Env:CONDA_PREFIX/ (lib and bin), and that bin directory doesn't even exist, i.e. conda installs all dlls and execs in $Env:CONDA_PREFIX/Library/bin.

Something somewhere must add the Library. I have no clue what.

KrisThielemans avatar May 02 '25 16:05 KrisThielemans

the wiki suggests to pass -DCMAKE_INSTALL_PREFIX:PATH="$CONDA_PREFIX".

only on Linux. For windows, the wiki says to use add Library. (I think you used it as well @paskino). I have no idea why the conda people decided to use different locations on Linux and Windows. Frustrating.

KrisThielemans avatar May 02 '25 16:05 KrisThielemans

@KrisThielemans could you try pip install "git+https://github.com/TomographicImaging/CIL@skbuild" instead of cmake? Hoping #2145 will put these hacky path handling issues to rest.

casperdcl avatar May 02 '25 16:05 casperdcl

I created a new conda env (with only python) and executed @casperdcl 's command.

Successfully installed cil-24.3.1.dev40+g6f78f052

great. However,

(ciltest) PS C:\Users\krisf\Documents\devel\stir-feedstock> python
Python 3.11.0 | packaged by conda-forge | (main, Oct 25 2022, 06:12:32) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import cil
>>> import cil.framework
Traceback (most recent call last):
  File "C:\Users\krisf\miniconda3\envs\ciltest\Lib\site-packages\cil\framework\cilacc.py", line 22, in <module>
    cilacc_path = next((Path(__file__).parent.parent / 'lib').resolve().glob("*cilacc.*"))
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
StopIteration

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\krisf\miniconda3\envs\ciltest\Lib\site-packages\cil\framework\__init__.py", line 19, in <module>
    from .cilacc import cilacc
  File "C:\Users\krisf\miniconda3\envs\ciltest\Lib\site-packages\cil\framework\cilacc.py", line 24, in <module>
    raise FileNotFoundError("cilacc library not found")
FileNotFoundError: cilacc library not found

I find it in C:\Users\krisf\miniconda3\envs\ciltest\Lib\site-packages\bin which is not in the path.

(ciltest)  echo $Env:Path
C:\Users\krisf\miniconda3\envs\cilsirfbuild\Library\bin;C:\Users\krisf\miniconda3\envs\ciltest;C:\Users\krisf\miniconda3\envs\ciltest\Library\mingw-w64\bin;C:\Users\krisf\miniconda3\envs\ciltest\Library\usr\bin;C:\Users\krisf\miniconda3\envs\ciltest\Library\bin;C:\Users\krisf\miniconda3\envs\ciltest\Scripts;C:\Users\krisf\miniconda3\envs\ciltest\bin;C:\Users\krisf\miniconda3\condabin;C:\WINDOWS\system32;C:\WINDOWS;<some more Windows stuff>

KrisThielemans avatar May 02 '25 18:05 KrisThielemans

Don't you have miniconda3\envs\ciltest\Lib\site-packages\cil\lib?

Could you post the verbose output (pip install --verbose "git+https://github.com/TomographicImaging/CIL@skbuild")?

Meanwhile miniconda3\envs\ciltest\Lib\site-packages\bin\*cil* should not exist and hopefully is just leftover from a previous (non-pip) installation.

casperdcl avatar May 03 '25 03:05 casperdcl

I created a new env, to be sure, as ciltest might have existed. For that, I have $Env:CONDA_PREFIX/Lib/site-packages/bin/cilacc.dll and $Env:CONDA_PREFIX/Lib/site-packages/lib/cilacc.lib while

>>> (pathlib.Path(r"C:\Users\krisf\miniconda3\envs\ciltest2\Lib\site-packages\cil\framework\cilacc.py").parent.parent / 'lib').resolve()
WindowsPath('C:/Users/krisf/miniconda3/envs/ciltest2/Lib/site-packages/cil/lib')

So, the cilacc.lib/dll are not installed in the correct place.

some output of the pip install (let me know if you need more)

  Running command git rev-parse HEAD
  6f78f052bf68246d92f29fc812ba36ffd6fca382
  Running command Building wheel for cil (pyproject.toml)
  *** scikit-build-core 0.11.2 using CMake 3.31.6 (wheel)
  *** Configuring CMake...
  2025-05-03 23:18:17,905 - scikit_build_core - WARNING - Can't find a Python library, got libdir=None, ldlibrary=None, multiarch=None, masd=None
  loading initial cache file C:\Users\krisf\AppData\Local\Temp\tmp1vix7db7\build\CMakeInit.txt
  -- Building for: Visual Studio 16 2019
  CMake Deprecation Warning at CMakeLists.txt:21 (cmake_minimum_required):
    Compatibility with CMake < 3.10 will be removed from a future version of
    CMake.

    Update the VERSION argument <min> value.  Or, use the <min>...<max> syntax
    to tell CMake that the project requires at least <min> but has been updated
    to work with policies introduced by <max> or earlier.


  -- Selecting Windows SDK version 10.0.18362.0 to target Windows 10.0.22631.
  -- The CXX compiler identification is MSVC 19.29.30138.0
  -- Detecting CXX compiler ABI info
  -- Detecting CXX compiler ABI info - done
  -- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.29.30133/bin/Hostx64/x64/cl.exe - skipped
  -- Detecting CXX compile features
  -- Detecting CXX compile features - done
  OpenMP_CXX_FLAGS
  -- Found OpenMP_CXX: -openmp (found version "2.0")
  -- Found OpenMP: TRUE (found version "2.0")
  CMAKE_CXX_FLAGS /DWIN32 /D_WINDOWS /W3 /GR /EHsc
  CMAKE_EXE_LINKER_FLAGS /machine:x64
  CMAKE_SHARED_LINKER_FLAGS /machine:x64
  CMAKE_STATIC_LINKER_FLAGS /machine:x64
  -- IPP not found
  CMake Warning at src/Core/CMakeLists.txt:64 (message):
    IPP libraries not found, FBP_filtering not in build


  -- Configuring done (15.8s)
  -- Generating done (0.1s)
  -- Build files have been written to: C:/Users/krisf/AppData/Local/Temp/tmp1vix7db7/build
  *** Building project with Visual Studio 16 2019...
  Microsoft (R) Build Engine version 16.11.2+f32259642 for .NET Framework
  Copyright (C) Microsoft Corporation. All rights reserved.

  C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Microsoft\VC\v160\Microsoft.CppBuild.targets(517,5): warning MSB8029: The Intermediate directory or Output directory cannot reside under the Temporary directory as it could lead to issues with incremental build. [C:\Users\krisf\AppData\Local\Temp\tmp1vix7db7\build\ZERO_CHECK.vcxproj]
    1>Checking Build System
  C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Microsoft\VC\v160\Microsoft.CppBuild.targets(517,5): warning MSB8029: The Intermediate directory or Output directory cannot reside under the Temporary directory as it could lead to issues with incremental build. [C:\Users\krisf\AppData\Local\Temp\tmp1vix7db7\build\src\Core\cilacc.vcxproj]
    Building Custom Rule C:/Users/krisf/AppData/Local/Temp/pip-req-build-600dgm4r/src/Core/CMakeLists.txt
    utilities.cpp
    axpby.cpp
    FiniteDifferenceLibrary.cpp

<snip load of warnings on unsigned int etc>

    Generating Code...
       Creating library C:/Users/krisf/AppData/Local/Temp/tmp1vix7db7/build/src/Core/Release/cilacc.lib and object C:/Users/krisf/AppData/Local/Temp/tmp1vix7db7/build/src/Core/Release/cilacc.exp
    cilacc.vcxproj -> C:\Users\krisf\AppData\Local\Temp\tmp1vix7db7\build\src\Core\Release\cilacc.dll
  C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Microsoft\VC\v160\Microsoft.CppBuild.targets(517,5): warning MSB8029: The Intermediate directory or Output directory cannot reside under the Temporary directory as it could lead to issues with incremental build. [C:\Users\krisf\AppData\Local\Temp\tmp1vix7db7\build\ALL_BUILD.vcxproj]
    Building Custom Rule C:/Users/krisf/AppData/Local/Temp/pip-req-build-600dgm4r/CMakeLists.txt
  *** Installing project into wheel...
  -- Installing: C:\Users\krisf\AppData\Local\Temp\tmp1vix7db7\wheel\platlib/lib/cilacc.lib
  -- Installing: C:\Users\krisf\AppData\Local\Temp\tmp1vix7db7\wheel\platlib/bin/cilacc.dll
  -- Installing: C:\Users\krisf\AppData\Local\Temp\tmp1vix7db7\wheel\platlib/cil/include/cil
  -- Installing: C:\Users\krisf\AppData\Local\Temp\tmp1vix7db7\wheel\platlib/cil/include/cil/axpby.h
  -- Installing: C:\Users\krisf\AppData\Local\Temp\tmp1vix7db7\wheel\platlib/cil/include/cil/Binning.h
  -- Installing: C:\Users\krisf\AppData\Local\Temp\tmp1vix7db7\wheel\platlib/cil/include/cil/dll_export.h
  -- Installing: C:\Users\krisf\AppData\Local\Temp\tmp1vix7db7\wheel\platlib/cil/include/cil/FBP_filtering.h
  -- Installing: C:\Users\krisf\AppData\Local\Temp\tmp1vix7db7\wheel\platlib/cil/include/cil/FiniteDifferenceLibrary.h
  -- Installing: C:\Users\krisf\AppData\Local\Temp\tmp1vix7db7\wheel\platlib/cil/include/cil/utilities.h
  *** Making wheel...

KrisThielemans avatar May 03 '25 22:05 KrisThielemans

So, the cilacc.lib/dll are not installed in the correct place.

Manually moving lib and bin subdirs inside cil gives

>>> import cil.framework
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\krisf\miniconda3\envs\ciltest2\Lib\site-packages\cil\framework\__init__.py", line 19, in <module>
    from .cilacc import cilacc
  File "C:\Users\krisf\miniconda3\envs\ciltest2\Lib\site-packages\cil\framework\cilacc.py", line 25, in <module>
    cilacc = ctypes.cdll.LoadLibrary(str(cilacc_path))
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\krisf\miniconda3\envs\ciltest2\Lib\ctypes\__init__.py", line 454, in LoadLibrary
    return self._dlltype(name)
           ^^^^^^^^^^^^^^^^^^^
  File "C:\Users\krisf\miniconda3\envs\ciltest2\Lib\ctypes\__init__.py", line 376, in __init__
    self._handle = _dlopen(self._name, mode)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^
OSError: [WinError 193] %1 is not a valid Win32 application

This is not surprising, as cillacc.lib is now found, but the DLL is not in anywhere in the Windows PATH (see above for what that is).

KrisThielemans avatar May 04 '25 07:05 KrisThielemans

Going back to current master

I've checked all of @TomographicImaging and can't find any reference to CONDA_PREFIX[/\\]Library

You shouldn't need the /Library bit afaik @KrisThielemans

https://github.com/TomographicImaging/CIL/blob/e88749677cd55a15a4d12810780a3e125aba09d2/src/Core/CMakeLists.txt#L86-L93 This was introduced in #749 but is incorrect IMO. It was presumably a work-around for an install on conda when using CMAKE_INSTALL_PREFIX=$Env:CONDA_PREFIX, but the Library prefix would only be appropriate for conda.

KrisThielemans avatar May 04 '25 07:05 KrisThielemans

Checking conda docs, https://conda-forge.org/docs/maintainer/knowledge_base/#simple-cmake-based-bldbat says to use

cmake -DCMAKE_INSTALL_PREFIX:PATH="%LIBRARY_PREFIX%" ^
      -DCMAKE_PREFIX_PATH:PATH="%LIBRARY_PREFIX%"

https://docs.conda.io/projects/conda-build/en/latest/user-guide/environment-variables.html says

Unix-style packages on Windows, which are usually statically linked to executables, are built in a special Library directory under the host prefix.

and that LIBRARY_PREFIX=%PREFIX%\Library.

This is what the STIR feedstock does. STIR's CMakeLists.txt don't know anything about conda (nor should it) and just uses CMAKE_INSTALL_PREFIX.

Another example, ISMRMRD uses CMAKE_INSTALL_LIBDIR which is relative to CMAKE_INSTALL_PREFIX.

So, forcing Library is a bug IMO.

(I have no idea where one should put libraries and dlls with skbuild, and will leave that up to @casperdcl ).

KrisThielemans avatar May 04 '25 07:05 KrisThielemans

@KrisThielemans can you try the pip install again? I just updated the RUNTIME path.

casperdcl avatar May 05 '25 06:05 casperdcl

@KrisThielemans can you try the pip install again? I just updated the RUNTIME path.

That worked. The DLL is now in $Env:CONDA_PREFIX\Lib\site-packages\cil\lib, and there's no .lib anymore.

I mean import cil.framework worked. I have no idea how to run tests in the pip installed version.

KrisThielemans avatar May 05 '25 07:05 KrisThielemans

So, what's the timeline on #2145 ? Should the bug introduced in #749 be fixed, or #2145 will be merged for the next release anyway?

KrisThielemans avatar May 05 '25 07:05 KrisThielemans

#2145 should be immiment so no point addressing #749.

You can actually help get it merged by confirming the tests work for you!

git clone https://github.com/TomographicImaging/CIL --branch skbuild
cd CIL
pip install -U pip
pip install . --group test
python -m unittest discover -v ./Wrappers/Python/test

casperdcl avatar May 05 '25 12:05 casperdcl

You can actually help get it merged by confirming the tests work for you!

it didn't work... I'll put this in #2145 as it no longer seems appropriate here.

However, I'm hoping that you guys can test this further as I've run out of time really. (It's just a miniconda install on Windows 11...)

KrisThielemans avatar May 05 '25 22:05 KrisThielemans