Skip to content

Commit

Permalink
Make libcudacxx's codegen part of CI and add it to the project. (#1526)
Browse files Browse the repository at this point in the history
* Add a CMake config for building/installing/testing libcudacxx's codegen

* Move some functions in build_common.sh to a helper

* Add a CI script to verify codegen is up to date.

* Add a CI step that verifies that codegen or generated header are synchronized

* Fix verify_codegen.sh permissions

* Install pre-reqs for build on default ubuntu runner

* Fix output file in codegen.cpp

* Make codegen build/test default to OFF

* Whitespace fixup

Co-authored-by: Michael Schellenberger Costa <[email protected]>

---------

Co-authored-by: Michael Schellenberger Costa <[email protected]>
  • Loading branch information
wmaxey and miscco authored Mar 11, 2024
1 parent 8abee78 commit dbf9749
Show file tree
Hide file tree
Showing 8 changed files with 221 additions and 116 deletions.
15 changes: 15 additions & 0 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,20 @@ jobs:
contents: read
uses: ./.github/workflows/verify-devcontainers.yml

verify-codegen:
name: Verify Codegen in libcudacxx
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v3
- name: Run libcudacxx codegen verification
id: verify-codegen
run: |
sudo apt-get update
sudo apt-get install ninja-build
export CXX="g++"
./ci/verify_codegen.sh
# This job is the final job that runs after all other jobs and is used for branch protection status checks.
# See: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/about-status-checks
# https://github.com/orgs/community/discussions/26822#discussioncomment-5122101
Expand All @@ -183,6 +197,7 @@ jobs:
- thrust
- cccl-infra
- verify-devcontainers
- verify-codegen
steps:
- name: Check status of all precursor jobs
if: >-
Expand Down
31 changes: 31 additions & 0 deletions CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,18 @@
"THRUST_MULTICONFIG_ENABLE_SYSTEM_TBB": true
}
},
{
"name": "libcudacxx-codegen",
"displayName": "libcu++: codegen",
"inherits": "base",
"cacheVariables": {
"CCCL_ENABLE_LIBCUDACXX": true,
"LIBCUDACXX_ENABLE_LIBCUDACXX_TESTS": false,
"libcudacxx_ENABLE_CMAKE_TESTS": false,
"libcudacxx_ENABLE_CODEGEN": true,
"LIBCUDACXX_ENABLE_CUDA": false
}
},
{
"name": "libcudacxx-base",
"hidden": true,
Expand Down Expand Up @@ -266,6 +278,16 @@
"name": "all-dev",
"configurePreset": "all-dev"
},
{
"name": "libcudacxx-codegen",
"configurePreset": "libcudacxx-codegen",
"targets": ["libcudacxx.atomics.codegen"]
},
{
"name": "libcudacxx-codegen-install",
"configurePreset": "libcudacxx-codegen",
"targets": ["libcudacxx.atomics.codegen.install"]
},
{
"name": "libcudacxx-nvrtcc",
"hidden": true,
Expand Down Expand Up @@ -391,6 +413,15 @@
}
}
},
{
"name": "libcudacxx-codegen",
"configurePreset": "libcudacxx-codegen",
"filter": {
"include": {
"name": "^libcudacxx\\.atomics\\.codegen.*$"
}
}
},
{
"name": "libcudacxx-ctest-cpp11",
"configurePreset": "libcudacxx-cpp11",
Expand Down
107 changes: 1 addition & 106 deletions ci/build_common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -105,112 +105,7 @@ export CUDACXX="${CUDA_COMPILER}"
export CUDAHOSTCXX="${HOST_COMPILER}"
export CXX_STANDARD

# Print "ARG=${ARG}" for all args.
function print_var_values() {
# Iterate through the arguments
for var_name in "$@"; do
if [ -z "$var_name" ]; then
echo "Usage: print_var_values <variable_name1> <variable_name2> ..."
return 1
fi

# Dereference the variable and print the result
echo "$var_name=${!var_name:-(undefined)}"
done
}

# begin_group: Start a named section of log output, possibly with color.
# Usage: begin_group "Group Name" [Color]
# Group Name: A string specifying the name of the group.
# Color (optional): ANSI color code to set text color. Default is blue (1;34).
function begin_group() {
# See options for colors here: https://gist.github.com/JBlond/2fea43a3049b38287e5e9cefc87b2124
local blue="34"
local name="${1:-}"
local color="${2:-$blue}"

if [ -n "${GITHUB_ACTIONS:-}" ]; then
echo -e "::group::\e[${color}m${name}\e[0m"
else
echo -e "\e[${color}m================== ${name} ======================\e[0m"
fi
}

# end_group: End a named section of log output and print status based on exit status.
# Usage: end_group "Group Name" [Exit Status]
# Group Name: A string specifying the name of the group.
# Exit Status (optional): The exit status of the command run within the group. Default is 0.
function end_group() {
local name="${1:-}"
local build_status="${2:-0}"
local duration="${3:-}"
local red="31"
local blue="34"

if [ -n "${GITHUB_ACTIONS:-}" ]; then
echo "::endgroup::"

if [ "$build_status" -ne 0 ]; then
echo -e "::error::\e[${red}m ${name} - Failed (⬆️ click above for full log ⬆️)\e[0m"
fi
else
if [ "$build_status" -ne 0 ]; then
echo -e "\e[${red}m================== End ${name} - Failed${duration:+ - Duration: ${duration}s} ==================\e[0m"
else
echo -e "\e[${blue}m================== End ${name} - Success${duration:+ - Duration: ${duration}s} ==================\n\e[0m"
fi
fi
}

declare -A command_durations

# Runs a command within a named group, handles the exit status, and prints appropriate messages based on the result.
# Usage: run_command "Group Name" command [arguments...]
function run_command() {
local group_name="${1:-}"
shift
local command=("$@")
local status

begin_group "$group_name"
set +e
local start_time=$(date +%s)
"${command[@]}"
status=$?
local end_time=$(date +%s)
set -e
local duration=$((end_time - start_time))
end_group "$group_name" $status $duration
command_durations["$group_name"]=$duration
return $status
}

function string_width() {
local str="$1"
echo "$str" | awk '{print length}'
}

function print_time_summary() {
local max_length=0
local group

# Find the longest group name for formatting
for group in "${!command_durations[@]}"; do
local group_length=$(echo "$group" | awk '{print length}')
if [ "$group_length" -gt "$max_length" ]; then
max_length=$group_length
fi
done

echo "Time Summary:"
for group in "${!command_durations[@]}"; do
printf "%-${max_length}s : %s seconds\n" "$group" "${command_durations[$group]}"
done

# Clear the array of timing info
declare -gA command_durations=()
}

source ./pretty_printing.sh

print_environment_details() {
begin_group "⚙️ Environment Details"
Expand Down
105 changes: 105 additions & 0 deletions ci/pretty_printing.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# Print "ARG=${ARG}" for all args.
function print_var_values() {
# Iterate through the arguments
for var_name in "$@"; do
if [ -z "$var_name" ]; then
echo "Usage: print_var_values <variable_name1> <variable_name2> ..."
return 1
fi

# Dereference the variable and print the result
echo "$var_name=${!var_name:-(undefined)}"
done
}

# begin_group: Start a named section of log output, possibly with color.
# Usage: begin_group "Group Name" [Color]
# Group Name: A string specifying the name of the group.
# Color (optional): ANSI color code to set text color. Default is blue (1;34).
function begin_group() {
# See options for colors here: https://gist.github.com/JBlond/2fea43a3049b38287e5e9cefc87b2124
local blue="34"
local name="${1:-}"
local color="${2:-$blue}"

if [ -n "${GITHUB_ACTIONS:-}" ]; then
echo -e "::group::\e[${color}m${name}\e[0m"
else
echo -e "\e[${color}m================== ${name} ======================\e[0m"
fi
}

# end_group: End a named section of log output and print status based on exit status.
# Usage: end_group "Group Name" [Exit Status]
# Group Name: A string specifying the name of the group.
# Exit Status (optional): The exit status of the command run within the group. Default is 0.
function end_group() {
local name="${1:-}"
local build_status="${2:-0}"
local duration="${3:-}"
local red="31"
local blue="34"

if [ -n "${GITHUB_ACTIONS:-}" ]; then
echo "::endgroup::"

if [ "$build_status" -ne 0 ]; then
echo -e "::error::\e[${red}m ${name} - Failed (⬆️ click above for full log ⬆️)\e[0m"
fi
else
if [ "$build_status" -ne 0 ]; then
echo -e "\e[${red}m================== End ${name} - Failed${duration:+ - Duration: ${duration}s} ==================\e[0m"
else
echo -e "\e[${blue}m================== End ${name} - Success${duration:+ - Duration: ${duration}s} ==================\n\e[0m"
fi
fi
}

declare -A command_durations

# Runs a command within a named group, handles the exit status, and prints appropriate messages based on the result.
# Usage: run_command "Group Name" command [arguments...]
function run_command() {
local group_name="${1:-}"
shift
local command=("$@")
local status

begin_group "$group_name"
set +e
local start_time=$(date +%s)
"${command[@]}"
status=$?
local end_time=$(date +%s)
set -e
local duration=$((end_time - start_time))
end_group "$group_name" $status $duration
command_durations["$group_name"]=$duration
return $status
}

function string_width() {
local str="$1"
echo "$str" | awk '{print length}'
}

function print_time_summary() {
local max_length=0
local group

# Find the longest group name for formatting
for group in "${!command_durations[@]}"; do
local group_length=$(echo "$group" | awk '{print length}')
if [ "$group_length" -gt "$max_length" ]; then
max_length=$group_length
fi
done

echo "Time Summary:"
for group in "${!command_durations[@]}"; do
printf "%-${max_length}s : %s seconds\n" "$group" "${command_durations[$group]}"
done

# Clear the array of timing info
declare -gA command_durations=()
}
28 changes: 28 additions & 0 deletions ci/verify_codegen.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/bin/bash
set -eo pipefail

# Ensure the script is being executed in its containing directory
cd "$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )";

# TBD: verbose? any extra args?

source ./pretty_printing.sh

pushd .. > /dev/null
GROUP_NAME="🛠️ CMake Configure Libcudacxx Codegen"
run_command "$GROUP_NAME" cmake --preset libcudacxx-codegen
status=$?
popd > /dev/null

pushd .. > /dev/null
GROUP_NAME="🏗️ Build Libcudacxx Codegen"
run_command "$GROUP_NAME" cmake --build --preset libcudacxx-codegen

status=$?
popd > /dev/null

pushd .. > /dev/null
GROUP_NAME="🚀 Test Libcudacxx Codegen"
run_command "$GROUP_NAME" ctest --preset libcudacxx-codegen
status=$?
popd > /dev/null
6 changes: 6 additions & 0 deletions libcudacxx/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ endif()
include(CTest)
enable_testing()

# Add codegen module
option(libcudacxx_ENABLE_CODEGEN "Enable ctest-based testing." OFF)
if (libcudacxx_ENABLE_CODEGEN)
add_subdirectory(codegen)
endif()

# Note that this currently returns and skips the rest of the build
# system.
option(libcudacxx_ENABLE_CMAKE_TESTS "Enable ctest-based testing." ON)
Expand Down
43 changes: 34 additions & 9 deletions libcudacxx/codegen/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,19 +1,44 @@
cmake_minimum_required(VERSION 3.8)
## Codegen adds the following build targets
# libcudacxx.atomics.codegen
# libcudacxx.atomics.codegen.execute
# libcudacxx.atomics.codegen.install
## Test targets:
# libcudacxx.atomics.codegen.diff

project(cuda-atomics-codegen LANGUAGES CXX)
add_custom_target(libcudacxx.atomics.codegen)

set(CMAKE_CXX_STANDARD 14)
add_executable(codegen
add_executable(
codegen
EXCLUDE_FROM_ALL
codegen.cpp
)

target_compile_features(
codegen PRIVATE cxx_std_14
)

add_dependencies(libcudacxx.atomics.codegen codegen)

set(atomic_generated_output "${libcudacxx_BINARY_DIR}/codegen/atomic_cuda_generated.h")
set(atomic_install_location "${libcudacxx_SOURCE_DIR}/include/cuda/std/detail/libcxx/include/support/atomic")

add_custom_target(
run ALL
libcudacxx.atomics.codegen.execute
COMMAND codegen
BYPRODUCS "${libcudacxx_BINARY_DIR}/__atomic_generated"
BYPRODUCTS "${atomic_generated_output}"
)

install(
FILES "${libcudacxx_BINARY_DIR}/__atomic_generated"
DESTINATION "${libcudacxx_SOURCE_DIR}/../include/cuda/std/detail/"
add_dependencies(libcudacxx.atomics.codegen libcudacxx.atomics.codegen.execute)

add_custom_target(
libcudacxx.atomics.codegen.install
COMMAND ${CMAKE_COMMAND} -E copy "${atomic_generated_output}" "${atomic_install_location}/atomic_cuda_generated.h"
BYPRODUCTS "${atomic_install_location}/atomic_cuda_generated.h"
)

add_dependencies(libcudacxx.atomics.codegen.install libcudacxx.atomics.codegen.execute)

add_test(
NAME libcudacxx.atomics.codegen.diff
COMMAND ${CMAKE_COMMAND} -E compare_files "${atomic_install_location}/atomic_cuda_generated.h" "${atomic_generated_output}"
)
Loading

0 comments on commit dbf9749

Please sign in to comment.