Imported Upstream version 2.8.12.2
[platform/upstream/cmake.git] / Source / cmIncludeDirectoryCommand.cxx
1 /*============================================================================
2   CMake - Cross Platform Makefile Generator
3   Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
4
5   Distributed under the OSI-approved BSD License (the "License");
6   see accompanying file Copyright.txt for details.
7
8   This software is distributed WITHOUT ANY WARRANTY; without even the
9   implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10   See the License for more information.
11 ============================================================================*/
12 #include "cmIncludeDirectoryCommand.h"
13
14 // cmIncludeDirectoryCommand
15 bool cmIncludeDirectoryCommand
16 ::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
17 {
18   if(args.size() < 1 )
19     {
20     return true;
21     }
22
23   std::vector<std::string>::const_iterator i = args.begin();
24
25   bool before = this->Makefile->IsOn("CMAKE_INCLUDE_DIRECTORIES_BEFORE");
26   bool system = false;
27
28   if ((*i) == "BEFORE")
29     {
30     before = true;
31     ++i;
32     }
33   else if ((*i) == "AFTER")
34     {
35     before = false;
36     ++i;
37     }
38
39   std::vector<std::string> beforeIncludes;
40   std::vector<std::string> afterIncludes;
41   std::set<cmStdString> systemIncludes;
42
43   for(; i != args.end(); ++i)
44     {
45     if(*i == "SYSTEM")
46       {
47       system = true;
48       continue;
49       }
50     if(i->size() == 0)
51       {
52       this->SetError("given empty-string as include directory.");
53       return false;
54       }
55
56     std::vector<std::string> includes;
57
58     GetIncludes(*i, includes);
59
60     if (before)
61       {
62       beforeIncludes.insert(beforeIncludes.end(),
63                             includes.begin(),
64                             includes.end());
65       }
66     else
67       {
68       afterIncludes.insert(afterIncludes.end(),
69                            includes.begin(),
70                            includes.end());
71       }
72     if (system)
73       {
74       for (std::vector<std::string>::const_iterator li = includes.begin();
75         li != includes.end(); ++li)
76         {
77         systemIncludes.insert(*li);
78         }
79       }
80     }
81   std::reverse(beforeIncludes.begin(), beforeIncludes.end());
82
83   this->Makefile->AddIncludeDirectories(afterIncludes);
84   this->Makefile->AddIncludeDirectories(beforeIncludes, before);
85   this->Makefile->AddSystemIncludeDirectories(systemIncludes);
86
87   return true;
88 }
89
90 static bool StartsWithGeneratorExpression(const std::string &input)
91 {
92   return input[0] == '$' && input[1] == '<';
93 }
94
95 // do a lot of cleanup on the arguments because this is one place where folks
96 // sometimes take the output of a program and pass it directly into this
97 // command not thinking that a single argument could be filled with spaces
98 // and newlines etc liek below:
99 //
100 // "   /foo/bar
101 //    /boo/hoo /dingle/berry "
102 //
103 // ideally that should be three separate arguments but when sucking the
104 // output from a program and passing it into a command the cleanup doesn't
105 // always happen
106 //
107 void cmIncludeDirectoryCommand::GetIncludes(const std::string &arg,
108                                             std::vector<std::string> &incs)
109 {
110   // break apart any line feed arguments
111   std::string::size_type pos = 0;
112   std::string::size_type lastPos = 0;
113   while((pos = arg.find('\n', lastPos)) != std::string::npos)
114     {
115     if (pos)
116       {
117       std::string inc = arg.substr(lastPos,pos);
118       this->NormalizeInclude(inc);
119       if (!inc.empty())
120         {
121         incs.push_back(inc);
122         }
123       }
124     lastPos = pos + 1;
125     }
126   std::string inc = arg.substr(lastPos);
127   this->NormalizeInclude(inc);
128   if (!inc.empty())
129     {
130     incs.push_back(inc);
131     }
132 }
133
134 void cmIncludeDirectoryCommand::NormalizeInclude(std::string &inc)
135 {
136   std::string::size_type b = inc.find_first_not_of(" \r");
137   std::string::size_type e = inc.find_last_not_of(" \r");
138   if ((b!=inc.npos) && (e!=inc.npos))
139     {
140     inc.assign(inc, b, 1+e-b);   // copy the remaining substring
141     }
142   else
143     {
144     inc = "";
145     return;
146     }
147
148   if (!cmSystemTools::IsOff(inc.c_str()))
149     {
150     cmSystemTools::ConvertToUnixSlashes(inc);
151
152     if(!cmSystemTools::FileIsFullPath(inc.c_str()))
153       {
154       if(!StartsWithGeneratorExpression(inc))
155         {
156         std::string tmp = this->Makefile->GetStartDirectory();
157         tmp += "/";
158         tmp += inc;
159         inc = tmp;
160         }
161       }
162     }
163 }