| 245 | } |
| 246 | |
| 247 | void cmFastbuildTargetGenerator::AddOutput(cmCustomCommandGenerator const& ccg, |
| 248 | FastbuildExecNode& exec) |
| 249 | { |
| 250 | std::string dummyOutput = cmSystemTools::JoinPath( |
| 251 | { LocalCommonGenerator->GetMakefile()->GetHomeOutputDirectory(), |
| 252 | "/_fbuild_dummy" }); |
| 253 | this->GetGlobalGenerator()->AllFoldersToClean.insert(dummyOutput); |
| 254 | |
| 255 | dummyOutput.append("/").append(exec.Name).append( |
| 256 | FASTBUILD_DUMMY_OUTPUT_EXTENSION); |
| 257 | |
| 258 | std::vector<std::string> const& outputs = ccg.GetOutputs(); |
| 259 | std::vector<std::string> const& byproducts = ccg.GetByproducts(); |
| 260 | |
| 261 | exec.OutputsAlias.Name = exec.Name + FASTBUILD_OUTPUTS_ALIAS_POSTFIX; |
| 262 | // If CC doesn't have any output - we should always run it. |
| 263 | // Tested in "RunCMake.CMakePresetsBuild" test. |
| 264 | bool hasAnyNonSymbolicOutput = false; |
| 265 | |
| 266 | bool const trackByproducts = |
| 267 | this->Makefile->IsDefinitionSet(FASTBUILD_TRACK_BYPRODUCTS_AS_OUTPUT); |
| 268 | |
| 269 | auto const isSymbolic = [this](std::string const& file) { |
| 270 | cmSourceFile* sf = this->Makefile->GetSource(file); |
| 271 | if (sf && sf->GetPropertyAsBool("SYMBOLIC")) { |
| 272 | LogMessage("Skipping symbolic file: " + file); |
| 273 | return true; |
| 274 | } |
| 275 | return false; |
| 276 | }; |
| 277 | |
| 278 | for (std::string const& output : outputs) { |
| 279 | // Tested in "RunCMake.BuildDepends". |
| 280 | if (isSymbolic(output)) { |
| 281 | continue; |
| 282 | } |
| 283 | hasAnyNonSymbolicOutput = true; |
| 284 | std::string const outputPath = this->ConvertToFastbuildPath(output); |
| 285 | LogMessage("CC's output: " + outputPath); |
| 286 | exec.OutputsAlias.PreBuildDependencies.emplace(outputPath); |
| 287 | // Ensure output path exists. For some reason, "CMake -E touch" fails with |
| 288 | // "cmake -E touch: failed to update "... |
| 289 | cmSystemTools::MakeDirectory(cmSystemTools::GetFilenamePath(outputPath)); |
| 290 | this->GetGlobalGenerator()->AddFileToClean(outputPath); |
| 291 | } |
| 292 | |
| 293 | exec.ByproductsAlias.Name = exec.Name + FASTBUILD_BYPRODUCTS_ALIAS_POSTFIX; |
| 294 | for (std::string const& byproduct : byproducts) { |
| 295 | if (trackByproducts) { |
| 296 | hasAnyNonSymbolicOutput = true; |
| 297 | } |
| 298 | std::string const byproductPath = this->ConvertToFastbuildPath(byproduct); |
| 299 | exec.ByproductsAlias.PreBuildDependencies.emplace(byproductPath); |
| 300 | this->GetGlobalGenerator()->AddFileToClean(byproductPath); |
| 301 | } |
| 302 | |
| 303 | auto const addDummyOutput = [&] { |
| 304 | // So that the dummy file is always created. |
nothing calls this directly
no test coverage detected