Add a 'Green Hills MULTI' generator on Windows

Green Hills MULTI is an IDE for embedded real-time systems.  The IDE's
product page can be found here:

 http://www.ghs.com/products/MULTI_IDE.html

It supports cross compiling on ARM, Intel x86, and other architectures
with various operating systems.  The IDE exists on Linux and Windows
host systems, but CMake will currently only generate the project files
on Windows host systems.
This commit is contained in:
Geoff Viola 2015-03-23 23:12:55 -06:00 committed by Brad King
parent 051d8be17f
commit 48004d9dbe
38 changed files with 1868 additions and 1 deletions

View File

@ -0,0 +1,16 @@
Green Hills MULTI
-----------------
Generates Green Hills MULTI project files (experimental, work-in-progress).
Customizations are available through the following cache variables:
* ``GHS_BSP_NAME``
* ``GHS_CUSTOMIZATION``
* ``GHS_GPJ_MACROS``
* ``GHS_OS_DIR``
.. note::
This generator is deemed experimental as of CMake |release|
and is still a work in progress. Future versions of CMake
may make breaking changes as the generator matures.

View File

@ -73,6 +73,7 @@ Visual Studio Generators
.. toctree::
:maxdepth: 1
/generator/Green Hills MULTI
/generator/Visual Studio 6
/generator/Visual Studio 7
/generator/Visual Studio 7 .NET 2003

View File

@ -182,6 +182,7 @@ Variables that Describe the System
/variable/CMAKE_SYSTEM_VERSION
/variable/CYGWIN
/variable/ENV
/variable/GHS-MULTI
/variable/MINGW
/variable/MSVC10
/variable/MSVC11
@ -307,6 +308,10 @@ Variables for Languages
/variable/CMAKE_LANG_FLAGS_RELEASE
/variable/CMAKE_LANG_FLAGS_RELWITHDEBINFO
/variable/CMAKE_LANG_FLAGS
/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_DEBUG
/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_MINSIZEREL
/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_RELEASE
/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_RELWITHDEBINFO
/variable/CMAKE_LANG_IGNORE_EXTENSIONS
/variable/CMAKE_LANG_IMPLICIT_INCLUDE_DIRECTORIES
/variable/CMAKE_LANG_IMPLICIT_LINK_DIRECTORIES

View File

@ -0,0 +1,6 @@
CMAKE_<LANG>_GHS_KERNEL_FLAGS_DEBUG
-----------------------------------
GHS kernel flags for Debug build type or configuration.
<LANG> flags used when CMAKE_BUILD_TYPE is Debug.

View File

@ -0,0 +1,7 @@
CMAKE_<LANG>_GHS_KERNEL_FLAGS_MINSIZEREL
----------------------------------------
GHS kernel flags for MinSizeRel build type or configuration.
<LANG> flags used when CMAKE_BUILD_TYPE is MinSizeRel.Short for
minimum size release.

View File

@ -0,0 +1,6 @@
CMAKE_<LANG>_GHS_KERNEL_FLAGS_RELEASE
-------------------------------------
GHS kernel flags for Release build type or configuration.
<LANG> flags used when CMAKE_BUILD_TYPE is Release

View File

@ -0,0 +1,7 @@
CMAKE_<LANG>_GHS_KERNEL_FLAGS_RELWITHDEBINFO
--------------------------------------------
GHS kernel flags for RelWithDebInfo type or configuration.
<LANG> flags used when CMAKE_BUILD_TYPE is RelWithDebInfo. Short for
Release With Debug Information.

View File

@ -56,6 +56,10 @@ to configure the project:
the CMake cache then CMake will use the specified value if
possible.
* The :generator:`Green Hills MULTI` generator sets this to ``gbuild``.
If a user or project explicitly adds ``CMAKE_MAKE_PROGRAM`` to
the CMake cache then CMake will use the specified value.
The ``CMAKE_MAKE_PROGRAM`` variable is set for use by project code.
The value is also used by the :manual:`cmake(1)` ``--build`` and
:manual:`ctest(1)` ``--build-and-test`` tools to launch the native

View File

@ -6,3 +6,5 @@ The name of the CPU CMake is building for.
This variable is the same as :variable:`CMAKE_HOST_SYSTEM_PROCESSOR` if
you build for the host system instead of the target system when
cross compiling.
* The Green Hills MULTI generator sets this to ``ARM`` by default

View File

@ -0,0 +1,4 @@
GHS-MULTI
---------
True when using Green Hills MULTI

View File

@ -0,0 +1,27 @@
set(CMAKE_C_VERBOSE_FLAG "-v")
set(CMAKE_C_FLAGS_INIT "")
set(CMAKE_C_FLAGS_DEBUG_INIT "-Odebug -g")
set(CMAKE_C_FLAGS_MINSIZEREL_INIT "-Ospace")
set(CMAKE_C_FLAGS_RELEASE_INIT "-O")
set(CMAKE_C_FLAGS_RELWITHDEBINFO_INIT "-O -g")
set(CMAKE_C_GHS_KERNEL_FLAGS_DEBUG_INIT "-ldebug ${CMAKE_C_FLAGS_DEBUG_INIT}")
set(CMAKE_C_GHS_KERNEL_FLAGS_MINSIZEREL_INIT "${CMAKE_C_FLAGS_MINSIZEREL_INIT}")
set(CMAKE_C_GHS_KERNEL_FLAGS_RELEASE_INIT "${CMAKE_C_FLAGS_RELEASE_INIT}")
set(CMAKE_C_GHS_KERNEL_FLAGS_RELWITHDEBINFO_INIT
"-ldebug ${CMAKE_C_FLAGS_RELWITHDEBINFO_INIT}")
if(NOT CMAKE_NOT_USING_CONFIG_FLAGS)
set (CMAKE_C_GHS_KERNEL_FLAGS_DEBUG "${CMAKE_C_GHS_KERNEL_FLAGS_DEBUG_INIT}"
CACHE STRING "Kernel flags used by the compiler during debug builds.")
set (CMAKE_C_GHS_KERNEL_FLAGS_MINSIZEREL
"${CMAKE_C_GHS_KERNEL_FLAGS_MINSIZEREL_INIT}" CACHE STRING
"Kernel flags used by the compiler during release builds for minimum size.")
set (CMAKE_C_GHS_KERNEL_FLAGS_RELEASE
"${CMAKE_C_GHS_KERNEL_FLAGS_RELEASE_INIT}"
CACHE STRING "Kernel flags used by the compiler during release builds.")
set (CMAKE_C_GHS_KERNEL_FLAGS_RELWITHDEBINFO
"${CMAKE_C_GHS_KERNEL_FLAGS_RELWITHDEBINFO_INIT}" CACHE STRING
"Kernel flags used by the compiler during release builds with debug info.")
endif()

View File

@ -0,0 +1,31 @@
set(CMAKE_CXX_VERBOSE_FLAG "-v")
set(CMAKE_CXX_FLAGS_INIT "")
set(CMAKE_CXX_FLAGS_DEBUG_INIT "-Odebug -g")
set(CMAKE_CXX_FLAGS_MINSIZEREL_INIT "-Ospace")
set(CMAKE_CXX_FLAGS_RELEASE_INIT "-O")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT "-O -g")
set(CMAKE_CXX_GHS_KERNEL_FLAGS_DEBUG_INIT
"-ldebug ${CMAKE_CXX_FLAGS_DEBUG_INIT}")
set(CMAKE_CXX_GHS_KERNEL_FLAGS_MINSIZEREL_INIT
"${CMAKE_CXX_FLAGS_MINSIZEREL_INIT}")
set(CMAKE_CXX_GHS_KERNEL_FLAGS_RELEASE_INIT
"${CMAKE_CXX_FLAGS_RELEASE_INIT}")
set(CMAKE_CXX_GHS_KERNEL_FLAGS_RELWITHDEBINFO_INIT
"-ldebug ${CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT}")
if(NOT CMAKE_NOT_USING_CONFIG_FLAGS)
set (CMAKE_CXX_GHS_KERNEL_FLAGS_DEBUG
"${CMAKE_CXX_GHS_KERNEL_FLAGS_DEBUG_INIT}"
CACHE STRING "Kernel flags used by the compiler during debug builds.")
set (CMAKE_CXX_GHS_KERNEL_FLAGS_MINSIZEREL
"${CMAKE_CXX_GHS_KERNEL_FLAGS_MINSIZEREL_INIT}" CACHE STRING
"Kernel flags used by the compiler during release builds for minimum size.")
set (CMAKE_CXX_GHS_KERNEL_FLAGS_RELEASE
"${CMAKE_CXX_GHS_KERNEL_FLAGS_RELEASE_INIT}"
CACHE STRING "Kernel flags used by the compiler during release builds.")
set (CMAKE_CXX_GHS_KERNEL_FLAGS_RELWITHDEBINFO
"${CMAKE_CXX_GHS_KERNEL_FLAGS_RELWITHDEBINFO_INIT}" CACHE STRING
"Kernel flags used by the compiler during release builds with debug info.")
endif()

View File

@ -0,0 +1,6 @@
set(_compiler_id_pp_test "defined(__INTEGRITY)")
set(_compiler_id_version_compute "
# define @PREFIX@COMPILER_VERSION_MAJOR @MACRO_DEC@(__INTEGRITY_MAJOR_VERSION)
# define @PREFIX@COMPILER_VERSION_MINOR @MACRO_DEC@(__INTEGRITY_MINOR_VERSION)
# define @PREFIX@COMPILER_VERSION_PATCH @MACRO_DEC@(__INTEGRITY_PATCH_VERSION)")

View File

@ -405,6 +405,8 @@ function(_Boost_GUESS_COMPILER_PREFIX _ret)
else()
set (_boost_COMPILER "-il")
endif()
elseif (GHSMULTI)
set(_boost_COMPILER "-ghs")
elseif (MSVC14)
set(_boost_COMPILER "-vc140")
elseif (MSVC12)
@ -777,7 +779,8 @@ endif()
# ------------------------------------------------------------------------
set(Boost_LIB_PREFIX "")
if ( WIN32 AND Boost_USE_STATIC_LIBS AND NOT CYGWIN)
if ( (GHSMULTI AND Boost_USE_STATIC_LIBS) OR
(WIN32 AND Boost_USE_STATIC_LIBS AND NOT CYGWIN) )
set(Boost_LIB_PREFIX "lib")
endif()

View File

@ -0,0 +1,29 @@
#=============================================================================
# Copyright 2015 Geoffrey Viola <geoffrey.viola@asirobots.com>
#
# 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.)
#Setup Greenhills MULTI specific compilation information
find_path(GHS_INT_DIRECTORY INTEGRITY.ld PATHS
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\GreenHillsSoftware6433c345;InstallLocation]" #int1122
"C:/ghs/int1122"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\GreenHillsSoftware289b6625;InstallLocation]" #int1104
"C:/ghs/int1104"
DOC "Path to integrity directory"
)
set(GHS_OS_DIR ${GHS_INT_DIRECTORY} CACHE PATH "OS directory")
set(GHS_PRIMARY_TARGET "arm_integrity.tgt" CACHE STRING "target for compilation")
set(GHS_BSP_NAME "simarm" CACHE STRING "BSP name")
set(GHS_CUSTOMIZATION "" CACHE FILEPATH "optional GHS customization")
mark_as_advanced(GHS_CUSTOMIZATION)
set(GHS_GPJ_MACROS "" CACHE STRING "optional GHS macros generated in the .gpjs for legacy reasons")
mark_as_advanced(GHS_GPJ_MACROS)

View File

@ -0,0 +1,27 @@
#=============================================================================
# Copyright 2015 Geoffrey Viola <geoffrey.viola@asirobots.com>
#
# 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.)
# This module is shared by multiple languages; use include blocker.
if(__GHSMULTI)
return()
endif()
set(__GHSMULTI 1)
set(GHSMULTI 1)
set(CMAKE_FIND_LIBRARY_PREFIXES "")
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
include(Platform/WindowsPaths)

View File

@ -472,6 +472,14 @@ if (WIN32)
cmVisualStudioSlnParser.cxx
cmVisualStudioWCEPlatformParser.h
cmVisualStudioWCEPlatformParser.cxx
cmGlobalGhsMultiGenerator.cxx
cmGlobalGhsMultiGenerator.h
cmLocalGhsMultiGenerator.cxx
cmLocalGhsMultiGenerator.h
cmGhsMultiTargetGenerator.cxx
cmGhsMultiTargetGenerator.h
cmGhsMultiGpj.cxx
cmGhsMultiGpj.h
)
endif()
endif ()
@ -499,6 +507,7 @@ set(SRCS ${SRCS}
cmNinjaUtilityTargetGenerator.cxx
cmNinjaUtilityTargetGenerator.h
)
if(WIN32 AND NOT CYGWIN)
set_source_files_properties(cmcldeps.cxx PROPERTIES COMPILE_DEFINITIONS _WIN32_WINNT=0x0501)
add_executable(cmcldeps cmcldeps.cxx)

44
Source/cmGhsMultiGpj.cxx Normal file
View File

@ -0,0 +1,44 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2015 Geoffrey Viola <geoffrey.viola@asirobots.com>
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 "cmGhsMultiGpj.h"
#include "cmGeneratedFileStream.h"
void GhsMultiGpj::WriteGpjTag(Types const gpjType,
cmGeneratedFileStream *const filestream)
{
char const *tag;
switch (gpjType)
{
case INTERGRITY_APPLICATION:
tag = "INTEGRITY Application";
break;
case LIBRARY:
tag = "Library";
break;
case PROJECT:
tag = "Project";
break;
case PROGRAM:
tag = "Program";
break;
case REFERENCE:
tag = "Reference";
break;
case SUBPROJECT:
tag = "Subproject";
break;
default:
tag = "";
}
*filestream << "[" << tag << "]" << std::endl;
}

34
Source/cmGhsMultiGpj.h Normal file
View File

@ -0,0 +1,34 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2015 Geoffrey Viola <geoffrey.viola@asirobots.com>
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 cmGhsMultiGpj_h
#define cmGhsMultiGpj_h
class cmGeneratedFileStream;
class GhsMultiGpj
{
public:
enum Types
{
INTERGRITY_APPLICATION,
LIBRARY,
PROJECT,
PROGRAM,
REFERENCE,
SUBPROJECT
};
static void WriteGpjTag(Types const gpjType,
cmGeneratedFileStream *filestream);
};
#endif // ! cmGhsMultiGpjType_h

View File

@ -0,0 +1,600 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2015 Geoffrey Viola <geoffrey.viola@asirobots.com>
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>
#include <cmAlgorithms.h>
std::string const cmGhsMultiTargetGenerator::DDOption("-dynamic");
cmGhsMultiTargetGenerator::cmGhsMultiTargetGenerator(cmTarget *target)
: Target(target)
, LocalGenerator(static_cast<cmLocalGhsMultiGenerator *>(
target->GetMakefile()->GetLocalGenerator()))
, Makefile(target->GetMakefile())
, TargetGroup(DetermineIfTargetGroup(target))
, DynamicDownload(false)
{
this->RelBuildFilePath = this->GetRelBuildFilePath(target);
this->RelOutputFileName =
this->RelBuildFilePath + this->Target->GetName() + ".a";
this->RelBuildFileName = this->RelBuildFilePath;
this->RelBuildFileName += this->GetBuildFileName(target);
std::string absPathToRoot = this->GetAbsPathToRoot(target);
absPathToRoot = this->AddSlashIfNeededToPath(absPathToRoot);
this->AbsBuildFilePath = absPathToRoot + this->RelBuildFilePath;
this->AbsBuildFileName = absPathToRoot + this->RelBuildFileName;
this->AbsOutputFileName = absPathToRoot + this->RelOutputFileName;
}
cmGhsMultiTargetGenerator::~cmGhsMultiTargetGenerator()
{
cmDeleteAll(this->FolderBuildStreams);
}
std::string
cmGhsMultiTargetGenerator::GetRelBuildFilePath(const cmTarget *target)
{
std::string output;
char const *folderProp = target->GetProperty("FOLDER");
output = NULL == folderProp ? "" : folderProp;
cmSystemTools::ConvertToUnixSlashes(output);
if (!output.empty())
{
output += "/";
}
output += target->GetName() + "/";
return output;
}
std::string
cmGhsMultiTargetGenerator::GetAbsPathToRoot(const cmTarget *target)
{
return target->GetMakefile()->GetHomeOutputDirectory();
}
std::string
cmGhsMultiTargetGenerator::GetAbsBuildFilePath(const cmTarget *target)
{
std::string output;
output = cmGhsMultiTargetGenerator::GetAbsPathToRoot(target);
output = cmGhsMultiTargetGenerator::AddSlashIfNeededToPath(output);
output += cmGhsMultiTargetGenerator::GetRelBuildFilePath(target);
return output;
}
std::string
cmGhsMultiTargetGenerator::GetRelBuildFileName(const cmTarget *target)
{
std::string output;
output = cmGhsMultiTargetGenerator::GetRelBuildFilePath(target);
output = cmGhsMultiTargetGenerator::AddSlashIfNeededToPath(output);
output += cmGhsMultiTargetGenerator::GetBuildFileName(target);
return output;
}
std::string cmGhsMultiTargetGenerator::GetBuildFileName(const cmTarget *target)
{
std::string output;
output = target->GetName();
output += cmGlobalGhsMultiGenerator::FILE_EXTENSION;
return output;
}
std::string
cmGhsMultiTargetGenerator::AddSlashIfNeededToPath(std::string const &input)
{
std::string output(input);
if (!cmHasLiteralSuffix(output, "/"))
{
output += "/";
}
return output;
}
void cmGhsMultiTargetGenerator::Generate()
{
const std::vector<cmSourceFile *> objectSources = this->GetSources();
if (!objectSources.empty() && this->IncludeThisTarget())
{
if (!cmSystemTools::FileExists(this->AbsBuildFilePath.c_str()))
{
cmSystemTools::MakeDirectory(this->AbsBuildFilePath.c_str());
}
cmGlobalGhsMultiGenerator::Open(std::string(""), this->AbsBuildFileName,
&this->FolderBuildStreams);
cmGlobalGhsMultiGenerator::OpenBuildFileStream(
this->GetFolderBuildStreams());
std::string config = this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
if (0 == config.length())
{
config = "RELEASE";
}
const std::string language(this->Target->GetLinkerLanguage(config));
config = cmSystemTools::UpperCase(config);
this->DynamicDownload = this->DetermineIfDynamicDownload(config, language);
if (this->DynamicDownload)
{
*this->GetFolderBuildStreams() << "#component integrity_dynamic_download"
<< std::endl;
}
GhsMultiGpj::WriteGpjTag(this->GetGpjTag(), this->GetFolderBuildStreams());
cmGlobalGhsMultiGenerator::WriteDisclaimer(this->GetFolderBuildStreams());
bool const notKernel = this->IsNotKernel(config, language);
this->WriteTypeSpecifics(config, notKernel);
this->SetCompilerFlags(config, language, notKernel);
this->WriteCompilerFlags(config, language);
this->WriteCompilerDefinitions(config, language);
this->WriteIncludes(config, language);
if (this->Target->GetType() == cmTarget::EXECUTABLE)
{
this->WriteTargetLinkLibraries();
}
this->WriteCustomCommands();
if (this->DynamicDownload)
{
*this->GetFolderBuildStreams() << " " << this->DDOption << std::endl;
}
this->WriteSources(objectSources);
}
}
bool cmGhsMultiTargetGenerator::IncludeThisTarget()
{
bool output = true;
char const *excludeFromAll = this->Target->GetProperty("EXCLUDE_FROM_ALL");
if (NULL != 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;
}
GhsMultiGpj::Types cmGhsMultiTargetGenerator::GetGpjTag() const
{
return cmGhsMultiTargetGenerator::GetGpjTag(this->Target);
}
GhsMultiGpj::Types cmGhsMultiTargetGenerator::GetGpjTag(const cmTarget *target)
{
GhsMultiGpj::Types output;
if (cmGhsMultiTargetGenerator::DetermineIfTargetGroup(target))
{
output = GhsMultiGpj::INTERGRITY_APPLICATION;
}
else if (target->GetType() == cmTarget::STATIC_LIBRARY)
{
output = GhsMultiGpj::LIBRARY;
}
else
{
output = GhsMultiGpj::PROGRAM;
}
return output;
}
cmGlobalGhsMultiGenerator*
cmGhsMultiTargetGenerator::GetGlobalGenerator() const
{
return static_cast<cmGlobalGhsMultiGenerator *>(
this->LocalGenerator->GetGlobalGenerator());
}
void cmGhsMultiTargetGenerator::WriteTypeSpecifics(const std::string &config,
bool const notKernel)
{
std::string outputDir(this->GetOutputDirectory(config));
std::string outputFilename(this->GetOutputFilename(config));
if (this->Target->GetType() == cmTarget::STATIC_LIBRARY)
{
*this->GetFolderBuildStreams() << " {optgroup=GhsCommonOptions} -o \""
<< outputDir << outputFilename << ".a\""
<< std::endl;
}
else if (this->Target->GetType() == cmTarget::EXECUTABLE)
{
if (notKernel && !this->IsTargetGroup())
{
*this->GetFolderBuildStreams() << " -relprog" << std::endl;
}
if (this->IsTargetGroup())
{
*this->GetFolderBuildStreams() << " -non_shared" << std::endl;
*this->GetFolderBuildStreams() << " -o \"" << outputDir
<< outputFilename << ".elf\""
<< std::endl;
}
else
{
*this->GetFolderBuildStreams() << " {optgroup=GhsCommonOptions} -o \""
<< outputDir << outputFilename << ".as\""
<< std::endl;
}
}
}
void cmGhsMultiTargetGenerator::SetCompilerFlags(std::string const &config,
const std::string &language,
bool const notKernel)
{
std::map<std::string, std::string>::iterator i =
this->FlagsByLanguage.find(language);
if (i == this->FlagsByLanguage.end())
{
std::string flags;
const char *lang = language.c_str();
if (notKernel)
{
this->LocalGenerator->AddLanguageFlags(flags, lang, config);
}
else
{
this->LocalGenerator->AddLanguageFlags(
flags, lang + std::string("_GHS_KERNEL"), config);
}
this->LocalGenerator->AddCMP0018Flags(flags, this->Target, lang, config);
this->LocalGenerator->AddVisibilityPresetFlags(flags, this->Target, lang);
// Append old-style preprocessor definition flags.
if (std::string(" ") != std::string(this->Makefile->GetDefineFlags()))
{
this->LocalGenerator->AppendFlags(flags,
this->Makefile->GetDefineFlags());
}
// Add target-specific flags.
this->LocalGenerator->AddCompileOptions(flags, this->Target, lang, config);
std::map<std::string, std::string>::value_type entry(language, flags);
i = this->FlagsByLanguage.insert(entry).first;
}
}
std::string cmGhsMultiTargetGenerator::GetDefines(const std::string &language,
std::string const &config)
{
std::map<std::string, std::string>::iterator i =
this->DefinesByLanguage.find(language);
if (i == this->DefinesByLanguage.end())
{
std::set<std::string> defines;
const char *lang = language.c_str();
// Add the export symbol definition for shared library objects.
if (const char *exportMacro = this->Target->GetExportMacro())
{
this->LocalGenerator->AppendDefines(defines, exportMacro);
}
// Add preprocessor definitions for this target and configuration.
this->LocalGenerator->AddCompileDefinitions(defines, this->Target, config,
language);
std::string definesString;
this->LocalGenerator->JoinDefines(defines, definesString, lang);
std::map<std::string, std::string>::value_type entry(language,
definesString);
i = this->DefinesByLanguage.insert(entry).first;
}
return i->second;
}
void cmGhsMultiTargetGenerator::WriteCompilerFlags(std::string const &,
const std::string &language)
{
std::map<std::string, std::string>::iterator flagsByLangI =
this->FlagsByLanguage.find(language);
if (flagsByLangI != this->FlagsByLanguage.end())
{
if (!flagsByLangI->second.empty())
{
*this->GetFolderBuildStreams() << " " << flagsByLangI->second
<< std::endl;
}
}
}
void cmGhsMultiTargetGenerator::WriteCompilerDefinitions(
const std::string &config, const std::string &language)
{
std::vector<std::string> compileDefinitions;
this->Target->GetCompileDefinitions(compileDefinitions, config, language);
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,
const std::string &language)
{
std::vector<std::string> includes =
this->Target->GetIncludeDirectories(config, language);
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 =
this->GetGlobalGenerator()->GetTargetDirectDepends(*this->Target);
for (cmTargetDependSet::iterator tdsI = tds.begin(); tdsI != tds.end();
++tdsI)
{
const cmTarget *tg(*tdsI);
*this->GetFolderBuildStreams() << " -L\"" << GetAbsBuildFilePath(tg)
<< "\"" << 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 (NULL != tg)
{
cmGhsMultiTargetGenerator gmtg(tg);
libName = tg->GetName() + ".a";
}
*this->GetFolderBuildStreams() << " -l\"" << libName << "\""
<< std::endl;
}
}
void cmGhsMultiTargetGenerator::WriteCustomCommands()
{
WriteCustomCommandsHelper(this->Target->GetPreBuildCommands(),
cmTarget::PRE_BUILD);
WriteCustomCommandsHelper(this->Target->GetPostBuildCommands(),
cmTarget::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::PRE_BUILD:
*this->GetFolderBuildStreams() << " :preexecShellSafe=";
break;
case cmTarget::POST_BUILD:
*this->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)
{
std::string subCommandE =
this->LocalGenerator->EscapeForShell(*commandLineI, true);
if (!command.empty())
{
*this->GetFolderBuildStreams()
<< (command.begin() == commandLineI ? "'" : " ");
//Need to double escape backslashes
cmSystemTools::ReplaceString(subCommandE, "\\", "\\\\");
}
*this->GetFolderBuildStreams() << subCommandE;
}
if (!command.empty())
{
*this->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(
this->GetFolderBuildStreams(), &this->FolderBuildStreams,
this->Makefile->GetHomeOutputDirectory(), sgPath,
GhsMultiGpj::SUBPROJECT, this->RelBuildFilePath);
if ((*si)->GetExtension() == ".int")
{
*this->FolderBuildStreams[sgPath] << "\"" << (*si)->GetFullPath() << "\""
<< std::endl;
}
else
{
*this->FolderBuildStreams[sgPath] << (*si)->GetFullPath() << std::endl;
}
if ("ld" != (*si)->GetExtension() && "int" != (*si)->GetExtension() &&
"bsp" != (*si)->GetExtension())
{
this->WriteObjectLangOverride(this->FolderBuildStreams[sgPath], (*si));
this->WriteObjectDir(this->FolderBuildStreams[sgPath],
this->AbsBuildFilePath + sgPath);
}
}
}
void cmGhsMultiTargetGenerator::WriteObjectLangOverride(
cmGeneratedFileStream *fileStream, cmSourceFile *sourceFile)
{
const char *rawLangProp = sourceFile->GetProperty("LANGUAGE");
if (NULL != 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);
cmSystemTools::ConvertToUnixSlashes(workingDir);
if (!workingDir.empty())
{
workingDir += "/";
}
workingDir += "Objs";
*fileStream << " -object_dir=\"" << workingDir << "\"" << std::endl;
}
std::string
cmGhsMultiTargetGenerator::GetOutputDirectory(const std::string &config) const
{
std::string outputDir(AbsBuildFilePath);
const char *runtimeOutputProp =
this->Target->GetProperty("RUNTIME_OUTPUT_DIRECTORY");
if (NULL != runtimeOutputProp)
{
outputDir = runtimeOutputProp;
}
std::string configCapped(cmSystemTools::UpperCase(config));
const char *runtimeOutputSProp =
this->Target->GetProperty("RUNTIME_OUTPUT_DIRECTORY_" + configCapped);
if (NULL != runtimeOutputSProp)
{
outputDir = runtimeOutputSProp;
}
cmSystemTools::ConvertToUnixSlashes(outputDir);
if (!outputDir.empty())
{
outputDir += "/";
}
return outputDir;
}
std::string
cmGhsMultiTargetGenerator::GetOutputFilename(const std::string &config) const
{
std::string outputFilename(this->Target->GetName());
const char *outputNameProp = this->Target->GetProperty("OUTPUT_NAME");
if (NULL != outputNameProp)
{
outputFilename = outputNameProp;
}
std::string configCapped(cmSystemTools::UpperCase(config));
const char *outputNameSProp =
this->Target->GetProperty(configCapped + "_OUTPUT_NAME");
if (NULL != outputNameSProp)
{
outputFilename = outputNameSProp;
}
return outputFilename;
}
bool cmGhsMultiTargetGenerator::IsNotKernel(std::string const &config,
const std::string &language)
{
bool output;
std::vector<std::string> options;
this->Target->GetCompileOptions(options, config, language);
output =
options.end() == std::find(options.begin(), options.end(), "-kernel");
return output;
}
bool cmGhsMultiTargetGenerator::DetermineIfTargetGroup(const cmTarget *target)
{
bool output = false;
std::vector<cmSourceFile *> sources;
std::string config =
target->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE");
target->GetSourceFiles(sources, config);
for (std::vector<cmSourceFile *>::const_iterator sources_i = sources.begin();
sources.end() != sources_i; ++sources_i)
{
if ("int" == (*sources_i)->GetExtension())
{
output = true;
}
}
return output;
}
bool cmGhsMultiTargetGenerator::DetermineIfDynamicDownload(
std::string const &config, const std::string &language)
{
std::vector<std::string> options;
bool output = false;
this->Target->GetCompileOptions(options, config, language);
for (std::vector<std::string>::const_iterator options_i = options.begin();
options_i != options.end(); ++options_i)
{
std::string option = *options_i;
if (this->DDOption == option)
{
output = true;
}
}
return output;
}

View File

@ -0,0 +1,119 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2015 Geoffrey Viola <geoffrey.viola@asirobots.com>
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"
#include "cmGhsMultiGpj.h"
class cmGeneratedFileStream;
class cmGlobalGhsMultiGenerator;
class cmLocalGhsMultiGenerator;
class cmMakefile;
class cmSourceFile;
class cmGeneratedFileStream;
class cmCustomCommand;
class cmGhsMultiTargetGenerator
{
public:
cmGhsMultiTargetGenerator(cmTarget *target);
virtual ~cmGhsMultiTargetGenerator();
virtual void Generate();
bool IncludeThisTarget();
std::vector<cmSourceFile *> GetSources() const;
GhsMultiGpj::Types GetGpjTag() const;
static GhsMultiGpj::Types GetGpjTag(const cmTarget *target);
const char *GetAbsBuildFilePath() const
{
return this->AbsBuildFilePath.c_str();
}
const char *GetRelBuildFileName() const
{
return this->RelBuildFileName.c_str();
}
const char *GetAbsBuildFileName() const
{
return this->AbsBuildFileName.c_str();
}
const char *GetAbsOutputFileName() const
{
return this->AbsOutputFileName.c_str();
}
static std::string GetRelBuildFilePath(const cmTarget *target);
static std::string GetAbsPathToRoot(const cmTarget *target);
static std::string GetAbsBuildFilePath(const cmTarget *target);
static std::string GetRelBuildFileName(const cmTarget *target);
static std::string GetBuildFileName(const cmTarget *target);
static std::string AddSlashIfNeededToPath(std::string const &input);
private:
cmGlobalGhsMultiGenerator *GetGlobalGenerator() const;
cmGeneratedFileStream *GetFolderBuildStreams()
{
return this->FolderBuildStreams[""];
};
bool IsTargetGroup() const { return this->TargetGroup; }
void WriteTypeSpecifics(const std::string &config, bool notKernel);
void WriteCompilerFlags(const std::string &config,
const std::string &language);
void WriteCompilerDefinitions(const std::string &config,
const std::string &language);
void SetCompilerFlags(std::string const &config, const std::string &language,
bool const notKernel);
std::string GetDefines(const std::string &langugae,
std::string const &config);
void WriteIncludes(const std::string &config, const std::string &language);
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);
std::string GetOutputDirectory(const std::string &config) const;
std::string GetOutputFilename(const std::string &config) const;
bool IsNotKernel(std::string const &config, const std::string &language);
static bool DetermineIfTargetGroup(const cmTarget *target);
bool DetermineIfDynamicDownload(std::string const &config,
const std::string &language);
cmTarget *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;
bool TargetGroup;
bool DynamicDownload;
static std::string const DDOption;
std::map<std::string, std::string> FlagsByLanguage;
std::map<std::string, std::string> DefinesByLanguage;
};
#endif // ! cmGhsMultiTargetGenerator_h

View File

@ -0,0 +1,548 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2015 Geoffrey Viola <geoffrey.viola@asirobots.com>
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"
#include <cmsys/SystemTools.hxx>
#include <cmAlgorithms.h>
const char *cmGlobalGhsMultiGenerator::FILE_EXTENSION = ".gpj";
const char *cmGlobalGhsMultiGenerator::DEFAULT_MAKE_PROGRAM = "gbuild";
cmGlobalGhsMultiGenerator::cmGlobalGhsMultiGenerator()
: OSDirRelative(false)
{
this->GhsBuildCommandInitialized = false;
}
cmGlobalGhsMultiGenerator::~cmGlobalGhsMultiGenerator()
{
cmDeleteAll(TargetFolderBuildStreams);
}
cmLocalGenerator *cmGlobalGhsMultiGenerator::CreateLocalGenerator()
{
cmLocalGenerator *lg = new cmLocalGhsMultiGenerator;
lg->SetGlobalGenerator(this);
this->SetCurrentLocalGenerator(lg);
return lg;
}
void cmGlobalGhsMultiGenerator::GetDocumentation(cmDocumentationEntry &entry)
{
entry.Name = GetActualName();
entry.Brief =
"Generates Green Hills MULTI files (experimental, work-in-progress).";
}
void cmGlobalGhsMultiGenerator::EnableLanguage(
std::vector<std::string> const &l, cmMakefile *mf, bool optional)
{
mf->AddDefinition("CMAKE_SYSTEM_NAME", "GHS-MULTI");
mf->AddDefinition("CMAKE_SYSTEM_PROCESSOR", "ARM");
const std::string ghsCompRoot(GetCompRoot());
mf->AddDefinition("GHS_COMP_ROOT", ghsCompRoot.c_str());
std::string ghsCompRootStart =
0 == ghsCompRootStart.size() ? "" : ghsCompRoot + "/";
mf->AddDefinition("CMAKE_C_COMPILER",
std::string(ghsCompRootStart + "ccarm.exe").c_str());
mf->AddDefinition("CMAKE_C_COMPILER_ID_RUN", "TRUE");
mf->AddDefinition("CMAKE_C_COMPILER_ID", "GHS");
mf->AddDefinition("CMAKE_C_COMPILER_FORCED", "TRUE");
mf->AddDefinition("CMAKE_CXX_COMPILER",
std::string(ghsCompRootStart + "cxarm.exe").c_str());
mf->AddDefinition("CMAKE_CXX_COMPILER_ID_RUN", "TRUE");
mf->AddDefinition("CMAKE_CXX_COMPILER_ID", "GHS");
mf->AddDefinition("CMAKE_CXX_COMPILER_FORCED", "TRUE");
if (!ghsCompRoot.empty())
{
static const char *compPreFix = "comp_";
std::string compFilename =
cmsys::SystemTools::FindLastString(ghsCompRoot.c_str(), compPreFix);
cmsys::SystemTools::ReplaceString(compFilename, compPreFix, "");
mf->AddDefinition("CMAKE_SYSTEM_VERSION", compFilename.c_str());
}
mf->AddDefinition("GHSMULTI", "1"); // identifier for user CMake files
this->cmGlobalGenerator::EnableLanguage(l, mf, optional);
}
void cmGlobalGhsMultiGenerator::FindMakeProgram(cmMakefile *mf)
{
// The GHS generator knows how to lookup its build tool
// directly instead of needing a helper module to do it, so we
// do not actually need to put CMAKE_MAKE_PROGRAM into the cache.
if (cmSystemTools::IsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM")))
{
mf->AddDefinition("CMAKE_MAKE_PROGRAM",
this->GetGhsBuildCommand().c_str());
}
}
std::string const &cmGlobalGhsMultiGenerator::GetGhsBuildCommand()
{
if (!this->GhsBuildCommandInitialized)
{
this->GhsBuildCommandInitialized = true;
this->GhsBuildCommand = this->FindGhsBuildCommand();
}
return this->GhsBuildCommand;
}
std::string cmGlobalGhsMultiGenerator::FindGhsBuildCommand()
{
std::vector<std::string> userPaths;
userPaths.push_back(this->GetCompRoot());
std::string makeProgram =
cmSystemTools::FindProgram(DEFAULT_MAKE_PROGRAM, userPaths);
if (makeProgram.empty())
{
makeProgram = DEFAULT_MAKE_PROGRAM;
}
return makeProgram;
}
std::string cmGlobalGhsMultiGenerator::GetCompRoot()
{
std::string output;
const std::vector<std::string>
potentialDirsHardPaths(GetCompRootHardPaths());
const std::vector<std::string> potentialDirsRegistry(GetCompRootRegistry());
std::vector<std::string> potentialDirsComplete;
potentialDirsComplete.insert(potentialDirsComplete.end(),
potentialDirsHardPaths.begin(),
potentialDirsHardPaths.end());
potentialDirsComplete.insert(potentialDirsComplete.end(),
potentialDirsRegistry.begin(),
potentialDirsRegistry.end());
// Use latest version
std::string outputDirName;
for (std::vector<std::string>::const_iterator potentialDirsCompleteIt =
potentialDirsComplete.begin();
potentialDirsCompleteIt != potentialDirsComplete.end();
++potentialDirsCompleteIt)
{
const std::string dirName(
cmsys::SystemTools::GetFilenameName(*potentialDirsCompleteIt));
if (dirName.compare(outputDirName) > 0)
{
output = *potentialDirsCompleteIt;
outputDirName = dirName;
}
}
return output;
}
std::vector<std::string> cmGlobalGhsMultiGenerator::GetCompRootHardPaths()
{
std::vector<std::string> output;
cmSystemTools::Glob("C:/ghs", "comp_[^;]+", output);
for (std::vector<std::string>::iterator outputIt = output.begin();
outputIt != output.end(); ++outputIt)
{
*outputIt = "C:/ghs/" + *outputIt;
}
return output;
}
std::vector<std::string> cmGlobalGhsMultiGenerator::GetCompRootRegistry()
{
std::vector<std::string> output(2);
cmsys::SystemTools::ReadRegistryValue(
"HKEY_LOCAL_"
"MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\"
"Windows\\CurrentVersion\\Uninstall\\"
"GreenHillsSoftwared771f1b4;InstallLocation",
output[0]);
cmsys::SystemTools::ReadRegistryValue(
"HKEY_LOCAL_"
"MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\"
"Windows\\CurrentVersion\\Uninstall\\"
"GreenHillsSoftware9881cef6;InstallLocation",
output[1]);
return output;
}
void cmGlobalGhsMultiGenerator::OpenBuildFileStream(
std::string const &filepath, cmGeneratedFileStream **filestream)
{
// Get a stream where to generate things.
if (NULL == *filestream)
{
*filestream = new cmGeneratedFileStream(filepath.c_str());
if (NULL != *filestream)
{
OpenBuildFileStream(*filestream);
}
}
}
void cmGlobalGhsMultiGenerator::OpenBuildFileStream(
cmGeneratedFileStream *filestream)
{
*filestream << "#!gbuild" << std::endl;
}
void cmGlobalGhsMultiGenerator::OpenBuildFileStream()
{
// Compute GHS MULTI's build file path.
std::string buildFilePath =
this->GetCMakeInstance()->GetHomeOutputDirectory();
buildFilePath += "/";
buildFilePath += "default";
buildFilePath += FILE_EXTENSION;
this->Open(std::string(""), buildFilePath, &this->TargetFolderBuildStreams);
OpenBuildFileStream(GetBuildFileStream());
char const *osDir =
this->GetCMakeInstance()->GetCacheDefinition("GHS_OS_DIR");
if (NULL == osDir)
{
osDir = "";
cmSystemTools::Error("GHS_OS_DIR cache variable must be set");
}
else
{
this->GetCMakeInstance()->MarkCliAsUsed("GHS_OS_DIR");
}
std::string fOSDir(this->trimQuotes(osDir));
cmSystemTools::ReplaceString(fOSDir, "\\", "/");
if (!fOSDir.empty() && ('c' == fOSDir[0] || 'C' == fOSDir[0]))
{
this->OSDirRelative = false;
}
else
{
this->OSDirRelative = true;
}
char const *bspName =
this->GetCMakeInstance()->GetCacheDefinition("GHS_BSP_NAME");
if (NULL == bspName)
{
bspName = "";
cmSystemTools::Error("GHS_BSP_NAME cache variable must be set");
}
else
{
this->GetCMakeInstance()->MarkCliAsUsed("GHS_BSP_NAME");
}
std::string fBspName(this->trimQuotes(bspName));
cmSystemTools::ReplaceString(fBspName, "\\", "/");
this->WriteMacros();
this->WriteHighLevelDirectives();
GhsMultiGpj::WriteGpjTag(GhsMultiGpj::PROJECT, this->GetBuildFileStream());
this->WriteDisclaimer(this->GetBuildFileStream());
*this->GetBuildFileStream() << "# Top Level Project File" << std::endl;
if (!fBspName.empty())
{
*this->GetBuildFileStream() << " -bsp " << fBspName << std::endl;
}
this->WriteCompilerOptions(fOSDir);
}
void cmGlobalGhsMultiGenerator::CloseBuildFileStream(
cmGeneratedFileStream **filestream)
{
if (filestream)
{
delete *filestream;
*filestream = NULL;
}
else
{
cmSystemTools::Error("Build file stream was not open.");
}
}
void cmGlobalGhsMultiGenerator::Generate()
{
this->cmGlobalGenerator::Generate();
if (!this->LocalGenerators.empty())
{
this->OpenBuildFileStream();
// 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();
this->UpdateBuildFiles(&tgts);
}
}
cmDeleteAll(TargetFolderBuildStreams);
this->TargetFolderBuildStreams.clear();
}
void cmGlobalGhsMultiGenerator::GenerateBuildCommand(
std::vector<std::string> &makeCommand, const std::string &makeProgram,
const std::string & /*projectName*/, const std::string & /*projectDir*/,
const std::string &targetName, const std::string & /*config*/,
bool /*fast*/, bool /*verbose*/,
std::vector<std::string> const &makeOptions)
{
makeCommand.push_back(
this->SelectMakeProgram(makeProgram, this->GetGhsBuildCommand())
);
makeCommand.insert(makeCommand.end(),
makeOptions.begin(), makeOptions.end());
if (!targetName.empty())
{
if (targetName == "clean")
{
makeCommand.push_back("-clean");
}
else
{
makeCommand.push_back(targetName);
}
}
}
void cmGlobalGhsMultiGenerator::WriteMacros()
{
char const *ghsGpjMacros =
this->GetCMakeInstance()->GetCacheDefinition("GHS_GPJ_MACROS");
if (NULL != ghsGpjMacros)
{
std::vector<std::string> expandedList;
cmSystemTools::ExpandListArgument(std::string(ghsGpjMacros), expandedList);
for (std::vector<std::string>::const_iterator expandedListI =
expandedList.begin();
expandedListI != expandedList.end(); ++expandedListI)
{
*this->GetBuildFileStream() << "macro " << *expandedListI << std::endl;
}
}
}
void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives()
{
*this->GetBuildFileStream() << "primaryTarget=arm_integrity.tgt"
<< std::endl;
char const *const customization =
this->GetCMakeInstance()->GetCacheDefinition("GHS_CUSTOMIZATION");
if (NULL != customization && strlen(customization) > 0)
{
*this->GetBuildFileStream() << "customization="
<< trimQuotes(customization)
<< std::endl;
this->GetCMakeInstance()->MarkCliAsUsed("GHS_CUSTOMIZATION");
}
}
void cmGlobalGhsMultiGenerator::WriteCompilerOptions(std::string const &fOSDir)
{
*this->GetBuildFileStream() << " -os_dir=\"" << fOSDir << "\""
<< std::endl;
}
void cmGlobalGhsMultiGenerator::WriteDisclaimer(std::ostream *os)
{
(*os) << "#" << std::endl
<< "# CMAKE generated file: DO NOT EDIT!" << std::endl
<< "# Generated by \"" << 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,
GhsMultiGpj::Types projType, std::string const &relPath)
{
std::string workingPath(path);
cmSystemTools::ConvertToUnixSlashes(workingPath);
std::vector<cmsys::String> splitPath =
cmSystemTools::SplitString(workingPath);
std::string workingRelPath(relPath);
cmSystemTools::ConvertToUnixSlashes(workingRelPath);
if (!workingRelPath.empty())
{
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::Open(
std::string const &mapKeyName, std::string const &fileName,
std::map<std::string, cmGeneratedFileStream *> *fileMap)
{
if (fileMap->end() == fileMap->find(fileName))
{
cmGeneratedFileStream *temp(new cmGeneratedFileStream);
temp->open(fileName.c_str());
(*fileMap)[mapKeyName] = temp;
}
}
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,
GhsMultiGpj::Types 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(GetFileNameFromPath(pathUpTo));
std::string absFilename = absPath + relFilename;
Open(pathUpTo, absFilename, targetFolderBuildStreams);
OpenBuildFileStream((*targetFolderBuildStreams)[pathUpTo]);
GhsMultiGpj::WriteGpjTag(projType, (*targetFolderBuildStreams)[pathUpTo]);
WriteDisclaimer((*targetFolderBuildStreams)[pathUpTo]);
// Add to main build file
if (isFirst)
{
*mainBuildFile << relFilename << " ";
GhsMultiGpj::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,
GhsMultiGpj::Types 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 = GetFileNameFromPath(nextFilename);
*(*targetFolderBuildStreams)[pathUpTo] << nextFilename << " ";
GhsMultiGpj::WriteGpjTag(projType, (*targetFolderBuildStreams)[pathUpTo]);
}
}
std::string
cmGlobalGhsMultiGenerator::GetFileNameFromPath(std::string const &path)
{
std::string output(path);
if (!path.empty())
{
cmSystemTools::ConvertToUnixSlashes(output);
std::vector<cmsys::String> splitPath = cmSystemTools::SplitString(output);
output += "/" + splitPath.back() + FILE_EXTENSION;
}
return output;
}
void cmGlobalGhsMultiGenerator::UpdateBuildFiles(
cmGeneratorTargetsType *tgts)
{
for (cmGeneratorTargetsType::iterator tgtsI = tgts->begin();
tgtsI != tgts->end(); ++tgtsI)
{
const cmTarget *tgt(tgtsI->first);
if (IsTgtForBuild(tgt))
{
char const *rawFolderName = tgtsI->first->GetProperty("FOLDER");
if (NULL == rawFolderName)
{
rawFolderName = "";
}
std::string folderName(rawFolderName);
if (this->TargetFolderBuildStreams.end() ==
this->TargetFolderBuildStreams.find(folderName))
{
this->AddFilesUpToPath(
GetBuildFileStream(), &this->TargetFolderBuildStreams,
this->GetCMakeInstance()->GetHomeOutputDirectory(), folderName,
GhsMultiGpj::PROJECT);
}
std::vector<cmsys::String> splitPath = cmSystemTools::SplitString(
cmGhsMultiTargetGenerator::GetRelBuildFileName(tgt));
std::string foldNameRelBuildFile(*(splitPath.end() - 2) + "/" +
splitPath.back());
*this->TargetFolderBuildStreams[folderName] << foldNameRelBuildFile
<< " ";
GhsMultiGpj::WriteGpjTag(cmGhsMultiTargetGenerator::GetGpjTag(tgt),
this->TargetFolderBuildStreams[folderName]);
}
}
}
bool cmGlobalGhsMultiGenerator::IsTgtForBuild(const cmTarget *tgt)
{
const std::string config =
tgt->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE");
std::vector<cmSourceFile *> tgtSources;
tgt->GetSourceFiles(tgtSources, config);
bool tgtInBuild = true;
char const *excludeFromAll = tgt->GetProperty("EXCLUDE_FROM_ALL");
if (NULL != excludeFromAll && '1' == excludeFromAll[0] &&
'\0' == excludeFromAll[1])
{
tgtInBuild = false;
}
return !tgtSources.empty() && tgtInBuild;
}
std::string cmGlobalGhsMultiGenerator::trimQuotes(std::string const &str)
{
std::string result;
result.reserve(str.size());
for (const char *ch = str.c_str(); *ch != '\0'; ++ch)
{
if (*ch != '"')
{
result += *ch;
}
}
return result;
}

View File

@ -0,0 +1,127 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2015 Geoffrey Viola <geoffrey.viola@asirobots.com>
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"
#include "cmGhsMultiGpj.h"
class cmGeneratedFileStream;
class cmGlobalGhsMultiGenerator : public cmGlobalGenerator
{
public:
/// The default name of GHS MULTI's build file. Typically: monolith.gpj.
static const char *FILE_EXTENSION;
cmGlobalGhsMultiGenerator();
~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 this->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);
/*
* Determine what program to use for building the project.
*/
virtual void FindMakeProgram(cmMakefile *);
cmGeneratedFileStream *GetBuildFileStream()
{
return this->TargetFolderBuildStreams[""];
}
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 this->LibDirs; }
static void AddFilesUpToPath(
cmGeneratedFileStream *mainBuildFile,
std::map<std::string, cmGeneratedFileStream *> *targetFolderBuildStreams,
char const *homeOutputDirectory, std::string const &path,
GhsMultiGpj::Types projType, std::string const &relPath = "");
static void Open(std::string const &mapKeyName, std::string const &fileName,
std::map<std::string, cmGeneratedFileStream *> *fileMap);
static std::string trimQuotes(std::string const &str);
inline bool IsOSDirRelative() { return this->OSDirRelative; }
protected:
virtual void Generate();
virtual void GenerateBuildCommand(
std::vector<std::string> &makeCommand, const std::string &makeProgram,
const std::string &projectName, const std::string &projectDir,
const std::string &targetName, const std::string &config, bool fast,
bool verbose,
std::vector<std::string> const& makeOptions = std::vector<std::string>()
);
private:
std::string const &GetGhsBuildCommand();
std::string FindGhsBuildCommand();
std::string GetCompRoot();
std::vector<std::string> GetCompRootHardPaths();
std::vector<std::string> GetCompRootRegistry();
void OpenBuildFileStream();
void WriteMacros();
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, GhsMultiGpj::Types 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,
GhsMultiGpj::Types projType);
static std::string GetFileNameFromPath(std::string const &path);
void UpdateBuildFiles(cmGeneratorTargetsType *tgts);
bool IsTgtForBuild(const cmTarget *tgt);
std::vector<cmGeneratedFileStream *> TargetSubProjects;
std::map<std::string, cmGeneratedFileStream *> TargetFolderBuildStreams;
std::vector<std::string> LibDirs;
bool OSDirRelative;
bool GhsBuildCommandInitialized;
std::string GhsBuildCommand;
static const char *DEFAULT_MAKE_PROGRAM;
};
#endif

View File

@ -576,6 +576,7 @@ bool cmGlobalNinjaGenerator::UsingMinGW = false;
// Implemented by:
// cmGlobalUnixMakefileGenerator3
// cmGlobalGhsMultiGenerator
// cmGlobalVisualStudio10Generator
// cmGlobalVisualStudio6Generator
// cmGlobalVisualStudio7Generator

View File

@ -0,0 +1,55 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2015 Geoffrey Viola <geoffrey.viola@asirobots.com>
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.empty())
{
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();
}

View File

@ -0,0 +1,56 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2015 Geoffrey Viola <geoffrey.viola@asirobots.com>
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 this->BuildFileName.c_str(); }
protected:
virtual bool CustomCommandUseLocal() const { return true; }
private:
std::string BuildFileName;
std::string HomeRelativeOutputPath;
};
#endif

View File

@ -63,6 +63,7 @@
# include "cmGlobalBorlandMakefileGenerator.h"
# include "cmGlobalNMakeMakefileGenerator.h"
# include "cmGlobalJOMMakefileGenerator.h"
# include "cmGlobalGhsMultiGenerator.h"
# define CMAKE_HAVE_VS_GENERATORS
# endif
# include "cmGlobalMSYSMakefileGenerator.h"
@ -1840,6 +1841,8 @@ void cmake::AddDefaultGenerators()
cmGlobalNMakeMakefileGenerator::NewFactory());
this->Generators.push_back(
cmGlobalJOMMakefileGenerator::NewFactory());
this->Generators.push_back(
cmGlobalGhsMultiGenerator::NewFactory());
# endif
this->Generators.push_back(
cmGlobalMSYSMakefileGenerator::NewFactory());

View File

@ -1978,6 +1978,23 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
endif()
endif()
if (CMake_TEST_GreenHillsMULTI)
macro(add_test_GhsMulti name primaryTarget bspName)
add_test(NAME GhsMulti.${name} COMMAND ${CMAKE_CTEST_COMMAND}
--build-and-test
"${CMake_SOURCE_DIR}/Tests/GhsMulti"
"${CMake_BINARY_DIR}/Tests/GhsMulti/${name}"
--build-generator "Green Hills MULTI"
--build-project ReturnNum
--build-config $<CONFIGURATION>
--build-options -DGHS_PRIMARY_TARGET=${primaryTarget}
-DGHS_BSP_NAME=${bspName}
)
endmacro ()
add_test_GhsMulti("arm_integrity_simarm" "arm_integrity.tgt" "simarm")
add_test_GhsMulti("arm64_integrity_simarm" "arm64_integrity.tgt" "simarm")
endif ()
if(tegra AND NOT "${CMake_SOURCE_DIR};${CMake_BINARY_DIR}" MATCHES " ")
macro(add_test_VSNsightTegra name generator)
add_test(NAME VSNsightTegra.${name} COMMAND ${CMAKE_CTEST_COMMAND}

View File

@ -0,0 +1,4 @@
cmake_minimum_required(VERSION 3.1)
project(ReturnNum)
add_subdirectory(ReturnNum)

View File

@ -0,0 +1,4 @@
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../Lib)
add_executable(App Main.c)
target_link_libraries(App Lib)
target_compile_options(App PUBLIC "-non_shared")

View File

@ -0,0 +1,8 @@
#include "HelperFun.h"
int main(int argc, const char* argv[])
{
int out;
out = giveNum();
return out;
}

View File

@ -0,0 +1,3 @@
add_subdirectory(App)
add_subdirectory(Int)
add_subdirectory(Lib)

View File

@ -0,0 +1,12 @@
# Input File for the Integrate utility for use with the INTEGRITY real-time
# operating system by Green Hills Software.
# Before editing this file, refer to the Integrate Reference Manual.
Kernel
Filename DynamicDownload
EndKernel
AddressSpace App
Filename "App/App.as"
Language C
EndAddressSpace

View File

@ -0,0 +1 @@
add_executable(AppDD AppDD.int Default.bsp)

View File

@ -0,0 +1,35 @@
# Target description File for the Integrate utility for use with the
# INTEGRITY real-time operating system by Green Hills Software.
# Before editing this file, refer to your Integrate documentation.
# default.bsp is appropriate for INTEGRITY applications which are
# fully linked with the kernel (for RAM or ROM) or dynamically downloaded.
#
# MinimumAddress must match the value of .ramend in the linker directives
# file used for the KernelSpace program - see default.ld for more info.
# The MaximumAddress used here allows memory mappings to be specified
# for up to the 16 MB mark in RAM. Intex will not permit programs
# that require more memory for its mappings. If the board has less
# memory, this number can be reduced by the user.
Target
MinimumAddress .ramend
MaximumAddress .ramlimit
Clock StandardTick
EndClock
Clock HighResTimer
EndClock
IODevice "SerialDev0"
InitialKernelObjects 200
DefaultStartIt false
DefaultMaxPriority 255
DefaultPriority 127
DefaultWeight 1
DefaultMaxWeight 255
DefaultHeapSize 0x10000
LastVirtualAddress 0x3fffffff
PageSize 0x1000
ArchitectedPageSize 0x1000
ArchitectedPageSize 0x10000
ArchitectedPageSize 0x100000
DefaultMemoryRegionSize 0x20000
EndTarget

View File

@ -0,0 +1 @@
add_library(Lib HelperFun.c HelperFun.h)

View File

@ -0,0 +1,4 @@
int giveNum(void)
{
return 1;
}

View File

@ -0,0 +1 @@
int giveNum(void);