File: hook.cmake

package info (click to toggle)
cmake 4.3.0-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 158,704 kB
  • sloc: ansic: 406,077; cpp: 309,512; sh: 4,233; python: 3,696; yacc: 3,109; lex: 1,279; f90: 538; asm: 471; lisp: 375; java: 310; cs: 270; fortran: 239; objc: 215; perl: 213; xml: 198; makefile: 110; javascript: 83; pascal: 63; tcl: 55; php: 25; ruby: 22; sed: 2
file content (170 lines) | stat: -rw-r--r-- 7,087 bytes parent folder | download | duplicates (3)
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
cmake_minimum_required(VERSION 3.30)

include(${CMAKE_CURRENT_LIST_DIR}/json.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/verify-snippet.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/verify-trace.cmake)

# Test CALLBACK script. Prints output information and verifies index file
# Called as: cmake -P hook.cmake [CheckForStaticQuery?] [CheckForTrace?] [index.json]
set(index ${CMAKE_ARGV5})
if (NOT ${CMAKE_ARGV3})
  set(hasStaticInfo "UNEXPECTED")
endif()
if (NOT ${CMAKE_ARGV4})
  set(hasTrace "UNEXPECTED")
endif()
read_json("${index}" contents)
string(JSON hook GET "${contents}" hook)

# Output is verified by *-stdout.txt files that the HOOK is run
message(STATUS ${hook})
# Not a check-*.cmake script, this is called as an instrumentation CALLBACK
set(ERROR_MESSAGE "")
function(add_error error)
  string(APPEND ERROR_MESSAGE "${error}\n")
  return(PROPAGATE ERROR_MESSAGE)
endfunction()

json_has_key("${index}" "${contents}" version)
json_has_key("${index}" "${contents}" buildDir)
json_has_key("${index}" "${contents}" dataDir)
json_has_key("${index}" "${contents}" snippets)

if (NOT version EQUAL 1)
  add_error("Version must be 1, got: ${version}")
endif()

string(JSON n_snippets LENGTH "${snippets}")

math(EXPR snippets_range "${n_snippets}-1")
foreach(i RANGE ${snippets_range})
  string(JSON filename GET "${snippets}" ${i})
  if (NOT EXISTS ${dataDir}/${filename})
    add_error("Listed snippet: ${dataDir}/${filename} does not exist")
  endif()
  read_json(${dataDir}/${filename} snippet_contents)
  verify_snippet_file(${dataDir}/${filename} "${snippet_contents}")
endforeach()

json_has_key("${index}" "${contents}" trace ${hasTrace})
if (NOT hasTrace STREQUAL UNEXPECTED)
  if (NOT EXISTS ${dataDir}/${trace})
    add_error("Listed trace file: ${dataDir}/${trace} does not exist")
  endif()
  verify_trace_file_name("${index}" "${trace}")
  read_json(${dataDir}/${trace} trace_contents)
  string(JSON n_entries LENGTH "${trace_contents}")
  if (n_entries EQUAL 0)
    add_error("Listed trace file: ${dataDir}/${trace} has no entries")
  endif()
  if (NOT n_entries EQUAL n_snippets)
    add_error("Differing number of trace entries (${n_entries}) and snippets (${n_snippets})")
  endif()

  math(EXPR entries_range "${n_entries}-1")
  foreach (i RANGE ${entries_range})
    string(JSON entry GET "${trace_contents}" ${i})
    verify_trace_entry("${trace}" "${entry}")

    # In addition to validating the data in the trace entry, check that
    # it is strictly equal to its corresponding snippet data.
    # Ideally, the args from all trace entries could be checked at once
    # against the list of snippets from the index file, but the order of
    # snippets is not preserved in the trace file, so being equal to data from
    # any snippet file is sufficient.
    set(args_equals_snippet OFF)
    string(JSON trace_args GET "${entry}" args)
    foreach (j RANGE ${entries_range})
      string(JSON snippet_file GET "${snippets}" ${j})
      read_json(${dataDir}/${snippet_file} snippet_contents)
      string(JSON args_equals_snippet EQUAL "${snippet_contents}" "${trace_args}")
      if (args_equals_snippet)
        break()
      endif()
    endforeach()
    if (NOT args_equals_snippet)
      add_error("Trace entry args does not match any snippet data: ${entry}")
    endif()
  endforeach()
endif()

json_has_key("${index}" "${contents}" staticSystemInformation ${hasStaticInfo})
if (NOT hasStaticInfo STREQUAL UNEXPECTED)
  json_has_key("${index}" "${staticSystemInformation}" OSName ${hasStaticInfo})
  json_has_key("${index}" "${staticSystemInformation}" OSPlatform ${hasStaticInfo})
  json_has_key("${index}" "${staticSystemInformation}" OSRelease ${hasStaticInfo})
  json_has_key("${index}" "${staticSystemInformation}" OSVersion ${hasStaticInfo})
  json_has_key("${index}" "${staticSystemInformation}" familyId ${hasStaticInfo})
  json_has_key("${index}" "${staticSystemInformation}" hostname ${hasStaticInfo})
  json_has_key("${index}" "${staticSystemInformation}" is64Bits ${hasStaticInfo})
  json_has_key("${index}" "${staticSystemInformation}" modelId ${hasStaticInfo})
  json_has_key("${index}" "${staticSystemInformation}" modelName ${hasStaticInfo})
  json_has_key("${index}" "${staticSystemInformation}" numberOfLogicalCPU ${hasStaticInfo})
  json_has_key("${index}" "${staticSystemInformation}" numberOfPhysicalCPU ${hasStaticInfo})
  json_has_key("${index}" "${staticSystemInformation}" processorAPICID ${hasStaticInfo})
  json_has_key("${index}" "${staticSystemInformation}" processorCacheSize ${hasStaticInfo})
  json_has_key("${index}" "${staticSystemInformation}" processorClockFrequency ${hasStaticInfo})
  json_has_key("${index}" "${staticSystemInformation}" processorName ${hasStaticInfo})
  json_has_key("${index}" "${staticSystemInformation}" totalPhysicalMemory ${hasStaticInfo})
  json_has_key("${index}" "${staticSystemInformation}" totalVirtualMemory ${hasStaticInfo})
  json_has_key("${index}" "${staticSystemInformation}" vendorID ${hasStaticInfo})
  json_has_key("${index}" "${staticSystemInformation}" vendorString ${hasStaticInfo})

  # FIXME(#27545): We currently do not guarantee that the fields above which
  # output strings are non-empty. `vendorString` and `processorName` especially
  # have shown issues on some platforms. This test is logically equivalent to
  # RunCMake.cmake_host_system_information, which uses the same underlying
  # implementation.
  set(string_fields
    OSName
    OSPlatform
    OSRelease
    OSVersion
    familyId
    hostname
    modelId
    modelName
    vendorID
    vendorString
  )
  foreach (field IN LISTS string_fields)
    string(JSON ${field}_type TYPE "${staticSystemInformation}" ${field})
    if (NOT "${${field}_type}" STREQUAL "NULL" AND NOT "${${field}_type}" STREQUAL "STRING")
      add_error("Got bad type '${${field}_type}' for field '${field}': ${${field}}")
    endif()
    if ("${${field}_type}" STREQUAL "STRING" AND ${field} STREQUAL "")
      add_error("Got empty string for field '${field}'")
    endif()
  endforeach()

  # We guarantee that the numeric fields are either indeed numeric, or else
  # null.
  set(numeric_fields
    numberOfLogicalCPU
    numberOfPhysicalCPU
    processorAPICID
    processorCacheSize
    processorClockFrequency
    totalPhysicalMemory
    totalVirtualMemory
  )
  foreach (field IN LISTS numeric_fields)
    string(JSON ${field}_type TYPE "${staticSystemInformation}" ${field})
    if (NOT "${${field}_type}" STREQUAL "NULL" AND NOT "${${field}_type}" STREQUAL "NUMBER")
      add_error("Got bad type '${${field}_type}' for field '${field}': ${${field}}")
    endif()
    if ("${${field}_type}" STREQUAL "NUMBER" AND ${field} LESS_EQUAL 0)
      add_error("Got bad value for field '${field}': ${${field}}")
    endif()
  endforeach()
endif()

get_filename_component(v1 ${dataDir} DIRECTORY)
if (EXISTS ${v1}/${hook}.hook)
  add_error("Received multiple triggers of the same hook: ${hook}")
endif()
file(WRITE ${v1}/${hook}.hook "${ERROR_MESSAGE}")

if (NOT ERROR_MESSAGE MATCHES "^$")
  message(FATAL_ERROR ${ERROR_MESSAGE})
endif()