diff --git a/Help/generator/Green Hills MULTI.rst b/Help/generator/Green Hills MULTI.rst new file mode 100644 index 000000000..4d3169026 --- /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 6f76fb19a..723c308b9 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 63f704da5..865e1ef25 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/release/dev/add-GreenHills-MULTI-generator.rst b/Help/release/dev/add-GreenHills-MULTI-generator.rst new file mode 100644 index 000000000..b4c5c5ad3 --- /dev/null +++ b/Help/release/dev/add-GreenHills-MULTI-generator.rst @@ -0,0 +1,8 @@ +add-GreenHills-MULTI-generator +------------------------------ + +* A new experimental :generator:`Green Hills MULTI` generator was + added on Windows. `Green Hills MULTI`_ is an IDE for embedded + real-time systems. + +.. _`Green Hills MULTI`: http://www.ghs.com/products/MULTI_IDE.html 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 000000000..c5915c390 --- /dev/null +++ b/Help/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_DEBUG.rst @@ -0,0 +1,6 @@ +CMAKE__GHS_KERNEL_FLAGS_DEBUG +----------------------------------- + +GHS kernel flags for Debug build type or configuration. + + 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 000000000..f80e785d5 --- /dev/null +++ b/Help/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_MINSIZEREL.rst @@ -0,0 +1,7 @@ +CMAKE__GHS_KERNEL_FLAGS_MINSIZEREL +---------------------------------------- + +GHS kernel flags for MinSizeRel build type or configuration. + + 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 000000000..fe02bc342 --- /dev/null +++ b/Help/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_RELEASE.rst @@ -0,0 +1,6 @@ +CMAKE__GHS_KERNEL_FLAGS_RELEASE +------------------------------------- + +GHS kernel flags for Release build type or configuration. + + 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 000000000..220f7f941 --- /dev/null +++ b/Help/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_RELWITHDEBINFO.rst @@ -0,0 +1,7 @@ +CMAKE__GHS_KERNEL_FLAGS_RELWITHDEBINFO +-------------------------------------------- + +GHS kernel flags for RelWithDebInfo type or configuration. + + 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 f1d88a557..85b098bd6 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 8ad89f128..2f5313bc9 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 000000000..0f91be8ad --- /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 000000000..e97d62c22 --- /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 000000000..71a0dec78 --- /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 000000000..56d24e266 --- /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 466090b68..c844aed08 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 000000000..342ad21b4 --- /dev/null +++ b/Modules/Platform/GHS-MULTI-Initialize.cmake @@ -0,0 +1,29 @@ + +#============================================================================= +# Copyright 2015 Geoffrey Viola +# +# 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 000000000..211cf3eb2 --- /dev/null +++ b/Modules/Platform/GHS-MULTI.cmake @@ -0,0 +1,27 @@ + +#============================================================================= +# Copyright 2015 Geoffrey Viola +# +# 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 786e3ebe9..6f12785dd 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -480,6 +480,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 () @@ -507,6 +515,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 000000000..e1dce52bd --- /dev/null +++ b/Source/cmGhsMultiGpj.cxx @@ -0,0 +1,44 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2015 Geoffrey Viola + + 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 000000000..91ff0f4a5 --- /dev/null +++ b/Source/cmGhsMultiGpj.h @@ -0,0 +1,34 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2015 Geoffrey Viola + + 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 000000000..01e2011c5 --- /dev/null +++ b/Source/cmGhsMultiTargetGenerator.cxx @@ -0,0 +1,600 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2015 Geoffrey Viola + + 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 +#include + +std::string const cmGhsMultiTargetGenerator::DDOption("-dynamic"); + +cmGhsMultiTargetGenerator::cmGhsMultiTargetGenerator(cmTarget *target) + : Target(target) + , LocalGenerator(static_cast( + 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 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 cmGhsMultiTargetGenerator::GetSources() const +{ + std::vector 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( + 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::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::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::iterator i = + this->DefinesByLanguage.find(language); + if (i == this->DefinesByLanguage.end()) + { + std::set 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::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::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 compileDefinitions; + this->Target->GetCompileDefinitions(compileDefinitions, config, language); + for (std::vector::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 includes = + this->Target->GetIncludeDirectories(config, language); + for (std::vector::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 const &commandsSet, + cmTarget::CustomCommandType const commandType) +{ + for (std::vector::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 const &objectSources) +{ + for (std::vector::const_iterator si = objectSources.begin(); + si != objectSources.end(); ++si) + { + std::vector 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 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 sources; + std::string config = + target->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE"); + target->GetSourceFiles(sources, config); + for (std::vector::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 options; + bool output = false; + this->Target->GetCompileOptions(options, config, language); + for (std::vector::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 000000000..8e81db870 --- /dev/null +++ b/Source/cmGhsMultiTargetGenerator.h @@ -0,0 +1,119 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2015 Geoffrey Viola + + 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 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 const &commandsSet, + cmTarget::CustomCommandType commandType); + void WriteSources(std::vector 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 FolderBuildStreams; + bool TargetGroup; + bool DynamicDownload; + static std::string const DDOption; + std::map FlagsByLanguage; + std::map DefinesByLanguage; +}; + +#endif // ! cmGhsMultiTargetGenerator_h diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx new file mode 100644 index 000000000..bba29b1db --- /dev/null +++ b/Source/cmGlobalGhsMultiGenerator.cxx @@ -0,0 +1,548 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2015 Geoffrey Viola + + 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 +#include + +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 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 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 + potentialDirsHardPaths(GetCompRootHardPaths()); + const std::vector potentialDirsRegistry(GetCompRootRegistry()); + + std::vector 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::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 cmGlobalGhsMultiGenerator::GetCompRootHardPaths() +{ + std::vector output; + cmSystemTools::Glob("C:/ghs", "comp_[^;]+", output); + for (std::vector::iterator outputIt = output.begin(); + outputIt != output.end(); ++outputIt) + { + *outputIt = "C:/ghs/" + *outputIt; + } + return output; +} + +std::vector cmGlobalGhsMultiGenerator::GetCompRootRegistry() +{ + std::vector 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(this->LocalGenerators[i]); + cmGeneratorTargetsType tgts = lg->GetMakefile()->GetGeneratorTargets(); + this->UpdateBuildFiles(&tgts); + } + } + + cmDeleteAll(TargetFolderBuildStreams); + this->TargetFolderBuildStreams.clear(); +} + +void cmGlobalGhsMultiGenerator::GenerateBuildCommand( + std::vector &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 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 expandedList; + cmSystemTools::ExpandListArgument(std::string(ghsGpjMacros), expandedList); + for (std::vector::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 *targetFolderBuildStreams, + char const *homeOutputDirectory, std::string const &path, + GhsMultiGpj::Types projType, std::string const &relPath) +{ + std::string workingPath(path); + cmSystemTools::ConvertToUnixSlashes(workingPath); + std::vector splitPath = + cmSystemTools::SplitString(workingPath); + std::string workingRelPath(relPath); + cmSystemTools::ConvertToUnixSlashes(workingRelPath); + if (!workingRelPath.empty()) + { + workingRelPath += "/"; + } + std::string pathUpTo; + for (std::vector::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 *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 *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 *targetFolderBuildStreams, + std::string const &pathUpTo, + std::vector::const_iterator splitPathI, + std::vector::const_iterator end, + GhsMultiGpj::Types const projType) +{ + std::vector::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 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 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 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 000000000..b934c3a10 --- /dev/null +++ b/Source/cmGlobalGhsMultiGenerator.h @@ -0,0 +1,127 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2015 Geoffrey Viola + + 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(); } + + ///! 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 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 GetLibDirs() { return this->LibDirs; } + + static void AddFilesUpToPath( + cmGeneratedFileStream *mainBuildFile, + std::map *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 *fileMap); + + static std::string trimQuotes(std::string const &str); + inline bool IsOSDirRelative() { return this->OSDirRelative; } + +protected: + virtual void Generate(); + virtual void GenerateBuildCommand( + std::vector &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 const& makeOptions = std::vector() + ); + +private: + std::string const &GetGhsBuildCommand(); + std::string FindGhsBuildCommand(); + std::string GetCompRoot(); + std::vector GetCompRootHardPaths(); + std::vector GetCompRootRegistry(); + void OpenBuildFileStream(); + + void WriteMacros(); + void WriteHighLevelDirectives(); + void WriteCompilerOptions(std::string const &fOSDir); + + static void AddFilesUpToPathNewBuildFile( + cmGeneratedFileStream *mainBuildFile, + std::map *targetFolderBuildStreams, + char const *homeOutputDirectory, std::string const &pathUpTo, + bool isFirst, std::string const &relPath, GhsMultiGpj::Types projType); + static void AddFilesUpToPathAppendNextFile( + std::map *targetFolderBuildStreams, + std::string const &pathUpTo, + std::vector::const_iterator splitPathI, + std::vector::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 TargetSubProjects; + std::map TargetFolderBuildStreams; + + std::vector 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 9a00fa6bb..505914e2f 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/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index c143bce83..6bce08849 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -2003,7 +2003,7 @@ void cmLocalGenerator::OutputLinkLibraries(std::string& linkLibraries, //---------------------------------------------------------------------------- void cmLocalGenerator::AddArchitectureFlags(std::string& flags, - cmGeneratorTarget* target, + cmGeneratorTarget const* target, const std::string& lang, const std::string& config) { @@ -2190,7 +2190,7 @@ void cmLocalGenerator::AddSharedFlags(std::string& flags, //---------------------------------------------------------------------------- void cmLocalGenerator:: -AddCompilerRequirementFlag(std::string &flags, cmTarget* target, +AddCompilerRequirementFlag(std::string &flags, cmTarget const* target, const std::string& lang) { if (lang.empty()) @@ -2312,7 +2312,8 @@ AddCompilerRequirementFlag(std::string &flags, cmTarget* target, } } -static void AddVisibilityCompileOption(std::string &flags, cmTarget* target, +static void AddVisibilityCompileOption(std::string &flags, + cmTarget const* target, cmLocalGenerator *lg, const std::string& lang) { @@ -2346,7 +2347,7 @@ static void AddVisibilityCompileOption(std::string &flags, cmTarget* target, } static void AddInlineVisibilityCompileOption(std::string &flags, - cmTarget* target, + cmTarget const* target, cmLocalGenerator *lg) { std::string compileOption @@ -2367,7 +2368,7 @@ static void AddInlineVisibilityCompileOption(std::string &flags, //---------------------------------------------------------------------------- void cmLocalGenerator -::AddVisibilityPresetFlags(std::string &flags, cmTarget* target, +::AddVisibilityPresetFlags(std::string &flags, cmTarget const* target, const std::string& lang) { int targetType = target->GetType(); @@ -2393,7 +2394,8 @@ void cmLocalGenerator } //---------------------------------------------------------------------------- -void cmLocalGenerator::AddCMP0018Flags(std::string &flags, cmTarget* target, +void cmLocalGenerator::AddCMP0018Flags(std::string &flags, + cmTarget const* target, std::string const& lang, const std::string& config) { diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 6cdee42c9..a005f5ffc 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -138,18 +138,19 @@ public: std::vector& GetChildren() { return this->Children; } - void AddArchitectureFlags(std::string& flags, cmGeneratorTarget* target, + void AddArchitectureFlags(std::string& flags, + cmGeneratorTarget const* target, const std::string&lang, const std::string& config); void AddLanguageFlags(std::string& flags, const std::string& lang, const std::string& config); - void AddCMP0018Flags(std::string &flags, cmTarget* target, + void AddCMP0018Flags(std::string &flags, cmTarget const* target, std::string const& lang, const std::string& config); - void AddVisibilityPresetFlags(std::string &flags, cmTarget* target, + void AddVisibilityPresetFlags(std::string &flags, cmTarget const* target, const std::string& lang); void AddConfigVariableFlags(std::string& flags, const std::string& var, const std::string& config); - void AddCompilerRequirementFlag(std::string &flags, cmTarget* target, + void AddCompilerRequirementFlag(std::string &flags, cmTarget const* target, const std::string& lang); ///! Append flags to a string. virtual void AppendFlags(std::string& flags, const std::string& newFlags); diff --git a/Source/cmLocalGhsMultiGenerator.cxx b/Source/cmLocalGhsMultiGenerator.cxx new file mode 100644 index 000000000..782fec4a8 --- /dev/null +++ b/Source/cmLocalGhsMultiGenerator.cxx @@ -0,0 +1,55 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2015 Geoffrey Viola + + 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 000000000..a8df3e7aa --- /dev/null +++ b/Source/cmLocalGhsMultiGenerator.h @@ -0,0 +1,56 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2015 Geoffrey Viola + + 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 a542a24b4..e624a8371 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -64,6 +64,7 @@ # include "cmGlobalBorlandMakefileGenerator.h" # include "cmGlobalNMakeMakefileGenerator.h" # include "cmGlobalJOMMakefileGenerator.h" +# include "cmGlobalGhsMultiGenerator.h" # define CMAKE_HAVE_VS_GENERATORS # endif # include "cmGlobalMSYSMakefileGenerator.h" @@ -1756,6 +1757,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 b474d3262..699b61669 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1967,6 +1967,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 $ + --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 000000000..6e15ba9a7 --- /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 000000000..2adbd4e3d --- /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 000000000..1133834d8 --- /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 000000000..7bcc5f96a --- /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 000000000..9e22b5e25 --- /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 000000000..44c5de1c5 --- /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 000000000..224ec2906 --- /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 000000000..9c822da56 --- /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 000000000..d7515d7da --- /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 000000000..00971b04f --- /dev/null +++ b/Tests/GhsMulti/ReturnNum/Lib/HelperFun.h @@ -0,0 +1 @@ +int giveNum(void);