ENH: some cleanup of the makefile generator
This commit is contained in:
parent
3bce601c41
commit
7740ccd1a4
|
@ -0,0 +1,334 @@
|
|||
/*=========================================================================
|
||||
|
||||
Program: CMake - Cross-Platform Makefile Generator
|
||||
Module: $RCSfile$
|
||||
Language: C++
|
||||
Date: $Date$
|
||||
Version: $Revision$
|
||||
|
||||
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
|
||||
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
|
||||
|
||||
This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. See the above copyright notices for more information.
|
||||
|
||||
=========================================================================*/
|
||||
#include "cmMakefileExecutableTargetGenerator.h"
|
||||
|
||||
#include "cmGeneratedFileStream.h"
|
||||
#include "cmGlobalGenerator.h"
|
||||
#include "cmLocalUnixMakefileGenerator3.h"
|
||||
#include "cmMakefile.h"
|
||||
#include "cmSourceFile.h"
|
||||
#include "cmTarget.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmMakefileExecutableTargetGenerator::WriteRuleFiles()
|
||||
{
|
||||
// create the build.make file and directory, put in the common blocks
|
||||
this->CreateRuleFile();
|
||||
|
||||
// Add in any rules for custom commands
|
||||
this->WriteCustomCommandsForTarget();
|
||||
|
||||
// write in rules for object files
|
||||
this->WriteCommonCodeRules();
|
||||
|
||||
// write the link rules
|
||||
this->WriteExecutableRule();
|
||||
|
||||
// Write the requires target.
|
||||
this->WriteTargetRequiresRules();
|
||||
|
||||
// Write clean target
|
||||
this->WriteTargetCleanRules();
|
||||
|
||||
// close the streams
|
||||
this->CloseFileStreams();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmMakefileExecutableTargetGenerator::WriteExecutableRule()
|
||||
{
|
||||
// Write the dependency generation rule.
|
||||
this->WriteTargetDependRules();
|
||||
|
||||
std::vector<std::string> commands;
|
||||
|
||||
std::string relPath = this->LocalGenerator->GetHomeRelativeOutputPath();
|
||||
std::string objTarget;
|
||||
|
||||
// Build list of dependencies.
|
||||
std::vector<std::string> depends;
|
||||
for(std::vector<std::string>::const_iterator obj = this->Objects.begin();
|
||||
obj != this->Objects.end(); ++obj)
|
||||
{
|
||||
objTarget = relPath;
|
||||
objTarget += *obj;
|
||||
depends.push_back(objTarget);
|
||||
}
|
||||
|
||||
// Add dependencies on targets that must be built first.
|
||||
this->AppendTargetDepends(depends);
|
||||
|
||||
// Add a dependency on the rule file itself.
|
||||
this->LocalGenerator->AppendRuleDepend(depends,
|
||||
this->BuildFileNameFull.c_str());
|
||||
|
||||
for(std::vector<std::string>::const_iterator obj =
|
||||
this->ExternalObjects.begin();
|
||||
obj != this->ExternalObjects.end(); ++obj)
|
||||
{
|
||||
depends.push_back(*obj);
|
||||
}
|
||||
|
||||
// from here up is the same for exe or lib
|
||||
|
||||
// Get the name of the executable to generate.
|
||||
std::string targetName;
|
||||
std::string targetNameReal;
|
||||
this->Target->GetExecutableNames(targetName, targetNameReal,
|
||||
this->LocalGenerator->m_ConfigurationName.c_str());
|
||||
|
||||
// Construct the full path version of the names.
|
||||
std::string outpath = this->LocalGenerator->m_ExecutableOutputPath;
|
||||
if(outpath.length() == 0)
|
||||
{
|
||||
outpath = this->Makefile->GetStartOutputDirectory();
|
||||
outpath += "/";
|
||||
}
|
||||
#ifdef __APPLE__
|
||||
if(this->Target->GetPropertyAsBool("MACOSX_BUNDLE"))
|
||||
{
|
||||
// Make bundle directories
|
||||
outpath += this->Target->GetName();
|
||||
outpath += ".app/Contents/MacOS/";
|
||||
std::string f1 =
|
||||
this->Makefile->GetModulesFile("MacOSXBundleInfo.plist.in");
|
||||
if ( f1.size() == 0 )
|
||||
{
|
||||
cmSystemTools::Error("could not find Mac OSX bundle template file.");
|
||||
}
|
||||
std::string macdir =
|
||||
this->Makefile->GetSafeDefinition("EXECUTABLE_OUTPUT_PATH");
|
||||
if ( macdir.size() == 0 )
|
||||
{
|
||||
macdir = this->Makefile->GetCurrentOutputDirectory();
|
||||
}
|
||||
if(macdir.size() && macdir[macdir.size()-1] != '/')
|
||||
{
|
||||
macdir += "/";
|
||||
}
|
||||
macdir += this->Target->GetName();
|
||||
macdir += ".app/Contents/";
|
||||
std::string f2 = macdir + "Info.plist";
|
||||
macdir += "MacOS";
|
||||
cmSystemTools::MakeDirectory(macdir.c_str());
|
||||
this->Makefile->AddDefinition("MACOSX_BUNDLE_EXECUTABLE_NAME", this->Target->GetName());
|
||||
this->Makefile->ConfigureFile(f1.c_str(), f2.c_str(),
|
||||
false, false, false);
|
||||
}
|
||||
#endif
|
||||
std::string targetFullPath = outpath + targetName;
|
||||
std::string targetFullPathReal = outpath + targetNameReal;
|
||||
|
||||
// Convert to the output path to use in constructing commands.
|
||||
std::string targetOutPath =
|
||||
this->Convert(targetFullPath.c_str(),
|
||||
cmLocalGenerator::START_OUTPUT,
|
||||
cmLocalGenerator::MAKEFILE);
|
||||
std::string targetOutPathReal =
|
||||
this->Convert(targetFullPathReal.c_str(),
|
||||
cmLocalGenerator::START_OUTPUT,
|
||||
cmLocalGenerator::MAKEFILE);
|
||||
|
||||
// Get the language to use for linking this executable.
|
||||
const char* linkLanguage =
|
||||
this->Target->GetLinkerLanguage(this->GlobalGenerator);
|
||||
|
||||
// Make sure we have a link language.
|
||||
if(!linkLanguage)
|
||||
{
|
||||
cmSystemTools::Error("Cannot determine link language for target \"",
|
||||
this->Target->GetName(), "\".");
|
||||
return;
|
||||
}
|
||||
|
||||
// Add the link message.
|
||||
std::string buildEcho = "Linking ";
|
||||
buildEcho += linkLanguage;
|
||||
buildEcho += " executable ";
|
||||
buildEcho += targetOutPath;
|
||||
this->LocalGenerator->AppendEcho(commands, buildEcho.c_str());
|
||||
|
||||
// Build a list of compiler flags and linker flags.
|
||||
std::string flags;
|
||||
std::string linkFlags;
|
||||
|
||||
// Add flags to deal with shared libraries. Any library being
|
||||
// linked in might be shared, so always use shared flags for an
|
||||
// executable.
|
||||
this->LocalGenerator->AddSharedFlags(linkFlags, linkLanguage, true);
|
||||
|
||||
// Add flags to create an executable.
|
||||
this->LocalGenerator->
|
||||
AddConfigVariableFlags(linkFlags, "CMAKE_EXE_LINKER_FLAGS");
|
||||
|
||||
|
||||
if(this->Target->GetPropertyAsBool("WIN32_EXECUTABLE"))
|
||||
{
|
||||
this->LocalGenerator->AppendFlags(linkFlags,
|
||||
this->Makefile->GetDefinition("CMAKE_CREATE_WIN32_EXE"));
|
||||
}
|
||||
else
|
||||
{
|
||||
this->LocalGenerator->AppendFlags(linkFlags,
|
||||
this->Makefile->GetDefinition("CMAKE_CREATE_CONSOLE_EXE"));
|
||||
}
|
||||
|
||||
// Add language-specific flags.
|
||||
this->LocalGenerator->AddLanguageFlags(flags, linkLanguage);
|
||||
|
||||
// Add target-specific linker flags.
|
||||
this->LocalGenerator->AppendFlags(linkFlags, this->Target->GetProperty("LINK_FLAGS"));
|
||||
|
||||
// Construct a list of files associated with this executable that
|
||||
// may need to be cleaned.
|
||||
std::vector<std::string> exeCleanFiles;
|
||||
{
|
||||
std::string cleanName;
|
||||
std::string cleanRealName;
|
||||
this->Target->GetExecutableCleanNames(cleanName, cleanRealName,
|
||||
this->LocalGenerator->m_ConfigurationName.c_str());
|
||||
std::string cleanFullName = outpath + cleanName;
|
||||
std::string cleanFullRealName = outpath + cleanRealName;
|
||||
exeCleanFiles.push_back(this->Convert(cleanFullName.c_str(),
|
||||
cmLocalGenerator::START_OUTPUT,
|
||||
cmLocalGenerator::MAKEFILE));
|
||||
if(cleanRealName != cleanName)
|
||||
{
|
||||
exeCleanFiles.push_back(this->Convert(cleanFullRealName.c_str(),
|
||||
cmLocalGenerator::START_OUTPUT,
|
||||
cmLocalGenerator::MAKEFILE));
|
||||
}
|
||||
}
|
||||
|
||||
// Add a command to remove any existing files for this executable.
|
||||
std::vector<std::string> commands1;
|
||||
this->LocalGenerator->AppendCleanCommand(commands1, exeCleanFiles);
|
||||
this->LocalGenerator->CreateCDCommand(commands1,
|
||||
this->Makefile->GetStartOutputDirectory(),
|
||||
this->Makefile->GetHomeOutputDirectory());
|
||||
commands.insert(commands.end(), commands1.begin(), commands1.end());
|
||||
commands1.clear();
|
||||
// Add the pre-build and pre-link rules.
|
||||
this->LocalGenerator->
|
||||
AppendCustomCommands(commands, this->Target->GetPreBuildCommands());
|
||||
this->LocalGenerator->
|
||||
AppendCustomCommands(commands, this->Target->GetPreLinkCommands());
|
||||
|
||||
// Construct the main link rule.
|
||||
std::string linkRuleVar = "CMAKE_";
|
||||
linkRuleVar += linkLanguage;
|
||||
linkRuleVar += "_LINK_EXECUTABLE";
|
||||
std::string linkRule =
|
||||
this->Makefile->GetRequiredDefinition(linkRuleVar.c_str());
|
||||
cmSystemTools::ExpandListArgument(linkRule, commands1);
|
||||
this->LocalGenerator->CreateCDCommand
|
||||
(commands1,
|
||||
this->Makefile->GetStartOutputDirectory(),
|
||||
this->Makefile->GetHomeOutputDirectory());
|
||||
commands.insert(commands.end(), commands1.begin(), commands1.end());
|
||||
|
||||
// Add a rule to create necessary symlinks for the library.
|
||||
if(targetOutPath != targetOutPathReal)
|
||||
{
|
||||
std::string symlink = "$(CMAKE_COMMAND) -E cmake_symlink_executable ";
|
||||
symlink += targetOutPathReal;
|
||||
symlink += " ";
|
||||
symlink += targetOutPath;
|
||||
commands.push_back(symlink);
|
||||
}
|
||||
|
||||
// Add the post-build rules.
|
||||
this->LocalGenerator->AppendCustomCommands
|
||||
(commands, this->Target->GetPostBuildCommands());
|
||||
|
||||
// Collect up flags to link in needed libraries.
|
||||
cmOStringStream linklibs;
|
||||
this->LocalGenerator->OutputLinkLibraries(linklibs, *this->Target);
|
||||
|
||||
// Construct object file lists that may be needed to expand the
|
||||
// rule.
|
||||
std::string variableName;
|
||||
std::string variableNameExternal;
|
||||
this->WriteObjectsVariable(variableName, variableNameExternal);
|
||||
std::string buildObjs = "$(";
|
||||
buildObjs += variableName;
|
||||
buildObjs += ") $(";
|
||||
buildObjs += variableNameExternal;
|
||||
buildObjs += ")";
|
||||
std::string cleanObjs = "$(";
|
||||
cleanObjs += variableName;
|
||||
cleanObjs += ")";
|
||||
|
||||
// Expand placeholders in the commands.
|
||||
for(std::vector<std::string>::iterator i = commands.begin();
|
||||
i != commands.end(); ++i)
|
||||
{
|
||||
this->LocalGenerator->ExpandRuleVariables(*i,
|
||||
linkLanguage,
|
||||
buildObjs.c_str(),
|
||||
targetOutPathReal.c_str(),
|
||||
linklibs.str().c_str(),
|
||||
0,
|
||||
0,
|
||||
flags.c_str(),
|
||||
0,
|
||||
0,
|
||||
linkFlags.c_str());
|
||||
}
|
||||
|
||||
// Write the build rule.
|
||||
this->LocalGenerator->WriteMakeRule(*this->BuildFileStream,
|
||||
0,
|
||||
targetFullPathReal.c_str(),
|
||||
depends, commands);
|
||||
|
||||
// The symlink name for the target should depend on the real target
|
||||
// so if the target version changes it rebuilds and recreates the
|
||||
// symlink.
|
||||
if(targetFullPath != targetFullPathReal)
|
||||
{
|
||||
depends.clear();
|
||||
commands.clear();
|
||||
depends.push_back(targetFullPathReal.c_str());
|
||||
this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
|
||||
targetFullPath.c_str(),
|
||||
depends, commands);
|
||||
}
|
||||
|
||||
// Write convenience targets.
|
||||
std::string dir = this->Makefile->GetStartOutputDirectory();
|
||||
dir += "/";
|
||||
dir += this->LocalGenerator->GetTargetDirectory(*this->Target);
|
||||
std::string buildTargetRuleName = dir;
|
||||
buildTargetRuleName += "/build";
|
||||
buildTargetRuleName =
|
||||
this->Convert(buildTargetRuleName.c_str(),
|
||||
cmLocalGenerator::HOME_OUTPUT,
|
||||
cmLocalGenerator::MAKEFILE);
|
||||
this->LocalGenerator->WriteConvenienceRule(*this->BuildFileStream,
|
||||
targetFullPath.c_str(),
|
||||
buildTargetRuleName.c_str());
|
||||
|
||||
// Clean all the possible executable names and symlinks and object files.
|
||||
this->CleanFiles.insert(this->CleanFiles.end(),
|
||||
exeCleanFiles.begin(),
|
||||
exeCleanFiles.end());
|
||||
this->CleanFiles.push_back(cleanObjs);
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/*=========================================================================
|
||||
|
||||
Program: CMake - Cross-Platform Makefile Generator
|
||||
Module: $RCSfile$
|
||||
Language: C++
|
||||
Date: $Date$
|
||||
Version: $Revision$
|
||||
|
||||
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
|
||||
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
|
||||
|
||||
This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. See the above copyright notices for more information.
|
||||
|
||||
=========================================================================*/
|
||||
#ifndef cmMakefileExecutableTargetGenerator_h
|
||||
#define cmMakefileExecutableTargetGenerator_h
|
||||
|
||||
#include "cmMakefileTargetGenerator.h"
|
||||
|
||||
class cmMakefileExecutableTargetGenerator: public cmMakefileTargetGenerator
|
||||
{
|
||||
public:
|
||||
/* the main entry point for this class. Writes the Makefiles associated
|
||||
with this target */
|
||||
virtual void WriteRuleFiles();
|
||||
|
||||
protected:
|
||||
virtual void WriteExecutableRule();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,394 @@
|
|||
/*=========================================================================
|
||||
|
||||
Program: CMake - Cross-Platform Makefile Generator
|
||||
Module: $RCSfile$
|
||||
Language: C++
|
||||
Date: $Date$
|
||||
Version: $Revision$
|
||||
|
||||
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
|
||||
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
|
||||
|
||||
This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. See the above copyright notices for more information.
|
||||
|
||||
=========================================================================*/
|
||||
#include "cmMakefileLibraryTargetGenerator.h"
|
||||
|
||||
#include "cmGeneratedFileStream.h"
|
||||
#include "cmGlobalGenerator.h"
|
||||
#include "cmLocalUnixMakefileGenerator3.h"
|
||||
#include "cmMakefile.h"
|
||||
#include "cmSourceFile.h"
|
||||
#include "cmTarget.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmMakefileLibraryTargetGenerator::WriteRuleFiles()
|
||||
{
|
||||
// create the build.make file and directory, put in the common blocks
|
||||
this->CreateRuleFile();
|
||||
|
||||
// Add in any rules for custom commands
|
||||
this->WriteCustomCommandsForTarget();
|
||||
|
||||
// write in rules for object files
|
||||
this->WriteCommonCodeRules();
|
||||
|
||||
// write the link rules
|
||||
// Write the rule for this target type.
|
||||
switch(this->Target->GetType())
|
||||
{
|
||||
case cmTarget::STATIC_LIBRARY:
|
||||
this->WriteStaticLibraryRules();
|
||||
break;
|
||||
case cmTarget::SHARED_LIBRARY:
|
||||
this->WriteSharedLibraryRules();
|
||||
break;
|
||||
case cmTarget::MODULE_LIBRARY:
|
||||
this->WriteModuleLibraryRules();
|
||||
break;
|
||||
default:
|
||||
// If language is not known, this is an error.
|
||||
cmSystemTools::Error("Unknown Library Type");
|
||||
break;
|
||||
}
|
||||
|
||||
// Write the requires target.
|
||||
this->WriteTargetRequiresRules();
|
||||
|
||||
// Write clean target
|
||||
this->WriteTargetCleanRules();
|
||||
|
||||
// close the streams
|
||||
this->CloseFileStreams();
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules()
|
||||
{
|
||||
const char* linkLanguage =
|
||||
this->Target->GetLinkerLanguage(this->GlobalGenerator);
|
||||
std::string linkRuleVar = "CMAKE_";
|
||||
if (linkLanguage)
|
||||
{
|
||||
linkRuleVar += linkLanguage;
|
||||
}
|
||||
linkRuleVar += "_CREATE_STATIC_LIBRARY";
|
||||
|
||||
std::string extraFlags;
|
||||
this->LocalGenerator->AppendFlags(extraFlags, this->Target->GetProperty("STATIC_LIBRARY_FLAGS"));
|
||||
this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str());
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules()
|
||||
{
|
||||
const char* linkLanguage =
|
||||
this->Target->GetLinkerLanguage(this->GlobalGenerator);
|
||||
std::string linkRuleVar = "CMAKE_";
|
||||
if (linkLanguage)
|
||||
{
|
||||
linkRuleVar += linkLanguage;
|
||||
}
|
||||
linkRuleVar += "_CREATE_SHARED_LIBRARY";
|
||||
|
||||
std::string extraFlags;
|
||||
this->LocalGenerator->AppendFlags(extraFlags, this->Target->GetProperty("LINK_FLAGS"));
|
||||
this->LocalGenerator->AddConfigVariableFlags(extraFlags, "CMAKE_SHARED_LINKER_FLAGS");
|
||||
if(this->Makefile->IsOn("WIN32") && !(this->Makefile->IsOn("CYGWIN") || this->Makefile->IsOn("MINGW")))
|
||||
{
|
||||
const std::vector<cmSourceFile*>& sources = this->Target->GetSourceFiles();
|
||||
for(std::vector<cmSourceFile*>::const_iterator i = sources.begin();
|
||||
i != sources.end(); ++i)
|
||||
{
|
||||
if((*i)->GetSourceExtension() == "def")
|
||||
{
|
||||
extraFlags += " ";
|
||||
extraFlags += this->Makefile->GetSafeDefinition("CMAKE_LINK_DEF_FILE_FLAG");
|
||||
extraFlags +=
|
||||
this->Convert((*i)->GetFullPath().c_str(),cmLocalGenerator::START_OUTPUT,cmLocalGenerator::MAKEFILE);
|
||||
}
|
||||
}
|
||||
}
|
||||
this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str());
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules()
|
||||
{
|
||||
const char* linkLanguage =
|
||||
this->Target->GetLinkerLanguage(this->GlobalGenerator);
|
||||
std::string linkRuleVar = "CMAKE_";
|
||||
if (linkLanguage)
|
||||
{
|
||||
linkRuleVar += linkLanguage;
|
||||
}
|
||||
linkRuleVar += "_CREATE_SHARED_MODULE";
|
||||
|
||||
std::string extraFlags;
|
||||
this->LocalGenerator->AppendFlags(extraFlags, this->Target->GetProperty("LINK_FLAGS"));
|
||||
this->LocalGenerator->AddConfigVariableFlags(extraFlags, "CMAKE_MODULE_LINKER_FLAGS");
|
||||
// TODO: .def files should be supported here also.
|
||||
this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str());
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmMakefileLibraryTargetGenerator::WriteLibraryRules
|
||||
(const char* linkRuleVar, const char* extraFlags)
|
||||
{
|
||||
// Write the dependency generation rule.
|
||||
this->WriteTargetDependRules();
|
||||
|
||||
// TODO: Merge the methods that call this method to avoid
|
||||
// code duplication.
|
||||
std::vector<std::string> commands;
|
||||
|
||||
std::string relPath = this->LocalGenerator->GetHomeRelativeOutputPath();
|
||||
std::string objTarget;
|
||||
|
||||
// Build list of dependencies.
|
||||
std::vector<std::string> depends;
|
||||
for(std::vector<std::string>::const_iterator obj = this->Objects.begin();
|
||||
obj != this->Objects.end(); ++obj)
|
||||
{
|
||||
objTarget = relPath;
|
||||
objTarget += *obj;
|
||||
depends.push_back(objTarget);
|
||||
}
|
||||
|
||||
// Add dependencies on targets that must be built first.
|
||||
this->AppendTargetDepends(depends);
|
||||
|
||||
// Add a dependency on the rule file itself.
|
||||
this->LocalGenerator->AppendRuleDepend(depends,
|
||||
this->BuildFileNameFull.c_str());
|
||||
|
||||
for(std::vector<std::string>::const_iterator obj
|
||||
= this->ExternalObjects.begin();
|
||||
obj != this->ExternalObjects.end(); ++obj)
|
||||
{
|
||||
depends.push_back(*obj);
|
||||
}
|
||||
|
||||
// Get the language to use for linking this library.
|
||||
const char* linkLanguage =
|
||||
this->Target->GetLinkerLanguage(this->GlobalGenerator);
|
||||
|
||||
// Make sure we have a link language.
|
||||
if(!linkLanguage)
|
||||
{
|
||||
cmSystemTools::Error("Cannot determine link language for target \"",
|
||||
this->Target->GetName(), "\".");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create set of linking flags.
|
||||
std::string linkFlags;
|
||||
this->LocalGenerator->AppendFlags(linkFlags, extraFlags);
|
||||
|
||||
// Construct the name of the library.
|
||||
std::string targetName;
|
||||
std::string targetNameSO;
|
||||
std::string targetNameReal;
|
||||
this->Target->GetLibraryNames(targetName, targetNameSO, targetNameReal,
|
||||
this->LocalGenerator->m_ConfigurationName.c_str());
|
||||
|
||||
// Construct the full path version of the names.
|
||||
std::string outpath = this->LocalGenerator->m_LibraryOutputPath;
|
||||
if(outpath.length() == 0)
|
||||
{
|
||||
outpath = this->Makefile->GetStartOutputDirectory();
|
||||
outpath += "/";
|
||||
}
|
||||
std::string targetFullPath = outpath + targetName;
|
||||
std::string targetFullPathSO = outpath + targetNameSO;
|
||||
std::string targetFullPathReal = outpath + targetNameReal;
|
||||
|
||||
// Construct the output path version of the names for use in command
|
||||
// arguments.
|
||||
std::string targetOutPath =
|
||||
this->Convert(targetFullPath.c_str(),cmLocalGenerator::START_OUTPUT,
|
||||
cmLocalGenerator::MAKEFILE);
|
||||
std::string targetOutPathSO =
|
||||
this->Convert(targetFullPathSO.c_str(),cmLocalGenerator::START_OUTPUT,
|
||||
cmLocalGenerator::MAKEFILE);
|
||||
std::string targetOutPathReal =
|
||||
this->Convert(targetFullPathReal.c_str(),cmLocalGenerator::START_OUTPUT,
|
||||
cmLocalGenerator::MAKEFILE);
|
||||
|
||||
// Add the link message.
|
||||
std::string buildEcho = "Linking ";
|
||||
buildEcho += linkLanguage;
|
||||
switch(this->Target->GetType())
|
||||
{
|
||||
case cmTarget::STATIC_LIBRARY:
|
||||
buildEcho += " static library "; break;
|
||||
case cmTarget::SHARED_LIBRARY:
|
||||
buildEcho += " shared library "; break;
|
||||
case cmTarget::MODULE_LIBRARY:
|
||||
buildEcho += " shared module "; break;
|
||||
default:
|
||||
buildEcho += " library "; break;
|
||||
}
|
||||
buildEcho += targetOutPath.c_str();
|
||||
this->LocalGenerator->AppendEcho(commands, buildEcho.c_str());
|
||||
|
||||
// Construct a list of files associated with this library that may
|
||||
// need to be cleaned.
|
||||
std::vector<std::string> libCleanFiles;
|
||||
{
|
||||
std::string cleanStaticName;
|
||||
std::string cleanSharedName;
|
||||
std::string cleanSharedSOName;
|
||||
std::string cleanSharedRealName;
|
||||
this->Target->GetLibraryCleanNames(cleanStaticName,
|
||||
cleanSharedName,
|
||||
cleanSharedSOName,
|
||||
cleanSharedRealName,
|
||||
this->LocalGenerator->m_ConfigurationName.c_str());
|
||||
std::string cleanFullStaticName = outpath + cleanStaticName;
|
||||
std::string cleanFullSharedName = outpath + cleanSharedName;
|
||||
std::string cleanFullSharedSOName = outpath + cleanSharedSOName;
|
||||
std::string cleanFullSharedRealName = outpath + cleanSharedRealName;
|
||||
libCleanFiles.push_back
|
||||
(this->Convert(cleanFullStaticName.c_str(),cmLocalGenerator::START_OUTPUT,
|
||||
cmLocalGenerator::MAKEFILE));
|
||||
if(cleanSharedRealName != cleanStaticName)
|
||||
{
|
||||
libCleanFiles.push_back(this->Convert(cleanFullSharedRealName.c_str(),
|
||||
cmLocalGenerator::START_OUTPUT,
|
||||
cmLocalGenerator::MAKEFILE));
|
||||
}
|
||||
if(cleanSharedSOName != cleanStaticName &&
|
||||
cleanSharedSOName != cleanSharedRealName)
|
||||
{
|
||||
libCleanFiles.push_back(this->Convert(cleanFullSharedSOName.c_str(),
|
||||
cmLocalGenerator::START_OUTPUT,
|
||||
cmLocalGenerator::MAKEFILE));
|
||||
}
|
||||
if(cleanSharedName != cleanStaticName &&
|
||||
cleanSharedName != cleanSharedSOName &&
|
||||
cleanSharedName != cleanSharedRealName)
|
||||
{
|
||||
libCleanFiles.push_back(this->Convert(cleanFullSharedName.c_str(),
|
||||
cmLocalGenerator::START_OUTPUT,
|
||||
cmLocalGenerator::MAKEFILE));
|
||||
}
|
||||
}
|
||||
// Add a command to remove any existing files for this library.
|
||||
std::vector<std::string> commands1;
|
||||
this->LocalGenerator->AppendCleanCommand(commands1, libCleanFiles);
|
||||
this->LocalGenerator->CreateCDCommand(commands1,
|
||||
this->Makefile->GetStartOutputDirectory(),
|
||||
this->Makefile->GetHomeOutputDirectory());
|
||||
commands.insert(commands.end(), commands1.begin(), commands1.end());
|
||||
commands1.clear();
|
||||
// Add the pre-build and pre-link rules.
|
||||
this->LocalGenerator->AppendCustomCommands(commands, this->Target->GetPreBuildCommands());
|
||||
this->LocalGenerator->AppendCustomCommands(commands, this->Target->GetPreLinkCommands());
|
||||
|
||||
// Construct the main link rule.
|
||||
std::string linkRule = this->Makefile->GetRequiredDefinition(linkRuleVar);
|
||||
cmSystemTools::ExpandListArgument(linkRule, commands1);
|
||||
this->LocalGenerator->CreateCDCommand(commands1,
|
||||
this->Makefile->GetStartOutputDirectory(),
|
||||
this->Makefile->GetHomeOutputDirectory());
|
||||
commands.insert(commands.end(), commands1.begin(), commands1.end());
|
||||
|
||||
// Add a rule to create necessary symlinks for the library.
|
||||
if(targetOutPath != targetOutPathReal)
|
||||
{
|
||||
std::string symlink = "$(CMAKE_COMMAND) -E cmake_symlink_library ";
|
||||
symlink += targetOutPathReal;
|
||||
symlink += " ";
|
||||
symlink += targetOutPathSO;
|
||||
symlink += " ";
|
||||
symlink += targetOutPath;
|
||||
commands1.clear();
|
||||
commands1.push_back(symlink);
|
||||
this->LocalGenerator->CreateCDCommand(commands1,
|
||||
this->Makefile->GetStartOutputDirectory(),
|
||||
this->Makefile->GetHomeOutputDirectory());
|
||||
commands.insert(commands.end(), commands1.begin(), commands1.end());
|
||||
}
|
||||
|
||||
// Add the post-build rules.
|
||||
this->LocalGenerator->AppendCustomCommands(commands, this->Target->GetPostBuildCommands());
|
||||
|
||||
// Collect up flags to link in needed libraries.
|
||||
cmOStringStream linklibs;
|
||||
this->LocalGenerator->OutputLinkLibraries(linklibs, *this->Target);
|
||||
|
||||
// Construct object file lists that may be needed to expand the
|
||||
// rule.
|
||||
std::string variableName;
|
||||
std::string variableNameExternal;
|
||||
this->WriteObjectsVariable(variableName, variableNameExternal);
|
||||
std::string buildObjs = "$(";
|
||||
buildObjs += variableName;
|
||||
buildObjs += ") $(";
|
||||
buildObjs += variableNameExternal;
|
||||
buildObjs += ")";
|
||||
std::string cleanObjs = "$(";
|
||||
cleanObjs += variableName;
|
||||
cleanObjs += ")";
|
||||
|
||||
// Expand placeholders in the commands.
|
||||
for(std::vector<std::string>::iterator i = commands.begin();
|
||||
i != commands.end(); ++i)
|
||||
{
|
||||
this->LocalGenerator->ExpandRuleVariables(*i,
|
||||
linkLanguage,
|
||||
buildObjs.c_str(),
|
||||
targetOutPathReal.c_str(),
|
||||
linklibs.str().c_str(),
|
||||
0, 0, 0, buildObjs.c_str(),
|
||||
targetNameSO.c_str(),
|
||||
linkFlags.c_str());
|
||||
}
|
||||
|
||||
// Write the build rule.
|
||||
this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
|
||||
targetFullPathReal.c_str(), depends, commands);
|
||||
|
||||
// The symlink names for the target should depend on the real target
|
||||
// so if the target version changes it rebuilds and recreates the
|
||||
// symlinks.
|
||||
if(targetFullPathSO != targetFullPathReal)
|
||||
{
|
||||
depends.clear();
|
||||
commands.clear();
|
||||
depends.push_back(targetFullPathReal.c_str());
|
||||
this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
|
||||
targetFullPathSO.c_str(), depends, commands);
|
||||
}
|
||||
if(targetFullPath != targetFullPathSO)
|
||||
{
|
||||
depends.clear();
|
||||
commands.clear();
|
||||
depends.push_back(targetFullPathSO.c_str());
|
||||
this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
|
||||
targetFullPath.c_str(), depends, commands);
|
||||
}
|
||||
|
||||
// Write convenience targets.
|
||||
std::string dir = this->Makefile->GetStartOutputDirectory();
|
||||
dir += "/";
|
||||
dir += this->LocalGenerator->GetTargetDirectory(*this->Target);
|
||||
std::string buildTargetRuleName = dir;
|
||||
buildTargetRuleName += "/build";
|
||||
buildTargetRuleName =
|
||||
this->Convert(buildTargetRuleName.c_str(),
|
||||
cmLocalGenerator::HOME_OUTPUT,cmLocalGenerator::MAKEFILE);
|
||||
this->LocalGenerator->WriteConvenienceRule(*this->BuildFileStream,
|
||||
targetFullPath.c_str(),
|
||||
buildTargetRuleName.c_str());
|
||||
|
||||
// Clean all the possible library names and symlinks and object files.
|
||||
this->CleanFiles.insert(this->CleanFiles.end(),
|
||||
libCleanFiles.begin(),libCleanFiles.end());
|
||||
this->CleanFiles.push_back(cleanObjs);
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/*=========================================================================
|
||||
|
||||
Program: CMake - Cross-Platform Makefile Generator
|
||||
Module: $RCSfile$
|
||||
Language: C++
|
||||
Date: $Date$
|
||||
Version: $Revision$
|
||||
|
||||
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
|
||||
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
|
||||
|
||||
This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. See the above copyright notices for more information.
|
||||
|
||||
=========================================================================*/
|
||||
#ifndef cmMakefileLibraryTargetGenerator_h
|
||||
#define cmMakefileLibraryTargetGenerator_h
|
||||
|
||||
#include "cmMakefileTargetGenerator.h"
|
||||
|
||||
class cmMakefileLibraryTargetGenerator:
|
||||
public cmMakefileTargetGenerator
|
||||
{
|
||||
public:
|
||||
/* the main entry point for this class. Writes the Makefiles associated
|
||||
with this target */
|
||||
virtual void WriteRuleFiles();
|
||||
|
||||
protected:
|
||||
void WriteStaticLibraryRules();
|
||||
void WriteSharedLibraryRules();
|
||||
void WriteModuleLibraryRules();
|
||||
void WriteLibraryRules(const char *linkRule, const char *extraFlags);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,794 @@
|
|||
/*=========================================================================
|
||||
|
||||
Program: CMake - Cross-Platform Makefile Generator
|
||||
Module: $RCSfile$
|
||||
Language: C++
|
||||
Date: $Date$
|
||||
Version: $Revision$
|
||||
|
||||
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
|
||||
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
|
||||
|
||||
This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. See the above copyright notices for more information.
|
||||
|
||||
=========================================================================*/
|
||||
#include "cmMakefileTargetGenerator.h"
|
||||
|
||||
#include "cmGeneratedFileStream.h"
|
||||
#include "cmGlobalGenerator.h"
|
||||
#include "cmLocalUnixMakefileGenerator3.h"
|
||||
#include "cmMakefile.h"
|
||||
#include "cmSourceFile.h"
|
||||
#include "cmTarget.h"
|
||||
|
||||
#include "cmMakefileExecutableTargetGenerator.h"
|
||||
#include "cmMakefileLibraryTargetGenerator.h"
|
||||
#include "cmMakefileUtilityTargetGenerator.h"
|
||||
|
||||
|
||||
cmMakefileTargetGenerator::cmMakefileTargetGenerator()
|
||||
{
|
||||
this->BuildFileStream = 0;
|
||||
this->InfoFileStream = 0;
|
||||
this->FlagFileStream = 0;
|
||||
}
|
||||
|
||||
cmMakefileTargetGenerator *
|
||||
cmMakefileTargetGenerator::New(cmLocalUnixMakefileGenerator3 *lg,
|
||||
cmStdString tgtName, cmTarget *tgt)
|
||||
{
|
||||
cmMakefileTargetGenerator *result = 0;
|
||||
|
||||
switch (tgt->GetType())
|
||||
{
|
||||
case cmTarget::EXECUTABLE:
|
||||
result = new cmMakefileExecutableTargetGenerator;
|
||||
break;
|
||||
case cmTarget::STATIC_LIBRARY:
|
||||
case cmTarget::SHARED_LIBRARY:
|
||||
case cmTarget::MODULE_LIBRARY:
|
||||
result = new cmMakefileLibraryTargetGenerator;
|
||||
break;
|
||||
case cmTarget::UTILITY:
|
||||
result = new cmMakefileUtilityTargetGenerator;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
result->TargetName = tgtName;
|
||||
result->Target = tgt;
|
||||
result->LocalGenerator = lg;
|
||||
result->GlobalGenerator = lg->GetGlobalGenerator();
|
||||
result->Makefile = lg->GetMakefile();
|
||||
return result;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmMakefileTargetGenerator::CreateRuleFile()
|
||||
{
|
||||
// Create a directory for this target.
|
||||
this->TargetBuildDirectory =
|
||||
this->LocalGenerator->GetTargetDirectory(*this->Target);
|
||||
this->TargetBuildDirectoryFull =
|
||||
this->LocalGenerator->ConvertToFullPath(this->TargetBuildDirectory);
|
||||
cmSystemTools::MakeDirectory(this->TargetBuildDirectoryFull.c_str());
|
||||
|
||||
// Construct the rule file name.
|
||||
this->BuildFileName = this->TargetBuildDirectory;
|
||||
this->BuildFileName += "/build.make";
|
||||
this->BuildFileNameFull = this->TargetBuildDirectoryFull;
|
||||
this->BuildFileNameFull += "/build.make";
|
||||
|
||||
// Open the rule file. This should be copy-if-different because the
|
||||
// rules may depend on this file itself.
|
||||
this->BuildFileStream =
|
||||
new cmGeneratedFileStream(this->BuildFileNameFull.c_str());
|
||||
this->BuildFileStream->SetCopyIfDifferent(true);
|
||||
if(!this->BuildFileStream)
|
||||
{
|
||||
return;
|
||||
}
|
||||
this->LocalGenerator->WriteDisclaimer(*this->BuildFileStream);
|
||||
this->LocalGenerator->WriteSpecialTargetsTop(*this->BuildFileStream);
|
||||
this->LocalGenerator->WriteMakeVariables(*this->BuildFileStream);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmMakefileTargetGenerator::WriteCustomCommandsForTarget()
|
||||
{
|
||||
// write the custom commands for this target
|
||||
// Look for files registered for cleaning in this directory.
|
||||
if(const char* additional_clean_files =
|
||||
this->Makefile->GetProperty
|
||||
("ADDITIONAL_MAKE_CLEAN_FILES"))
|
||||
{
|
||||
cmSystemTools::ExpandListArgument(additional_clean_files,
|
||||
this->CleanFiles);
|
||||
}
|
||||
this->WriteCustomCommands();
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmMakefileTargetGenerator::WriteCommonCodeRules()
|
||||
{
|
||||
// Include the dependencies for the target.
|
||||
std::string dependFileNameFull = this->TargetBuildDirectoryFull;
|
||||
dependFileNameFull += "/depend.make";
|
||||
*this->BuildFileStream
|
||||
<< "# Include any dependencies generated for this target.\n"
|
||||
<< this->LocalGenerator->m_IncludeDirective << " "
|
||||
<< this->Convert(dependFileNameFull.c_str(),
|
||||
cmLocalGenerator::HOME_OUTPUT,
|
||||
cmLocalGenerator::MAKEFILE)
|
||||
<< "\n\n";
|
||||
|
||||
// make sure the depend file exists
|
||||
if (!cmSystemTools::FileExists(dependFileNameFull.c_str()))
|
||||
{
|
||||
// Write an empty dependency file.
|
||||
cmGeneratedFileStream depFileStream(dependFileNameFull.c_str());
|
||||
depFileStream
|
||||
<< "# Empty dependencies file for " << this->Target->GetName() << ".\n"
|
||||
<< "# This may be replaced when dependencies are built." << std::endl;
|
||||
}
|
||||
|
||||
// Open the flags file. This should be copy-if-different because the
|
||||
// rules may depend on this file itself.
|
||||
this->FlagFileNameFull = this->TargetBuildDirectoryFull;
|
||||
this->FlagFileNameFull += "/flags.make";
|
||||
this->FlagFileStream =
|
||||
new cmGeneratedFileStream(this->FlagFileNameFull.c_str());
|
||||
this->FlagFileStream->SetCopyIfDifferent(true);
|
||||
if(!this->FlagFileStream)
|
||||
{
|
||||
return;
|
||||
}
|
||||
this->LocalGenerator->WriteDisclaimer(*this->FlagFileStream);
|
||||
|
||||
// Include the flags for the target.
|
||||
*this->BuildFileStream
|
||||
<< "# Include the compile flags for this target's objects.\n"
|
||||
<< this->LocalGenerator->m_IncludeDirective << " "
|
||||
<< this->Convert(this->FlagFileNameFull.c_str(),
|
||||
cmLocalGenerator::HOME_OUTPUT,
|
||||
cmLocalGenerator::MAKEFILE)
|
||||
<< "\n\n";
|
||||
|
||||
// First generate the object rule files. Save a list of all object
|
||||
// files for this target.
|
||||
const std::vector<cmSourceFile*>& sources = this->Target->GetSourceFiles();
|
||||
for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
|
||||
source != sources.end(); ++source)
|
||||
{
|
||||
if(!(*source)->GetPropertyAsBool("HEADER_FILE_ONLY") &&
|
||||
!(*source)->GetCustomCommand())
|
||||
{
|
||||
if(!this->GlobalGenerator->IgnoreFile
|
||||
((*source)->GetSourceExtension().c_str()))
|
||||
{
|
||||
// Generate this object file's rule file.
|
||||
this->WriteObjectRuleFiles(*(*source));
|
||||
}
|
||||
else if((*source)->GetPropertyAsBool("EXTERNAL_OBJECT"))
|
||||
{
|
||||
// This is an external object file. Just add it.
|
||||
this->ExternalObjects.push_back((*source)->GetFullPath());
|
||||
}
|
||||
else
|
||||
{
|
||||
// We only get here if a source file is not an external object
|
||||
// and has an extension that is listed as an ignored file type
|
||||
// for this language. No message or diagnosis should be
|
||||
// given.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// write language flags for target
|
||||
std::map<cmStdString,cmLocalUnixMakefileGenerator3::IntegrityCheckSet>&
|
||||
checkSet =
|
||||
this->LocalGenerator->GetIntegrityCheckSet()[this->Target->GetName()];
|
||||
for(std::map<cmStdString,
|
||||
cmLocalUnixMakefileGenerator3::IntegrityCheckSet>::const_iterator
|
||||
l = checkSet.begin(); l != checkSet.end(); ++l)
|
||||
{
|
||||
const char *lang = l->first.c_str();
|
||||
std::string flags;
|
||||
// Add the export symbol definition for shared library objects.
|
||||
bool shared = ((this->Target->GetType() == cmTarget::SHARED_LIBRARY) ||
|
||||
(this->Target->GetType() == cmTarget::MODULE_LIBRARY));
|
||||
if(shared)
|
||||
{
|
||||
flags += "-D";
|
||||
if(const char* custom_export_name =
|
||||
this->Target->GetProperty("DEFINE_SYMBOL"))
|
||||
{
|
||||
flags += custom_export_name;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string in = this->Target->GetName();
|
||||
in += "_EXPORTS";
|
||||
flags += cmSystemTools::MakeCindentifier(in.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// Add language-specific flags.
|
||||
this->LocalGenerator->AddLanguageFlags(flags, lang);
|
||||
|
||||
// Add shared-library flags if needed.
|
||||
this->LocalGenerator->AddSharedFlags(flags, lang, shared);
|
||||
|
||||
// Add include directory flags.
|
||||
this->LocalGenerator->
|
||||
AppendFlags(flags, this->LocalGenerator->GetIncludeFlags(lang));
|
||||
// Add include directory flags.
|
||||
this->LocalGenerator->
|
||||
AppendFlags(flags,this->GetFrameworkFlags().c_str());
|
||||
|
||||
*this->FlagFileStream << lang << "_FLAGS = " << flags << "\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmMakefileTargetGenerator::WriteObjectRuleFiles(cmSourceFile& source)
|
||||
{
|
||||
// Identify the language of the source file.
|
||||
const char* lang = this->LocalGenerator->GetSourceFileLanguage(source);
|
||||
if(!lang)
|
||||
{
|
||||
// If language is not known, this is an error.
|
||||
cmSystemTools::Error("Source file \"", source.GetFullPath().c_str(),
|
||||
"\" has unknown type.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the full path name of the object file.
|
||||
std::string objNoTargetDir;
|
||||
std::string obj =
|
||||
this->LocalGenerator->GetObjectFileName(*this->Target, source, &objNoTargetDir);
|
||||
|
||||
// Avoid generating duplicate rules.
|
||||
if(m_ObjectFiles.find(obj) == m_ObjectFiles.end())
|
||||
{
|
||||
m_ObjectFiles.insert(obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
cmOStringStream err;
|
||||
err << "Warning: Source file \""
|
||||
<< source.GetSourceName().c_str() << "."
|
||||
<< source.GetSourceExtension().c_str()
|
||||
<< "\" is listed multiple times for target \""
|
||||
<< this->Target->GetName()
|
||||
<< "\".";
|
||||
cmSystemTools::Message(err.str().c_str(), "Warning");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the directory containing the object file. This may be a
|
||||
// subdirectory under the target's directory.
|
||||
std::string dir = cmSystemTools::GetFilenamePath(obj.c_str());
|
||||
cmSystemTools::MakeDirectory
|
||||
(this->LocalGenerator->ConvertToFullPath(dir).c_str());
|
||||
|
||||
// Save this in the target's list of object files.
|
||||
this->Objects.push_back(obj);
|
||||
std::string relativeObj = this->LocalGenerator->GetHomeRelativeOutputPath();
|
||||
relativeObj += obj;
|
||||
// we compute some depends when writing the depend.make that we will also
|
||||
// use in the build.make, same with depMakeFile
|
||||
std::vector<std::string> depends;
|
||||
std::string depMakeFile;
|
||||
|
||||
// generate the build rule file
|
||||
this->WriteObjectBuildFile(obj, lang, source, depends);
|
||||
|
||||
// The object file should be checked for dependency integrity.
|
||||
this->LocalGenerator->m_CheckDependFiles[this->Target->GetName()][lang].insert(&source);
|
||||
// add this to the list of objects for this local generator
|
||||
if(cmSystemTools::FileIsFullPath(objNoTargetDir.c_str()))
|
||||
{
|
||||
objNoTargetDir = cmSystemTools::GetFilenameName(objNoTargetDir);
|
||||
}
|
||||
this->LocalGenerator->m_LocalObjectFiles[objNoTargetDir].push_back(this->Target);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
cmMakefileTargetGenerator
|
||||
::WriteObjectBuildFile(std::string &obj,
|
||||
const char *lang,
|
||||
cmSourceFile& source,
|
||||
std::vector<std::string>& depends)
|
||||
{
|
||||
this->LocalGenerator->AppendRuleDepend(depends, this->FlagFileNameFull.c_str());
|
||||
|
||||
// generate the depend scanning rule
|
||||
this->WriteObjectDependRules(source, depends);
|
||||
|
||||
std::string relativeObj = this->LocalGenerator->GetHomeRelativeOutputPath();
|
||||
relativeObj += obj;
|
||||
if(this->Makefile->GetDefinition("CMAKE_WINDOWS_OBJECT_PATH"))
|
||||
{
|
||||
relativeObj = cmSystemTools::ConvertToOutputPath(relativeObj.c_str());
|
||||
}
|
||||
// Write the build rule.
|
||||
// Build the set of compiler flags.
|
||||
std::string flags;
|
||||
if(this->Target->GetProperty("COMPILE_FLAGS"))
|
||||
{
|
||||
this->LocalGenerator->AppendFlags(flags, this->Target->GetProperty("COMPILE_FLAGS"));
|
||||
}
|
||||
|
||||
// Add flags from source file properties.
|
||||
if (source.GetProperty("COMPILE_FLAGS"))
|
||||
{
|
||||
this->LocalGenerator->AppendFlags(flags, source.GetProperty("COMPILE_FLAGS"));
|
||||
*this->FlagFileStream << "# Custom flags: "
|
||||
<< relativeObj << "_FLAGS = "
|
||||
<< source.GetProperty("COMPILE_FLAGS")
|
||||
<< "\n"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
// Add language-specific flags.
|
||||
std::string langFlags = "$(";
|
||||
langFlags += lang;
|
||||
langFlags += "_FLAGS)";
|
||||
this->LocalGenerator->AppendFlags(flags, langFlags.c_str());
|
||||
|
||||
// Get the output paths for source and object files.
|
||||
std::string sourceFile = source.GetFullPath();
|
||||
if(this->LocalGenerator->m_UseRelativePaths)
|
||||
{
|
||||
sourceFile = this->Convert(sourceFile.c_str(),
|
||||
cmLocalGenerator::HOME_OUTPUT);
|
||||
}
|
||||
sourceFile = this->Convert(sourceFile.c_str(),
|
||||
cmLocalGenerator::NONE,
|
||||
cmLocalGenerator::SHELL);
|
||||
std::string objectFile =
|
||||
this->Convert(obj.c_str(),
|
||||
cmLocalGenerator::START_OUTPUT,
|
||||
cmLocalGenerator::SHELL);
|
||||
|
||||
// Construct the build message.
|
||||
std::vector<std::string> no_commands;
|
||||
std::vector<std::string> commands;
|
||||
std::string buildEcho = "Building ";
|
||||
buildEcho += lang;
|
||||
buildEcho += " object ";
|
||||
buildEcho += relativeObj;
|
||||
this->LocalGenerator->AppendEcho(commands, buildEcho.c_str());
|
||||
|
||||
// Construct the compile rules.
|
||||
std::string compileRuleVar = "CMAKE_";
|
||||
compileRuleVar += lang;
|
||||
compileRuleVar += "_COMPILE_OBJECT";
|
||||
std::string compileRule =
|
||||
this->Makefile->GetRequiredDefinition(compileRuleVar.c_str());
|
||||
cmSystemTools::ExpandListArgument(compileRule, commands);
|
||||
|
||||
// Expand placeholders in the commands.
|
||||
for(std::vector<std::string>::iterator i = commands.begin();
|
||||
i != commands.end(); ++i)
|
||||
{
|
||||
this->LocalGenerator->ExpandRuleVariables(*i,
|
||||
lang,
|
||||
0, // no objects
|
||||
0, // no target
|
||||
0, // no link libs
|
||||
sourceFile.c_str(),
|
||||
relativeObj.c_str(),
|
||||
flags.c_str());
|
||||
}
|
||||
|
||||
// Make the target dependency scanning rule include cmake-time-known
|
||||
// dependencies. The others are handled by the check-build-system
|
||||
// path.
|
||||
std::string depMark =
|
||||
this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
|
||||
depMark += "/depend.make.mark";
|
||||
this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
|
||||
depMark.c_str(), depends, no_commands);
|
||||
|
||||
// Write the rule.
|
||||
this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
|
||||
relativeObj.c_str(), depends, commands);
|
||||
|
||||
// If the language needs provides-requires mode, create the
|
||||
// corresponding targets.
|
||||
std::string objectRequires = relativeObj;
|
||||
objectRequires += ".requires";
|
||||
std::vector<std::string> p_depends;
|
||||
// always provide an empty requires target
|
||||
this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
|
||||
objectRequires.c_str(), p_depends,
|
||||
no_commands);
|
||||
|
||||
// write a build rule to recursively build what this obj provides
|
||||
std::string objectProvides = relativeObj;
|
||||
objectProvides += ".provides";
|
||||
std::string temp = relativeObj;
|
||||
temp += ".provides.build";
|
||||
std::vector<std::string> r_commands;
|
||||
std::string tgtMakefileName =
|
||||
this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
|
||||
tgtMakefileName += "/build.make";
|
||||
r_commands.push_back
|
||||
(this->LocalGenerator->GetRecursiveMakeCall(tgtMakefileName.c_str(),temp.c_str()));
|
||||
p_depends.clear();
|
||||
p_depends.push_back(objectRequires);
|
||||
this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
|
||||
objectProvides.c_str(), p_depends,
|
||||
r_commands);
|
||||
|
||||
// write the provides.build rule dependency on the obj file
|
||||
p_depends.clear();
|
||||
p_depends.push_back(relativeObj);
|
||||
this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
|
||||
temp.c_str(), p_depends, no_commands);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmMakefileTargetGenerator::WriteTargetRequiresRules()
|
||||
{
|
||||
std::vector<std::string> depends;
|
||||
std::vector<std::string> no_commands;
|
||||
|
||||
// Construct the name of the dependency generation target.
|
||||
std::string depTarget =
|
||||
this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
|
||||
depTarget += "/requires";
|
||||
|
||||
// This target drives dependency generation for all object files.
|
||||
std::string relPath = this->LocalGenerator->GetHomeRelativeOutputPath();
|
||||
std::string objTarget;
|
||||
for(std::vector<std::string>::const_iterator obj = this->Objects.begin();
|
||||
obj != this->Objects.end(); ++obj)
|
||||
{
|
||||
objTarget = relPath;
|
||||
objTarget += *obj;
|
||||
objTarget += ".requires";
|
||||
depends.push_back(objTarget);
|
||||
}
|
||||
|
||||
// Write the rule.
|
||||
this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
|
||||
depTarget.c_str(), depends, no_commands);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmMakefileTargetGenerator::WriteTargetCleanRules()
|
||||
{
|
||||
std::vector<std::string> depends;
|
||||
const char* sym = this->Makefile->GetDefinition("CMAKE_MAKE_SYMBOLIC_RULE");
|
||||
if(sym)
|
||||
{
|
||||
depends.push_back(sym);
|
||||
}
|
||||
std::vector<std::string> commands;
|
||||
|
||||
// Construct the clean target name.
|
||||
std::string cleanTarget =
|
||||
this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
|
||||
cleanTarget += "/clean";
|
||||
|
||||
// Construct the clean command.
|
||||
this->LocalGenerator->AppendCleanCommand(commands, this->CleanFiles);
|
||||
this->LocalGenerator->CreateCDCommand(commands,
|
||||
this->Makefile->GetStartOutputDirectory(),
|
||||
this->Makefile->GetHomeOutputDirectory());
|
||||
|
||||
// Write the rule.
|
||||
this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
|
||||
cleanTarget.c_str(), depends, commands);
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmMakefileTargetGenerator::WriteTargetDependRules()
|
||||
{
|
||||
// must write the targets depend info file
|
||||
std::string dir = this->LocalGenerator->GetTargetDirectory(*this->Target);
|
||||
this->InfoFileNameFull = dir;
|
||||
this->InfoFileNameFull += "/DependInfo.cmake";
|
||||
this->InfoFileNameFull =
|
||||
this->LocalGenerator->ConvertToFullPath(this->InfoFileNameFull);
|
||||
this->InfoFileStream =
|
||||
new cmGeneratedFileStream(this->InfoFileNameFull.c_str());
|
||||
this->InfoFileStream->SetCopyIfDifferent(true);
|
||||
if(!*this->InfoFileStream)
|
||||
{
|
||||
return;
|
||||
}
|
||||
this->LocalGenerator->
|
||||
WriteDependLanguageInfo(*this->InfoFileStream,*this->Target);
|
||||
|
||||
// and now write the rule to use it
|
||||
std::vector<std::string> depends;
|
||||
std::vector<std::string> commands;
|
||||
|
||||
// Construct the name of the dependency generation target.
|
||||
std::string depTarget =
|
||||
this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
|
||||
depTarget += "/depend";
|
||||
|
||||
std::string depMark = depTarget;
|
||||
depMark += ".make.mark";
|
||||
depends.push_back(depMark);
|
||||
|
||||
this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
|
||||
depTarget.c_str(), depends, commands);
|
||||
depends.clear();
|
||||
|
||||
// Write the dependency generation rule.
|
||||
std::string depEcho = "Scanning dependencies of target ";
|
||||
depEcho += this->Target->GetName();
|
||||
this->LocalGenerator->AppendEcho(commands, depEcho.c_str());
|
||||
|
||||
// Add a command to call CMake to scan dependencies. CMake will
|
||||
// touch the corresponding depends file after scanning dependencies.
|
||||
cmOStringStream depCmd;
|
||||
// TODO: Account for source file properties and directory-level
|
||||
// definitions when scanning for dependencies.
|
||||
depCmd << "$(CMAKE_COMMAND) -E cmake_depends "
|
||||
<< " \""
|
||||
<< this->GlobalGenerator->GetName() << "\" "
|
||||
<< this->LocalGenerator->Convert
|
||||
(this->Makefile->GetHomeOutputDirectory(),
|
||||
cmLocalGenerator::FULL,cmLocalGenerator::SHELL)
|
||||
<< " "
|
||||
<< this->LocalGenerator->Convert
|
||||
(this->Makefile->GetStartOutputDirectory(),
|
||||
cmLocalGenerator::FULL,cmLocalGenerator::SHELL)
|
||||
<< " "
|
||||
<< this->Convert(this->InfoFileNameFull.c_str(),
|
||||
cmLocalGenerator::FULL,
|
||||
cmLocalGenerator::SHELL);
|
||||
commands.push_back(depCmd.str());
|
||||
|
||||
// Write the rule.
|
||||
this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
|
||||
depMark.c_str(), depends, commands);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmMakefileTargetGenerator
|
||||
::WriteObjectDependRules(cmSourceFile& source,
|
||||
std::vector<std::string>& depends)
|
||||
{
|
||||
// Create the list of dependencies known at cmake time. These are
|
||||
// shared between the object file and dependency scanning rule.
|
||||
depends.push_back(source.GetFullPath());
|
||||
if(const char* objectDeps = source.GetProperty("OBJECT_DEPENDS"))
|
||||
{
|
||||
std::vector<std::string> deps;
|
||||
cmSystemTools::ExpandListArgument(objectDeps, deps);
|
||||
for(std::vector<std::string>::iterator i = deps.begin();
|
||||
i != deps.end(); ++i)
|
||||
{
|
||||
depends.push_back(i->c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cmMakefileTargetGenerator::WriteCustomCommands()
|
||||
{
|
||||
// add custom commands to the clean rules?
|
||||
const char* clean_no_custom = this->Makefile->GetProperty("CLEAN_NO_CUSTOM");
|
||||
bool clean = cmSystemTools::IsOff(clean_no_custom);
|
||||
|
||||
// Generate the rule files for each custom command.
|
||||
const std::vector<cmSourceFile*> &classes = this->Makefile->GetSourceFiles();
|
||||
for(std::vector<cmSourceFile*>::const_iterator i = classes.begin();
|
||||
i != classes.end(); i++)
|
||||
{
|
||||
if(cmCustomCommand* cc = (*i)->GetCustomCommand())
|
||||
{
|
||||
this->GenerateCustomRuleFile(*cc);
|
||||
if (clean)
|
||||
{
|
||||
this->CleanFiles.push_back
|
||||
(this->Convert(cc->GetOutput(),
|
||||
cmLocalGenerator::START_OUTPUT,
|
||||
cmLocalGenerator::SHELL));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmMakefileTargetGenerator
|
||||
::GenerateCustomRuleFile(const cmCustomCommand& cc)
|
||||
{
|
||||
// Convert the output name to a relative path if possible.
|
||||
std::string output = this->Convert(cc.GetOutput(),
|
||||
cmLocalGenerator::START_OUTPUT);
|
||||
|
||||
// Collect the commands.
|
||||
std::vector<std::string> commands;
|
||||
std::string preEcho = "Generating ";
|
||||
preEcho += output;
|
||||
this->LocalGenerator->AppendEcho(commands, preEcho.c_str());
|
||||
this->LocalGenerator->AppendCustomCommand(commands, cc);
|
||||
|
||||
// Collect the dependencies.
|
||||
std::vector<std::string> depends;
|
||||
this->LocalGenerator->AppendCustomDepend(depends, cc);
|
||||
|
||||
// Write the rule.
|
||||
const char* comment = 0;
|
||||
if(cc.GetComment() && *cc.GetComment())
|
||||
{
|
||||
comment = cc.GetComment();
|
||||
}
|
||||
this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, comment,
|
||||
cc.GetOutput(), depends, commands);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
cmMakefileTargetGenerator
|
||||
::WriteObjectsVariable(std::string& variableName,
|
||||
std::string& variableNameExternal)
|
||||
{
|
||||
// Write a make variable assignment that lists all objects for the
|
||||
// target.
|
||||
variableName =
|
||||
this->LocalGenerator->CreateMakeVariable(this->Target->GetName(), "_OBJECTS");
|
||||
*this->BuildFileStream
|
||||
<< "# Object files for target " << this->Target->GetName() << "\n"
|
||||
<< variableName.c_str() << " =";
|
||||
std::string object;
|
||||
const char* objName =
|
||||
this->Makefile->GetDefinition("CMAKE_NO_QUOTED_OBJECTS");
|
||||
const char* lineContinue =
|
||||
this->Makefile->GetDefinition("CMAKE_MAKE_LINE_CONTINUE");
|
||||
if(!lineContinue)
|
||||
{
|
||||
lineContinue = "\\";
|
||||
}
|
||||
for(std::vector<std::string>::const_iterator i = this->Objects.begin();
|
||||
i != this->Objects.end(); ++i)
|
||||
{
|
||||
*this->BuildFileStream << " " << lineContinue << "\n";
|
||||
if(objName)
|
||||
{
|
||||
*this->BuildFileStream <<
|
||||
this->Convert(i->c_str(), cmLocalGenerator::START_OUTPUT,
|
||||
cmLocalGenerator::MAKEFILE);
|
||||
}
|
||||
else
|
||||
{
|
||||
*this->BuildFileStream <<
|
||||
this->LocalGenerator->ConvertToQuotedOutputPath(i->c_str());
|
||||
}
|
||||
}
|
||||
*this->BuildFileStream << "\n";
|
||||
|
||||
// Write a make variable assignment that lists all external objects
|
||||
// for the target.
|
||||
variableNameExternal =
|
||||
this->LocalGenerator->CreateMakeVariable(this->Target->GetName(),"_EXTERNAL_OBJECTS");
|
||||
*this->BuildFileStream
|
||||
<< "\n"
|
||||
<< "# External object files for target " << this->Target->GetName() << "\n"
|
||||
<< variableNameExternal.c_str() << " =";
|
||||
for(std::vector<std::string>::const_iterator i =
|
||||
this->ExternalObjects.begin();
|
||||
i != this->ExternalObjects.end(); ++i)
|
||||
{
|
||||
object = this->Convert(i->c_str(),cmLocalGenerator::START_OUTPUT);
|
||||
*this->BuildFileStream
|
||||
<< " " << lineContinue << "\n"
|
||||
<< this->Makefile->GetSafeDefinition("CMAKE_OBJECT_NAME");
|
||||
if(objName)
|
||||
{
|
||||
*this->BuildFileStream << this->Convert(i->c_str(),
|
||||
cmLocalGenerator::START_OUTPUT,
|
||||
cmLocalGenerator::MAKEFILE);
|
||||
}
|
||||
else
|
||||
{
|
||||
*this->BuildFileStream <<
|
||||
this->LocalGenerator->ConvertToQuotedOutputPath(i->c_str());
|
||||
}
|
||||
}
|
||||
*this->BuildFileStream << "\n" << "\n";
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
std::string cmMakefileTargetGenerator::GetFrameworkFlags()
|
||||
{
|
||||
#ifndef __APPLE__
|
||||
return std::string();
|
||||
#else
|
||||
std::set<cmStdString> emitted;
|
||||
std::vector<std::string> includes;
|
||||
this->GetIncludeDirectories(includes);
|
||||
std::vector<std::string>::iterator i;
|
||||
// check all include directories for frameworks as this
|
||||
// will already have added a -F for the framework
|
||||
for(i = includes.begin(); i != includes.end(); ++i)
|
||||
{
|
||||
if(cmSystemTools::IsPathToFramework(i->c_str()))
|
||||
{
|
||||
std::string frameworkDir = *i;
|
||||
frameworkDir += "/../";
|
||||
frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir.c_str());
|
||||
emitted.insert(frameworkDir);
|
||||
}
|
||||
}
|
||||
|
||||
std::string flags;
|
||||
std::vector<std::string>& frameworks = this->Target->GetFrameworks();
|
||||
for(i = frameworks.begin();
|
||||
i != frameworks.end(); ++i)
|
||||
{
|
||||
if(emitted.insert(*i).second)
|
||||
{
|
||||
flags += "-F";
|
||||
flags += this->LocalGenerator->ConvertToOutputForExisting(i->c_str());
|
||||
flags += " ";
|
||||
}
|
||||
}
|
||||
return flags;
|
||||
#endif
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmMakefileTargetGenerator
|
||||
::AppendTargetDepends(std::vector<std::string>& depends)
|
||||
{
|
||||
// Static libraries never depend on anything for linking.
|
||||
if(this->Target->GetType() == cmTarget::STATIC_LIBRARY)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Keep track of dependencies already listed.
|
||||
std::set<cmStdString> emitted;
|
||||
|
||||
// A target should not depend on itself.
|
||||
emitted.insert(this->Target->GetName());
|
||||
|
||||
// Loop over all library dependencies.
|
||||
const cmTarget::LinkLibraries& tlibs = this->Target->GetLinkLibraries();
|
||||
for(cmTarget::LinkLibraries::const_iterator lib = tlibs.begin();
|
||||
lib != tlibs.end(); ++lib)
|
||||
{
|
||||
// Don't emit the same library twice for this target.
|
||||
if(emitted.insert(lib->first).second)
|
||||
{
|
||||
// Depend only on other CMake targets.
|
||||
if(cmTarget* tgt =
|
||||
this->GlobalGenerator->FindTarget(0, lib->first.c_str()))
|
||||
{
|
||||
if(const char* location =
|
||||
tgt->GetLocation(this->LocalGenerator->m_ConfigurationName.c_str()))
|
||||
{
|
||||
depends.push_back(location);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmMakefileTargetGenerator
|
||||
::CloseFileStreams()
|
||||
{
|
||||
delete this->BuildFileStream;
|
||||
delete this->InfoFileStream;
|
||||
delete this->FlagFileStream;
|
||||
}
|
|
@ -0,0 +1,152 @@
|
|||
/*=========================================================================
|
||||
|
||||
Program: CMake - Cross-Platform Makefile Generator
|
||||
Module: $RCSfile$
|
||||
Language: C++
|
||||
Date: $Date$
|
||||
Version: $Revision$
|
||||
|
||||
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
|
||||
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
|
||||
|
||||
This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. See the above copyright notices for more information.
|
||||
|
||||
=========================================================================*/
|
||||
#ifndef cmMakefileTargetGenerator_h
|
||||
#define cmMakefileTargetGenerator_h
|
||||
|
||||
#include "cmLocalUnixMakefileGenerator3.h"
|
||||
|
||||
class cmCustomCommand;
|
||||
class cmDependInformation;
|
||||
class cmDepends;
|
||||
class cmGeneratedFileStream;
|
||||
class cmGlobalGenerator;
|
||||
class cmLocalUnixMakefileGenerator3;
|
||||
class cmMakeDepend;
|
||||
class cmMakefile;
|
||||
class cmTarget;
|
||||
class cmSourceFile;
|
||||
|
||||
/** \class cmMakefileTargetGenerator
|
||||
* \brief Support Routines for writing makefiles
|
||||
*
|
||||
*/
|
||||
class cmMakefileTargetGenerator
|
||||
{
|
||||
public:
|
||||
// construct using this factory call
|
||||
static cmMakefileTargetGenerator *New(cmLocalUnixMakefileGenerator3 *lg,
|
||||
cmStdString tgtName,
|
||||
cmTarget *tgt);
|
||||
|
||||
/* the main entry point for this class. Writes the Makefiles associated
|
||||
with this target */
|
||||
virtual void WriteRuleFiles() = 0;
|
||||
|
||||
protected:
|
||||
|
||||
// create the file and directory etc
|
||||
void CreateRuleFile();
|
||||
|
||||
// outputs the rules for any custom commands used by this target
|
||||
void WriteCustomCommandsForTarget();
|
||||
|
||||
// write some common code at the top of build.make
|
||||
void WriteCommonCodeRules();
|
||||
|
||||
// write the provide require rules for this target
|
||||
void WriteTargetRequiresRules();
|
||||
|
||||
// write the clean rules for this target
|
||||
void WriteTargetCleanRules();
|
||||
|
||||
// write the depend rules for this target
|
||||
void WriteTargetDependRules();
|
||||
|
||||
// write the rules for an object
|
||||
void WriteObjectRuleFiles(cmSourceFile& source);
|
||||
|
||||
// write the build rule for an object
|
||||
void WriteObjectBuildFile(std::string &obj,
|
||||
const char *lang,
|
||||
cmSourceFile& source,
|
||||
std::vector<std::string>& depends);
|
||||
|
||||
// write the depend.make file for an object
|
||||
void WriteObjectDependRules(cmSourceFile& source,
|
||||
std::vector<std::string>& depends);
|
||||
|
||||
// this is responsible for writing all of the rules for all this
|
||||
// directories custom commands (but not utility targets)
|
||||
void WriteCustomCommands();
|
||||
void GenerateCustomRuleFile(const cmCustomCommand& cc);
|
||||
|
||||
// write out the variable that lists the objects for this target
|
||||
void WriteObjectsVariable(std::string& variableName,
|
||||
std::string& variableNameExternal);
|
||||
|
||||
// Return the a string with -F flags on apple
|
||||
std::string GetFrameworkFlags();
|
||||
|
||||
// append intertarget dependencies
|
||||
void AppendTargetDepends(std::vector<std::string>& depends);
|
||||
|
||||
virtual void CloseFileStreams();
|
||||
|
||||
cmStdString TargetName;
|
||||
cmTarget *Target;
|
||||
cmLocalUnixMakefileGenerator3 *LocalGenerator;
|
||||
cmGlobalGenerator *GlobalGenerator;
|
||||
cmMakefile *Makefile;
|
||||
|
||||
// the full path to the build file
|
||||
std::string BuildFileName;
|
||||
std::string BuildFileNameFull;
|
||||
|
||||
// the path to the directory the build file is in
|
||||
std::string TargetBuildDirectory;
|
||||
std::string TargetBuildDirectoryFull;
|
||||
|
||||
// the stream for the build file
|
||||
cmGeneratedFileStream *BuildFileStream;
|
||||
|
||||
// the stream for the flag file
|
||||
std::string FlagFileNameFull;
|
||||
cmGeneratedFileStream *FlagFileStream;
|
||||
|
||||
// the stream for the info file
|
||||
std::string InfoFileNameFull;
|
||||
cmGeneratedFileStream *InfoFileStream;
|
||||
|
||||
// files to clean
|
||||
std::vector<std::string> CleanFiles;
|
||||
|
||||
// objects used by this target
|
||||
std::vector<std::string> Objects;
|
||||
std::vector<std::string> ExternalObjects;
|
||||
|
||||
// Set of object file names that will be built in this directory.
|
||||
std::set<cmStdString> m_ObjectFiles;
|
||||
|
||||
|
||||
//==================================================================
|
||||
// Convenience routines that do nothing more than forward to
|
||||
// implementaitons
|
||||
std::string Convert(const char* source,
|
||||
cmLocalGenerator::RelativeRoot relative,
|
||||
cmLocalGenerator::OutputFormat output =
|
||||
cmLocalGenerator::UNCHANGED,
|
||||
bool optional = false)
|
||||
{
|
||||
return this->LocalGenerator->Convert(source, relative, output, optional);
|
||||
}
|
||||
|
||||
// constructor to set the ivarscmMakefileTargetGenerator
|
||||
cmMakefileTargetGenerator();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,90 @@
|
|||
/*=========================================================================
|
||||
|
||||
Program: CMake - Cross-Platform Makefile Generator
|
||||
Module: $RCSfile$
|
||||
Language: C++
|
||||
Date: $Date$
|
||||
Version: $Revision$
|
||||
|
||||
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
|
||||
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
|
||||
|
||||
This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. See the above copyright notices for more information.
|
||||
|
||||
=========================================================================*/
|
||||
#include "cmMakefileUtilityTargetGenerator.h"
|
||||
|
||||
#include "cmGeneratedFileStream.h"
|
||||
#include "cmGlobalGenerator.h"
|
||||
#include "cmLocalUnixMakefileGenerator3.h"
|
||||
#include "cmMakefile.h"
|
||||
#include "cmSourceFile.h"
|
||||
#include "cmTarget.h"
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmMakefileUtilityTargetGenerator::WriteRuleFiles()
|
||||
{
|
||||
this->CreateRuleFile();
|
||||
|
||||
*this->BuildFileStream
|
||||
<< "# Utility rule file for " << this->Target->GetName() << ".\n\n";
|
||||
|
||||
// write the custom commands for this target
|
||||
this->WriteCustomCommandsForTarget();
|
||||
|
||||
// Collect the commands and dependencies.
|
||||
std::vector<std::string> commands;
|
||||
std::vector<std::string> depends;
|
||||
const char* sym = this->Makefile->GetDefinition("CMAKE_MAKE_SYMBOLIC_RULE");
|
||||
if(sym)
|
||||
{
|
||||
depends.push_back(sym);
|
||||
}
|
||||
|
||||
// Utility targets store their rules in pre- and post-build commands.
|
||||
this->LocalGenerator->AppendCustomDepends
|
||||
(depends, this->Target->GetPreBuildCommands());
|
||||
this->LocalGenerator->AppendCustomDepends
|
||||
(depends, this->Target->GetPostBuildCommands());
|
||||
this->LocalGenerator->AppendCustomCommands
|
||||
(commands, this->Target->GetPreBuildCommands());
|
||||
this->LocalGenerator->AppendCustomCommands
|
||||
(commands, this->Target->GetPostBuildCommands());
|
||||
|
||||
// Add dependencies on targets that must be built first.
|
||||
this->AppendTargetDepends(depends);
|
||||
|
||||
// Add a dependency on the rule file itself.
|
||||
std::string relPath = this->LocalGenerator->GetHomeRelativeOutputPath();
|
||||
std::string objTarget = relPath;
|
||||
objTarget += this->BuildFileName;
|
||||
this->LocalGenerator->AppendRuleDepend(depends, objTarget.c_str());
|
||||
|
||||
// Write the rule.
|
||||
this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
|
||||
this->Target->GetName(), depends, commands);
|
||||
|
||||
// Write convenience targets.
|
||||
std::string dir = this->Makefile->GetStartOutputDirectory();
|
||||
dir += "/";
|
||||
dir += this->LocalGenerator->GetTargetDirectory(*this->Target);
|
||||
std::string buildTargetRuleName = dir;
|
||||
buildTargetRuleName += "/build";
|
||||
buildTargetRuleName =
|
||||
this->LocalGenerator->Convert(buildTargetRuleName.c_str(),
|
||||
cmLocalGenerator::HOME_OUTPUT,
|
||||
cmLocalGenerator::MAKEFILE);
|
||||
this->LocalGenerator->WriteConvenienceRule(*this->BuildFileStream,
|
||||
this->Target->GetName(),
|
||||
buildTargetRuleName.c_str());
|
||||
|
||||
// Write clean target
|
||||
this->WriteTargetCleanRules();
|
||||
|
||||
// close the streams
|
||||
this->CloseFileStreams();
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/*=========================================================================
|
||||
|
||||
Program: CMake - Cross-Platform Makefile Generator
|
||||
Module: $RCSfile$
|
||||
Language: C++
|
||||
Date: $Date$
|
||||
Version: $Revision$
|
||||
|
||||
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
|
||||
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
|
||||
|
||||
This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. See the above copyright notices for more information.
|
||||
|
||||
=========================================================================*/
|
||||
#ifndef cmMakefileUtilityTargetGenerator_h
|
||||
#define cmMakefileUtilityTargetGenerator_h
|
||||
|
||||
#include "cmMakefileTargetGenerator.h"
|
||||
|
||||
class cmMakefileUtilityTargetGenerator:
|
||||
public cmMakefileTargetGenerator
|
||||
{
|
||||
public:
|
||||
/* the main entry point for this class. Writes the Makefiles associated
|
||||
with this target */
|
||||
virtual void WriteRuleFiles();
|
||||
|
||||
protected:
|
||||
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue