Imported Upstream version 2.8.9
[platform/upstream/cmake.git] / Source / cmCreateTestSourceList.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 "cmCreateTestSourceList.h"
13 #include "cmSourceFile.h"
14
15 // cmCreateTestSourceList
16 bool cmCreateTestSourceList
17 ::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
18 {
19   if (args.size() < 3)
20     {
21     this->SetError("called with wrong number of arguments.");
22     return false;
23     }
24
25
26   std::vector<std::string>::const_iterator i = args.begin();
27   std::string extraInclude;
28   std::string function;
29   std::vector<std::string> tests;
30   // extract extra include and function ot
31   for(; i != args.end(); i++)
32     {
33     if(*i == "EXTRA_INCLUDE")
34       {
35       ++i;
36       if(i == args.end())
37         {
38         this->SetError("incorrect arguments to EXTRA_INCLUDE");
39         return false;
40         }
41       extraInclude = "#include \"";
42       extraInclude += *i;
43       extraInclude += "\"\n";
44       }
45     else if(*i == "FUNCTION")
46       {
47       ++i;
48       if(i == args.end())
49         {
50         this->SetError("incorrect arguments to FUNCTION");
51         return false;
52         }
53       function = *i;
54       function += "(&ac, &av);\n";
55       }
56     else
57       {
58       tests.push_back(*i);
59       }
60     }
61   i = tests.begin();
62
63   // Name of the source list
64
65   const char* sourceList = i->c_str();
66   ++i;
67
68   // Name of the test driver
69   // make sure they specified an extension
70   if (cmSystemTools::GetFilenameExtension(*i).size() < 2)
71     {
72     this->SetError(
73       "You must specify a file extension for the test driver file.");
74     return false;
75     }
76   std::string driver = this->Makefile->GetCurrentOutputDirectory();
77   driver += "/";
78   driver += *i;
79   ++i;
80
81   std::string configFile =
82     this->Makefile->GetRequiredDefinition("CMAKE_ROOT");
83
84   configFile += "/Templates/TestDriver.cxx.in";
85   // Create the test driver file
86
87   std::vector<std::string>::const_iterator testsBegin = i;
88   std::vector<std::string> tests_func_name;
89
90   // The rest of the arguments consist of a list of test source files.
91   // Sadly, they can be in directories. Let's find a unique function
92   // name for the corresponding test, and push it to the tests_func_name
93   // list.
94   // For the moment:
95   //   - replace spaces ' ', ':' and '/' with underscores '_'
96   std::string forwardDeclareCode;
97   for(i = testsBegin; i != tests.end(); ++i)
98     {
99     if(*i == "EXTRA_INCLUDE")
100       {
101       break;
102       }
103     std::string func_name;
104     if (cmSystemTools::GetFilenamePath(*i).size() > 0)
105       {
106       func_name = cmSystemTools::GetFilenamePath(*i) + "/" +
107         cmSystemTools::GetFilenameWithoutLastExtension(*i);
108       }
109     else
110       {
111       func_name = cmSystemTools::GetFilenameWithoutLastExtension(*i);
112       }
113     cmSystemTools::ConvertToUnixSlashes(func_name);
114     cmSystemTools::ReplaceString(func_name, " ", "_");
115     cmSystemTools::ReplaceString(func_name, "/", "_");
116     cmSystemTools::ReplaceString(func_name, ":", "_");
117     tests_func_name.push_back(func_name);
118     forwardDeclareCode += "int ";
119     forwardDeclareCode += func_name;
120     forwardDeclareCode += "(int, char*[]);\n";
121     }
122
123   std::string functionMapCode;
124   int numTests = 0;
125   std::vector<std::string>::iterator j;
126   for(i = testsBegin, j = tests_func_name.begin(); i != tests.end(); ++i, ++j)
127     {
128     std::string func_name;
129     if (cmSystemTools::GetFilenamePath(*i).size() > 0)
130       {
131       func_name = cmSystemTools::GetFilenamePath(*i) + "/" +
132         cmSystemTools::GetFilenameWithoutLastExtension(*i);
133       }
134     else
135       {
136       func_name = cmSystemTools::GetFilenameWithoutLastExtension(*i);
137       }
138     functionMapCode += "  {\n"
139       "    \"";
140     functionMapCode += func_name;
141     functionMapCode += "\",\n"
142       "    ";
143     functionMapCode +=  *j;
144     functionMapCode += "\n"
145       "  },\n";
146     numTests++;
147     }
148   if(extraInclude.size())
149     {
150     this->Makefile->AddDefinition("CMAKE_TESTDRIVER_EXTRA_INCLUDES",
151                                   extraInclude.c_str());
152     }
153   if(function.size())
154     {
155     this->Makefile->AddDefinition("CMAKE_TESTDRIVER_ARGVC_FUNCTION",
156                                   function.c_str());
157     }
158   this->Makefile->AddDefinition("CMAKE_FORWARD_DECLARE_TESTS",
159     forwardDeclareCode.c_str());
160   this->Makefile->AddDefinition("CMAKE_FUNCTION_TABLE_ENTIRES",
161     functionMapCode.c_str());
162   bool res = true;
163   if ( !this->Makefile->ConfigureFile(configFile.c_str(), driver.c_str(),
164       false, true, false) )
165     {
166     res = false;
167     }
168
169   // Construct the source list.
170   std::string sourceListValue;
171   {
172   cmSourceFile* sf = this->Makefile->GetOrCreateSource(driver.c_str());
173   sf->SetProperty("ABSTRACT","0");
174   sourceListValue = args[1];
175   }
176   for(i = testsBegin; i != tests.end(); ++i)
177     {
178     cmSourceFile* sf = this->Makefile->GetOrCreateSource(i->c_str());
179     sf->SetProperty("ABSTRACT","0");
180     sourceListValue += ";";
181     sourceListValue += *i;
182     }
183
184   this->Makefile->AddDefinition(sourceList, sourceListValue.c_str());
185   return res;
186 }
187
188
189