Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ci): support building python on windows #1885

Merged
merged 34 commits into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
f928890
feat(ci): support building python on windows
An-DJ Oct 14, 2024
375f5d7
Merge remote-tracking branch 'upstream/main' into python-win-build
An-DJ Nov 2, 2024
2647e8e
Empty-Commit
An-DJ Nov 2, 2024
939a37e
Empty-Commit
An-DJ Nov 2, 2024
3ee5666
fix(ci): use (git) bash to run python steps on Windows
An-DJ Nov 2, 2024
8085249
fix(ci): add conda/bin to Windows system path
An-DJ Nov 2, 2024
5e9a753
remove conda/bin from python ci windows runner
An-DJ Nov 2, 2024
eb6af9a
fix(cpp): add missing header
An-DJ Nov 2, 2024
0637214
fix(cpp): rename FuryLogLevel::ERROR to FuryLogLevel::ERR
An-DJ Nov 2, 2024
8efdc83
fix(python): rename pyx built dynamic lib name to '*.pyd'
An-DJ Nov 2, 2024
5ec5b12
fix(python): rename .so to .pyd on windows
An-DJ Nov 2, 2024
4d15089
fix(misc): add *.pyd to .gitignore
An-DJ Nov 2, 2024
fa649b9
fix wrong shell syntax
An-DJ Nov 2, 2024
f14f0f4
fix wrong shell syntax
An-DJ Nov 2, 2024
64b91bb
fix wrong shell syntax
An-DJ Nov 2, 2024
6582f9c
revert
An-DJ Nov 2, 2024
0bc925b
Merge remote-tracking branch 'upstream/main' into python-win-build
An-DJ Jan 19, 2025
40846ce
fix(ci): use different dtypes on Windows and *nix
An-DJ Jan 19, 2025
3778e0d
fix wrong variable name
An-DJ Jan 19, 2025
508a262
make lint happy
An-DJ Jan 19, 2025
7e64bde
fix bazel install error on windows
An-DJ Jan 19, 2025
9b2e9be
use bazelisk to manage bazel version
An-DJ Jan 20, 2025
cd6c554
skip install bazel manually on windows
An-DJ Jan 20, 2025
b8e4990
replace manual install with official bazel action
An-DJ Jan 20, 2025
f0dcf77
simplify serialize.py
An-DJ Jan 20, 2025
b3adbca
fix wrong bazel version on Windows
An-DJ Jan 20, 2025
9ab1b8c
Force to install old version bazel
An-DJ Jan 20, 2025
8547912
make lint happy
An-DJ Jan 20, 2025
1f57495
add numpy memoryview test
An-DJ Jan 20, 2025
aa104dc
fix wrong test
An-DJ Jan 20, 2025
7785cd2
fix missing import
An-DJ Jan 20, 2025
f97a643
fix wrong ci
An-DJ Jan 20, 2025
687b02e
remove useless dot file
An-DJ Jan 20, 2025
c11d467
Update python/pyfury/_util.pyx
chaokunyang Jan 20, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .bazelversion
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
6.3.2
12 changes: 10 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@
name: Rust CI
strategy:
matrix:
os: [ubuntu-latest, macos-13, macos-14] # macos-13: x86, macos-14: arm64

Check warning on line 188 in .github/workflows/ci.yml

View workflow job for this annotation

GitHub Actions / 🍏 YAML

188:49 [comments] too few spaces before comment
runs-on: ${{ matrix.os }}
timeout-minutes: 45
steps:
Expand All @@ -201,7 +201,7 @@
name: C++ CI
strategy:
matrix:
os: [ubuntu-latest, macos-13, macos-14, windows-2022] # macos-13: x86, macos-14: arm64

Check warning on line 204 in .github/workflows/ci.yml

View workflow job for this annotation

GitHub Actions / 🍏 YAML

204:63 [comments] too few spaces before comment
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
Expand All @@ -215,19 +215,27 @@
name: Python CI
# Fix python 3.6 install issue, see
# https://github.com/rwth-i6/returnn/commit/38ecab17d781c4b74db6a174c8097187380b4ddc
runs-on: ubuntu-20.04
runs-on: ${{ matrix.os }}
strategy:
matrix:
python-version: [3.8, 3.12]
os: [ubuntu-20.04, windows-2022]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install bazel
run: ./ci/run_ci.sh install_bazel
shell: bash
run: |
if [ "$RUNNER_OS" == "Windows" ]; then
./ci/run_ci.sh install_bazel_windows
else
./ci/run_ci.sh install_bazel
fi
- name: Run Python CI
shell: bash
run: ./ci/run_ci.sh python

go:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
**/*.cpp
**/*.so
**/*.dylib
**/*.pyd
bazel-*
.whl
python/.cache
Expand Down
17 changes: 13 additions & 4 deletions BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,19 @@ genrule(
set -e
set -x
WORK_DIR=$$(pwd)
cp -f $(location python/pyfury/_util.so) "$$WORK_DIR/python/pyfury"
cp -f $(location python/pyfury/lib/mmh3/mmh3.so) "$$WORK_DIR/python/pyfury/lib/mmh3"
cp -f $(location python/pyfury/format/_format.so) "$$WORK_DIR/python/pyfury/format"
cp -f $(location python/pyfury/_serialization.so) "$$WORK_DIR/python/pyfury"
u_name=`uname -s`
if [ "$${u_name: 0: 4}" == "MING" ] || [ "$${u_name: 0: 4}" == "MSYS" ]
then
cp -f $(location python/pyfury/_util.so) "$$WORK_DIR/python/pyfury/_util.pyd"
cp -f $(location python/pyfury/lib/mmh3/mmh3.so) "$$WORK_DIR/python/pyfury/lib/mmh3/mmh3.pyd"
cp -f $(location python/pyfury/format/_format.so) "$$WORK_DIR/python/pyfury/format/_format.pyd"
cp -f $(location python/pyfury/_serialization.so) "$$WORK_DIR/python/pyfury/_serialization.pyd"
else
cp -f $(location python/pyfury/_util.so) "$$WORK_DIR/python/pyfury"
cp -f $(location python/pyfury/lib/mmh3/mmh3.so) "$$WORK_DIR/python/pyfury/lib/mmh3"
cp -f $(location python/pyfury/format/_format.so) "$$WORK_DIR/python/pyfury/format"
cp -f $(location python/pyfury/_serialization.so) "$$WORK_DIR/python/pyfury"
fi
echo $$(date) > $@
""",
local = 1,
Expand Down
4 changes: 2 additions & 2 deletions ci/deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,8 @@ VERSIONS=("3.7"
"3.11"
"3.12")

source $(conda info --base)/etc/profile.d/conda.sh

create_py_envs() {
source $(conda info --base)/etc/profile.d/conda.sh
for version in "${VERSIONS[@]}"; do
conda create -y --name "py$version" python="$version"
done
Expand Down Expand Up @@ -94,6 +93,7 @@ deploy_jars() {
}

deploy_python() {
source $(conda info --base)/etc/profile.d/conda.sh
if command -v pyenv; then
pyenv local system
fi
Expand Down
6 changes: 6 additions & 0 deletions ci/run_ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@ install_bazel() {
fi
}

install_bazel_windows() {
choco install bazel --version=6.3.2 --force
VERSION=`bazel version`
echo "bazel version: $VERSION"
}

JDKS=(
"zulu21.28.85-ca-jdk21.0.0-linux_x64"
"zulu17.44.17-ca-crac-jdk17.0.8-linux_x64"
Expand Down
1 change: 1 addition & 0 deletions cpp/fury/thirdparty/MurmurHash3.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#define FORCE_INLINE __forceinline

#include <cstdint>
#include <cstdlib>

#define ROTL32(x, y) _rotl(x, y)
#define ROTL64(x, y) _rotl64(x, y)
Expand Down
4 changes: 2 additions & 2 deletions cpp/fury/util/logging.cc
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ std::string GetCallTrace() {

std::unordered_map<FuryLogLevel, std::string> log_level_to_str = {
{FuryLogLevel::DEBUG, "DEBUG"}, {FuryLogLevel::INFO, "INFO"},
{FuryLogLevel::WARNING, "WARNING"}, {FuryLogLevel::ERROR, "ERROR"},
{FuryLogLevel::WARNING, "WARNING"}, {FuryLogLevel::ERR, "ERROR"},
{FuryLogLevel::FATAL, "FATAL"},
};

Expand All @@ -77,7 +77,7 @@ FuryLogLevel FuryLog::GetLogLevel() {
} else if (data == "warning") {
severity_threshold = FuryLogLevel::WARNING;
} else if (data == "error") {
severity_threshold = FuryLogLevel::ERROR;
severity_threshold = FuryLogLevel::ERR;
} else if (data == "fatal") {
severity_threshold = FuryLogLevel::FATAL;
} else {
Expand Down
2 changes: 1 addition & 1 deletion cpp/fury/util/logging.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ enum class FuryLogLevel {
DEBUG = -1,
INFO = 0,
WARNING = 1,
ERROR = 2,
ERR = 2,
Copy link
Member

@PragmaTwice PragmaTwice Dec 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename FuryLogLevel::ERROR to FuryLogLevel::ERR. I don't know why this enum make build failed, but it is successed if renaming it to FuryLogLevel::ERR

Could you attach the error message/log you face about the original ERROR identifier?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just took a glance, and I think that maybe the Cython generated code defines a macro named ERROR and it's included before this header so that weird thing happens. Not familiar with related code here, maybe @penguin-wwy has ideas about this.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from chatgpt:

MSVC and Macros: The MSVC environment automatically defines some macros that can interfere with your code. One such macro is ERROR, which is commonly defined within Windows headers or other libraries. When you use ERROR as a name for an enumeration or variable in your code, it collides with this pre-existing macro definition, causing syntax errors.

We can use ERR here, for better compatibility, maybe we should define the enum value with FURY prefix:

enum class FuryLogLevel {
  FURY_DEBUG = -1,
  FURY_INFO = 0,
  FURY_WARNING = 1,
  FURY_ERROR = 2,
  FURY_FATAL = 3
};

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea. Restyle it in #2016 . : )

FATAL = 3
};

Expand Down
10 changes: 10 additions & 0 deletions python/pyfury/_util.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,13 @@ from libcpp cimport bool as c_bool
from pyfury.includes.libutil cimport(
CBuffer, AllocateBuffer, GetBit, SetBit, ClearBit, SetBitTo, CStatus, StatusCode, utf16HasSurrogatePairs
)
import os

cdef int32_t max_buffer_size = 2 ** 31 - 1
cdef int UTF16_LE = -1

cdef c_bool _WINDOWS = os.name == 'nt'


@cython.final
cdef class Buffer:
Expand Down Expand Up @@ -686,6 +689,13 @@ cdef inline uint8_t* get_address(v):
signed_int_data = v
ptr = <uint8_t*>(&signed_int_data[0])
elif dtype == "l":
if _WINDOWS:
signed_int_data = v
ptr = <uint8_t*>(&signed_int_data[0])
else:
signed_long_data = v
ptr = <uint8_t*>(&signed_long_data[0])
elif dtype == "q":
signed_long_data = v
ptr = <uint8_t*>(&signed_long_data[0])
elif dtype == "f":
Expand Down
107 changes: 75 additions & 32 deletions python/pyfury/serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
BufferObject,
)

_WINDOWS = os.name == "nt"

from pyfury._serialization import ENABLE_FURY_CYTHON_SERIALIZATION

if ENABLE_FURY_CYTHON_SERIALIZATION:
Expand Down Expand Up @@ -420,33 +422,63 @@ def xread(self, buffer):


# Use numpy array or python array module.
typecode_dict = {
# use bytes serializer for byte array.
"h": (2, Int16ArrayType, TypeId.INT16_ARRAY),
"i": (4, Int32ArrayType, TypeId.INT32_ARRAY),
"l": (8, Int64ArrayType, TypeId.INT64_ARRAY),
"f": (4, Float32ArrayType, TypeId.FLOAT32_ARRAY),
"d": (8, Float64ArrayType, TypeId.FLOAT64_ARRAY),
}

typeid_code = {
TypeId.INT16_ARRAY: "h",
TypeId.INT32_ARRAY: "i",
TypeId.INT64_ARRAY: "l",
TypeId.FLOAT32_ARRAY: "f",
TypeId.FLOAT64_ARRAY: "d",
}
typecode_dict = (
{
# use bytes serializer for byte array.
"h": (2, Int16ArrayType, TypeId.INT16_ARRAY),
"i": (4, Int32ArrayType, TypeId.INT32_ARRAY),
"l": (8, Int64ArrayType, TypeId.INT64_ARRAY),
"f": (4, Float32ArrayType, TypeId.FLOAT32_ARRAY),
"d": (8, Float64ArrayType, TypeId.FLOAT64_ARRAY),
}
if not _WINDOWS
else {
"h": (2, Int16ArrayType, TypeId.INT16_ARRAY),
"l": (4, Int32ArrayType, TypeId.INT32_ARRAY),
"q": (8, Int64ArrayType, TypeId.INT64_ARRAY),
"f": (4, Float32ArrayType, TypeId.FLOAT32_ARRAY),
"d": (8, Float64ArrayType, TypeId.FLOAT64_ARRAY),
}
)

typeid_code = (
{
TypeId.INT16_ARRAY: "h",
TypeId.INT32_ARRAY: "i",
TypeId.INT64_ARRAY: "l",
TypeId.FLOAT32_ARRAY: "f",
TypeId.FLOAT64_ARRAY: "d",
}
if not _WINDOWS
else {
TypeId.INT16_ARRAY: "h",
TypeId.INT32_ARRAY: "l",
TypeId.INT64_ARRAY: "q",
TypeId.FLOAT32_ARRAY: "f",
TypeId.FLOAT64_ARRAY: "d",
}
)


class PyArraySerializer(CrossLanguageCompatibleSerializer):
typecode_dict = typecode_dict
typecodearray_type = {
"h": Int16ArrayType,
"i": Int32ArrayType,
"l": Int64ArrayType,
"f": Float32ArrayType,
"d": Float64ArrayType,
}
typecodearray_type = (
{
"h": Int16ArrayType,
"i": Int32ArrayType,
"l": Int64ArrayType,
"f": Float32ArrayType,
"d": Float64ArrayType,
}
if not _WINDOWS
else {
"h": Int16ArrayType,
"l": Int32ArrayType,
"q": Int64ArrayType,
"f": Float32ArrayType,
"d": Float64ArrayType,
}
)

def __init__(self, fury, ftype, type_id: str):
super().__init__(fury, ftype)
Expand Down Expand Up @@ -511,15 +543,26 @@ def read(self, buffer):


if np:
_np_dtypes_dict = {
# use bytes serializer for byte array.
np.dtype(np.bool_): (1, "?", BoolNDArrayType, TypeId.BOOL_ARRAY),
np.dtype(np.int16): (2, "h", Int16NDArrayType, TypeId.INT16_ARRAY),
np.dtype(np.int32): (4, "i", Int32NDArrayType, TypeId.INT32_ARRAY),
np.dtype(np.int64): (8, "l", Int64NDArrayType, TypeId.INT64_ARRAY),
np.dtype(np.float32): (4, "f", Float32NDArrayType, TypeId.FLOAT32_ARRAY),
np.dtype(np.float64): (8, "d", Float64NDArrayType, TypeId.FLOAT64_ARRAY),
}
_np_dtypes_dict = (
{
# use bytes serializer for byte array.
np.dtype(np.bool_): (1, "?", BoolNDArrayType, TypeId.BOOL_ARRAY),
np.dtype(np.int16): (2, "h", Int16NDArrayType, TypeId.INT16_ARRAY),
np.dtype(np.int32): (4, "i", Int32NDArrayType, TypeId.INT32_ARRAY),
np.dtype(np.int64): (8, "l", Int64NDArrayType, TypeId.INT64_ARRAY),
np.dtype(np.float32): (4, "f", Float32NDArrayType, TypeId.FLOAT32_ARRAY),
np.dtype(np.float64): (8, "d", Float64NDArrayType, TypeId.FLOAT64_ARRAY),
}
if not _WINDOWS
else {
np.dtype(np.bool_): (1, "?", BoolNDArrayType, TypeId.BOOL_ARRAY),
np.dtype(np.int16): (2, "h", Int16NDArrayType, TypeId.INT16_ARRAY),
np.dtype(np.int32): (4, "l", Int32NDArrayType, TypeId.INT32_ARRAY),
np.dtype(np.int64): (8, "q", Int64NDArrayType, TypeId.INT64_ARRAY),
np.dtype(np.float32): (4, "f", Float32NDArrayType, TypeId.FLOAT32_ARRAY),
np.dtype(np.float64): (8, "d", Float64NDArrayType, TypeId.FLOAT64_ARRAY),
}
)
else:
_np_dtypes_dict = {}

Expand Down
23 changes: 23 additions & 0 deletions python/pyfury/tests/test_serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import datetime
import gc
import io
import os
import pickle
import weakref
from enum import Enum
Expand Down Expand Up @@ -249,6 +250,28 @@ def test_array_serializer(language):
np.testing.assert_array_equal(new_arr, arr)


def test_numpy_array_memoryview():
_WINDOWS = os.name == "nt"
if _WINDOWS:
arr = np.array(list(range(10)), dtype="int32")
view = memoryview(arr)
assert view.format == "l"
assert view.itemsize == 4
arr = np.array(list(range(10)), dtype="int64")
view = memoryview(arr)
assert view.format == "q"
assert view.itemsize == 8
else:
arr = np.array(list(range(10)), dtype="int32")
view = memoryview(arr)
assert view.format == "i"
assert view.itemsize == 4
arr = np.array(list(range(10)), dtype="int64")
view = memoryview(arr)
assert view.format == "l"
assert view.itemsize == 8


def ser_de(fury, obj):
binary = fury.serialize(obj)
return fury.deserialize(binary)
Expand Down
Loading