Ben Boeckel | a02c4cc | 2019-03-12 19:16:46 | [diff] [blame] | 1 | /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
Kitware Robot | 1772622 | 2025-03-03 02:08:52 | [diff] [blame] | 2 | file LICENSE.rst or https://cmake.org/licensing for details. */ |
Ben Boeckel | a02c4cc | 2019-03-12 19:16:46 | [diff] [blame] | 3 | |
| 4 | #include "cmScanDepFormat.h" |
| 5 | |
| 6 | #include <cctype> |
| 7 | #include <cstdio> |
Ben Boeckel | 3e5b609 | 2021-06-08 15:27:39 | [diff] [blame] | 8 | #include <utility> |
| 9 | |
| 10 | #include <cm/optional> |
Ben Boeckel | ccc0466 | 2021-06-08 15:27:39 | [diff] [blame] | 11 | #include <cm/string_view> |
| 12 | #include <cmext/string_view> |
Ben Boeckel | a02c4cc | 2019-03-12 19:16:46 | [diff] [blame] | 13 | |
| 14 | #include <cm3p/json/reader.h> |
| 15 | #include <cm3p/json/value.h> |
| 16 | #include <cm3p/json/writer.h> |
| 17 | |
| 18 | #include "cmsys/FStream.hxx" |
| 19 | |
Ben Boeckel | a02c4cc | 2019-03-12 19:16:46 | [diff] [blame] | 20 | #include "cmGeneratedFileStream.h" |
| 21 | #include "cmStringAlgorithms.h" |
| 22 | #include "cmSystemTools.h" |
| 23 | |
| 24 | static bool ParseFilename(Json::Value const& val, std::string& result) |
| 25 | { |
Brad King | 2cb1d77 | 2020-11-18 15:42:57 | [diff] [blame] | 26 | if (val.isString()) { |
Ben Boeckel | a02c4cc | 2019-03-12 19:16:46 | [diff] [blame] | 27 | result = val.asString(); |
| 28 | } else { |
| 29 | return false; |
| 30 | } |
| 31 | |
| 32 | return true; |
| 33 | } |
| 34 | |
| 35 | static Json::Value EncodeFilename(std::string const& path) |
| 36 | { |
Brad King | 2cb1d77 | 2020-11-18 15:42:57 | [diff] [blame] | 37 | std::string data; |
| 38 | data.reserve(path.size()); |
Ben Boeckel | a02c4cc | 2019-03-12 19:16:46 | [diff] [blame] | 39 | |
Brad King | 2cb1d77 | 2020-11-18 15:42:57 | [diff] [blame] | 40 | for (auto const& byte : path) { |
| 41 | if (std::iscntrl(byte)) { |
| 42 | // Control characters. |
| 43 | data.append("\\u"); |
| 44 | char buf[5]; |
| 45 | std::snprintf(buf, sizeof(buf), "%04x", byte); |
| 46 | data.append(buf); |
| 47 | } else if (byte == '"' || byte == '\\') { |
| 48 | // Special JSON characters. |
| 49 | data.push_back('\\'); |
| 50 | data.push_back(byte); |
| 51 | } else { |
| 52 | // Other data. |
| 53 | data.push_back(byte); |
Ben Boeckel | a02c4cc | 2019-03-12 19:16:46 | [diff] [blame] | 54 | } |
Ben Boeckel | a02c4cc | 2019-03-12 19:16:46 | [diff] [blame] | 55 | } |
| 56 | |
| 57 | return data; |
| 58 | } |
| 59 | |
| 60 | #define PARSE_BLOB(val, res) \ |
| 61 | do { \ |
| 62 | if (!ParseFilename(val, res)) { \ |
Brad King | 988f997 | 2020-12-01 21:47:44 | [diff] [blame] | 63 | cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to parse ", \ |
| 64 | arg_pp, ": invalid blob")); \ |
Ben Boeckel | a02c4cc | 2019-03-12 19:16:46 | [diff] [blame] | 65 | return false; \ |
| 66 | } \ |
| 67 | } while (0) |
| 68 | |
| 69 | #define PARSE_FILENAME(val, res) \ |
| 70 | do { \ |
| 71 | if (!ParseFilename(val, res)) { \ |
Brad King | 988f997 | 2020-12-01 21:47:44 | [diff] [blame] | 72 | cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to parse ", \ |
| 73 | arg_pp, ": invalid filename")); \ |
Ben Boeckel | a02c4cc | 2019-03-12 19:16:46 | [diff] [blame] | 74 | return false; \ |
| 75 | } \ |
| 76 | \ |
Ben Boeckel | 3e5b609 | 2021-06-08 15:27:39 | [diff] [blame] | 77 | if (work_directory && !work_directory->empty() && \ |
| 78 | !cmSystemTools::FileIsFullPath(res)) { \ |
| 79 | res = cmStrCat(*work_directory, '/', res); \ |
Ben Boeckel | a02c4cc | 2019-03-12 19:16:46 | [diff] [blame] | 80 | } \ |
| 81 | } while (0) |
| 82 | |
Brad King | bd12b97 | 2021-05-11 12:24:29 | [diff] [blame] | 83 | bool cmScanDepFormat_P1689_Parse(std::string const& arg_pp, |
| 84 | cmScanDepInfo* info) |
Ben Boeckel | a02c4cc | 2019-03-12 19:16:46 | [diff] [blame] | 85 | { |
| 86 | Json::Value ppio; |
| 87 | Json::Value const& ppi = ppio; |
| 88 | cmsys::ifstream ppf(arg_pp.c_str(), std::ios::in | std::ios::binary); |
| 89 | { |
| 90 | Json::Reader reader; |
| 91 | if (!reader.parse(ppf, ppio, false)) { |
Brad King | 988f997 | 2020-12-01 21:47:44 | [diff] [blame] | 92 | cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to parse ", |
Ben Boeckel | a02c4cc | 2019-03-12 19:16:46 | [diff] [blame] | 93 | arg_pp, |
| 94 | reader.getFormattedErrorMessages())); |
| 95 | return false; |
| 96 | } |
| 97 | } |
| 98 | |
| 99 | Json::Value const& version = ppi["version"]; |
Brad King | 9ed1d7b | 2021-11-03 14:50:54 | [diff] [blame] | 100 | if (version.asUInt() > 1) { |
Brad King | 988f997 | 2020-12-01 21:47:44 | [diff] [blame] | 101 | cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to parse ", |
Ben Boeckel | a02c4cc | 2019-03-12 19:16:46 | [diff] [blame] | 102 | arg_pp, ": version ", version.asString())); |
| 103 | return false; |
| 104 | } |
| 105 | |
Ben Boeckel | a02c4cc | 2019-03-12 19:16:46 | [diff] [blame] | 106 | Json::Value const& rules = ppi["rules"]; |
| 107 | if (rules.isArray()) { |
| 108 | if (rules.size() != 1) { |
Brad King | 988f997 | 2020-12-01 21:47:44 | [diff] [blame] | 109 | cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to parse ", |
Ben Boeckel | a02c4cc | 2019-03-12 19:16:46 | [diff] [blame] | 110 | arg_pp, ": expected 1 source entry")); |
| 111 | return false; |
| 112 | } |
| 113 | |
| 114 | for (auto const& rule : rules) { |
Ben Boeckel | 3e5b609 | 2021-06-08 15:27:39 | [diff] [blame] | 115 | cm::optional<std::string> work_directory; |
Brad King | 2cb1d77 | 2020-11-18 15:42:57 | [diff] [blame] | 116 | Json::Value const& workdir = rule["work-directory"]; |
Brad King | 3a71534 | 2021-05-12 14:05:50 | [diff] [blame] | 117 | if (workdir.isString()) { |
Ben Boeckel | 3e5b609 | 2021-06-08 15:27:39 | [diff] [blame] | 118 | std::string wd; |
| 119 | PARSE_BLOB(workdir, wd); |
| 120 | work_directory = std::move(wd); |
Brad King | 3a71534 | 2021-05-12 14:05:50 | [diff] [blame] | 121 | } else if (!workdir.isNull()) { |
Brad King | 988f997 | 2020-12-01 21:47:44 | [diff] [blame] | 122 | cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to parse ", |
| 123 | arg_pp, |
| 124 | ": work-directory is not a string")); |
Brad King | 2cb1d77 | 2020-11-18 15:42:57 | [diff] [blame] | 125 | return false; |
| 126 | } |
Brad King | 2cb1d77 | 2020-11-18 15:42:57 | [diff] [blame] | 127 | |
Ben Boeckel | aab9a5f | 2021-06-08 15:27:39 | [diff] [blame] | 128 | if (rule.isMember("primary-output")) { |
| 129 | Json::Value const& primary_output = rule["primary-output"]; |
| 130 | PARSE_FILENAME(primary_output, info->PrimaryOutput); |
| 131 | } |
| 132 | |
Ben Boeckel | 82c867a | 2021-06-08 15:27:39 | [diff] [blame] | 133 | if (rule.isMember("outputs")) { |
| 134 | Json::Value const& outputs = rule["outputs"]; |
| 135 | if (outputs.isArray()) { |
Ben Boeckel | aab9a5f | 2021-06-08 15:27:39 | [diff] [blame] | 136 | for (auto const& output : outputs) { |
| 137 | std::string extra_output; |
| 138 | PARSE_FILENAME(output, extra_output); |
Ben Boeckel | a02c4cc | 2019-03-12 19:16:46 | [diff] [blame] | 139 | |
Ben Boeckel | aab9a5f | 2021-06-08 15:27:39 | [diff] [blame] | 140 | info->ExtraOutputs.emplace_back(extra_output); |
| 141 | } |
Ben Boeckel | 82c867a | 2021-06-08 15:27:39 | [diff] [blame] | 142 | } |
| 143 | } |
| 144 | |
| 145 | if (rule.isMember("provides")) { |
| 146 | Json::Value const& provides = rule["provides"]; |
Ben Boeckel | b0a8fa9 | 2021-06-08 15:27:39 | [diff] [blame] | 147 | if (!provides.isArray()) { |
| 148 | cmSystemTools::Error( |
| 149 | cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp, |
| 150 | ": provides is not an array")); |
| 151 | return false; |
| 152 | } |
Ben Boeckel | 82c867a | 2021-06-08 15:27:39 | [diff] [blame] | 153 | |
Ben Boeckel | b0a8fa9 | 2021-06-08 15:27:39 | [diff] [blame] | 154 | for (auto const& provide : provides) { |
| 155 | cmSourceReqInfo provide_info; |
Ben Boeckel | 82c867a | 2021-06-08 15:27:39 | [diff] [blame] | 156 | |
Ben Boeckel | b0a8fa9 | 2021-06-08 15:27:39 | [diff] [blame] | 157 | Json::Value const& logical_name = provide["logical-name"]; |
| 158 | PARSE_BLOB(logical_name, provide_info.LogicalName); |
Ben Boeckel | a02c4cc | 2019-03-12 19:16:46 | [diff] [blame] | 159 | |
Ben Boeckel | b0a8fa9 | 2021-06-08 15:27:39 | [diff] [blame] | 160 | if (provide.isMember("compiled-module-path")) { |
| 161 | Json::Value const& compiled_module_path = |
| 162 | provide["compiled-module-path"]; |
| 163 | PARSE_FILENAME(compiled_module_path, |
| 164 | provide_info.CompiledModulePath); |
Ben Boeckel | a02c4cc | 2019-03-12 19:16:46 | [diff] [blame] | 165 | } |
Ben Boeckel | b0a8fa9 | 2021-06-08 15:27:39 | [diff] [blame] | 166 | |
Ben Boeckel | ccc0466 | 2021-06-08 15:27:39 | [diff] [blame] | 167 | if (provide.isMember("unique-on-source-path")) { |
| 168 | Json::Value const& unique_on_source_path = |
| 169 | provide["unique-on-source-path"]; |
| 170 | if (!unique_on_source_path.isBool()) { |
| 171 | cmSystemTools::Error( |
| 172 | cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp, |
| 173 | ": unique-on-source-path is not a boolean")); |
| 174 | return false; |
| 175 | } |
| 176 | provide_info.UseSourcePath = unique_on_source_path.asBool(); |
| 177 | } else { |
| 178 | provide_info.UseSourcePath = false; |
| 179 | } |
| 180 | |
| 181 | if (provide.isMember("source-path")) { |
| 182 | Json::Value const& source_path = provide["source-path"]; |
| 183 | PARSE_FILENAME(source_path, provide_info.SourcePath); |
| 184 | } else if (provide_info.UseSourcePath) { |
| 185 | cmSystemTools::Error( |
| 186 | cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp, |
| 187 | ": source-path is missing")); |
| 188 | return false; |
| 189 | } |
| 190 | |
Ben Boeckel | d7f5064 | 2022-07-18 16:05:58 | [diff] [blame] | 191 | if (provide.isMember("is-interface")) { |
| 192 | Json::Value const& is_interface = provide["is-interface"]; |
| 193 | if (!is_interface.isBool()) { |
| 194 | cmSystemTools::Error( |
| 195 | cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp, |
| 196 | ": is-interface is not a boolean")); |
| 197 | return false; |
| 198 | } |
| 199 | provide_info.IsInterface = is_interface.asBool(); |
| 200 | } else { |
| 201 | provide_info.IsInterface = true; |
| 202 | } |
| 203 | |
Ben Boeckel | b0a8fa9 | 2021-06-08 15:27:39 | [diff] [blame] | 204 | info->Provides.push_back(provide_info); |
Ben Boeckel | a02c4cc | 2019-03-12 19:16:46 | [diff] [blame] | 205 | } |
Ben Boeckel | 82c867a | 2021-06-08 15:27:39 | [diff] [blame] | 206 | } |
Ben Boeckel | a02c4cc | 2019-03-12 19:16:46 | [diff] [blame] | 207 | |
Ben Boeckel | 82c867a | 2021-06-08 15:27:39 | [diff] [blame] | 208 | if (rule.isMember("requires")) { |
| 209 | Json::Value const& reqs = rule["requires"]; |
Ben Boeckel | b0a8fa9 | 2021-06-08 15:27:39 | [diff] [blame] | 210 | if (!reqs.isArray()) { |
| 211 | cmSystemTools::Error( |
| 212 | cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp, |
| 213 | ": requires is not an array")); |
| 214 | return false; |
| 215 | } |
Ben Boeckel | a02c4cc | 2019-03-12 19:16:46 | [diff] [blame] | 216 | |
Ben Boeckel | b0a8fa9 | 2021-06-08 15:27:39 | [diff] [blame] | 217 | for (auto const& require : reqs) { |
| 218 | cmSourceReqInfo require_info; |
Ben Boeckel | a02c4cc | 2019-03-12 19:16:46 | [diff] [blame] | 219 | |
Ben Boeckel | b0a8fa9 | 2021-06-08 15:27:39 | [diff] [blame] | 220 | Json::Value const& logical_name = require["logical-name"]; |
| 221 | PARSE_BLOB(logical_name, require_info.LogicalName); |
Ben Boeckel | a02c4cc | 2019-03-12 19:16:46 | [diff] [blame] | 222 | |
Ben Boeckel | b0a8fa9 | 2021-06-08 15:27:39 | [diff] [blame] | 223 | if (require.isMember("compiled-module-path")) { |
| 224 | Json::Value const& compiled_module_path = |
| 225 | require["compiled-module-path"]; |
| 226 | PARSE_FILENAME(compiled_module_path, |
| 227 | require_info.CompiledModulePath); |
Ben Boeckel | a02c4cc | 2019-03-12 19:16:46 | [diff] [blame] | 228 | } |
Ben Boeckel | b0a8fa9 | 2021-06-08 15:27:39 | [diff] [blame] | 229 | |
Ben Boeckel | ccc0466 | 2021-06-08 15:27:39 | [diff] [blame] | 230 | if (require.isMember("unique-on-source-path")) { |
| 231 | Json::Value const& unique_on_source_path = |
| 232 | require["unique-on-source-path"]; |
| 233 | if (!unique_on_source_path.isBool()) { |
| 234 | cmSystemTools::Error( |
| 235 | cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp, |
| 236 | ": unique-on-source-path is not a boolean")); |
| 237 | return false; |
| 238 | } |
| 239 | require_info.UseSourcePath = unique_on_source_path.asBool(); |
| 240 | } else { |
| 241 | require_info.UseSourcePath = false; |
| 242 | } |
| 243 | |
| 244 | if (require.isMember("source-path")) { |
| 245 | Json::Value const& source_path = require["source-path"]; |
| 246 | PARSE_FILENAME(source_path, require_info.SourcePath); |
| 247 | } else if (require_info.UseSourcePath) { |
| 248 | cmSystemTools::Error( |
| 249 | cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp, |
| 250 | ": source-path is missing")); |
| 251 | return false; |
| 252 | } |
| 253 | |
| 254 | if (require.isMember("lookup-method")) { |
| 255 | Json::Value const& lookup_method = require["lookup-method"]; |
| 256 | if (!lookup_method.isString()) { |
| 257 | cmSystemTools::Error( |
| 258 | cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp, |
| 259 | ": lookup-method is not a string")); |
| 260 | return false; |
| 261 | } |
| 262 | |
| 263 | std::string lookup_method_str = lookup_method.asString(); |
| 264 | if (lookup_method_str == "by-name"_s) { |
| 265 | require_info.Method = LookupMethod::ByName; |
| 266 | } else if (lookup_method_str == "include-angle"_s) { |
| 267 | require_info.Method = LookupMethod::IncludeAngle; |
| 268 | } else if (lookup_method_str == "include-quote"_s) { |
| 269 | require_info.Method = LookupMethod::IncludeQuote; |
| 270 | } else { |
| 271 | cmSystemTools::Error(cmStrCat( |
| 272 | "-E cmake_ninja_dyndep failed to parse ", arg_pp, |
| 273 | ": lookup-method is not a valid: ", lookup_method_str)); |
| 274 | return false; |
| 275 | } |
| 276 | } else if (require_info.UseSourcePath) { |
| 277 | require_info.Method = LookupMethod::ByName; |
| 278 | } |
| 279 | |
Ben Boeckel | b0a8fa9 | 2021-06-08 15:27:39 | [diff] [blame] | 280 | info->Requires.push_back(require_info); |
Ben Boeckel | a02c4cc | 2019-03-12 19:16:46 | [diff] [blame] | 281 | } |
| 282 | } |
| 283 | } |
| 284 | } |
| 285 | |
| 286 | return true; |
| 287 | } |
| 288 | |
| 289 | bool cmScanDepFormat_P1689_Write(std::string const& path, |
Brad King | bd12b97 | 2021-05-11 12:24:29 | [diff] [blame] | 290 | cmScanDepInfo const& info) |
Ben Boeckel | a02c4cc | 2019-03-12 19:16:46 | [diff] [blame] | 291 | { |
| 292 | Json::Value ddi(Json::objectValue); |
| 293 | ddi["version"] = 0; |
| 294 | ddi["revision"] = 0; |
Ben Boeckel | a02c4cc | 2019-03-12 19:16:46 | [diff] [blame] | 295 | |
| 296 | Json::Value& rules = ddi["rules"] = Json::arrayValue; |
| 297 | |
| 298 | Json::Value rule(Json::objectValue); |
Ben Boeckel | a02c4cc | 2019-03-12 19:16:46 | [diff] [blame] | 299 | |
Ben Boeckel | aab9a5f | 2021-06-08 15:27:39 | [diff] [blame] | 300 | rule["primary-output"] = EncodeFilename(info.PrimaryOutput); |
| 301 | |
| 302 | Json::Value& rule_outputs = rule["outputs"] = Json::arrayValue; |
| 303 | for (auto const& output : info.ExtraOutputs) { |
| 304 | rule_outputs.append(EncodeFilename(output)); |
| 305 | } |
Ben Boeckel | a02c4cc | 2019-03-12 19:16:46 | [diff] [blame] | 306 | |
Ben Boeckel | 82c867a | 2021-06-08 15:27:39 | [diff] [blame] | 307 | Json::Value& provides = rule["provides"] = Json::arrayValue; |
Ben Boeckel | a02c4cc | 2019-03-12 19:16:46 | [diff] [blame] | 308 | for (auto const& provide : info.Provides) { |
| 309 | Json::Value provide_obj(Json::objectValue); |
| 310 | auto const encoded = EncodeFilename(provide.LogicalName); |
| 311 | provide_obj["logical-name"] = encoded; |
Brad King | 10b2e53 | 2021-06-14 20:14:35 | [diff] [blame] | 312 | if (!provide.CompiledModulePath.empty()) { |
Ben Boeckel | a02c4cc | 2019-03-12 19:16:46 | [diff] [blame] | 313 | provide_obj["compiled-module-path"] = |
| 314 | EncodeFilename(provide.CompiledModulePath); |
| 315 | } |
| 316 | |
Ben Boeckel | ccc0466 | 2021-06-08 15:27:39 | [diff] [blame] | 317 | if (provide.UseSourcePath) { |
| 318 | provide_obj["unique-on-source-path"] = true; |
| 319 | provide_obj["source-path"] = EncodeFilename(provide.SourcePath); |
| 320 | } else if (!provide.SourcePath.empty()) { |
| 321 | provide_obj["source-path"] = EncodeFilename(provide.SourcePath); |
| 322 | } |
Ben Boeckel | a02c4cc | 2019-03-12 19:16:46 | [diff] [blame] | 323 | |
Ben Boeckel | d7f5064 | 2022-07-18 16:05:58 | [diff] [blame] | 324 | provide_obj["is-interface"] = provide.IsInterface; |
| 325 | |
Ben Boeckel | a02c4cc | 2019-03-12 19:16:46 | [diff] [blame] | 326 | provides.append(provide_obj); |
| 327 | } |
| 328 | |
Ben Boeckel | 82c867a | 2021-06-08 15:27:39 | [diff] [blame] | 329 | Json::Value& reqs = rule["requires"] = Json::arrayValue; |
Ben Boeckel | a02c4cc | 2019-03-12 19:16:46 | [diff] [blame] | 330 | for (auto const& require : info.Requires) { |
| 331 | Json::Value require_obj(Json::objectValue); |
| 332 | auto const encoded = EncodeFilename(require.LogicalName); |
| 333 | require_obj["logical-name"] = encoded; |
Brad King | 10b2e53 | 2021-06-14 20:14:35 | [diff] [blame] | 334 | if (!require.CompiledModulePath.empty()) { |
Ben Boeckel | a02c4cc | 2019-03-12 19:16:46 | [diff] [blame] | 335 | require_obj["compiled-module-path"] = |
| 336 | EncodeFilename(require.CompiledModulePath); |
| 337 | } |
| 338 | |
Ben Boeckel | ccc0466 | 2021-06-08 15:27:39 | [diff] [blame] | 339 | if (require.UseSourcePath) { |
| 340 | require_obj["unique-on-source-path"] = true; |
| 341 | require_obj["source-path"] = EncodeFilename(require.SourcePath); |
| 342 | } else if (!require.SourcePath.empty()) { |
| 343 | require_obj["source-path"] = EncodeFilename(require.SourcePath); |
| 344 | } |
| 345 | |
Kitware Robot | 0b96ae1 | 2025-01-23 16:54:40 | [diff] [blame] | 346 | char const* lookup_method = nullptr; |
Ben Boeckel | ccc0466 | 2021-06-08 15:27:39 | [diff] [blame] | 347 | switch (require.Method) { |
| 348 | case LookupMethod::ByName: |
Brad King | 2b9890e | 2021-06-14 19:32:31 | [diff] [blame] | 349 | // No explicit value needed for the default. |
Ben Boeckel | ccc0466 | 2021-06-08 15:27:39 | [diff] [blame] | 350 | break; |
| 351 | case LookupMethod::IncludeAngle: |
| 352 | lookup_method = "include-angle"; |
| 353 | break; |
| 354 | case LookupMethod::IncludeQuote: |
| 355 | lookup_method = "include-quote"; |
| 356 | break; |
| 357 | } |
Brad King | 2b9890e | 2021-06-14 19:32:31 | [diff] [blame] | 358 | if (lookup_method) { |
| 359 | require_obj["lookup-method"] = lookup_method; |
| 360 | } |
Ben Boeckel | a02c4cc | 2019-03-12 19:16:46 | [diff] [blame] | 361 | |
| 362 | reqs.append(require_obj); |
| 363 | } |
| 364 | |
| 365 | rules.append(rule); |
| 366 | |
| 367 | cmGeneratedFileStream ddif(path); |
| 368 | ddif << ddi; |
| 369 | |
| 370 | return !!ddif; |
| 371 | } |