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 char* workingDirectory = cc.GetWorkingDirectory();
88 cmCustomCommandGenerator ccg(cc, configName, this->Makefile);
89 RelativeRoot relativeRoot = workingDirectory? NONE : START_OUTPUT;
91 // Avoid leading or trailing newlines.
92 const char* newline = "";
94 // Line to check for error between commands.
95 std::string check_error = newline_text;
98 check_error += "if %errorlevel% neq 0 goto :cmEnd";
102 check_error += "if errorlevel 1 goto ";
103 check_error += this->GetReportErrorLabel();
106 // Store the script in a string.
109 // Open a local context.
113 newline = newline_text;
114 script += "setlocal";
119 // Change the working directory.
121 newline = newline_text;
123 script += this->Convert(workingDirectory, FULL, SHELL);
124 script += check_error;
126 // Change the working drive.
127 if(workingDirectory[0] && workingDirectory[1] == ':')
130 newline = newline_text;
131 script += workingDirectory[0];
132 script += workingDirectory[1];
133 script += check_error;
137 // for visual studio IDE add extra stuff to the PATH
138 // if CMAKE_MSVCIDE_RUN_PATH is set.
139 if(this->Makefile->GetDefinition("MSVC_IDE"))
141 const char* extraPath =
142 this->Makefile->GetDefinition("CMAKE_MSVCIDE_RUN_PATH");
146 newline = newline_text;
147 script += "set PATH=";
153 // Write each command on a single line.
154 for(unsigned int c = 0; c < ccg.GetNumberOfCommands(); ++c)
158 newline = newline_text;
160 // Add this command line.
161 std::string cmd = ccg.GetCommand(c);
163 // Use "call " before any invocations of .bat or .cmd files
164 // invoked as custom commands.
169 suffix = cmSystemTools::LowerCase(cmd.substr(cmd.size()-4));
170 if (suffix == ".bat" || suffix == ".cmd")
176 script += this->Convert(cmd.c_str(), relativeRoot, SHELL);
177 ccg.AppendArguments(c, script);
179 // After each custom command, check for an error result.
180 // If there was an error, jump to the VCReportError label,
181 // skipping the run of any subsequent commands in this
183 script += check_error;
186 // Close the local context.
192 script += "endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone";
194 script += ":cmErrorLevel";
196 script += "exit /b %1";
200 script += "if %errorlevel% neq 0 goto ";
201 script += this->GetReportErrorLabel();