summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Help/generator/Green Hills MULTI.rst16
-rw-r--r--Help/manual/cmake-generators.7.rst1
-rw-r--r--Help/manual/cmake-variables.7.rst5
-rw-r--r--Help/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_DEBUG.rst6
-rw-r--r--Help/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_MINSIZEREL.rst7
-rw-r--r--Help/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_RELEASE.rst6
-rw-r--r--Help/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_RELWITHDEBINFO.rst7
-rw-r--r--Help/variable/CMAKE_MAKE_PROGRAM.rst4
-rw-r--r--Help/variable/CMAKE_SYSTEM_PROCESSOR.rst2
-rw-r--r--Help/variable/GHS-MULTI.rst4
-rw-r--r--Modules/Compiler/GHS-C.cmake27
-rw-r--r--Modules/Compiler/GHS-CXX.cmake31
-rw-r--r--Modules/Compiler/GHS-DetermineCompiler.cmake6
-rw-r--r--Modules/FindBoost.cmake5
-rw-r--r--Modules/Platform/GHS-MULTI-Initialize.cmake29
-rw-r--r--Modules/Platform/GHS-MULTI.cmake27
-rw-r--r--Source/CMakeLists.txt9
-rw-r--r--Source/cmGhsMultiGpj.cxx44
-rw-r--r--Source/cmGhsMultiGpj.h34
-rw-r--r--Source/cmGhsMultiTargetGenerator.cxx600
-rw-r--r--Source/cmGhsMultiTargetGenerator.h119
-rw-r--r--Source/cmGlobalGhsMultiGenerator.cxx548
-rw-r--r--Source/cmGlobalGhsMultiGenerator.h127
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx1
-rw-r--r--Source/cmLocalGhsMultiGenerator.cxx55
-rw-r--r--Source/cmLocalGhsMultiGenerator.h56
-rw-r--r--Source/cmake.cxx3
-rw-r--r--Tests/CMakeLists.txt17
-rw-r--r--Tests/GhsMulti/CMakeLists.txt4
-rw-r--r--Tests/GhsMulti/ReturnNum/App/CMakeLists.txt4
-rw-r--r--Tests/GhsMulti/ReturnNum/App/Main.c8
-rw-r--r--Tests/GhsMulti/ReturnNum/CMakeLists.txt3
-rw-r--r--Tests/GhsMulti/ReturnNum/Int/AppDD.int12
-rw-r--r--Tests/GhsMulti/ReturnNum/Int/CMakeLists.txt1
-rw-r--r--Tests/GhsMulti/ReturnNum/Int/Default.bsp35
-rw-r--r--Tests/GhsMulti/ReturnNum/Lib/CMakeLists.txt1
-rw-r--r--Tests/GhsMulti/ReturnNum/Lib/HelperFun.c4
-rw-r--r--Tests/GhsMulti/ReturnNum/Lib/HelperFun.h1
38 files changed, 1868 insertions, 1 deletions
diff --git a/Help/generator/Green Hills MULTI.rst b/Help/generator/Green Hills MULTI.rst
new file mode 100644
index 0000000000..4d31690266
--- /dev/null
+++ b/Help/generator/Green Hills MULTI.rst
@@ -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.
diff --git a/Help/manual/cmake-generators.7.rst b/Help/manual/cmake-generators.7.rst
index 6f76fb19a7..723c308b93 100644
--- a/Help/manual/cmake-generators.7.rst
+++ b/Help/manual/cmake-generators.7.rst
@@ -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
diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst
index 63f704da56..865e1ef256 100644
--- a/Help/manual/cmake-variables.7.rst
+++ b/Help/manual/cmake-variables.7.rst
@@ -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
diff --git a/Help/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_DEBUG.rst b/Help/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_DEBUG.rst
new file mode 100644
index 0000000000..c5915c390f
--- /dev/null
+++ b/Help/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_DEBUG.rst
@@ -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.
diff --git a/Help/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_MINSIZEREL.rst b/Help/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_MINSIZEREL.rst
new file mode 100644
index 0000000000..f80e785d56
--- /dev/null
+++ b/Help/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_MINSIZEREL.rst
@@ -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.
diff --git a/Help/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_RELEASE.rst b/Help/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_RELEASE.rst
new file mode 100644
index 0000000000..fe02bc342a
--- /dev/null
+++ b/Help/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_RELEASE.rst
@@ -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
diff --git a/Help/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_RELWITHDEBINFO.rst b/Help/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_RELWITHDEBINFO.rst
new file mode 100644
index 0000000000..220f7f941b
--- /dev/null
+++ b/Help/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_RELWITHDEBINFO.rst
@@ -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.
diff --git a/Help/variable/CMAKE_MAKE_PROGRAM.rst b/Help/variable/CMAKE_MAKE_PROGRAM.rst
index f1d88a557c..85b098bd68 100644
--- a/Help/variable/CMAKE_MAKE_PROGRAM.rst
+++ b/Help/variable/CMAKE_MAKE_PROGRAM.rst
@@ -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
diff --git a/Help/variable/CMAKE_SYSTEM_PROCESSOR.rst b/Help/variable/CMAKE_SYSTEM_PROCESSOR.rst
index 8ad89f128c..2f5313bc9c 100644
--- a/Help/variable/CMAKE_SYSTEM_PROCESSOR.rst
+++ b/Help/variable/CMAKE_SYSTEM_PROCESSOR.rst
@@ -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
diff --git a/Help/variable/GHS-MULTI.rst b/Help/variable/GHS-MULTI.rst
new file mode 100644
index 0000000000..0f91be8ad8
--- /dev/null
+++ b/Help/variable/GHS-MULTI.rst
@@ -0,0 +1,4 @@
+GHS-MULTI
+---------
+
+True when using Green Hills MULTI
diff --git a/Modules/Compiler/GHS-C.cmake b/Modules/Compiler/GHS-C.cmake
new file mode 100644
index 0000000000..e97d62c221
--- /dev/null
+++ b/Modules/Compiler/GHS-C.cmake
@@ -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()
diff --git a/Modules/Compiler/GHS-CXX.cmake b/Modules/Compiler/GHS-CXX.cmake
new file mode 100644
index 0000000000..71a0dec787
--- /dev/null
+++ b/Modules/Compiler/GHS-CXX.cmake
@@ -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()
diff --git a/Modules/Compiler/GHS-DetermineCompiler.cmake b/Modules/Compiler/GHS-DetermineCompiler.cmake
new file mode 100644
index 0000000000..56d24e266c
--- /dev/null
+++ b/Modules/Compiler/GHS-DetermineCompiler.cmake
@@ -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)")
diff --git a/Modules/FindBoost.cmake b/Modules/FindBoost.cmake
index 466090b687..c844aed086 100644
--- a/Modules/FindBoost.cmake
+++ b/Modules/FindBoost.cmake
@@ -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()
diff --git a/Modules/Platform/GHS-MULTI-Initialize.cmake b/Modules/Platform/GHS-MULTI-Initialize.cmake
new file mode 100644
index 0000000000..342ad21b46
--- /dev/null
+++ b/Modules/Platform/GHS-MULTI-Initialize.cmake
@@ -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)
diff --git a/Modules/Platform/GHS-MULTI.cmake b/Modules/Platform/GHS-MULTI.cmake
new file mode 100644
index 0000000000..211cf3eb2a
--- /dev/null
+++ b/Modules/Platform/GHS-MULTI.cmake
@@ -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)
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 04f6a81364..064b827208 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -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)
diff --git a/Source/cmGhsMultiGpj.cxx b/Source/cmGhsMultiGpj.cxx
new file mode 100644
index 0000000000..e1dce52bdf
--- /dev/null
+++ b/Source/cmGhsMultiGpj.cxx
@@ -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;
+}
diff --git a/Source/cmGhsMultiGpj.h b/Source/cmGhsMultiGpj.h
new file mode 100644
index 0000000000..91ff0f4a50
--- /dev/null
+++ b/Source/cmGhsMultiGpj.h
@@ -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
diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx
new file mode 100644
index 0000000000..01e2011c5e
--- /dev/null
+++ b/Source/cmGhsMultiTargetGenerator.cxx
@@ -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;
+}
diff --git a/Source/cmGhsMultiTargetGenerator.h b/Source/cmGhsMultiTargetGenerator.h
new file mode 100644
index 0000000000..8e81db8700
--- /dev/null
+++ b/Source/cmGhsMultiTargetGenerator.h
@@ -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
diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx
new file mode 100644
index 0000000000..bba29b1dbf
--- /dev/null
+++ b/Source/cmGlobalGhsMultiGenerator.cxx
@@ -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;
+}
diff --git a/Source/cmGlobalGhsMultiGenerator.h b/Source/cmGlobalGhsMultiGenerator.h
new file mode 100644
index 0000000000..b934c3a10f
--- /dev/null
+++ b/Source/cmGlobalGhsMultiGenerator.h
@@ -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
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index f74f1e0659..2ade825562 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -576,6 +576,7 @@ bool cmGlobalNinjaGenerator::UsingMinGW = false;
// Implemented by:
// cmGlobalUnixMakefileGenerator3
+// cmGlobalGhsMultiGenerator
// cmGlobalVisualStudio10Generator
// cmGlobalVisualStudio6Generator
// cmGlobalVisualStudio7Generator
diff --git a/Source/cmLocalGhsMultiGenerator.cxx b/Source/cmLocalGhsMultiGenerator.cxx
new file mode 100644
index 0000000000..782fec4a82
--- /dev/null
+++ b/Source/cmLocalGhsMultiGenerator.cxx
@@ -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();
+}
diff --git a/Source/cmLocalGhsMultiGenerator.h b/Source/cmLocalGhsMultiGenerator.h
new file mode 100644
index 0000000000..a8df3e7aa8
--- /dev/null
+++ b/Source/cmLocalGhsMultiGenerator.h
@@ -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
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 5c52a1a2d7..bfe9aea35e 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -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());
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index f80191b463..83c919d198 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -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}
diff --git a/Tests/GhsMulti/CMakeLists.txt b/Tests/GhsMulti/CMakeLists.txt
new file mode 100644
index 0000000000..6e15ba9a7f
--- /dev/null
+++ b/Tests/GhsMulti/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 3.1)
+project(ReturnNum)
+
+add_subdirectory(ReturnNum)
diff --git a/Tests/GhsMulti/ReturnNum/App/CMakeLists.txt b/Tests/GhsMulti/ReturnNum/App/CMakeLists.txt
new file mode 100644
index 0000000000..2adbd4e3d0
--- /dev/null
+++ b/Tests/GhsMulti/ReturnNum/App/CMakeLists.txt
@@ -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")
diff --git a/Tests/GhsMulti/ReturnNum/App/Main.c b/Tests/GhsMulti/ReturnNum/App/Main.c
new file mode 100644
index 0000000000..1133834d86
--- /dev/null
+++ b/Tests/GhsMulti/ReturnNum/App/Main.c
@@ -0,0 +1,8 @@
+#include "HelperFun.h"
+
+int main(int argc, const char* argv[])
+{
+ int out;
+ out = giveNum();
+ return out;
+}
diff --git a/Tests/GhsMulti/ReturnNum/CMakeLists.txt b/Tests/GhsMulti/ReturnNum/CMakeLists.txt
new file mode 100644
index 0000000000..7bcc5f96a5
--- /dev/null
+++ b/Tests/GhsMulti/ReturnNum/CMakeLists.txt
@@ -0,0 +1,3 @@
+add_subdirectory(App)
+add_subdirectory(Int)
+add_subdirectory(Lib)
diff --git a/Tests/GhsMulti/ReturnNum/Int/AppDD.int b/Tests/GhsMulti/ReturnNum/Int/AppDD.int
new file mode 100644
index 0000000000..9e22b5e258
--- /dev/null
+++ b/Tests/GhsMulti/ReturnNum/Int/AppDD.int
@@ -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
diff --git a/Tests/GhsMulti/ReturnNum/Int/CMakeLists.txt b/Tests/GhsMulti/ReturnNum/Int/CMakeLists.txt
new file mode 100644
index 0000000000..44c5de1c51
--- /dev/null
+++ b/Tests/GhsMulti/ReturnNum/Int/CMakeLists.txt
@@ -0,0 +1 @@
+add_executable(AppDD AppDD.int Default.bsp)
diff --git a/Tests/GhsMulti/ReturnNum/Int/Default.bsp b/Tests/GhsMulti/ReturnNum/Int/Default.bsp
new file mode 100644
index 0000000000..224ec29063
--- /dev/null
+++ b/Tests/GhsMulti/ReturnNum/Int/Default.bsp
@@ -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
diff --git a/Tests/GhsMulti/ReturnNum/Lib/CMakeLists.txt b/Tests/GhsMulti/ReturnNum/Lib/CMakeLists.txt
new file mode 100644
index 0000000000..9c822da565
--- /dev/null
+++ b/Tests/GhsMulti/ReturnNum/Lib/CMakeLists.txt
@@ -0,0 +1 @@
+add_library(Lib HelperFun.c HelperFun.h) \ No newline at end of file
diff --git a/Tests/GhsMulti/ReturnNum/Lib/HelperFun.c b/Tests/GhsMulti/ReturnNum/Lib/HelperFun.c
new file mode 100644
index 0000000000..d7515d7da0
--- /dev/null
+++ b/Tests/GhsMulti/ReturnNum/Lib/HelperFun.c
@@ -0,0 +1,4 @@
+int giveNum(void)
+{
+ return 1;
+}
diff --git a/Tests/GhsMulti/ReturnNum/Lib/HelperFun.h b/Tests/GhsMulti/ReturnNum/Lib/HelperFun.h
new file mode 100644
index 0000000000..00971b04f2
--- /dev/null
+++ b/Tests/GhsMulti/ReturnNum/Lib/HelperFun.h
@@ -0,0 +1 @@
+int giveNum(void);