1 /*============================================================================
2 CMake - Cross Platform Makefile Generator
3 Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
5 Distributed under the OSI-approved BSD License (the "License");
6 see accompanying file Copyright.txt for details.
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 "cmLocalVisualStudioGenerator.h"
13 #include "cmGlobalGenerator.h"
14 #include "cmMakefile.h"
15 #include "cmSourceFile.h"
16 #include "cmSystemTools.h"
17 #include "cmCustomCommandGenerator.h"
20 //----------------------------------------------------------------------------
21 cmLocalVisualStudioGenerator::cmLocalVisualStudioGenerator(VSVersion v)
23 this->WindowsShell = true;
24 this->WindowsVSIDE = true;
28 //----------------------------------------------------------------------------
29 cmLocalVisualStudioGenerator::~cmLocalVisualStudioGenerator()
33 //----------------------------------------------------------------------------
34 cmsys::auto_ptr<cmCustomCommand>
35 cmLocalVisualStudioGenerator::MaybeCreateImplibDir(cmTarget& target,
39 cmsys::auto_ptr<cmCustomCommand> pcc;
41 // If an executable exports symbols then VS wants to create an
42 // import library but forgets to create the output directory.
43 // The Intel Fortran plugin always forgets to the directory.
44 if(target.GetType() != cmTarget::EXECUTABLE &&
45 !(isFortran && target.GetType() == cmTarget::SHARED_LIBRARY))
47 std::string outDir = target.GetDirectory(config, false);
48 std::string impDir = target.GetDirectory(config, true);
49 if(impDir == outDir) { return pcc; }
51 // Add a pre-build event to create the directory.
52 cmCustomCommandLine command;
53 command.push_back(this->Makefile->GetRequiredDefinition("CMAKE_COMMAND"));
54 command.push_back("-E");
55 command.push_back("make_directory");
56 command.push_back(impDir);
57 std::vector<std::string> no_output;
58 std::vector<std::string> no_depends;
59 cmCustomCommandLines commands;
60 commands.push_back(command);
61 pcc.reset(new cmCustomCommand(0, no_output, no_depends, commands, 0, 0));
62 pcc->SetEscapeOldStyle(false);
63 pcc->SetEscapeAllowMakeVars(true);
67 //----------------------------------------------------------------------------
68 const char* cmLocalVisualStudioGenerator::ReportErrorLabel() const
70 return ":VCReportError";
73 //----------------------------------------------------------------------------
74 const char* cmLocalVisualStudioGenerator::GetReportErrorLabel() const
76 return this->ReportErrorLabel();
79 //----------------------------------------------------------------------------
81 cmLocalVisualStudioGenerator
82 ::ConstructScript(cmCustomCommand const& cc,
83 const char* configName,
84 const char* newline_text)
86 bool useLocal = this->CustomCommandUseLocal();
87 const cmCustomCommandLines& commandLines = cc.GetCommandLines();
88 const char* workingDirectory = cc.GetWorkingDirectory();
89 cmCustomCommandGenerator ccg(cc, configName, this->Makefile);
90 RelativeRoot relativeRoot = workingDirectory? NONE : START_OUTPUT;
92 // Avoid leading or trailing newlines.
93 const char* newline = "";
95 // Line to check for error between commands.
96 std::string check_error = newline_text;
99 check_error += "if %errorlevel% neq 0 goto :cmEnd";
103 check_error += "if errorlevel 1 goto ";
104 check_error += this->GetReportErrorLabel();
107 // Store the script in a string.
110 // Open a local context.
114 newline = newline_text;
115 script += "setlocal";
120 // Change the working directory.
122 newline = newline_text;
124 script += this->Convert(workingDirectory, FULL, SHELL);
125 script += check_error;
127 // Change the working drive.
128 if(workingDirectory[0] && workingDirectory[1] == ':')
131 newline = newline_text;
132 script += workingDirectory[0];
133 script += workingDirectory[1];
134 script += check_error;
138 // for visual studio IDE add extra stuff to the PATH
139 // if CMAKE_MSVCIDE_RUN_PATH is set.
140 if(this->Makefile->GetDefinition("MSVC_IDE"))
142 const char* extraPath =
143 this->Makefile->GetDefinition("CMAKE_MSVCIDE_RUN_PATH");
147 newline = newline_text;
148 script += "set PATH=";
154 // Write each command on a single line.
155 for(unsigned int c = 0; c < ccg.GetNumberOfCommands(); ++c)
159 newline = newline_text;
161 // Add this command line.
162 std::string cmd = ccg.GetCommand(c);
164 // Use "call " before any invocations of .bat or .cmd files
165 // invoked as custom commands.
170 suffix = cmSystemTools::LowerCase(cmd.substr(cmd.size()-4));
171 if (suffix == ".bat" || suffix == ".cmd")
177 script += this->Convert(cmd.c_str(), relativeRoot, SHELL);
178 ccg.AppendArguments(c, script);
180 // After each custom command, check for an error result.
181 // If there was an error, jump to the VCReportError label,
182 // skipping the run of any subsequent commands in this
184 script += check_error;
187 // Close the local context.
193 script += "endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone";
195 script += ":cmErrorLevel";
197 script += "exit /b %1";
201 script += "if %errorlevel% neq 0 goto ";
202 script += this->GetReportErrorLabel();