| 160 | } |
| 161 | |
| 162 | cmCustomCommandGenerator::cmCustomCommandGenerator( |
| 163 | cmCustomCommand const& cc, std::string config, cmLocalGenerator* lg, |
| 164 | bool transformDepfile, cm::optional<std::string> crossConfig, |
| 165 | std::function<std::string(std::string const&, std::string const&)> |
| 166 | computeInternalDepfile) |
| 167 | : CC(&cc) |
| 168 | , OutputConfig(crossConfig ? *crossConfig : config) |
| 169 | , CommandConfig(std::move(config)) |
| 170 | , Target(cc.GetTarget()) |
| 171 | , LG(lg) |
| 172 | , OldStyle(cc.GetEscapeOldStyle()) |
| 173 | , MakeVars(cc.GetEscapeAllowMakeVars()) |
| 174 | , EmulatorsWithArguments(cc.GetCommandLines().size()) |
| 175 | , ComputeInternalDepfile(std::move(computeInternalDepfile)) |
| 176 | { |
| 177 | |
| 178 | cmGeneratorExpression ge(*lg->GetCMakeInstance(), cc.GetBacktrace()); |
| 179 | cmGeneratorTarget const* target{ lg->FindGeneratorTargetToUse( |
| 180 | this->Target) }; |
| 181 | |
| 182 | bool const distinctConfigs = this->OutputConfig != this->CommandConfig; |
| 183 | |
| 184 | cmCustomCommandLines const& cmdlines = this->CC->GetCommandLines(); |
| 185 | for (cmCustomCommandLine const& cmdline : cmdlines) { |
| 186 | cmCustomCommandLine argv; |
| 187 | // For the command itself, we default to the COMMAND_CONFIG. |
| 188 | bool useOutputConfig = false; |
| 189 | for (std::string const& clarg : cmdline) { |
| 190 | std::string parsed_arg = EvaluateSplitConfigGenex( |
| 191 | clarg, ge, this->LG, useOutputConfig, this->OutputConfig, |
| 192 | this->CommandConfig, target, &this->Utilities); |
| 193 | if (this->CC->GetCommandExpandLists()) { |
| 194 | cm::append(argv, cmList{ parsed_arg }); |
| 195 | } else { |
| 196 | argv.push_back(std::move(parsed_arg)); |
| 197 | } |
| 198 | |
| 199 | if (distinctConfigs) { |
| 200 | // For remaining arguments, we default to the OUTPUT_CONFIG. |
| 201 | useOutputConfig = true; |
| 202 | } |
| 203 | } |
| 204 | |
| 205 | if (!argv.empty()) { |
| 206 | // If the command references an executable target by name, |
| 207 | // collect the target to add a target-level dependency on it. |
| 208 | cmGeneratorTarget* gt = this->LG->FindGeneratorTargetToUse(argv.front()); |
| 209 | if (gt && gt->GetType() == cmStateEnums::EXECUTABLE) { |
| 210 | // GetArgv0Location uses the command config, so use a cross-dependency. |
| 211 | bool const cross = true; |
| 212 | this->Utilities.emplace(BT<std::pair<std::string, bool>>( |
| 213 | { gt->GetName(), cross }, cc.GetBacktrace())); |
| 214 | } |
| 215 | } else { |
| 216 | // Later code assumes at least one entry exists, but expanding |
| 217 | // lists on an empty command may have left this empty. |
| 218 | // FIXME: Should we define behavior for removing empty commands? |
| 219 | argv.emplace_back(); |
nothing calls this directly
no test coverage detected