#!/bin/bash # Copyright (c) Advanced Micro Devices, Inc., or its affiliates. # SPDX-License-Identifier: MIT # CK Docker Tool - Build and test composable_kernel in Docker with ROCm support set -e set -o pipefail # Find script directory and load common utilities SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "${SCRIPT_DIR}/common.sh" # Initialize configuration PROJECT_ROOT=$(get_project_root "${SCRIPT_DIR}") CONTAINER_NAME=$(get_container_name "${PROJECT_ROOT}") # Help message show_help() { cat << EOF CK Docker Tool - Build and test composable_kernel in Docker Usage: ck-docker [options] Commands: start [name] Start Docker container build [target] [--reconfigure] Build target (optionally reconfigure CMake) test [options] Run test shell [name] Open shell in container status [name] Check container status stop [name] Stop and remove container Examples: ck-docker start ck-docker build test_amdgcn_mma ck-docker build --reconfigure test_amdgcn_mma ck-docker test test_amdgcn_mma --gtest_filter=*Fp16* ck-docker shell Environment: CK_CONTAINER_NAME - Override default container name (default: ck__) CK_DOCKER_IMAGE - Override Docker image (default: rocm/composable_kernel:ck_ub24.04_rocm7.0.1) GPU_TARGET - Override GPU target detection (e.g., gfx950, gfx942) EOF } # Start container cmd_start() { local name="${1:-${CONTAINER_NAME}}" local docker_image=$(get_docker_image) # Check if container exists and is running if container_exists "${name}"; then if container_is_running "${name}"; then echo "Container '${name}' is already running" return 0 else echo "Starting existing container '${name}'..." docker start "${name}" echo "Container started" return 0 fi fi echo "Creating new Docker container '${name}'..." docker run -d \ --name "${name}" \ --device=/dev/kfd --device=/dev/dri \ --security-opt seccomp=unconfined \ --group-add video \ -v "${PROJECT_ROOT}":/workspace \ -w /workspace \ "${docker_image}" \ tail -f /dev/null echo "Container '${name}' started successfully" docker exec "${name}" bash -c "echo 'Working directory:' && pwd" } # Build target cmd_build() { local target="" local name="${CONTAINER_NAME}" local reconfigure=false while [[ $# -gt 0 ]]; do case $1 in --name) name="$2" shift 2 ;; --reconfigure) reconfigure=true shift ;; *) target="$1" shift ;; esac done # Check if container is running if ! container_is_running "${name}"; then echo "Container '${name}' not running. Starting..." cmd_start "${name}" fi # Reconfigure CMake if requested or if build.ninja doesn't exist if [ "$reconfigure" = true ] || ! docker exec "${name}" test -f /workspace/build/build.ninja 2>/dev/null; then echo "Detecting GPU target..." local gpu_target=$(detect_gpu_target "${name}") if [ "$reconfigure" = true ]; then echo "Reconfiguring CMake from scratch for GPU target: ${gpu_target}" else echo "Configuring build with CMake for GPU target: ${gpu_target}" fi docker exec "${name}" bash -c " cd /workspace || exit 1 rm -rf /workspace/build mkdir /workspace/build cd /workspace/build || exit 1 cmake .. -GNinja \ -DGPU_TARGETS=${gpu_target} \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_CXX_COMPILER=/opt/rocm/llvm/bin/clang++ \ -DBUILD_TESTING=ON 2>&1 | tail -30 " fi if [ -z "$target" ]; then echo "Building all configured targets..." else echo "Building target: ${target}" fi docker exec "${name}" bash -c " cd /workspace/build || exit 1 ninja ${target} 2>&1 " echo "Build complete" } # Run test cmd_test() { local test_name="" local name="${CONTAINER_NAME}" local -a test_options=() while [[ $# -gt 0 ]]; do case $1 in --name) name="$2" shift 2 ;; --gtest_*|--help) test_options+=("$1") shift ;; *) if [ -z "$test_name" ]; then test_name="$1" else test_options+=("$1") fi shift ;; esac done if [ -z "$test_name" ]; then echo "Error: test_name required" echo "Usage: ck-docker test [--name container_name] [gtest_options]" return 1 fi # Check if container is running if ! container_is_running "${name}"; then echo "Error: Container '${name}' not running" echo "Start it with: ck-docker start --name ${name}" return 1 fi if ! docker exec "${name}" test -f "/workspace/build/bin/${test_name}" 2>/dev/null; then echo "Test executable not found. Building ${test_name}..." cmd_build "${test_name}" --name "${name}" fi echo "Running: ${test_name} ${test_options[*]}" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" # Build the command with proper quoting local cmd="cd /workspace/build && ./bin/${test_name}" for opt in "${test_options[@]}"; do cmd="${cmd} $(printf '%q' "$opt")" done docker exec "${name}" bash -c "${cmd}" } # Shell cmd_shell() { local name="${1:-${CONTAINER_NAME}}" # Check if container is running if ! container_is_running "${name}"; then echo "Container '${name}' not running. Starting..." cmd_start "${name}" fi echo "Opening shell in '${name}' (type 'exit' to leave)..." docker exec -it "${name}" bash } # Status cmd_status() { local name="${1:-}" local docker_image=$(get_docker_image) if [ -z "$name" ]; then echo "Composable Kernel Docker Containers:" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" docker ps -a --filter "ancestor=${docker_image}" \ --format "table {{.Names}}\t{{.Status}}\t{{.CreatedAt}}" || echo "No containers found" else # Check container status if container_is_running "${name}"; then echo "Container '${name}' is RUNNING" docker ps --filter "name=^${name}$" --format "table {{.Names}}\t{{.Status}}\t{{.Image}}" echo "" echo "GPU Information:" docker exec "${name}" bash -c "rocm-smi --showproductname 2>/dev/null | head -10 || echo 'No GPU detected'" elif container_exists "${name}"; then echo "Container '${name}' exists but is STOPPED" echo "Start with: ck-docker start ${name}" else echo "Container '${name}' does NOT exist" echo "Create with: ck-docker start ${name}" fi fi } # Stop cmd_stop() { local name="${1:-${CONTAINER_NAME}}" # Check if container exists if container_exists "${name}"; then echo "Stopping and removing container '${name}'..." docker stop "${name}" 2>/dev/null || true docker rm "${name}" 2>/dev/null || true echo "Container stopped and removed" else echo "Container '${name}' does not exist" fi } # Main command dispatcher case "${1:-}" in start) shift cmd_start "$@" ;; build) shift cmd_build "$@" ;; test) shift cmd_test "$@" ;; shell) shift cmd_shell "$@" ;; status) shift cmd_status "$@" ;; stop) shift cmd_stop "$@" ;; help|--help|-h) show_help ;; *) echo "Unknown command: ${1:-}" echo "" show_help exit 1 ;; esac