File: check_source_files.cmake

package info (click to toggle)
cccl 2.5.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 39,248 kB
  • sloc: cpp: 264,457; python: 6,421; sh: 2,762; perl: 460; makefile: 114; xml: 13
file content (185 lines) | stat: -rw-r--r-- 6,544 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# Check all source files for various issues that can be detected using pattern
# matching.
#
# This is run as a ctest test named `thrust.test.cmake.check_source_files`, or
# manually with:
# cmake -D "Thrust_SOURCE_DIR=<thrust project root>" -P check_source_files.cmake

cmake_minimum_required(VERSION 3.15)

function(count_substrings input search_regex output_var)
  string(REGEX MATCHALL "${search_regex}" matches "${input}")
  list(LENGTH matches num_matches)
  set(${output_var} ${num_matches} PARENT_SCOPE)
endfunction()

set(found_errors 0)
file(GLOB_RECURSE thrust_srcs
  RELATIVE "${Thrust_SOURCE_DIR}"
  "${Thrust_SOURCE_DIR}/thrust/*.h"
  "${Thrust_SOURCE_DIR}/thrust/*.inl"
)

################################################################################
# Namespace checks.
# Check all files in thrust to make sure that they use
# THRUST_NAMESPACE_BEGIN/END instead of bare `namespace thrust {}` declarations.
set(namespace_exclusions
  # This defines the macros and must have bare namespace declarations:
  thrust/detail/config/namespace.h
)

set(bare_ns_regex "namespace[ \n\r\t]+thrust[ \n\r\t]*\\{")

# Validation check for the above regex:
count_substrings([=[
namespace thrust{
namespace thrust {
namespace  thrust  {
 namespace thrust {
namespace thrust
{
namespace
thrust
{
]=]
  ${bare_ns_regex} valid_count)
if (NOT valid_count EQUAL 6)
  message(FATAL_ERROR "Validation of bare namespace regex failed: "
                      "Matched ${valid_count} times, expected 6.")
endif()

################################################################################
# stdpar header checks.
# Check all files in Thrust to make sure that they aren't including <algorithm>
# or <memory>, both of which will cause circular dependencies in nvc++'s
# stdpar library.
#
# The headers following headers should be used instead:
# <algorithm> -> <thrust/detail/algorithm_wrapper.h>
# <memory>    -> <thrust/detail/memory_wrapper.h>
#
set(stdpar_header_exclusions
  # The wrappers are allowed to include the unwrapped headers
  thrust/detail/algorithm_wrapper.h
  thrust/detail/memory_wrapper.h
  thrust/detail/numeric_wrapper.h
)

set(algorithm_regex "#[ \t]*include[ \t]+<algorithm>")
set(memory_regex    "#[ \t]*include[ \t]+<memory>")
set(numeric_regex   "#[ \t]*include[ \t]+<numeric>")

# Validation check for the above regex pattern:
count_substrings([=[
#include <algorithm>
# include <algorithm>
#include  <algorithm>
# include  <algorithm>
# include  <algorithm> // ...
]=]
  ${algorithm_regex} valid_count)
if (NOT valid_count EQUAL 5)
  message(FATAL_ERROR "Validation of stdpar header regex failed: "
    "Matched ${valid_count} times, expected 5.")
endif()

################################################################################
# Legacy macro checks.
# Check all files in Thrust to make sure that they aren't using the legacy
# CUB_RUNTIME_ENABLED and __THRUST_HAS_CUDART__ macros.
#
# These macros depend on __CUDA_ARCH__ and are not compatible with NV_IF_TARGET.
# They are provided for legacy purposes and should be replaced with
# [THRUST|CUB]_RDC_ENABLED and NV_IF_TARGET in Thrust/CUB code.
#
#
set(legacy_macro_header_exclusions
  # This header defines a legacy CUDART macro:
  thrust/system/cuda/config.h
)

set(cub_legacy_macro_regex "CUB_RUNTIME_ENABLED")
set(thrust_legacy_macro_regex "__THRUST_HAS_CUDART__")

################################################################################
# Read source files:
foreach(src ${thrust_srcs})
  file(READ "${Thrust_SOURCE_DIR}/${src}" src_contents)

  if (NOT ${src} IN_LIST namespace_exclusions)
    count_substrings("${src_contents}" "${bare_ns_regex}" bare_ns_count)
    count_substrings("${src_contents}" THRUST_NS_PREFIX prefix_count)
    count_substrings("${src_contents}" THRUST_NS_POSTFIX postfix_count)
    count_substrings("${src_contents}" THRUST_NAMESPACE_BEGIN begin_count)
    count_substrings("${src_contents}" THRUST_NAMESPACE_END end_count)
    count_substrings("${src_contents}" "#include <thrust/detail/config.h>" header_count)

    if (NOT bare_ns_count EQUAL 0)
      message("'${src}' contains 'namespace thrust {...}'. Replace with THRUST_NAMESPACE macros.")
      set(found_errors 1)
    endif()

    if (NOT prefix_count EQUAL 0)
      message("'${src}' contains 'THRUST_NS_PREFIX'. Replace with THRUST_NAMESPACE macros.")
      set(found_errors 1)
    endif()

    if (NOT postfix_count EQUAL 0)
      message("'${src}' contains 'THRUST_NS_POSTFIX'. Replace with THRUST_NAMESPACE macros.")
      set(found_errors 1)
    endif()

    if (NOT begin_count EQUAL end_count)
      message("'${src}' namespace macros are unbalanced:")
      message(" - THRUST_NAMESPACE_BEGIN occurs ${begin_count} times.")
      message(" - THRUST_NAMESPACE_END   occurs ${end_count} times.")
      set(found_errors 1)
    endif()

    if (begin_count GREATER 0 AND header_count EQUAL 0)
      message("'${src}' uses Thrust namespace macros, but does not (directly) `#include <thrust/detail/config.h>`.")
      set(found_errors 1)
    endif()
  endif()

  if (NOT ${src} IN_LIST stdpar_header_exclusions)
    count_substrings("${src_contents}" "${algorithm_regex}" algorithm_count)
    count_substrings("${src_contents}" "${memory_regex}" memory_count)
    count_substrings("${src_contents}" "${numeric_regex}" numeric_count)

    if (NOT algorithm_count EQUAL 0)
      message("'${src}' includes the <algorithm> header. Replace with <thrust/detail/algorithm_wrapper.h>.")
      set(found_errors 1)
    endif()

    if (NOT memory_count EQUAL 0)
      message("'${src}' includes the <memory> header. Replace with <thrust/detail/memory_wrapper.h>.")
      set(found_errors 1)
    endif()

    if (NOT numeric_count EQUAL 0)
      message("'${src}' includes the <numeric> header. Replace with <thrust/detail/numeric_wrapper.h>.")
      set(found_errors 1)
    endif()
  endif()

  if (NOT ${src} IN_LIST legacy_macro_header_exclusions)
    count_substrings("${src_contents}" "${thrust_legacy_macro_regex}" thrust_count)
    count_substrings("${src_contents}" "${cub_legacy_macro_regex}" cub_count)

    if (NOT thrust_count EQUAL 0)
      message("'${src}' uses __THRUST_HAS_CUDART__. Replace with THRUST_RDC_ENABLED and NV_IF_TARGET.")
      set(found_errors 1)
    endif()

    if (NOT cub_count EQUAL 0)
      message("'${src}' uses CUB_RUNTIME_ENABLED. Replace with CUB_RDC_ENABLED and NV_IF_TARGET.")
      set(found_errors 1)
    endif()
  endif()
endforeach()

if (NOT found_errors EQUAL 0)
  message(FATAL_ERROR "Errors detected.")
endif()