cmNinjaUtilityTargetGenerator.cxx 5.55 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
/*============================================================================
  CMake - Cross Platform Makefile Generator
  Copyright 2011 Peter Collingbourne <peter@pcc.me.uk>
  Copyright 2011 Nicolas Despres <nicolas.despres@gmail.com>

  Distributed under the OSI-approved BSD License (the "License");
  see accompanying file Copyright.txt for details.

  This software is distributed WITHOUT ANY WARRANTY; without even the
  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  See the License for more information.
============================================================================*/
13
14
15
16
17
18
19
#include "cmNinjaUtilityTargetGenerator.h"
#include "cmCustomCommand.h"
#include "cmGeneratedFileStream.h"
#include "cmGlobalNinjaGenerator.h"
#include "cmMakefile.h"
#include "cmSourceFile.h"
#include "cmTarget.h"
20
#include "cmCustomCommandGenerator.h"
21

22
23
cmNinjaUtilityTargetGenerator::cmNinjaUtilityTargetGenerator(
    cmGeneratorTarget *target)
24
  : cmNinjaTargetGenerator(target) {}
25
26
27
28
29

cmNinjaUtilityTargetGenerator::~cmNinjaUtilityTargetGenerator() {}

void cmNinjaUtilityTargetGenerator::Generate()
{
30
31
32
  std::string utilCommandName = cmake::GetCMakeFilesDirectoryPostSlash();
  utilCommandName += this->GetTargetName() + ".util";

33
  std::vector<std::string> commands;
34
  cmNinjaDeps deps, outputs, util_outputs(1, utilCommandName);
35
36
37
38
39
40

  const std::vector<cmCustomCommand> *cmdLists[2] = {
    &this->GetTarget()->GetPreBuildCommands(),
    &this->GetTarget()->GetPostBuildCommands()
  };

41
42
  bool uses_terminal = false;

43
44
45
  for (unsigned i = 0; i != 2; ++i) {
    for (std::vector<cmCustomCommand>::const_iterator
         ci = cmdLists[i]->begin(); ci != cmdLists[i]->end(); ++ci) {
46
47
48
49
      cmCustomCommandGenerator ccg(*ci, this->GetConfigName(),
                                   this->GetMakefile());
      this->GetLocalGenerator()->AppendCustomCommandDeps(ccg, deps);
      this->GetLocalGenerator()->AppendCustomCommandLines(ccg, commands);
50
51
52
      std::vector<std::string> const& ccByproducts = ccg.GetByproducts();
      std::transform(ccByproducts.begin(), ccByproducts.end(),
                     std::back_inserter(util_outputs), MapToNinjaPath());
53
54
      if (ci->GetUsesTerminal())
        uses_terminal = true;
55
56
57
    }
  }

58
  std::vector<cmSourceFile*> sources;
59
60
61
  std::string config = this->GetMakefile()
                           ->GetSafeDefinition("CMAKE_BUILD_TYPE");
  this->GetTarget()->GetSourceFiles(sources, config);
62
63
64
65
66
  for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
      source != sources.end(); ++source)
    {
    if(cmCustomCommand* cc = (*source)->GetCustomCommand())
      {
67
68
      cmCustomCommandGenerator ccg(*cc, this->GetConfigName(),
                                   this->GetMakefile());
69
70
71
      this->GetLocalGenerator()->AddCustomCommandTarget(cc, this->GetTarget());

      // Depend on all custom command outputs.
72
      const std::vector<std::string>& ccOutputs = ccg.GetOutputs();
73
      const std::vector<std::string>& ccByproducts = ccg.GetByproducts();
74
      std::transform(ccOutputs.begin(), ccOutputs.end(),
75
                     std::back_inserter(deps), MapToNinjaPath());
76
77
      std::transform(ccByproducts.begin(), ccByproducts.end(),
                     std::back_inserter(deps), MapToNinjaPath());
78
79
80
81
82
83
84
      }
    }

  this->GetLocalGenerator()->AppendTargetOutputs(this->GetTarget(), outputs);
  this->GetLocalGenerator()->AppendTargetDepends(this->GetTarget(), deps);

  if (commands.empty()) {
85
86
87
88
89
    this->GetGlobalGenerator()->WritePhonyBuild(this->GetBuildFileStream(),
                                                "Utility command for "
                                                  + this->GetTargetName(),
                                                outputs,
                                                deps);
90
91
92
93
94
95
96
97
98
99
100
101
  } else {
    std::string command =
      this->GetLocalGenerator()->BuildCommandLine(commands);
    const char *echoStr = this->GetTarget()->GetProperty("EchoString");
    std::string desc;
    if (echoStr)
      desc = echoStr;
    else
      desc = "Running utility command for " + this->GetTargetName();

    // TODO: fix problematic global targets.  For now, search and replace the
    // makefile vars.
102
103
104
105
106
107
108
109
110
111
112
113
    cmSystemTools::ReplaceString(
      command,
      "$(CMAKE_SOURCE_DIR)",
      this->GetLocalGenerator()->ConvertToOutputFormat(
        this->GetTarget()->GetMakefile()->GetHomeDirectory(),
        cmLocalGenerator::SHELL).c_str());
    cmSystemTools::ReplaceString(
      command,
      "$(CMAKE_BINARY_DIR)",
      this->GetLocalGenerator()->ConvertToOutputFormat(
        this->GetTarget()->GetMakefile()->GetHomeOutputDirectory(),
        cmLocalGenerator::SHELL).c_str());
114
115
116
117
118
    cmSystemTools::ReplaceString(command, "$(ARGS)", "");

    if (command.find('$') != std::string::npos)
      return;

119
120
121
122
123
124
    for (cmNinjaDeps::const_iterator
           oi = util_outputs.begin(), oe = util_outputs.end();
         oi != oe; ++oi)
      {
      this->GetGlobalGenerator()->SeenCustomCommandOutput(*oi);
      }
125
126
127
128
129

    this->GetGlobalGenerator()->WriteCustomCommandBuild(
      command,
      desc,
      "Utility command for " + this->GetTargetName(),
130
      uses_terminal,
131
      util_outputs,
132
133
      deps);

134
135
136
137
138
    this->GetGlobalGenerator()->WritePhonyBuild(this->GetBuildFileStream(),
                                                "",
                                                outputs,
                                                cmNinjaDeps(1, utilCommandName)
                                                );
139
140
141
142
143
  }

  this->GetGlobalGenerator()->AddTargetAlias(this->GetTargetName(),
                                             this->GetTarget());
}