On 10/09/2014 07:36 PM, Geoffrey Viola wrote: > Attached is a patch to make CMake generate files for the Green > Hills MULTI IDE. These patches are in reference to this feature > request: http://public.kitware.com/Bug/view.php?id=14992.
Thanks for working on this. First I've extracted the comment typo fixes from the second patch: Fix some spelling errors in comments http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=bef23e81 I've attached a patch rebasing the rest of the changes on 'master' after integration of the typo fixes. To aid others for review, please provide a high-level explanation of the MULTI IDE, its target platforms, and how developers might use it with CMake. > There were some limitations. It has been restricted to Windows, > because that is the version of the IDE that I have. There is a > special grouping called a Monolith that includes several > executables, shared libraries, and the kernel. These monoliths > have their own set of compile options. I’m not sure how CMake > would be able to create these. Also, there are some internal > macros that point to the compiler’s target BSP and OS that are > currently populated via CMake variables: GHS_CUSTOMIZATION, > GHS_OS_DIR, and GHS_BSP_NAME. Depending on the semantics, these may belong in Modules/Platform/<os>.cmake for some <os> name of the target platform. We'll need a better understanding of their role to say for sure though. See CMAKE_OSX_SYSROOT in Darwin*.cmake for example. Thanks, -Brad
>From 2a6c15be56d938d1fac6a06ef9acb06ceeec1e67 Mon Sep 17 00:00:00 2001 Message-Id: <2a6c15be56d938d1fac6a06ef9acb06ceeec1e67.1413294735.git.brad.k...@kitware.com> From: Geoff Viola <[email protected]> Date: Thu, 9 Oct 2014 17:07:48 -0600 Subject: [PATCH] Added basic and partial support for a Green Hill MULTI IDE. --- Modules/CMakeGreenHillsFindMake.cmake | 25 +++ Source/CMakeLists.txt | 6 + Source/cmGhsMultiTargetGenerator.cxx | 301 ++++++++++++++++++++++++++++++ Source/cmGhsMultiTargetGenerator.h | 74 ++++++++ Source/cmGlobalGhsMultiGenerator.cxx | 338 ++++++++++++++++++++++++++++++++++ Source/cmGlobalGhsMultiGenerator.h | 104 +++++++++++ Source/cmLocalGhsMultiGenerator.cxx | 56 ++++++ Source/cmLocalGhsMultiGenerator.h | 56 ++++++ Source/cmake.cxx | 4 + 9 files changed, 964 insertions(+) create mode 100644 Modules/CMakeGreenHillsFindMake.cmake create mode 100644 Source/cmGhsMultiTargetGenerator.cxx create mode 100644 Source/cmGhsMultiTargetGenerator.h create mode 100644 Source/cmGlobalGhsMultiGenerator.cxx create mode 100644 Source/cmGlobalGhsMultiGenerator.h create mode 100644 Source/cmLocalGhsMultiGenerator.cxx create mode 100644 Source/cmLocalGhsMultiGenerator.h diff --git a/Modules/CMakeGreenHillsFindMake.cmake b/Modules/CMakeGreenHillsFindMake.cmake new file mode 100644 index 0000000..7af9f18 --- /dev/null +++ b/Modules/CMakeGreenHillsFindMake.cmake @@ -0,0 +1,25 @@ + +#============================================================================= +# Copyright 2005-2009 Kitware, Inc. +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) +# set(CMAKE_CROSSCOMPILING TRUE) + +set(CMAKE_SYSTEM_NAME "Green Hills MULTI") +set(CMAKE_SYSTEM_PROCESSOR "ARM") +find_program(CMAKE_MAKE_PROGRAM gbuild.exe PATHS + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\GreenHillsSoftware9881cef6;InstallLocation]" + c:/ghs/comp_.* +) +string(REGEX MATCH "(comp_)([0-9]+)" CMAKE_SYSTEM_VERSION "${CMAKE_MAKE_PROGRAM}") +string(REPLACE "comp_" "" CMAKE_SYSTEM_VERSION "${CMAKE_SYSTEM_VERSION}") + +mark_as_advanced(CMAKE_MAKE_PROGRAM) diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index f9405b3..df642d5 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -446,6 +446,12 @@ if (WIN32) cmVisualStudioSlnParser.cxx cmVisualStudioWCEPlatformParser.h cmVisualStudioWCEPlatformParser.cxx + cmGlobalGhsMultiGenerator.cxx + cmGlobalGhsMultiGenerator.h + cmLocalGhsMultiGenerator.cxx + cmLocalGhsMultiGenerator.h + cmGhsMultiTargetGenerator.cxx + cmGhsMultiTargetGenerator.h ) endif() endif () diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx new file mode 100644 index 0000000..9a955bc --- /dev/null +++ b/Source/cmGhsMultiTargetGenerator.cxx @@ -0,0 +1,301 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2011 Peter Collingbourne <[email protected]> + Copyright 2011 Nicolas Despres <[email protected]> + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#include "cmGhsMultiTargetGenerator.h" +#include "cmGlobalGhsMultiGenerator.h" +#include "cmLocalGhsMultiGenerator.h" +#include "cmMakefile.h" +#include "cmTarget.h" +#include "cmGeneratedFileStream.h" +#include "cmSourceFile.h" +#include <assert.h> + +cmGhsMultiTargetGenerator::cmGhsMultiTargetGenerator(cmTarget const* target) + : Target(target) + , LocalGenerator(static_cast<cmLocalGhsMultiGenerator*> + (target->GetMakefile()->GetLocalGenerator())) + , Makefile(target->GetMakefile()) +{ + std::string BuildFileName; + BuildFileName = this->Target->GetFullName(); + BuildFileName += cmGlobalGhsMultiGenerator::FILE_EXTENSION; + + char const* folderProp = this->Target->GetProperty("FOLDER"); + RelBuildFilePath = nullptr == folderProp ? "" : folderProp; + if (RelBuildFilePath.size() > 0 && '/' != RelBuildFilePath.back()) + { + RelBuildFilePath += "/"; + } + RelBuildFilePath += Target->GetName() + "/"; + + RelOutputFileName = RelBuildFilePath + Target->GetName() + ".a"; + + RelBuildFileName = RelBuildFilePath; + if (RelBuildFileName.size() > 0 && '/' != RelBuildFileName.back()) + { + RelBuildFileName += "/"; + } + RelBuildFileName += BuildFileName; + + std::string absPathToRoot(this->Makefile->GetHomeOutputDirectory()); + if (absPathToRoot.size() > 0 && '/' != absPathToRoot.back()) + { + absPathToRoot += "/"; + } + AbsBuildFilePath = absPathToRoot + RelBuildFilePath; + AbsBuildFileName = absPathToRoot + RelBuildFileName; + AbsOutputFileName = absPathToRoot + RelOutputFileName; +} + +cmGhsMultiTargetGenerator::~cmGhsMultiTargetGenerator() +{ +} + +void cmGhsMultiTargetGenerator::Generate() +{ + std::vector<cmSourceFile*> objectSources = GetSources(); + if (objectSources.size() > 0 && IncludeThisTarget()) + { + if (!cmSystemTools::FileExists(AbsBuildFilePath.c_str())) + { + cmSystemTools::MakeDirectory(AbsBuildFilePath.c_str()); + } + FolderBuildStreams[""].open(this->AbsBuildFileName.c_str()); + cmGlobalGhsMultiGenerator::OpenBuildFileStream(GetFolderBuildStreams()); + cmGlobalGhsMultiGenerator::WriteGpjTag(cmGlobalGhsMultiGenerator::PROGRAM, + this->GetFolderBuildStreams()); + cmGlobalGhsMultiGenerator::WriteDisclaimer(GetFolderBuildStreams()); + + WriteTypeSpecifics(); + const std::string config = this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); + WriteCompilerOptions(config); + WriteCompilerFlags(); + WriteCompilerDefinitions(config); + WriteIncludes(config); + WriteTargetLinkLibraries(); + WriteCustomCommands(); + + WriteSources(objectSources); + } +} + +bool cmGhsMultiTargetGenerator::IncludeThisTarget() +{ + bool output = true; + char const* excludeFromAll = this->Target->GetProperty("EXCLUDE_FROM_ALL"); + if (nullptr != excludeFromAll && + '1' == excludeFromAll[0] && + '\0' == excludeFromAll[1]) + { + output = false; + } + return output; +} + +std::vector<cmSourceFile*> cmGhsMultiTargetGenerator::GetSources() const +{ + std::vector<cmSourceFile*> output; + std::string config = this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); + this->Target->GetSourceFiles(output, config); + return output; +} + +cmGlobalGhsMultiGenerator* cmGhsMultiTargetGenerator::GetGlobalGenerator() const +{ + return static_cast<cmGlobalGhsMultiGenerator*>(LocalGenerator->GetGlobalGenerator()); +} + +void cmGhsMultiTargetGenerator::WriteTypeSpecifics() +{ + if (Target->GetType() == cmTarget::TargetType::STATIC_LIBRARY) + { + *GetFolderBuildStreams() << " -relobj" << std::endl; + *GetFolderBuildStreams() << " {optgroup=GhsCommonOptions} -o " << + AbsBuildFilePath << Target->GetFullName() << ".a" << std::endl; + } + else if (Target->GetType() == cmTarget::TargetType::EXECUTABLE) + { + *GetFolderBuildStreams() << " -relprog" << std::endl; + *GetFolderBuildStreams() << " {optgroup=GhsCommonOptions} -o " << + AbsBuildFilePath << Target->GetFullName() << ".a" << std::endl; + } +} + +void cmGhsMultiTargetGenerator::WriteCompilerOptions(std::string const& config) +{ + std::vector<std::string> options; + Target->GetCompileOptions(options, config); + for (std::vector<std::string>::const_iterator options_i = options.begin(); + options_i != options.end(); ++options_i) + { + std::string option = *options_i; + cmSystemTools::ConvertToUnixSlashes(option); + *this->GetFolderBuildStreams() << " " << option << std::endl; + } +} + +void cmGhsMultiTargetGenerator::WriteCompilerFlags() +{ + char const* const compileFlags = Target->GetProperty("COMPILE_FLAGS"); + if (nullptr != compileFlags) + { + *this->GetFolderBuildStreams() << " " << compileFlags << std::endl; + } +} + +void cmGhsMultiTargetGenerator::WriteCompilerDefinitions(const std::string& config) +{ + std::vector<std::string> compileDefinitions; + this->Target->GetCompileDefinitions(compileDefinitions, config); + for (std::vector<std::string>::const_iterator cdI = compileDefinitions.begin(); + cdI != compileDefinitions.end(); ++cdI) + { + *this->GetFolderBuildStreams() << " -D" << (*cdI) << std::endl; + } +} + +void cmGhsMultiTargetGenerator::WriteIncludes(const std::string& config) +{ + std::vector<std::string> includes = Target->GetIncludeDirectories(config); + for (std::vector<std::string>::const_iterator + includes_i = includes.begin(); includes_i != includes.end(); ++includes_i) + { + *this->GetFolderBuildStreams() << " -I" << *includes_i << std::endl; + } +} + +void cmGhsMultiTargetGenerator::WriteTargetLinkLibraries() +{ + //library directories + cmTargetDependSet tds = GetGlobalGenerator()->GetTargetDirectDepends(*this->Target); + for (cmTargetDependSet::iterator tdsI = tds.begin(); + tdsI != tds.end(); ++tdsI) + { + cmTarget const *tg(*tdsI); + cmGhsMultiTargetGenerator gmtg(tg); + *this->GetFolderBuildStreams() << " -L" << gmtg.GetAbsBuildFilePath() << std::endl; + } + //library targets + cmTarget::LinkLibraryVectorType llv = this->Target->GetOriginalLinkLibraries(); + for (cmTarget::LinkLibraryVectorType::const_iterator llvI = llv.begin(); + llvI != llv.end(); ++llvI) + { + std::string libName = llvI->first; + // if it is a user defined target get the full path to the lib + cmTarget *tg(GetGlobalGenerator()->FindTarget(libName)); + if (nullptr != tg) + { + cmGhsMultiTargetGenerator gmtg(tg); + libName = tg->GetName() + ".a"; + } + *this->GetFolderBuildStreams() << " -l" << libName << std::endl; + } +} + +void cmGhsMultiTargetGenerator::WriteCustomCommands() +{ + WriteCustomCommandsHelper(this->Target->GetPreBuildCommands(), + cmTarget::CustomCommandType::PRE_BUILD); + WriteCustomCommandsHelper(this->Target->GetPostBuildCommands(), + cmTarget::CustomCommandType::POST_BUILD); +} + +void cmGhsMultiTargetGenerator::WriteCustomCommandsHelper( + std::vector<cmCustomCommand> const& commandsSet, cmTarget::CustomCommandType const commandType) +{ + for (std::vector<cmCustomCommand>::const_iterator commandsSetI = commandsSet.begin(); + commandsSetI != commandsSet.end(); ++commandsSetI) + { + cmCustomCommandLines const& commands = commandsSetI->GetCommandLines(); + for (cmCustomCommandLines::const_iterator commandI = commands.begin(); + commandI != commands.end(); ++commandI) + { + switch (commandType) + { + case cmTarget::CustomCommandType::PRE_BUILD: + *GetFolderBuildStreams() << " :preexecShellSafe="; + break; + case cmTarget::CustomCommandType::POST_BUILD: + *GetFolderBuildStreams() << " :postexecShellSafe="; + break; + default: + assert("Only pre and post are supported"); + } + cmCustomCommandLine const& command = *commandI; + for (cmCustomCommandLine::const_iterator commandLineI = command.begin(); + commandLineI != command.end(); ++commandLineI) + { + if (command.size() > 0) + { + *GetFolderBuildStreams() << (command.begin() == commandLineI ? "'" : " "); + } + *GetFolderBuildStreams() << *commandLineI; + } + if (command.size() > 0) + { + *GetFolderBuildStreams() << "'" << std::endl; + } + } + } +} + +void cmGhsMultiTargetGenerator::WriteSources(std::vector<cmSourceFile*> + const& objectSources) +{ + for (std::vector<cmSourceFile*>::const_iterator + si = objectSources.begin(); si != objectSources.end(); ++si) + { + std::vector<cmSourceGroup> sourceGroups(this->Makefile->GetSourceGroups()); + char const* sourceFullPath = (*si)->GetFullPath().c_str(); + cmSourceGroup* sourceGroup = + this->Makefile->FindSourceGroup(sourceFullPath, sourceGroups); + std::string sgPath(sourceGroup->GetFullName()); + cmSystemTools::ConvertToUnixSlashes(sgPath); + cmGlobalGhsMultiGenerator::AddFilesUpToPath(GetFolderBuildStreams(), + &FolderBuildStreams, this->Makefile->GetHomeOutputDirectory(), + sgPath, cmGlobalGhsMultiGenerator::GpjType::SUBPROJECT, RelBuildFilePath); + + this->FolderBuildStreams[sgPath] << (*si)->GetFullPath() << std::endl; + + WriteObjectLangOverride(&this->FolderBuildStreams[sgPath], (*si)); + + WriteObjectDir(&this->FolderBuildStreams[sgPath], + AbsBuildFilePath + sgPath); + } +} + +void cmGhsMultiTargetGenerator::WriteObjectLangOverride( + cmGeneratedFileStream *fileStream, cmSourceFile *sourceFile) +{ + const char* rawLangProp = sourceFile->GetProperty("LANGUAGE"); + if (nullptr != rawLangProp) + { + std::string sourceLangProp(rawLangProp); + std::string extension(sourceFile->GetExtension()); + if ("CXX" == sourceLangProp && ("c" == extension || "C" == extension)) + { + *fileStream << " -dotciscxx" << std::endl; + } + } +} + +void cmGhsMultiTargetGenerator::WriteObjectDir( + cmGeneratedFileStream *fileStream, std::string const& dir) +{ + std::string workingDir(dir); + if (workingDir.size() > 0 && '/' != workingDir.back()) + { + workingDir += "/"; + } + workingDir += "Objs"; + *fileStream << " -object_dir=" << workingDir << std::endl; +} diff --git a/Source/cmGhsMultiTargetGenerator.h b/Source/cmGhsMultiTargetGenerator.h new file mode 100644 index 0000000..061a220 --- /dev/null +++ b/Source/cmGhsMultiTargetGenerator.h @@ -0,0 +1,74 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2011 Peter Collingbourne <[email protected]> + Copyright 2011 Nicolas Despres <[email protected]> + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#ifndef cmGhsMultiTargetGenerator_h +#define cmGhsMultiTargetGenerator_h + +#include "cmStandardIncludes.h" +#include "cmTarget.h" + +class cmGeneratedFileStream; +class cmGlobalGhsMultiGenerator; +class cmLocalGhsMultiGenerator; +class cmMakefile; +class cmSourceFile; +class cmGeneratedFileStream; +class cmCustomCommand; + +class cmGhsMultiTargetGenerator +{ +public: + cmGhsMultiTargetGenerator(cmTarget const* target); + + virtual ~cmGhsMultiTargetGenerator(); + + virtual void Generate(); + + bool IncludeThisTarget(); + std::vector<cmSourceFile*> GetSources() const; + const char* GetAbsBuildFilePath() const { return AbsBuildFilePath.c_str(); } + const char* GetRelBuildFileName() const { return RelBuildFileName.c_str(); } + const char* GetAbsBuildFileName() const { return AbsBuildFileName.c_str(); } + const char* GetAbsOutputFileName() const { return AbsOutputFileName.c_str(); } + +private: + cmGlobalGhsMultiGenerator* GetGlobalGenerator() const; + cmGeneratedFileStream* GetFolderBuildStreams() { return &(FolderBuildStreams[""]); }; + + void WriteTypeSpecifics(); + void WriteCompilerOptions(const std::string& config); + void WriteCompilerFlags(); + void WriteCompilerDefinitions(const std::string& config); + void WriteIncludes(std::string const& config); + void WriteTargetLinkLibraries(); + void WriteCustomCommands(); + void WriteCustomCommandsHelper(std::vector<cmCustomCommand> const& commandsSet, + cmTarget::CustomCommandType commandType); + void WriteSources(std::vector<cmSourceFile*> const& objectSources); + static void WriteObjectLangOverride( + cmGeneratedFileStream *fileStream, cmSourceFile *sourceFile); + static void WriteObjectDir(cmGeneratedFileStream *fileStream, + std::string const& dir); + + cmTarget const* Target; + cmLocalGhsMultiGenerator* LocalGenerator; + cmMakefile* Makefile; + std::string AbsBuildFilePath; + std::string RelBuildFilePath; + std::string AbsBuildFileName; + std::string RelBuildFileName; + std::string RelOutputFileName; + std::string AbsOutputFileName; + std::map<std::string, cmGeneratedFileStream> FolderBuildStreams; +}; + +#endif // ! cmNinjaTargetGenerator_h diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx new file mode 100644 index 0000000..52dd81f --- /dev/null +++ b/Source/cmGlobalGhsMultiGenerator.cxx @@ -0,0 +1,338 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2009 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#include "cmGlobalGhsMultiGenerator.h" +#include "cmLocalGhsMultiGenerator.h" +#include "cmMakefile.h" +#include "cmVersion.h" +#include "cmGeneratedFileStream.h" +#include "cmGhsMultiTargetGenerator.h" + +const char* cmGlobalGhsMultiGenerator::FILE_EXTENSION = ".gpj"; + +cmGlobalGhsMultiGenerator::cmGlobalGhsMultiGenerator() +{ + this->FindMakeProgramFile = "CMakeGreenHillsFindMake.cmake"; +} + +cmLocalGenerator *cmGlobalGhsMultiGenerator::CreateLocalGenerator() +{ + cmLocalGenerator* lg = + new cmLocalGhsMultiGenerator; + lg->SetGlobalGenerator(this); + this->SetCurrentLocalGenerator(lg); + return lg; +} + +void cmGlobalGhsMultiGenerator +::GetDocumentation(cmDocumentationEntry& entry) +{ + entry.Name = cmGlobalGhsMultiGenerator::GetActualName(); + entry.Brief = "Generates Green Hills MULTI files (experimental)."; +} + +void cmGlobalGhsMultiGenerator +::EnableLanguage(std::vector<std::string>const& l, +cmMakefile *mf, +bool optional) +{ + mf->AddDefinition("CMAKE_GENERATOR_CC", "ccarm"); + mf->AddDefinition("CMAKE_GENERATOR_CXX", "cxarm"); + mf->AddDefinition("GHSMULTI", "1"); //identifier for user CMake files +} + +void cmGlobalGhsMultiGenerator::OpenBuildFileStream(std::string const& filepath, + cmGeneratedFileStream** filestream) +{ + // Get a stream where to generate things. + if (nullptr == *filestream) + { + *filestream = new cmGeneratedFileStream(filepath.c_str()); + if (nullptr != *filestream) + { + OpenBuildFileStream(*filestream); + } + } +} + +void cmGlobalGhsMultiGenerator::OpenBuildFileStream(cmGeneratedFileStream* filestream) +{ + *filestream << "#!gbuild" << std::endl; +} + +void cmGlobalGhsMultiGenerator::WriteGpjTag(cmGlobalGhsMultiGenerator::GpjType const gpjType, + cmGeneratedFileStream *filestream) +{ + char const* tag; + switch (gpjType) + { + case cmGlobalGhsMultiGenerator::INTERGRITY_APPLICATION: + tag = "INTEGRITY Application"; + break; + case cmGlobalGhsMultiGenerator::PROJECT: + tag = "Project"; + break; + case cmGlobalGhsMultiGenerator::PROGRAM: + tag = "Program"; + break; + case cmGlobalGhsMultiGenerator::REFERENCE: + tag = "Reference"; + break; + case cmGlobalGhsMultiGenerator::SUBPROJECT: + tag = "Subproject"; + break; + default: + tag = ""; + } + *filestream << "[" << tag << "]" << std::endl; +} + +void cmGlobalGhsMultiGenerator::OpenBuildFileStream() +{ + // Compute GHS MULTI's build file path. + std::string buildFilePath = + this->GetCMakeInstance()->GetHomeOutputDirectory(); + buildFilePath += "/"; + buildFilePath += this->GetCurrentLocalGenerator()->GetMakefile()->GetProjectName(); + buildFilePath += cmGlobalGhsMultiGenerator::FILE_EXTENSION; + + TargetFolderBuildStreams[""].open(buildFilePath.c_str()); + cmGlobalGhsMultiGenerator::OpenBuildFileStream(GetBuildFileStream()); + + char const* osDir = + this->GetCMakeInstance()->GetCacheDefinition("GHS_OS_DIR"); + if (nullptr == osDir) + { + osDir = ""; + } + else + { + this->GetCMakeInstance()->MarkCliAsUsed("GHS_OS_DIR"); + } + std::string fOSDir(osDir); + cmSystemTools::ReplaceString(fOSDir, "\\", "/"); + char const* bspName = + this->GetCMakeInstance()->GetCacheDefinition("GHS_BSP_NAME"); + if (nullptr == bspName) + { + bspName = ""; + } + else + { + this->GetCMakeInstance()->MarkCliAsUsed("GHS_BSP_NAME"); + } + std::string fBspName(bspName); + cmSystemTools::ReplaceString(fBspName, "\\", "/"); + WriteMacros(fOSDir, fBspName); + WriteHighLevelDirectives(); + + WriteGpjTag(cmGlobalGhsMultiGenerator::PROJECT, GetBuildFileStream()); + cmGlobalGhsMultiGenerator::WriteDisclaimer(GetBuildFileStream()); + *GetBuildFileStream() << "# Top Level Project File" << std::endl; + if (fBspName.length() > 0) + { + *GetBuildFileStream() << " -bsp " << fBspName << std::endl; + } + WriteCompilerOptions(fOSDir); +} + +void cmGlobalGhsMultiGenerator::CloseBuildFileStream(cmGeneratedFileStream** filestream) +{ + if (filestream) + { + delete *filestream; + *filestream = nullptr; + } + else + { + cmSystemTools::Error("Build file stream was not open."); + } +} + +void cmGlobalGhsMultiGenerator::Generate() +{ + this->OpenBuildFileStream(); + + this->cmGlobalGenerator::Generate(); + + //Build all the folder build files + for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i) + { + cmLocalGhsMultiGenerator* lg = + static_cast<cmLocalGhsMultiGenerator*>(this->LocalGenerators[i]); + cmGeneratorTargetsType tgts = lg->GetMakefile()->GetGeneratorTargets(); + UpdateBuildFiles(tgts); + } +} + +void cmGlobalGhsMultiGenerator::WriteMacros(std::string const& fOSDir, std::string const& fBspName) +{ + *GetBuildFileStream() << "macro __BUILD_DIR=" << + this->GetCMakeInstance()->GetHomeOutputDirectory() << std::endl;; + *GetBuildFileStream() << "macro __OS_DIR=" << fOSDir << std::endl; + *GetBuildFileStream() << "macro __LIBS_DIR_BASE=" << fOSDir << "/libs" << std::endl; + *GetBuildFileStream() << "macro __BSP_NAME=" << fBspName << std::endl; + *GetBuildFileStream() << "macro __BSP_DIR=" << fOSDir << "/" << fBspName << std::endl; +} + +void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives() +{ + *GetBuildFileStream() << "primaryTarget=arm_integrity.tgt" << std::endl; + char const* const customization = this->GetCMakeInstance()->GetCacheDefinition("GHS_CUSTOMIZATION"); + if (nullptr != customization) + { + *GetBuildFileStream() << "customization=" << customization << std::endl; + this->GetCMakeInstance()->MarkCliAsUsed("GHS_CUSTOMIZATION"); + } +} + +void cmGlobalGhsMultiGenerator::WriteCompilerOptions(std::string const& fOSDir) +{ + *GetBuildFileStream() << " -os_dir=$(__OS_DIR)" << std::endl; + *GetBuildFileStream() << " --link_once_templates" << std::endl; +} + +void cmGlobalGhsMultiGenerator::WriteDisclaimer(std::ostream* os) +{ + (*os) + << "#" << std::endl + << "# CMAKE generated file: DO NOT EDIT!" << std::endl + << "# Generated by \"" << cmGlobalGhsMultiGenerator::GetActualName() << "\"" + << " Generator, CMake Version " + << cmVersion::GetMajorVersion() << "." + << cmVersion::GetMinorVersion() << std::endl + << "#" << std::endl; +} + +void cmGlobalGhsMultiGenerator::AddFilesUpToPath( + cmGeneratedFileStream* mainBuildFile, + std::map<std::string, cmGeneratedFileStream> *targetFolderBuildStreams, + char const *homeOutputDirectory, std::string const& path, + GpjType projType, std::string const& relPath) +{ + std::string workingPath(path); + cmSystemTools::ConvertToUnixSlashes(workingPath); + std::vector<cmsys::String> splitPath = cmSystemTools::SplitString(workingPath); + std::string workingRelPath(relPath); + if (relPath.size() > 0 && '/' != relPath.back()) + { + workingRelPath += "/"; + } + std::string pathUpTo; + for (std::vector<cmsys::String>::const_iterator splitPathI = splitPath.begin(); + splitPath.end() != splitPathI; ++splitPathI) + { + pathUpTo += *splitPathI; + if (targetFolderBuildStreams->end() == targetFolderBuildStreams->find(pathUpTo)) + { + AddFilesUpToPathNewBuildFile(mainBuildFile, + targetFolderBuildStreams, homeOutputDirectory, + pathUpTo, splitPath.begin() == splitPathI, workingRelPath, projType); + } + AddFilesUpToPathAppendNextFile(targetFolderBuildStreams, pathUpTo, + splitPathI, splitPath.end(), projType); + pathUpTo += "/"; + } +} + +void cmGlobalGhsMultiGenerator::AddFilesUpToPathNewBuildFile( + cmGeneratedFileStream* mainBuildFile, + std::map<std::string, cmGeneratedFileStream> *targetFolderBuildStreams, + char const *homeOutputDirectory, + std::string const& pathUpTo, bool const isFirst, std::string const& relPath, + GpjType const projType) +{ + //create folders up to file path + std::string absPath = std::string(homeOutputDirectory) + "/" + relPath; + std::string newPath = absPath + pathUpTo; + if (!cmSystemTools::FileExists(newPath.c_str())) + { + cmSystemTools::MakeDirectory(newPath.c_str()); + } + + //Write out to filename for first time + std::string relFilename(cmGlobalGhsMultiGenerator::GetFileNameFromPath(pathUpTo)); + std::string absFilename = absPath + relFilename; + (*targetFolderBuildStreams)[pathUpTo].open(absFilename.c_str()); + cmGlobalGhsMultiGenerator::OpenBuildFileStream(&(*targetFolderBuildStreams)[pathUpTo]); + cmGlobalGhsMultiGenerator::WriteGpjTag(projType, + &(*targetFolderBuildStreams)[pathUpTo]); + cmGlobalGhsMultiGenerator::WriteDisclaimer(&(*targetFolderBuildStreams)[pathUpTo]); + + //Add to main build file + if (isFirst) + { + *mainBuildFile << relFilename << " "; + WriteGpjTag(projType, mainBuildFile); + } +} + +void cmGlobalGhsMultiGenerator::AddFilesUpToPathAppendNextFile( + std::map<std::string, cmGeneratedFileStream> *targetFolderBuildStreams, + std::string const& pathUpTo, + std::vector<cmsys::String>::const_iterator splitPathI, + std::vector<cmsys::String>::const_iterator end, + GpjType const projType) +{ + std::vector<cmsys::String>::const_iterator splitPathNextI = splitPathI + 1; + if (end != splitPathNextI && + targetFolderBuildStreams->end() == + targetFolderBuildStreams->find(pathUpTo + "/" + *splitPathNextI)) + { + std::string nextFilename(*splitPathNextI); + nextFilename = cmGlobalGhsMultiGenerator::GetFileNameFromPath(nextFilename); + (*targetFolderBuildStreams)[pathUpTo] << nextFilename << " "; + cmGlobalGhsMultiGenerator::WriteGpjTag(projType, + &(*targetFolderBuildStreams)[pathUpTo]); + } +} + +std::string cmGlobalGhsMultiGenerator::GetFileNameFromPath(std::string const& path) +{ + std::string output(path); + if (path.length() > 0) + { + cmSystemTools::ConvertToUnixSlashes(output); + std::vector<cmsys::String> splitPath = cmSystemTools::SplitString(output); + output += "/" + splitPath.back() + cmGlobalGhsMultiGenerator::FILE_EXTENSION; + } + return output; +} + +void cmGlobalGhsMultiGenerator::UpdateBuildFiles(cmGeneratorTargetsType const& tgts) +{ + for (cmGeneratorTargetsType::const_iterator tgtsI = tgts.begin(); + tgtsI != tgts.end(); ++tgtsI) + { + cmGhsMultiTargetGenerator gmtg(tgtsI->first); + if (gmtg.GetSources().size() > 0 && gmtg.IncludeThisTarget()) + { + char const* rawFolderName = tgtsI->first->GetProperty("FOLDER"); + if (nullptr == rawFolderName) + { + rawFolderName = ""; + } + std::string folderName(rawFolderName); + if (TargetFolderBuildStreams.end() == TargetFolderBuildStreams.find(folderName)) + { + AddFilesUpToPath(GetBuildFileStream(), &TargetFolderBuildStreams, + this->GetCMakeInstance()->GetHomeOutputDirectory(), folderName, + GpjType::PROJECT); + } + std::vector<cmsys::String> splitPath = + cmSystemTools::SplitString(gmtg.GetRelBuildFileName()); + std::string foldNameRelBuildFile(*(splitPath.end() - 2) + + "/" + splitPath.back()); + TargetFolderBuildStreams[folderName] << foldNameRelBuildFile << " "; + WriteGpjTag(GpjType::PROGRAM, &TargetFolderBuildStreams[folderName]); + } + } +} diff --git a/Source/cmGlobalGhsMultiGenerator.h b/Source/cmGlobalGhsMultiGenerator.h new file mode 100644 index 0000000..0e33d87 --- /dev/null +++ b/Source/cmGlobalGhsMultiGenerator.h @@ -0,0 +1,104 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2009 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#ifndef cmGhsMultiGenerator_h +#define cmGhsMultiGenerator_h + +#include "cmGlobalGeneratorFactory.h" +#include "cmGlobalGenerator.h" + +class cmGeneratedFileStream; + +class cmGlobalGhsMultiGenerator : public cmGlobalGenerator +{ +public: + enum GpjType + { + INTERGRITY_APPLICATION, PROJECT, PROGRAM, REFERENCE, SUBPROJECT + }; + + /// The default name of GHS MULTI's build file. Typically: monolith.gpj. + static const char* FILE_EXTENSION; + + cmGlobalGhsMultiGenerator(); + + static cmGlobalGeneratorFactory* NewFactory() { + return new cmGlobalGeneratorSimpleFactory<cmGlobalGhsMultiGenerator>(); + } + + ///! create the correct local generator + virtual cmLocalGenerator *CreateLocalGenerator(); + + /// @return the name of this generator. + static std::string GetActualName() { return "Green Hills MULTI"; } + ///! Get the name for this generator + virtual std::string GetName() const { return cmGlobalGhsMultiGenerator::GetActualName(); } + + /// Overloaded methods. @see cmGlobalGenerator::GetDocumentation() + static void GetDocumentation(cmDocumentationEntry& entry); + + /** + * Try to determine system information such as shared library + * extension, pthreads, byte order etc. + */ + virtual void EnableLanguage(std::vector<std::string>const& languages, + cmMakefile *, bool optional); + + cmGeneratedFileStream* GetBuildFileStream() { + return &(TargetFolderBuildStreams[""]); + } + + static void WriteGpjTag(GpjType gpjType, cmGeneratedFileStream *filestream); + static void OpenBuildFileStream(std::string const& filepath, + cmGeneratedFileStream** filestream); + static void OpenBuildFileStream(cmGeneratedFileStream* filestream); + static void CloseBuildFileStream(cmGeneratedFileStream **filestream); + /// Write the common disclaimer text at the top of each build file. + static void WriteDisclaimer(std::ostream* os); + std::vector<std::string> GetLibDirs() { return LibDirs; } + + static void AddFilesUpToPath(cmGeneratedFileStream* mainBuildFile, + std::map<std::string, cmGeneratedFileStream> *targetFolderBuildStreams, + char const *homeOutputDirectory, + std::string const& path, GpjType projType, + std::string const& relPath = ""); + +protected: + virtual void Generate(); + +private: + void OpenBuildFileStream(); + + void WriteMacros(std::string const& fOSDir, std::string const& fBspName); + void WriteHighLevelDirectives(); + void WriteCompilerOptions(std::string const& fOSDir); + + static void AddFilesUpToPathNewBuildFile(cmGeneratedFileStream* mainBuildFile, + std::map<std::string, cmGeneratedFileStream> *targetFolderBuildStreams, + char const *homeOutputDirectory, + std::string const& pathUpTo, bool isFirst, std::string const& relPath, + GpjType projType); + static void AddFilesUpToPathAppendNextFile( + std::map<std::string, cmGeneratedFileStream> *targetFolderBuildStreams, + std::string const& pathUpTo, + std::vector<cmsys::String>::const_iterator splitPathI, + std::vector<cmsys::String>::const_iterator end, + GpjType projType); + static std::string GetFileNameFromPath(std::string const& path); + void UpdateBuildFiles(cmGeneratorTargetsType const& tgts); + + std::vector<cmGeneratedFileStream*> TargetSubProjects; + std::map<std::string, cmGeneratedFileStream> TargetFolderBuildStreams; + + std::vector<std::string> LibDirs; +}; + +#endif diff --git a/Source/cmLocalGhsMultiGenerator.cxx b/Source/cmLocalGhsMultiGenerator.cxx new file mode 100644 index 0000000..ce47569 --- /dev/null +++ b/Source/cmLocalGhsMultiGenerator.cxx @@ -0,0 +1,56 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2009 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#include "cmLocalGhsMultiGenerator.h" +#include "cmGlobalGhsMultiGenerator.h" +#include "cmGeneratorTarget.h" +#include "cmMakefile.h" +#include "cmGhsMultiTargetGenerator.h" +#include "cmGeneratedFileStream.h" + +cmLocalGhsMultiGenerator::cmLocalGhsMultiGenerator() +{ +} + +cmLocalGhsMultiGenerator::~cmLocalGhsMultiGenerator() +{ +} + +void cmLocalGhsMultiGenerator::Generate() +{ + cmGeneratorTargetsType tgts = this->GetMakefile()->GetGeneratorTargets(); + if (tgts.size() > 0) + { + for (cmGeneratorTargetsType::iterator l = tgts.begin(); l != tgts.end(); ++l) + { + cmGhsMultiTargetGenerator tg(l->second->Target); + tg.Generate(); + } + } +} + +// Implemented in: +// cmLocalGenerator. +// Used in: +// Source/cmMakefile.cxx +// Source/cmGlobalGenerator.cxx +void cmLocalGhsMultiGenerator::Configure() +{ + // Compute the path to use when referencing the current output + // directory from the top output directory. + this->HomeRelativeOutputPath = + this->Convert(this->Makefile->GetStartOutputDirectory(), HOME_OUTPUT); + if (this->HomeRelativeOutputPath == ".") + { + this->HomeRelativeOutputPath = ""; + } + this->cmLocalGenerator::Configure(); +} diff --git a/Source/cmLocalGhsMultiGenerator.h b/Source/cmLocalGhsMultiGenerator.h new file mode 100644 index 0000000..0b34a3b --- /dev/null +++ b/Source/cmLocalGhsMultiGenerator.h @@ -0,0 +1,56 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2009 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#ifndef cmLocalGhsMultiGenerator_h +#define cmLocalGhsMultiGenerator_h + +#include "cmLocalGenerator.h" + +class cmGeneratedFileStream; + +/** \class cmLocalGhsMultiGenerator + * \brief Write Green Hills MULTI project files. + * + * cmLocalGhsMultiGenerator produces a set of .gpj + * file for each target in its mirrored directory. + */ +class cmLocalGhsMultiGenerator : public cmLocalGenerator +{ +public: + cmLocalGhsMultiGenerator(); + + virtual ~cmLocalGhsMultiGenerator(); + + /// @returns the relative path between the HomeOutputDirectory and this + /// local generators StartOutputDirectory. + std::string GetHomeRelativeOutputPath() const + { + return this->HomeRelativeOutputPath; + } + + /** + * Generate the makefile for this directory. + */ + virtual void Generate(); + + /// Overloaded methods. @see cmLocalGenerator::Configure() + virtual void Configure(); + const char* GetBuildFileName() { return BuildFileName.c_str(); } + +protected: + virtual bool CustomCommandUseLocal() const { return true; } + +private: + std::string BuildFileName; + std::string HomeRelativeOutputPath; +}; + +#endif diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 09d270d..1bc265a 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -89,6 +89,8 @@ # include "cmExtraEclipseCDT4Generator.h" #endif +#include "cmGlobalGhsMultiGenerator.h" + #include <stdlib.h> // required for atoi #if defined( __APPLE__ ) @@ -1854,6 +1856,8 @@ void cmake::AddDefaultGenerators() cmGlobalUnixMakefileGenerator3::NewFactory()); this->Generators.push_back( cmGlobalNinjaGenerator::NewFactory()); + this->Generators.push_back( + cmGlobalGhsMultiGenerator::NewFactory()); #if defined(CMAKE_USE_WMAKE) this->Generators.push_back( cmGlobalWatcomWMakeGenerator::NewFactory()); -- 2.1.0
-- Powered by www.kitware.com Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Kitware offers various services to support the CMake community. For more information on each offering, please visit: CMake Support: http://cmake.org/cmake/help/support.html CMake Consulting: http://cmake.org/cmake/help/consulting.html CMake Training Courses: http://cmake.org/cmake/help/training.html Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Follow this link to subscribe/unsubscribe: http://public.kitware.com/mailman/listinfo/cmake-developers
