Skip to content

Commit b01942c

Browse files
authored
Build Windows CPU wheel (#753)
1 parent 3c865b2 commit b01942c

File tree

6 files changed

+207
-28
lines changed

6 files changed

+207
-28
lines changed
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
name: Build and test Windows wheel
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches:
7+
- nightly
8+
- main
9+
- release/*
10+
tags:
11+
- v[0-9]+.[0-9]+.[0-9]+-rc[0-9]+
12+
workflow_dispatch:
13+
14+
concurrency:
15+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref_name }}-${{ github.ref_type == 'branch' && github.sha }}-${{ github.event_name == 'workflow_dispatch' }}
16+
cancel-in-progress: true
17+
18+
permissions:
19+
id-token: write
20+
contents: write
21+
22+
defaults:
23+
run:
24+
shell: bash -l -eo pipefail {0}
25+
26+
jobs:
27+
28+
generate-matrix:
29+
uses: pytorch/test-infra/.github/workflows/generate_binary_build_matrix.yml@main
30+
with:
31+
package-type: wheel
32+
os: windows
33+
test-infra-repository: pytorch/test-infra
34+
test-infra-ref: main
35+
with-xpu: disable
36+
with-rocm: disable
37+
with-cuda: disable
38+
build-python-only: "disable"
39+
40+
build:
41+
needs: generate-matrix
42+
strategy:
43+
fail-fast: false
44+
name: Build and Upload Windows wheel
45+
# TODO: use @main
46+
uses: nicolashug/test-infra/.github/workflows/build_wheels_windows.yml@build-platform-windows
47+
with:
48+
repository: pytorch/torchcodec
49+
ref: ""
50+
test-infra-repository: nicolashug/test-infra
51+
test-infra-ref: build-platform-windows
52+
build-matrix: ${{ needs.generate-matrix.outputs.matrix }}
53+
pre-script: packaging/pre_build_script.sh
54+
# post-script: packaging/post_build_script.sh TODO: consider enabling post-build checks for Windows
55+
env-script: packaging/vc_env_helper.bat
56+
smoke-test-script: packaging/fake_smoke_test.py
57+
package-name: torchcodec
58+
trigger-event: ${{ github.event_name }}
59+
build-platform: "python-build-package"
60+
# The BUILD_AGAINST_ALL_FFMPEG_FROM_S3 var, needed to build the wheel, is
61+
# set in vc_env_helper.bat Couldn't find a way to set it from here.
62+
build-command: "python -m build --wheel -vvv --no-isolation"

packaging/vc_env_helper.bat

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ if "%VSDEVCMD_ARGS%" == "" (
2424
if "%CU_VERSION%" == "xpu" call "C:\Program Files (x86)\Intel\oneAPI\setvars.bat"
2525

2626
set DISTUTILS_USE_SDK=1
27+
set BUILD_AGAINST_ALL_FFMPEG_FROM_S3=1
2728

2829
set args=%1
2930
shift

setup.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,10 +155,10 @@ def copy_extensions_to_source(self):
155155
# dynamically loaded module. For more, see:
156156
# https://stackoverflow.com/a/2339910
157157
extensions = ["dylib", "so"]
158+
elif sys.platform in ("win32", "cygwin"):
159+
extensions = ["dll"]
158160
else:
159-
raise NotImplementedError(
160-
"Platforms other than linux/darwin are not supported yet"
161-
)
161+
raise NotImplementedError(f"Platform {sys.platform} is not supported")
162162

163163
for ext in extensions:
164164
for lib_file in self._install_prefix.glob(f"*.{ext}"):

src/torchcodec/_core/CMakeLists.txt

Lines changed: 57 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,29 @@ find_package(Python3 ${PYTHON_VERSION} EXACT COMPONENTS Development)
1111
if(DEFINED TORCHCODEC_DISABLE_COMPILE_WARNING_AS_ERROR AND TORCHCODEC_DISABLE_COMPILE_WARNING_AS_ERROR)
1212
set(TORCHCODEC_WERROR_OPTION "")
1313
else()
14-
set(TORCHCODEC_WERROR_OPTION "-Werror")
14+
if (WIN32)
15+
# TODO set warnings as errors on Windows as well.
16+
# set(TORCHCODEC_WERROR_OPTION "/WX")
17+
else()
18+
set(TORCHCODEC_WERROR_OPTION "-Werror")
19+
endif()
20+
endif()
21+
22+
if (WIN32)
23+
# Avoid warnings about non-ASCII characters in source files.
24+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4819")
25+
# Important for when we add Windows CUDA: exporting all symbols is limited to
26+
# 65535 symbols, which (apparently) will not work for CUDA.
27+
# https://github.com/pytorch/pytorch/pull/3650
28+
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
29+
endif()
30+
31+
if (WIN32)
32+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4 ${TORCHCODEC_WERROR_OPTION} ${TORCH_CXX_FLAGS}")
33+
else()
34+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic ${TORCHCODEC_WERROR_OPTION} ${TORCH_CXX_FLAGS}")
1535
endif()
1636

17-
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic ${TORCHCODEC_WERROR_OPTION} ${TORCH_CXX_FLAGS}")
1837

1938
function(make_torchcodec_sublibrary
2039
library_name
@@ -34,11 +53,26 @@ function(make_torchcodec_sublibrary
3453
# Avoid adding the "lib" prefix which we already add explicitly.
3554
set_target_properties(${library_name} PROPERTIES PREFIX "")
3655

56+
if(WIN32)
57+
# On Windows, the built artifacts are put in Release/Debug
58+
# subdirectories by default. We want to avoid that, otherwise our
59+
# install() step would not know where to find those.
60+
set_target_properties(${library_name} PROPERTIES
61+
RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR}
62+
RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_BINARY_DIR}
63+
LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR}
64+
LIBRARY_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_BINARY_DIR}
65+
ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR}
66+
ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_BINARY_DIR}
67+
)
68+
endif()
69+
3770
target_link_libraries(
3871
${library_name}
3972
PUBLIC
4073
${library_dependencies}
4174
)
75+
4276
endfunction()
4377

4478
function(make_torchcodec_libraries
@@ -144,11 +178,14 @@ function(make_torchcodec_libraries
144178
# stray initialization of py::objects. The rest of the object code must
145179
# match. See:
146180
# https://pybind11.readthedocs.io/en/stable/faq.html#someclass-declared-with-greater-visibility-than-the-type-of-its-field-someclass-member-wattributes
147-
target_compile_options(
148-
${pybind_ops_library_name}
149-
PUBLIC
150-
"-fvisibility=hidden"
151-
)
181+
if(NOT WIN32)
182+
target_compile_options(
183+
${pybind_ops_library_name}
184+
PUBLIC
185+
"-fvisibility=hidden"
186+
)
187+
endif()
188+
152189
# The value we use here must match the value we return from
153190
# _get_pybind_ops_module_name() on the Python side. If the values do not
154191
# match, then we will be unable to import the C++ shared library as a
@@ -158,14 +195,17 @@ function(make_torchcodec_libraries
158195
PRIVATE
159196
PYBIND_OPS_MODULE_NAME=core_pybind_ops
160197
)
161-
# If we don't make sure this flag is set, we run into segfauls at import
162-
# time on Mac. See:
163-
# https://github.com/pybind/pybind11/issues/3907#issuecomment-1170412764
164-
target_link_options(
165-
${pybind_ops_library_name}
166-
PUBLIC
167-
"LINKER:-undefined,dynamic_lookup"
168-
)
198+
199+
if(APPLE)
200+
# If we don't make sure this flag is set, we run into segfauls at import
201+
# time on Mac. See:
202+
# https://github.com/pybind/pybind11/issues/3907#issuecomment-1170412764
203+
target_link_options(
204+
${pybind_ops_library_name}
205+
PUBLIC
206+
"LINKER:-undefined,dynamic_lookup"
207+
)
208+
endif()
169209

170210
# Install all libraries.
171211
set(
@@ -183,7 +223,9 @@ function(make_torchcodec_libraries
183223
install(
184224
TARGETS ${all_libraries}
185225
LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}
226+
RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX} # For Windows DLLs
186227
)
228+
187229
endfunction()
188230

189231
if(DEFINED ENV{BUILD_AGAINST_ALL_FFMPEG_FROM_S3})

src/torchcodec/_core/fetch_and_expose_non_gpl_ffmpeg_libs.cmake

Lines changed: 81 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,20 @@ endif()
99

1010
include(FetchContent)
1111

12+
if (UNIX AND NOT APPLE)
13+
set(LINUX TRUE)
14+
else()
15+
set(LINUX FALSE)
16+
endif()
17+
1218
set(
1319
base_url
1420
https://pytorch.s3.amazonaws.com/torchcodec/ffmpeg/2025-03-14
1521
)
1622

17-
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
23+
if (LINUX)
24+
set(lib_dir "lib")
25+
1826
set(
1927
platform_url
2028
${base_url}/linux_x86_64
@@ -36,7 +44,6 @@ if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
3644
f7_sha256
3745
1cb946d8b7c6393c2c3ebe1f900b8de7a2885fe614c45d4ec32c9833084f2f26
3846
)
39-
4047
set(
4148
f4_library_file_names
4249
libavutil.so.56
@@ -77,7 +84,8 @@ if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
7784
libswscale.so.8
7885
libswresample.so.5
7986
)
80-
elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
87+
elseif (APPLE)
88+
set(lib_dir "lib")
8189
set(
8290
platform_url
8391
${base_url}/macos_arm64
@@ -98,6 +106,7 @@ elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
98106
f7_sha256
99107
48a4fc8ce098305cfd4a58f40889249c523ca3c285f66ba704b5bad0e3ada53a
100108
)
109+
101110
set(
102111
f4_library_file_names
103112
libavutil.56.dylib
@@ -138,6 +147,70 @@ elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
138147
libswscale.8.dylib
139148
libswresample.5.dylib
140149
)
150+
151+
elseif (WIN32)
152+
set(lib_dir "bin")
153+
set(
154+
platform_url
155+
${base_url}/windows_x86_64
156+
)
157+
set(
158+
f4_sha256
159+
270a1aa8892225267e68a7eb87c417931da30dccbf08ee2bde8833e659cab5cb
160+
)
161+
set(
162+
f5_sha256
163+
b8b2a349a847e56a6da875b066dff1cae53cb8ee7cf5ba9321ec1243dea0cde0
164+
)
165+
set(
166+
f6_sha256
167+
5d9f8c76dc55f790fa31d825985e9270bf9e498b8bfec21a0ad3a1feb1fa053a
168+
)
169+
set(
170+
f7_sha256
171+
ae391ace382330e912793b70b68529ee7c91026d2869b4df7e7c3e7d3656bdd5
172+
)
173+
174+
set(
175+
f4_library_file_names
176+
avutil.lib
177+
avcodec.lib
178+
avformat.lib
179+
avdevice.lib
180+
avfilter.lib
181+
swscale.lib
182+
swresample.lib
183+
)
184+
set(
185+
f5_library_file_names
186+
avutil.lib
187+
avcodec.lib
188+
avformat.lib
189+
avdevice.lib
190+
avfilter.lib
191+
swscale.lib
192+
swresample.lib
193+
)
194+
set(
195+
f6_library_file_names
196+
avutil.lib
197+
avcodec.lib
198+
avformat.lib
199+
avdevice.lib
200+
avfilter.lib
201+
swscale.lib
202+
swresample.lib
203+
)
204+
set(
205+
f7_library_file_names
206+
avutil.lib
207+
avcodec.lib
208+
avformat.lib
209+
avdevice.lib
210+
avfilter.lib
211+
swscale.lib
212+
swresample.lib
213+
)
141214
else()
142215
message(
143216
FATAL_ERROR
@@ -183,24 +256,25 @@ target_include_directories(ffmpeg5 INTERFACE ${f5_SOURCE_DIR}/include)
183256
target_include_directories(ffmpeg6 INTERFACE ${f6_SOURCE_DIR}/include)
184257
target_include_directories(ffmpeg7 INTERFACE ${f7_SOURCE_DIR}/include)
185258

259+
186260
list(
187261
TRANSFORM f4_library_file_names
188-
PREPEND ${f4_SOURCE_DIR}/lib/
262+
PREPEND ${f4_SOURCE_DIR}/${lib_dir}/
189263
OUTPUT_VARIABLE f4_library_paths
190264
)
191265
list(
192266
TRANSFORM f5_library_file_names
193-
PREPEND ${f5_SOURCE_DIR}/lib/
267+
PREPEND ${f5_SOURCE_DIR}/${lib_dir}/
194268
OUTPUT_VARIABLE f5_library_paths
195269
)
196270
list(
197271
TRANSFORM f6_library_file_names
198-
PREPEND ${f6_SOURCE_DIR}/lib/
272+
PREPEND ${f6_SOURCE_DIR}/${lib_dir}/
199273
OUTPUT_VARIABLE f6_library_paths
200274
)
201275
list(
202276
TRANSFORM f7_library_file_names
203-
PREPEND ${f7_SOURCE_DIR}/lib/
277+
PREPEND ${f7_SOURCE_DIR}/${lib_dir}/
204278
OUTPUT_VARIABLE f7_library_paths
205279
)
206280

src/torchcodec/_internally_replaced_utils.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ def _get_extension_path(lib_name: str) -> str:
1818
extension_suffixes = importlib.machinery.EXTENSION_SUFFIXES
1919
elif sys.platform == "darwin":
2020
extension_suffixes = importlib.machinery.EXTENSION_SUFFIXES + [".dylib"]
21+
elif sys.platform in ("win32", "cygwin"):
22+
extension_suffixes = importlib.machinery.EXTENSION_SUFFIXES + [".dll"]
2123
else:
22-
raise NotImplementedError(
23-
"Platforms other than linux/darwin are not supported yet"
24-
)
24+
raise NotImplementedError(f"{sys.platform = } is not not supported")
2525
loader_details = (
2626
importlib.machinery.ExtensionFileLoader,
2727
extension_suffixes,

0 commit comments

Comments
 (0)