Skip to content

Commit 1fc5a3f

Browse files
vpietila-amdUserafagaj
authored
Build CK on Windows (#3458)
* CMakeLists.txt hack for Windows. * Add Windows build instructions. * Fix type issue with variadic min function. * Use std::common_type to fix the variadic min/max functions. * Enable CPU guard compilation on Windows. * Suppress warnings related to std::getenv on Windows platform. * Git ignore the output directory on Windows platform. * Powershell script for running tests and generating reports. * Improve test logging. * Disable non-conv tests. * Fix Debug build on Windows. * More debug build changes. * Update Windows build instructions. * Enable all tests. * Test fixes. * Suppress not found linker options warning. * Update unsigned long literals and format specifiers to work correctly in Windows * Fix conv 3D bwd weight bilinear tests on Windows. * Revert changes on .gitignore. * Clean-up CMake project file for Windows builds. * clang-format * Fix definition of CMAKE_PREFIX_PATH on both Linux and Windows platforms. * Fix building examples on Windows. * Update Readme. * Remove the suppression of the deprecated warnings. * Remove Windows specific min/max implementations from CK Tile math core. * Remove unnecessary no-op on Windows. --------- Co-authored-by: User <user@example.com> Co-authored-by: Ville Pietilä <none> Co-authored-by: John Afaganis <john.afaganis@amd.com> Co-authored-by: Ville Pietilä <>
1 parent f173642 commit 1fc5a3f

7 files changed

Lines changed: 342 additions & 28 deletions

File tree

CMakeLists.txt

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,12 @@ endif()
3131
# Default installation path
3232
if(NOT WIN32)
3333
set(CMAKE_INSTALL_PREFIX "/opt/rocm" CACHE PATH "")
34+
else()
35+
set(CMAKE_INSTALL_PREFIX "C:/dist/TheRock" CACHE PATH "")
3436
endif()
3537

3638
set(version 1.2.0)
37-
# Check support for CUDA/HIP in Cmake
38-
project(composable_kernel VERSION ${version} LANGUAGES CXX HIP)
39+
project(composable_kernel VERSION ${version} LANGUAGES CXX)
3940
include(CTest)
4041

4142
option(ENABLE_CLANG_CPP_CHECKS "Enables clang tidy, cppcheck" ON)
@@ -162,7 +163,13 @@ execute_process(COMMAND "${GIT_EXECUTABLE}" rev-parse HEAD OUTPUT_VARIABLE COMMI
162163
configure_file(include/ck/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/include/ck/version.h)
163164

164165
set(ROCM_SYMLINK_LIBS OFF)
165-
find_package(ROCM REQUIRED PATHS /opt/rocm)
166+
167+
if (WIN32)
168+
find_package(ROCmCMakeBuildTools REQUIRED PATHS C:/dist/TheRock)
169+
set(HIP_PLATFORM "amd" CACHE STRING "HIP platform")
170+
else()
171+
find_package(ROCM REQUIRED PATHS /opt/rocm)
172+
endif()
166173

167174
include(ROCMInstallTargets)
168175
include(ROCMPackageConfigHelpers)
@@ -189,7 +196,10 @@ if(GPU_TARGETS)
189196
else()
190197
set(USER_GPU_TARGETS 0)
191198
endif()
199+
192200
find_package(hip REQUIRED)
201+
enable_language(HIP)
202+
193203
# No assumption that HIP kernels are launched with uniform block size for backward compatibility
194204
# SWDEV-413293 and https://reviews.llvm.org/D155213
195205
math(EXPR hip_VERSION_FLAT "(${hip_VERSION_MAJOR} * 1000 + ${hip_VERSION_MINOR}) * 100000 + ${hip_VERSION_PATCH}")

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,22 @@ Docker images are available on [DockerHub](https://hub.docker.com/r/rocm/composa
137137
```
138138
**[See Note on -j](#notes)**
139139
140+
### Building for Windows
141+
142+
Install TheRock and run CMake configure as
143+
144+
```bash
145+
cmake \
146+
-D CMAKE_PREFIX_PATH="C:/dist/TheRock" \
147+
-D CMAKE_CXX_COMPILER="C:/dist/TheRock/bin/hipcc.exe" \
148+
-D CMAKE_BUILD_TYPE=Release \
149+
-D GPU_TARGETS="gfx1151" \
150+
-G Ninja \
151+
..
152+
```
153+
154+
Use Ninja to build either the whole library or individual targets.
155+
140156
## Optional post-install steps
141157
142158
* Build examples and tests:

example/CMakeLists.txt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,35 @@ include_directories(BEFORE
66
${PROJECT_SOURCE_DIR}/library/include
77
)
88

9+
if(WIN32)
10+
# On Windows, HIP uses -nostdlib which prevents C runtime linking
11+
# We need legacy_stdio_definitions.lib to provide vfprintf and other legacy C functions
12+
# This is mainly needed for the getopt library.
13+
set(LEGACY_STDIO_SEARCH_PATHS)
14+
15+
# Try to use Visual C++ Tools environment variable (if build executes from Visual Studio Developer Command Prompt)
16+
if(DEFINED ENV{VCToolsInstallDir})
17+
list(APPEND LEGACY_STDIO_SEARCH_PATHS "$ENV{VCToolsInstallDir}/lib/x64")
18+
endif()
19+
20+
# Fallback: Search common Visual Studio installation locations
21+
file(GLOB MSVC_LIB_PATHS "C:/Program Files/Microsoft Visual Studio/*/*/VC/Tools/MSVC/*/lib/x64")
22+
list(APPEND LEGACY_STDIO_SEARCH_PATHS ${MSVC_LIB_PATHS})
23+
24+
# Use find_library to locate the library
25+
find_library(LEGACY_STDIO_LIB legacy_stdio_definitions
26+
PATHS ${LEGACY_STDIO_SEARCH_PATHS}
27+
NO_DEFAULT_PATH
28+
)
29+
30+
if(LEGACY_STDIO_LIB)
31+
message(STATUS "Found legacy_stdio_definitions.lib: ${LEGACY_STDIO_LIB}")
32+
add_link_options("SHELL:-Xlinker \"${LEGACY_STDIO_LIB}\"")
33+
else()
34+
message(WARNING "Could not find legacy_stdio_definitions.lib - examples may fail to link.")
35+
endif()
36+
endif()
37+
938
add_custom_target(examples)
1039

1140

@@ -216,6 +245,7 @@ function(add_example_executable_no_testing EXAMPLE_NAME FILE_NAME)
216245
set_source_files_properties(${FILE_NAME} PROPERTIES LANGUAGE HIP)
217246
add_executable(${EXAMPLE_NAME} ${FILE_NAME})
218247
target_link_libraries(${EXAMPLE_NAME} PRIVATE utility)
248+
target_link_libraries(${EXAMPLE_NAME} PRIVATE getopt::getopt)
219249
add_dependencies(examples ${EXAMPLE_NAME})
220250
set_property(TARGET ${EXAMPLE_NAME} PROPERTY HIP_ARCHITECTURES ${EX_TARGETS})
221251
rocm_install(TARGETS ${EXAMPLE_NAME} COMPONENT examples)

script/run-tests.ps1

Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
<#
2+
.SYNOPSIS
3+
Runs GTest executables and generates a markdown test report.
4+
5+
.DESCRIPTION
6+
This script searches for GTest executables in a specified binary directory,
7+
runs them, and generates a comprehensive markdown report with test results.
8+
9+
.PARAMETER BinaryDirectory
10+
The directory containing the GTest executables.
11+
12+
.PARAMETER TestName
13+
The name pattern of the GTest executable(s). Supports wildcards (e.g., "*test*.exe").
14+
15+
.PARAMETER OutputReport
16+
Optional. The path to the output markdown report file.
17+
Defaults to "test-report.md" in the current directory.
18+
19+
.PARAMETER FullTestOutput
20+
Optional. If specified, includes the full test output for failed tests instead of just error lines.
21+
Defaults to false (only error lines are included).
22+
23+
.PARAMETER ExcludeTests
24+
Optional. Pattern to exclude specific test executables. Supports wildcards (e.g., "*large_cases*").
25+
Test executables matching this pattern will be filtered out and not executed.
26+
27+
.EXAMPLE
28+
.\run-tests.ps1 -BinaryDirectory "C:\build\bin" -TestName "test_*.exe"
29+
30+
.EXAMPLE
31+
.\run-tests.ps1 -BinaryDirectory ".\build" -TestName "*test.exe" -OutputReport "test-results.md"
32+
33+
.EXAMPLE
34+
.\run-tests.ps1 -BinaryDirectory ".\build" -TestName "*test.exe" -FullTestOutput
35+
36+
.EXAMPLE
37+
.\run-tests.ps1 -BinaryDirectory ".\build" -TestName "*test.exe" -ExcludeTests "*large_cases*"
38+
#>
39+
40+
param(
41+
[Parameter(Mandatory=$true)]
42+
[string]$BinaryDirectory,
43+
44+
[Parameter(Mandatory=$true)]
45+
[string]$TestName,
46+
47+
[Parameter(Mandatory=$false)]
48+
[string]$OutputReport = "test-report.md",
49+
50+
[Parameter(Mandatory=$false)]
51+
[switch]$FullTestOutput,
52+
53+
[Parameter(Mandatory=$false)]
54+
[string]$ExcludeTests = ""
55+
)
56+
57+
# Validate binary directory exists
58+
if (-not (Test-Path -Path $BinaryDirectory -PathType Container)) {
59+
Write-Error "Binary directory does not exist: $BinaryDirectory"
60+
exit 1
61+
}
62+
63+
# Find all matching executables
64+
$executables = Get-ChildItem -Path $BinaryDirectory -Filter $TestName -File -Recurse -ErrorAction SilentlyContinue
65+
66+
# Filter out excluded executables if ExcludeTests is specified
67+
if ($ExcludeTests) {
68+
$originalCount = $executables.Count
69+
$executables = $executables | Where-Object { $_.Name -notlike $ExcludeTests }
70+
$excludedCount = $originalCount - $executables.Count
71+
if ($excludedCount -gt 0) {
72+
Write-Host "Excluded $excludedCount executable(s) matching pattern '$ExcludeTests'"
73+
}
74+
}
75+
76+
if ($executables.Count -eq 0) {
77+
Write-Error "No executables found matching pattern '$TestName' (after exclusions) in directory '$BinaryDirectory'"
78+
exit 1
79+
}
80+
81+
Write-Host "Found $($executables.Count) executable(s) to run"
82+
83+
# Initialize counters
84+
$totalTests = 0
85+
$totalPassed = 0
86+
$totalFailed = 0
87+
$failedTestDetails = @()
88+
$executionResults = @()
89+
90+
# Process each executable
91+
foreach ($exe in $executables) {
92+
Write-Host "Running: $($exe.FullName)"
93+
94+
$exeResult = @{
95+
Name = $exe.Name
96+
Path = $exe.FullName
97+
Tests = 0
98+
Passed = 0
99+
Failed = 0
100+
Output = ""
101+
FailedTests = @()
102+
}
103+
104+
try {
105+
# Run the GTest executable
106+
$output = & $exe.FullName --gtest_color=no 2>&1 | Out-String
107+
$exeResult.Output = $output
108+
109+
# Extract total tests run
110+
if ($output -match '\[==========\] Running (\d+) test') {
111+
$exeResult.Tests = [int]$matches[1]
112+
$totalTests += $exeResult.Tests
113+
}
114+
115+
# Extract passed tests
116+
if ($output -match '\[ PASSED \] (\d+) test') {
117+
$exeResult.Passed = [int]$matches[1]
118+
$totalPassed += $exeResult.Passed
119+
}
120+
121+
# Extract failed tests count
122+
if ($output -match '\[ FAILED \] (\d+) test') {
123+
$exeResult.Failed = [int]$matches[1]
124+
$totalFailed += $exeResult.Failed
125+
}
126+
127+
$failedTestPattern = '\[ FAILED \] ([^\r\n\(]+)'
128+
$failedMatches = [regex]::Matches($output, $failedTestPattern)
129+
130+
foreach ($match in $failedMatches) {
131+
if ($match.Groups[1].Value -notmatch '^\d+ test') {
132+
$failedTestName = $match.Groups[1].Value.Trim()
133+
$exeResult.FailedTests += $failedTestName
134+
135+
$parts = $failedTestName -split ", where "
136+
$escapedName = $parts[0]
137+
$runPattern = "\[\s+RUN\s+\]\s+$escapedName\s*[\r\n]+([\s\S]*?)\[\s+FAILED\s+\]\s+$escapedName.*"
138+
139+
$detailsText = ""
140+
if ($output -match $runPattern) {
141+
$testSection = $matches[1]
142+
143+
if ($FullTestOutput) {
144+
$detailsText = $testSection.Trim()
145+
} else {
146+
# Extract only lines containing "error" (case-insensitive)
147+
$errorLines = @()
148+
$lines = $testSection -split "`r?`n"
149+
foreach ($line in $lines) {
150+
if ($line -match 'error') {
151+
$errorLines += $line.Trim()
152+
}
153+
}
154+
155+
if ($errorLines.Count -gt 0) {
156+
$detailsText = $errorLines -join "`n"
157+
} else {
158+
# If no error lines found, show the full section (might contain other useful info)
159+
$detailsText = $testSection.Trim()
160+
if ($detailsText.Length -lt 10) {
161+
$detailsText = "Test failed without detailed error output."
162+
}
163+
}
164+
}
165+
} else {
166+
# If pattern doesn't match, provide a helpful message
167+
$detailsText = "Test failed without detailed error output."
168+
}
169+
170+
$failedTestDetails += @{
171+
Executable = $exe.Name
172+
TestName = $failedTestName
173+
Details = $detailsText
174+
}
175+
}
176+
}
177+
178+
} catch {
179+
Write-Warning "Error running $($exe.Name): $_"
180+
$exeResult.Output = "Error: $_"
181+
}
182+
183+
$executionResults += $exeResult
184+
}
185+
186+
# Generate Markdown Report
187+
$reportContent = @"
188+
# GTest Execution Report
189+
190+
**Generated:** $(Get-Date -Format "yyyy-MM-dd HH:mm:ss")
191+
192+
## Summary
193+
194+
| Metric | Count |
195+
|--------|-------|
196+
| **Total Tests Executed** | $totalTests |
197+
| **Tests Passed** | $totalPassed |
198+
| **Tests Failed** | $totalFailed |
199+
| **Success Rate** | $(if ($totalTests -gt 0) { [math]::Round(($totalPassed / $totalTests) * 100, 2) } else { 0 })% |
200+
201+
## Executable Results
202+
203+
"@
204+
205+
foreach ($result in $executionResults) {
206+
# Use emoji/symbols via string concatenation to avoid encoding issues
207+
$passSymbol = [char]0x2705 # ✅ white heavy check mark
208+
$failSymbol = [char]0x274C # ❌ cross mark
209+
$status = if ($result.Failed -eq 0) { "$passSymbol PASSED" } else { "$failSymbol FAILED" }
210+
211+
$reportContent += "`n`n### $($result.Name) $status`n`n"
212+
$reportContent += "- **Tests Run:** $($result.Tests)`n"
213+
$reportContent += "- **Passed:** $($result.Passed)`n"
214+
$reportContent += "- **Failed:** $($result.Failed)`n"
215+
$reportContent += "- **Path:** ``$($result.Path)```n"
216+
}
217+
218+
# Add failed test details section if there are failures
219+
if ($failedTestDetails.Count -gt 0) {
220+
$failSymbol = [char]0x274C # ❌ cross mark
221+
$reportContent += "`n`n---`n`n## Failed Test Details`n"
222+
223+
foreach ($failure in $failedTestDetails) {
224+
$reportContent += "`n`n$failSymbol $($failure.TestName)`n`n"
225+
$reportContent += "$($failure.Details)`n"
226+
}
227+
} else {
228+
$celebrationSymbol = [char]0x1F389 # 🎉 party popper
229+
$reportContent += "`n`n---`n`n$celebrationSymbol All Tests Passed!`n`n"
230+
$reportContent += "No test failures detected.`n"
231+
}
232+
233+
# Add footer
234+
$reportContent += "`n"
235+
236+
# Write report to file
237+
$reportContent | Out-File -FilePath $OutputReport -Encoding UTF8
238+
239+
Write-Host ""
240+
Write-Host "========================================" -ForegroundColor Cyan
241+
Write-Host "Test Execution Complete" -ForegroundColor Cyan
242+
Write-Host "========================================" -ForegroundColor Cyan
243+
Write-Host "Total Tests: $totalTests" -ForegroundColor White
244+
Write-Host "Passed: $totalPassed" -ForegroundColor Green
245+
Write-Host "Failed: $totalFailed" -ForegroundColor $(if ($totalFailed -gt 0) { "Red" } else { "Green" })
246+
Write-Host "Report saved: $((Get-Item $OutputReport).FullName)" -ForegroundColor Yellow
247+
Write-Host "========================================" -ForegroundColor Cyan
248+
249+
# Exit with appropriate code
250+
if ($totalFailed -gt 0) {
251+
exit 1
252+
} else {
253+
exit 0
254+
}

0 commit comments

Comments
 (0)