Skip to content

Commit b797a0c

Browse files
authored
TST: Add cygwin build to CI (numpy#18330)
* TST: Try to set up a test environment on Cygwin. Edit: Fix spelling of "pull request" TST: Follow workflow for other OSs using commands available on Cygwin. Other GitHub actions set fetch-depth to zero and use ./.github/actions for the actual testing. Let's see if this works. Edit: Drop shell from the last step in the action. Apparently "shell" isn't valid for steps. I hope the action knows to use bash rather than Power Shell or cmd.exe, or this is going to get very confused. TST: Adjust for cygwin The action assumes `sudo` exists, which is a bit of a problem. TST: Fetch with Cygwin git Make sure Cygwin git can access the repository. Versioneer depends on git, so this is kind of important. Edit: Include closing quote. Edit: Install Cygwin git. Versioneer needs this in order to function. Edit: FIXUP: build_src option is not spelled --verbose-config It's --verbose-cfg. TST: Check which version of Python is being used. I want to be sure it's a Cygwin one, not a Windows one. TST: Build a wheel for Cygwin. I may need to install in a virtualenv, and installing from a wheel is much faster than installing from a directory. TST: Use runtests.py to build the extensions. It couldn't find them during the tests, which is not a problem I've run into locally. Hopefully this fixes that. TST: Drop separate build step. TST: Cygwin CI: Install numpy and run tests from that. Running with runtests.py didn't work, but this should. TST: Add cygwin bin dir to path, not root dir. TST: Make sure Cygwin build fails when tests fail The tests managed to pass despite NumPy not importing. This is not a good thing. TST: Avoid steps after tests in Cygwin CI. I really need this to fail if NumPy doesn't import. TST: Ensure Cygwin CI is running in Cygwin. Kinda defeats the point if it's not. TST: Check that pip installed the C extensions. This really shouldn't need to be checked, but the CI runs have been failing due to a failed import of a C extension. I also printed the version, which will make me feel better about the right version being found and used. TST: Include closing quote in test command TST: Report loaded modules Still trying to find why the C extension module import fails. TST: Check permissions on NumPy C extensions TST: Ask python which files it's trying to load. Hopefully this gives me a general direction for where to look for "Cannot find file or directory" TST: Work around powershell syntax weirdness Drop a level of quoting and just write the command to a file, then run that. It should still show DLL permissions. TST: Fix line endings in script. bash expects \n powershell creates \r\n TST: Check for DLLs required by C extensions in Cygwin CI. It's still not working; hopefully this shows why. TST: Add import checks to the dll testing. I have a project where `python -c 'import module'` worked but `pytest --pyargs module` did not. Lets see if that happens here. Allow for global installs The runners have global install privileges, so pip will install NumPy there. I need to account for that in my script. Fix sed regex. Lots of leaning-toothpick syndrome, but it actually does what it's supposed to locally. Hopefully the CI agrees. Stop trying to import NumPy modules from sourcedir This doesn't work and hasn't for a while. TST: Simplify PATH and make sure lapack is on it. Most recent CI run said it couldn't find lapack. Reduce PATH to just Cygwin directories, make sure /usr/lib/lapack is included (after /usr/bin), and try again. Shortening PATH occasionally fixes some other problems. Let's see if that works here. TST: Change Cygwin CI python from 3.8 to 3.7 Let's see if this solves the problems. There was a change in DLL load path handling in 3.8 that might be causing the "cannot load numpy.linalg.lapack_lite" errors. TST: Stop running CI on PR branch. STY: Wrap long lines in Cygwin workflow file. TST: Update name of "main" branch used to trigger workflow. I forgot this changed a while back. TST: Specify full paths for commands. Also use dash in more places. TST: Change the newline-escape mechanism in Cygwin workflow. Backslash is apparently difficult. This reduces that step to a single command and tells YAML the string is to be interpreted as a single line. TST: Move the test command onto one line so GitHub can read it. Apparently the GitHub Actions YAML parser is incomplete. It should be reading what was there as a single-line string with no linebreak at the end and all linebreaks in the middle replaced by spaces. It seems to have parsed this as two lines. Does GitHub have a document saying which subset of YAML they actually recognize? TST: Add dependency on importlib-metadata. Pytest didn't declare it. TST: Move importlib-metadata earlier in install list. I hope this means it actually gets installed. The manager is ignoring it right now. TST: Add zipp to the package install list. Also tell pip to install the test_requirements, so I don't keep running into this problem. TST: Specify full path to python for testing. I apparently missed this earlier. TST: Add CFFI and pytz to Cygwin test environment. TST: Set global path to include /usr/lib/lapack. I'd forgotten there was a line for this already. TST: Shorten and unpin the Cygwin test requirements. I don't want to build more modules than I have to. It works fine on my machine with the system setuptools, pytz, and CFFI as well as system-ish Cython, so it should work fine on the CI runners. TST: Make sure test requirements are actually installed. Apparently pytest->importlib_metadata->"typing_extensions; python_version <= 3.7" isn't a declared dependency chain. Mentioning the last two explicitly should get them installed anyway. TST: Fix quoting in command line. * TST: Clean up the output from the extension module check. Also serves to document the script a bit. * BLD: Tell NumPy about functions that cause test failures. Several of the test failures still happen. I'm not entirely sure why. BLD: Add more functions to the Cygwin replace list. These functions are mentioned in test failures, so I mark them for replacement, along with the more obvious functions that might get called by functions that continue to fail. TST: List more functions to be replaced on Cygwin. casin and casinf don't pass the branch cut tests. Let's see if replacing them lets the test pass on CI. TST: Mark more functions to be replaced on Cygwin. I tried to note the tests each function fails by group, but I don't remember all of them anymore. Let's see if casin{,f,l} gets replaced on the CI runner. BLD: Mark more functions for replacement on Cygwin. I probably need to run `git clean` to see improvements locally. BLD:List more functions to be replaced on Cygwin. This is nearly the last of them. There are still a few failures I don't know how to deal with. The cabsl/hypotl overflows will be gone next Cygwin update. I may have an idea for cpowl (if cpowl(x, n) == cexpl(n*clogl(x))) I don't understand timezones, CFFI, or LAPACK, and that's the rest of the failures. BLD: Change list of functions marked for replacement on Cygwin. I hoped this would convince `cpowl` to flag its overflows, but that doesn't appear to have happened. * TST: Return to requirements in test_requirements.txt There will probably be compilation involved for coverage (from pytest-cov), maybe also cython, but the rest look like pure python and should be fast. * BLD: Export random distribution functions on Cygwin. CFFI should be able to find them now. The Cygwin runtime DLL loader is the Windows one, and the linker also shares most of the same semantics. * BUG: Set default hypotl to use npy_longdouble arithmetic. The implementation is already there, and the tests require npy_longdouble arithmetic, so I set up the boilerplate to make it so. It seems to fix only np.abs(npy_clongdouble), not abs(npy_clongdouble), for reasons I don't understand. * Go back to old npy_hypotl and mark the failing test case. * Undo the remaining changes from "SIMD: Force inlining all functions that accept AVX registers" These changes are not present in `main`. I see no commits likely to have specifically changed whether these SIMD functions are inlined. Adding these back to `main` is left for another PR. The symptoms I saw were segfaults, basically because function calls do not preserve alignment information. * Revert "Undo the remaining changes from "SIMD: Force inlining all functions that accept AVX registers"" This reverts commit bbd571a. That commit was original to this branch, but is now in main, so undoing it is a bad idea. * TST: Move the DLL checker to a separate script Instead of trying to write it every run, just add it to the repository and use that. I'm not sure how Windows git handles line endings; I suspect it changes things to \r\n, which is not what I want. I'm on Cygwin, not MSYS, so everything expects \n. * TST: Prettify the cabsl test xfail declaration. Marking this in the parametrize call gets really big. Moving this inside the function is much shorter, even if it won't tell me when a new Cygwin release makes this obsolete. Since this only needs to wait for one Cygwin release, I suppose that's not much of a stretch. * Wrap long line and change condition order. I want the `sys.platform == "cygwin"` check before I try to access `np.clongdouble`, so the check doesn't crash the test on platforms where np.clongdouble doesn't exist.
1 parent 2a6a8f5 commit b797a0c

File tree

5 files changed

+159
-1
lines changed

5 files changed

+159
-1
lines changed

.github/workflows/cygwin.yml

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
name: Test on Cygwin
2+
on:
3+
push:
4+
branches:
5+
- main
6+
pull_request:
7+
branches:
8+
- main
9+
jobs:
10+
cygwin_build_test:
11+
runs-on: windows-latest
12+
steps:
13+
- uses: actions/checkout@v2
14+
with:
15+
submodules: recursive
16+
fetch-depth: 0
17+
- name: Install Cygwin
18+
uses: egor-tensin/setup-cygwin@v3
19+
with:
20+
platform: x64
21+
install-dir: 'C:\tools\cygwin'
22+
packages: >
23+
python37-devel python37-zipp python37-importlib-metadata
24+
python37-cython python37-pip python37-wheel python37-cffi
25+
python37-pytz python37-setuptools python37-pytest
26+
python37-hypothesis liblapack-devel libopenblas
27+
gcc-fortran git dash
28+
- name: Set Windows PATH
29+
uses: egor-tensin/cleanup-path@v1
30+
with:
31+
dirs: 'C:\tools\cygwin\bin;C:\tools\cygwin\lib\lapack'
32+
- name: Verify that bash is Cygwin bash
33+
run: |
34+
command bash
35+
bash -c "uname -svrmo"
36+
- name: Update with Cygwin git
37+
# fetch-depth=0 above should make this short.
38+
run: |
39+
dash -c "which git; /usr/bin/git fetch --all -p"
40+
- name: Verify python version
41+
# Make sure it's the Cygwin one, not a Windows one
42+
run: |
43+
dash -c "which python3.7; /usr/bin/python3.7 --version -V"
44+
- name: Build NumPy wheel
45+
run: |
46+
dash -c "/usr/bin/python3.7 -m pip install 'setuptools<49.2.0' pytest pytz cffi pickle5 importlib_metadata typing_extensions"
47+
dash -c "/usr/bin/python3.7 -m pip install -r test_requirements.txt"
48+
dash -c "/usr/bin/python3.7 setup.py bdist_wheel"
49+
- name: Install new NumPy
50+
run: |
51+
bash -c "/usr/bin/python3.7 -m pip install dist/numpy-*cp37*.whl"
52+
- name: Run NumPy test suite
53+
run: >-
54+
dash -c "/usr/bin/python3.7 runtests.py -n -vv"
55+
- name: Upload wheel if tests fail
56+
uses: actions/upload-artifact@v2
57+
if: failure()
58+
with:
59+
name: numpy-cygwin-wheel
60+
path: dist/numpy-*cp37*.whl
61+
- name: On failure check the extension modules
62+
if: failure()
63+
run: |
64+
dash -c "/usr/bin/python3.7 -m pip show numpy"
65+
dash -c "/usr/bin/python3.7 -m pip show -f numpy | grep .dll"
66+
dash -c "/bin/tr -d '\r' <tools/list_installed_dll_dependencies_cygwin.sh >list_dlls_unix.sh"
67+
dash "list_dlls_unix.sh"

numpy/core/include/numpy/random/distributions.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ extern "C" {
2828
#define RAND_INT_MAX INT64_MAX
2929
#endif
3030

31-
#ifdef _MSC_VER
31+
#if defined(_MSC_VER) || defined(__CYGWIN__)
3232
#define DECLDIR __declspec(dllexport)
3333
#else
3434
#define DECLDIR extern

numpy/core/src/common/npy_config.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,51 @@
9696
#undef HAVE_POWL
9797
#endif
9898

99+
#ifdef __CYGWIN__
100+
/* Loss of precision */
101+
#undef HAVE_CASINHL
102+
#undef HAVE_CASINH
103+
#undef HAVE_CASINHF
104+
105+
/* Loss of precision */
106+
#undef HAVE_CATANHL
107+
#undef HAVE_CATANH
108+
#undef HAVE_CATANHF
109+
110+
/* Loss of precision and branch cuts */
111+
#undef HAVE_CATANL
112+
#undef HAVE_CATAN
113+
#undef HAVE_CATANF
114+
115+
/* Branch cuts */
116+
#undef HAVE_CACOSHF
117+
#undef HAVE_CACOSH
118+
119+
/* Branch cuts */
120+
#undef HAVE_CSQRTF
121+
#undef HAVE_CSQRT
122+
123+
/* Branch cuts and loss of precision */
124+
#undef HAVE_CASINF
125+
#undef HAVE_CASIN
126+
#undef HAVE_CASINL
127+
128+
/* Branch cuts */
129+
#undef HAVE_CACOSF
130+
#undef HAVE_CACOS
131+
132+
/* log2(exp2(i)) off by a few eps */
133+
#undef HAVE_LOG2
134+
135+
/* np.power(..., dtype=np.complex256) doesn't report overflow */
136+
#undef HAVE_CPOWL
137+
#undef HAVE_CEXPL
138+
139+
/* Builtin abs reports overflow */
140+
#undef HAVE_CABSL
141+
#undef HAVE_HYPOTL
142+
#endif
143+
99144
/* Disable broken gnu trig functions */
100145
#if defined(HAVE_FEATURES_H)
101146
#include <features.h>

numpy/core/tests/test_scalarmath.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -680,10 +680,18 @@ def _test_abs_func(self, absfunc, test_dtype):
680680

681681
@pytest.mark.parametrize("dtype", floating_types + complex_floating_types)
682682
def test_builtin_abs(self, dtype):
683+
if sys.platform == "cygwin" and dtype == np.clongdouble:
684+
pytest.xfail(
685+
reason="absl is computed in double precision on cygwin"
686+
)
683687
self._test_abs_func(abs, dtype)
684688

685689
@pytest.mark.parametrize("dtype", floating_types + complex_floating_types)
686690
def test_numpy_abs(self, dtype):
691+
if sys.platform == "cygwin" and dtype == np.clongdouble:
692+
pytest.xfail(
693+
reason="absl is computed in double precision on cygwin"
694+
)
687695
self._test_abs_func(np.abs, dtype)
688696

689697
class TestBitShifts:
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#!/bin/dash
2+
# Check permissions and dependencies on installed DLLs
3+
# DLLs need execute permissions to be used
4+
# DLLs must be able to find their dependencies
5+
# This checks both of those, then does a direct test
6+
# The best way of checking whether a C extension module is importable
7+
# is trying to import it. The rest is trying to give reasons why it
8+
# isn't importing.
9+
#
10+
# One of the tools and the extension for shared libraries are
11+
# Cygwin-specific, but the rest should work on most platforms with
12+
# /bin/sh
13+
14+
py_ver=3.7
15+
site_packages=$(python${py_ver} -m pip show numpy | \
16+
grep Location | cut -d " " -f 2 -);
17+
dll_list=$(for name in $(python${py_ver} -m pip show -f numpy | \
18+
grep -F .dll); do echo ${site_packages}/${name}; done)
19+
echo "Checks for existence, permissions and file type"
20+
ls -l ${dll_list}
21+
file ${dll_list}
22+
echo "Dependency checks"
23+
ldd ${dll_list} | grep -F -e " => not found" && exit 1
24+
cygcheck ${dll_list} >cygcheck_dll_list 2>cygcheck_missing_deps
25+
grep -F -e "cygcheck: track_down: could not find " cygcheck_missing_deps && exit 1
26+
echo "Import tests"
27+
mkdir -p dist/
28+
cd dist/
29+
for name in ${dll_list};
30+
do
31+
echo ${name}
32+
ext_module=$(echo ${name} | \
33+
sed -E \
34+
-e "s/^\/+(home|usr).*?site-packages\/+//" \
35+
-e "s/.cpython-3.m?-x86(_64)?-cygwin.dll$//" \
36+
-e "s/\//./g")
37+
python${py_ver} -c "import ${ext_module}"
38+
done

0 commit comments

Comments
 (0)