On 03/19/2015 09:57 AM, Geoffrey Viola wrote: > I moved it under > #if defined(_WIN32) && !defined(__CYGWIN__) > # if !defined(CMAKE_BOOT_MINGW)
The #include line needs to be moved similarly. I made that fix and a few whitespace fixes. I've attached a patch with those revisions. I noticed while making those fixes that you're using auto_ptr inside a map value. The auto_ptr is documented as not suitable for use in containers in general. For TargetFolderBuildStreams you could just use a normal pointer and then cleanup in the generator destructor using cmDeleteAll. Thanks, -Brad
>From 9ef934f7b3abcd8560197fa16ad6b06eb5708d3b Mon Sep 17 00:00:00 2001 Message-Id: <9ef934f7b3abcd8560197fa16ad6b06eb5708d3b.1427119119.git.brad.k...@kitware.com> From: Geoff Viola <[email protected]> Date: Mon, 26 Jan 2015 21:38:27 -0700 Subject: [PATCH] Added-some-support-for-a-Green-Hills-MULTI --- Help/generator/Green Hills MULTI.rst | 11 + Help/manual/cmake-generators.7.rst | 1 + Help/manual/cmake-variables.7.rst | 1 + Help/variable/CMAKE_MAKE_PROGRAM.rst | 2 + Help/variable/CMAKE_SYSTEM_PROCESSOR.rst | 2 + Help/variable/GHS-MULTI.rst | 4 + Modules/Compiler/GHS-DetermineCompiler.cmake | 6 + Modules/FindBoost.cmake | 5 +- Modules/Platform/GHS-MULTI-Initialize.cmake | 29 ++ Modules/Platform/GHS-MULTI.cmake | 27 ++ Source/CMakeLists.txt | 9 + Source/cmGhsMultiGpj.cxx | 39 +++ Source/cmGhsMultiGpj.h | 31 ++ Source/cmGhsMultiTargetGenerator.cxx | 431 ++++++++++++++++++++++++++ Source/cmGhsMultiTargetGenerator.h | 92 ++++++ Source/cmGlobalGhsMultiGenerator.cxx | 443 +++++++++++++++++++++++++++ Source/cmGlobalGhsMultiGenerator.h | 127 ++++++++ Source/cmGlobalNinjaGenerator.cxx | 1 + Source/cmLocalGhsMultiGenerator.cxx | 48 +++ Source/cmLocalGhsMultiGenerator.h | 54 ++++ Source/cmake.cxx | 3 + Tests/CMakeLists.txt | 17 + Tests/GhsMulti/CMakeLists.txt | 4 + Tests/GhsMulti/ReturnNum/App/CMakeLists.txt | 4 + Tests/GhsMulti/ReturnNum/App/Main.c | 8 + Tests/GhsMulti/ReturnNum/CMakeLists.txt | 3 + Tests/GhsMulti/ReturnNum/Int/AppDD.int | 12 + Tests/GhsMulti/ReturnNum/Int/CMakeLists.txt | 1 + Tests/GhsMulti/ReturnNum/Int/Default.bsp | 35 +++ Tests/GhsMulti/ReturnNum/Lib/CMakeLists.txt | 1 + Tests/GhsMulti/ReturnNum/Lib/HelperFun.c | 4 + Tests/GhsMulti/ReturnNum/Lib/HelperFun.h | 1 + 32 files changed, 1455 insertions(+), 1 deletion(-) create mode 100644 Help/generator/Green Hills MULTI.rst create mode 100644 Help/variable/GHS-MULTI.rst create mode 100644 Modules/Compiler/GHS-DetermineCompiler.cmake create mode 100644 Modules/Platform/GHS-MULTI-Initialize.cmake create mode 100644 Modules/Platform/GHS-MULTI.cmake create mode 100644 Source/cmGhsMultiGpj.cxx create mode 100644 Source/cmGhsMultiGpj.h create mode 100644 Source/cmGhsMultiTargetGenerator.cxx create mode 100644 Source/cmGhsMultiTargetGenerator.h create mode 100644 Source/cmGlobalGhsMultiGenerator.cxx create mode 100644 Source/cmGlobalGhsMultiGenerator.h create mode 100644 Source/cmLocalGhsMultiGenerator.cxx create mode 100644 Source/cmLocalGhsMultiGenerator.h create mode 100644 Tests/GhsMulti/CMakeLists.txt create mode 100644 Tests/GhsMulti/ReturnNum/App/CMakeLists.txt create mode 100644 Tests/GhsMulti/ReturnNum/App/Main.c create mode 100644 Tests/GhsMulti/ReturnNum/CMakeLists.txt create mode 100644 Tests/GhsMulti/ReturnNum/Int/AppDD.int create mode 100644 Tests/GhsMulti/ReturnNum/Int/CMakeLists.txt create mode 100644 Tests/GhsMulti/ReturnNum/Int/Default.bsp create mode 100644 Tests/GhsMulti/ReturnNum/Lib/CMakeLists.txt create mode 100644 Tests/GhsMulti/ReturnNum/Lib/HelperFun.c create mode 100644 Tests/GhsMulti/ReturnNum/Lib/HelperFun.h diff --git a/Help/generator/Green Hills MULTI.rst b/Help/generator/Green Hills MULTI.rst new file mode 100644 index 0000000..79695f1 --- /dev/null +++ b/Help/generator/Green Hills MULTI.rst @@ -0,0 +1,11 @@ +Green Hills MULTI +----------------- + +Generates Green Hills MULTI project files. + +Customizations are available through the following cache variables: + +* ``GHS_BSP_NAME`` +* ``GHS_CUSTOMIZATION`` +* ``GHS_GPJ_MACROS`` +* ``GHS_OS_DIR`` diff --git a/Help/manual/cmake-generators.7.rst b/Help/manual/cmake-generators.7.rst index 804229b..ce9f5c8 100644 --- a/Help/manual/cmake-generators.7.rst +++ b/Help/manual/cmake-generators.7.rst @@ -56,6 +56,7 @@ one may launch CMake from any environment. .. 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 c342dbe..5282872 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -181,6 +181,7 @@ Variables that Describe the System /variable/CMAKE_SYSTEM_VERSION /variable/CYGWIN /variable/ENV + /variable/GHS-MULTI /variable/MINGW /variable/MSVC10 /variable/MSVC11 diff --git a/Help/variable/CMAKE_MAKE_PROGRAM.rst b/Help/variable/CMAKE_MAKE_PROGRAM.rst index f1d88a5..1cc22b5 100644 --- a/Help/variable/CMAKE_MAKE_PROGRAM.rst +++ b/Help/variable/CMAKE_MAKE_PROGRAM.rst @@ -8,6 +8,8 @@ name if it is expected to be in the ``PATH``. The tool selected depends on the :variable:`CMAKE_GENERATOR` used to configure the project: +* The Green Hills MULTI generator sets this to ``GHS-MULTI`` + * The Makefile generators set this to ``make``, ``gmake``, or a generator-specific tool (e.g. ``nmake`` for "NMake Makefiles"). diff --git a/Help/variable/CMAKE_SYSTEM_PROCESSOR.rst b/Help/variable/CMAKE_SYSTEM_PROCESSOR.rst index 8ad89f1..2f5313b 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 0000000..0f91be8 --- /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-DetermineCompiler.cmake b/Modules/Compiler/GHS-DetermineCompiler.cmake new file mode 100644 index 0000000..56d24e2 --- /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 466090b..c844aed 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 0000000..342ad21 --- /dev/null +++ b/Modules/Platform/GHS-MULTI-Initialize.cmake @@ -0,0 +1,29 @@ + +#============================================================================= +# Copyright 2015 Geoffrey Viola <[email protected]> +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (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 0000000..211cf3e --- /dev/null +++ b/Modules/Platform/GHS-MULTI.cmake @@ -0,0 +1,27 @@ + +#============================================================================= +# Copyright 2015 Geoffrey Viola <[email protected]> +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (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 04f6a81..064b827 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 0000000..d630faa --- /dev/null +++ b/Source/cmGhsMultiGpj.cxx @@ -0,0 +1,39 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2015 Geoffrey Viola <[email protected]> + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#include "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 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 0000000..225ec47 --- /dev/null +++ b/Source/cmGhsMultiGpj.h @@ -0,0 +1,31 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2015 Geoffrey Viola <[email protected]> + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#ifndef cmGhsMultiGpj_h +#define cmGhsMultiGpj_h + +class cmGeneratedFileStream; + +class GhsMultiGpj { +public: + enum Types { + INTERGRITY_APPLICATION, + 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 0000000..f9b0548 --- /dev/null +++ b/Source/cmGhsMultiTargetGenerator.cxx @@ -0,0 +1,431 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2015 Geoffrey Viola <[email protected]> + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#include "cmGhsMultiTargetGenerator.h" +#include "cmGlobalGhsMultiGenerator.h" +#include "cmLocalGhsMultiGenerator.h" +#include "cmMakefile.h" +#include "cmTarget.h" +#include "cmGeneratedFileStream.h" +#include "cmSourceFile.h" +#include <assert.h> + +std::string const cmGhsMultiTargetGenerator::DDOption("-dynamic"); + +cmGhsMultiTargetGenerator::cmGhsMultiTargetGenerator(cmTarget const *target) + : Target(target), LocalGenerator(static_cast<cmLocalGhsMultiGenerator *>( + target->GetMakefile()->GetLocalGenerator())), + Makefile(target->GetMakefile()), TargetGroup(DetermineIfTargetGroup()), + DynamicDownload(false) { + std::string BuildFileName; + BuildFileName = this->Target->GetName(); + BuildFileName += cmGlobalGhsMultiGenerator::FILE_EXTENSION; + + char const *folderProp = this->Target->GetProperty("FOLDER"); + RelBuildFilePath = NULL == folderProp ? "" : folderProp; + if (RelBuildFilePath.size() > 0 && '/' != RelBuildFilePath.back()) { + RelBuildFilePath += "/"; + } + RelBuildFilePath += Target->GetName() + "/"; + + RelOutputFileName = RelBuildFilePath + Target->GetName() + ".a"; + + RelBuildFileName = RelBuildFilePath; + if (RelBuildFileName.size() > 0 && '/' != RelBuildFileName.back()) { + RelBuildFileName += "/"; + } + RelBuildFileName += BuildFileName; + + std::string absPathToRoot(this->Makefile->GetHomeOutputDirectory()); + if (absPathToRoot.size() > 0 && '/' != absPathToRoot.back()) { + absPathToRoot += "/"; + } + AbsBuildFilePath = absPathToRoot + RelBuildFilePath; + AbsBuildFileName = absPathToRoot + RelBuildFileName; + AbsOutputFileName = absPathToRoot + RelOutputFileName; +} + +cmGhsMultiTargetGenerator::~cmGhsMultiTargetGenerator() {} + +void cmGhsMultiTargetGenerator::Generate() { + std::vector<cmSourceFile *> objectSources = GetSources(); + if (objectSources.size() > 0 && IncludeThisTarget()) { + if (!cmSystemTools::FileExists(AbsBuildFilePath.c_str())) { + cmSystemTools::MakeDirectory(AbsBuildFilePath.c_str()); + } + cmGlobalGhsMultiGenerator::Open(std::string(""), this->AbsBuildFileName, + &FolderBuildStreams); + cmGlobalGhsMultiGenerator::OpenBuildFileStream(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); + DynamicDownload = DetermineIfDynamicDownload(config, language); + if (DynamicDownload) { + *this->GetFolderBuildStreams() << "#component integrity_dynamic_download" + << std::endl; + } + GhsMultiGpj::WriteGpjTag(GetGpjTag(), this->GetFolderBuildStreams()); + cmGlobalGhsMultiGenerator::WriteDisclaimer(GetFolderBuildStreams()); + + bool const notKernel = IsNotKernel(config, language); + WriteTypeSpecifics(config, notKernel); + WriteDebugOptions(config, notKernel); + WriteCompilerOptions(config, language); + WriteCompilerFlags(); + WriteCompilerDefinitions(config, language); + WriteIncludes(config, language); + WriteTargetLinkLibraries(); + WriteCustomCommands(); + if (DynamicDownload) { + *this->GetFolderBuildStreams() << " " << DDOption << std::endl; + } + + 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 { + GhsMultiGpj::Types output; + if (IsTargetGroup()) { + output = GhsMultiGpj::Types::INTERGRITY_APPLICATION; + } else { + output = GhsMultiGpj::Types::PROGRAM; + } + return output; +} + +cmGlobalGhsMultiGenerator * +cmGhsMultiTargetGenerator::GetGlobalGenerator() const { + return static_cast<cmGlobalGhsMultiGenerator *>( + LocalGenerator->GetGlobalGenerator()); +} + +void cmGhsMultiTargetGenerator::WriteTypeSpecifics(const std::string &config, + bool const notKernel) { + std::string outputDir(GetOutputDirectory(config)); + std::string outputFilename(GetOutputFilename(config)); + + if (Target->GetType() == cmTarget::TargetType::STATIC_LIBRARY) { + *GetFolderBuildStreams() << " -relobj" << std::endl; + *GetFolderBuildStreams() << " {optgroup=GhsCommonOptions} -o \"" + << outputDir << outputFilename << ".a\"" + << std::endl; + } else if (Target->GetType() == cmTarget::TargetType::EXECUTABLE) { + if (notKernel && !IsTargetGroup()) { + *GetFolderBuildStreams() << " -relprog" << std::endl; + } + if (IsTargetGroup()) { + *GetFolderBuildStreams() << " -non_shared" << std::endl; + *GetFolderBuildStreams() << " -o \"" << outputDir << outputFilename + << ".elf\"" << std::endl; + } else { + *GetFolderBuildStreams() << " {optgroup=GhsCommonOptions} -o \"" + << outputDir << outputFilename << ".as\"" + << std::endl; + } + } +} + +void cmGhsMultiTargetGenerator::WriteDebugOptions(std::string const &config, + bool const notKernel) { + if ("DEBUG" == config) { + if (notKernel) { + *GetFolderBuildStreams() << " -G" << std::endl; + *GetFolderBuildStreams() << " -Onone" << std::endl; + } else { + *GetFolderBuildStreams() << " -ldebug" << std::endl; + } + } else if (notKernel) { + *GetFolderBuildStreams() << " -O" << std::endl; + } +} + +void cmGhsMultiTargetGenerator::WriteCompilerOptions( + std::string const &config, const std::string &language) { + std::vector<std::string> options; + Target->GetCompileOptions(options, config, language); + bool hasStartfileDirProp = false; + std::string const startFilePropName("-startfile_dir="); + for (std::vector<std::string>::const_iterator options_i = options.begin(); + options_i != options.end(); ++options_i) { + std::string option = *options_i; + if (DDOption != option) { + if (option.length() >= startFilePropName.length() && + startFilePropName == option.substr(0, startFilePropName.length())) { + hasStartfileDirProp = true; + } + cmSystemTools::ConvertToUnixSlashes(option); + *this->GetFolderBuildStreams() << " " << option << std::endl; + } + } + + // If this property is relative, make it relative to the root lists file + if (!hasStartfileDirProp && GetGlobalGenerator()->IsOSDirRelative()) { + *this->GetFolderBuildStreams() << " " << startFilePropName << "\"" + << this->Makefile->GetHomeOutputDirectory() + << "/$(__LIBS_DIR_BASE)/$(__BSP_NAME)\"" + << std::endl; + } +} + +void cmGhsMultiTargetGenerator::WriteCompilerFlags() { + char const *const compileFlags = Target->GetProperty("COMPILE_FLAGS"); + if (NULL != compileFlags) { + *this->GetFolderBuildStreams() << " " << compileFlags << 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 = + 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 = + GetGlobalGenerator()->GetTargetDirectDepends(*this->Target); + for (cmTargetDependSet::iterator tdsI = tds.begin(); tdsI != tds.end(); + ++tdsI) { + cmTarget const *tg(*tdsI); + cmGhsMultiTargetGenerator gmtg(tg); + *this->GetFolderBuildStreams() << " -L\"" << gmtg.GetAbsBuildFilePath() + << "\"" << std::endl; + } + // library targets + cmTarget::LinkLibraryVectorType llv = + this->Target->GetOriginalLinkLibraries(); + for (cmTarget::LinkLibraryVectorType::const_iterator llvI = llv.begin(); + llvI != llv.end(); ++llvI) { + std::string libName = llvI->first; + // if it is a user defined target get the full path to the lib + cmTarget *tg(GetGlobalGenerator()->FindTarget(libName)); + if (NULL != tg) { + cmGhsMultiTargetGenerator gmtg(tg); + libName = tg->GetName() + ".a"; + } + *this->GetFolderBuildStreams() << " -l\"" << libName << "\"" + << std::endl; + } +} + +void cmGhsMultiTargetGenerator::WriteCustomCommands() { + WriteCustomCommandsHelper(this->Target->GetPreBuildCommands(), + cmTarget::CustomCommandType::PRE_BUILD); + WriteCustomCommandsHelper(this->Target->GetPostBuildCommands(), + cmTarget::CustomCommandType::POST_BUILD); +} + +void cmGhsMultiTargetGenerator::WriteCustomCommandsHelper( + std::vector<cmCustomCommand> const &commandsSet, + cmTarget::CustomCommandType const commandType) { + for (std::vector<cmCustomCommand>::const_iterator commandsSetI = + commandsSet.begin(); + commandsSetI != commandsSet.end(); ++commandsSetI) { + cmCustomCommandLines const &commands = commandsSetI->GetCommandLines(); + for (cmCustomCommandLines::const_iterator commandI = commands.begin(); + commandI != commands.end(); ++commandI) { + switch (commandType) { + case cmTarget::CustomCommandType::PRE_BUILD: + *GetFolderBuildStreams() << " :preexecShellSafe="; + break; + case cmTarget::CustomCommandType::POST_BUILD: + *GetFolderBuildStreams() << " :postexecShellSafe="; + break; + default: + assert("Only pre and post are supported"); + } + cmCustomCommandLine const &command = *commandI; + for (cmCustomCommandLine::const_iterator commandLineI = command.begin(); + commandLineI != command.end(); ++commandLineI) { + if (command.size() > 0) { + *GetFolderBuildStreams() + << (command.begin() == commandLineI ? "'" : " "); + } + *GetFolderBuildStreams() << *commandLineI; + } + if (command.size() > 0) { + *GetFolderBuildStreams() << "'" << std::endl; + } + } + } +} + +void cmGhsMultiTargetGenerator::WriteSources( + std::vector<cmSourceFile *> const &objectSources) { + for (std::vector<cmSourceFile *>::const_iterator si = objectSources.begin(); + si != objectSources.end(); ++si) { + std::vector<cmSourceGroup> sourceGroups(this->Makefile->GetSourceGroups()); + char const *sourceFullPath = (*si)->GetFullPath().c_str(); + cmSourceGroup *sourceGroup = + this->Makefile->FindSourceGroup(sourceFullPath, sourceGroups); + std::string sgPath(sourceGroup->GetFullName()); + cmSystemTools::ConvertToUnixSlashes(sgPath); + cmGlobalGhsMultiGenerator::AddFilesUpToPath( + GetFolderBuildStreams(), &FolderBuildStreams, + this->Makefile->GetHomeOutputDirectory(), sgPath, + GhsMultiGpj::Types::SUBPROJECT, 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()) { + WriteObjectLangOverride(this->FolderBuildStreams[sgPath].get(), (*si)); + + WriteObjectDir(this->FolderBuildStreams[sgPath].get(), + 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); + if (workingDir.size() > 0 && '/' != workingDir.back()) { + 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 = + Target->GetProperty("RUNTIME_OUTPUT_DIRECTORY"); + if (NULL != runtimeOutputProp) { + outputDir = runtimeOutputProp; + } + + std::string configCapped(cmSystemTools::UpperCase(config)); + const char *runtimeOutputSProp = + Target->GetProperty("RUNTIME_OUTPUT_DIRECTORY_" + configCapped); + if (NULL != runtimeOutputSProp) { + outputDir = runtimeOutputSProp; + } + cmSystemTools::ConvertToUnixSlashes(outputDir); + + if (outputDir.length() > 0 && ('/' != (*outputDir.rbegin()))) { + outputDir += "/"; + } + + return outputDir; +} + +std::string +cmGhsMultiTargetGenerator::GetOutputFilename(const std::string &config) const { + std::string outputFilename(Target->GetName()); + + const char *outputNameProp = Target->GetProperty("OUTPUT_NAME"); + if (NULL != outputNameProp) { + outputFilename = outputNameProp; + } + + std::string configCapped(cmSystemTools::UpperCase(config)); + const char *outputNameSProp = + 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; + Target->GetCompileOptions(options, config, language); + output = + options.end() == std::find(options.begin(), options.end(), "-kernel"); + return output; +} + +bool cmGhsMultiTargetGenerator::DetermineIfTargetGroup() { + bool output = false; + std::vector<cmSourceFile *> sources = GetSources(); + 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; + 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 (DDOption == option) { + output = true; + } + } + return output; +} diff --git a/Source/cmGhsMultiTargetGenerator.h b/Source/cmGhsMultiTargetGenerator.h new file mode 100644 index 0000000..3f53a58 --- /dev/null +++ b/Source/cmGhsMultiTargetGenerator.h @@ -0,0 +1,92 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2015 Geoffrey Viola <[email protected]> + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#ifndef cmGhsMultiTargetGenerator_h +#define cmGhsMultiTargetGenerator_h + +#include "cmStandardIncludes.h" +#include "cmTarget.h" +#include "cmGhsMultiGpj.h" + +class cmGeneratedFileStream; +class cmGlobalGhsMultiGenerator; +class cmLocalGhsMultiGenerator; +class cmMakefile; +class cmSourceFile; +class cmGeneratedFileStream; +class cmCustomCommand; + +class cmGhsMultiTargetGenerator { +public: + cmGhsMultiTargetGenerator(cmTarget const *target); + + virtual ~cmGhsMultiTargetGenerator(); + + virtual void Generate(); + + bool IncludeThisTarget(); + std::vector<cmSourceFile *> GetSources() const; + GhsMultiGpj::Types GetGpjTag() const; + const char *GetAbsBuildFilePath() const { return AbsBuildFilePath.c_str(); } + const char *GetRelBuildFileName() const { return RelBuildFileName.c_str(); } + const char *GetAbsBuildFileName() const { return AbsBuildFileName.c_str(); } + const char *GetAbsOutputFileName() const { return AbsOutputFileName.c_str(); } + +private: + cmGlobalGhsMultiGenerator *GetGlobalGenerator() const; + cmGeneratedFileStream *GetFolderBuildStreams() { + return FolderBuildStreams[""].get(); + }; + bool IsTargetGroup() const { return TargetGroup; } + + void WriteTypeSpecifics(const std::string &config, bool notKernel); + void WriteDebugOptions(std::string const &config, bool notKernel); + void WriteCompilerOptions(const std::string &config, + const std::string &language); + void WriteCompilerFlags(); + void WriteCompilerDefinitions(const std::string &config, + const std::string &language); + 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); + bool DetermineIfTargetGroup(); + bool DetermineIfDynamicDownload(std::string const &config, + const std::string &language); + + cmTarget const *Target; + cmLocalGhsMultiGenerator *LocalGenerator; + cmMakefile *Makefile; + std::string AbsBuildFilePath; + std::string RelBuildFilePath; + std::string AbsBuildFileName; + std::string RelBuildFileName; + std::string RelOutputFileName; + std::string AbsOutputFileName; + std::map<std::string, cmsys::auto_ptr<cmGeneratedFileStream>> + FolderBuildStreams; + bool TargetGroup; + bool DynamicDownload; + static std::string const DDOption; +}; + +#endif // ! cmGhsMultiTargetGenerator_h diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx new file mode 100644 index 0000000..4312e23 --- /dev/null +++ b/Source/cmGlobalGhsMultiGenerator.cxx @@ -0,0 +1,443 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2015 Geoffrey Viola <[email protected]> + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#include "cmGlobalGhsMultiGenerator.h" +#include "cmLocalGhsMultiGenerator.h" +#include "cmMakefile.h" +#include "cmVersion.h" +#include "cmGeneratedFileStream.h" +#include "cmGhsMultiTargetGenerator.h" +#include <cmsys/SystemTools.hxx> + +const char *cmGlobalGhsMultiGenerator::FILE_EXTENSION = ".gpj"; + +cmGlobalGhsMultiGenerator::cmGlobalGhsMultiGenerator() : OSDirRelative(false) { + this->FindMakeProgramFile = "CMakeGreenHillsFindMake.cmake"; +} + +cmLocalGenerator *cmGlobalGhsMultiGenerator::CreateLocalGenerator() { + cmLocalGenerator *lg = new cmLocalGhsMultiGenerator; + lg->SetGlobalGenerator(this); + this->SetCurrentLocalGenerator(lg); + return lg; +} + +void cmGlobalGhsMultiGenerator::GetDocumentation(cmDocumentationEntry &entry) { + entry.Name = GetActualName(); + entry.Brief = "Generates Green Hills MULTI files (experimental)."; +} + +void cmGlobalGhsMultiGenerator::EnableLanguage( + std::vector<std::string> const &l, cmMakefile *mf, bool optional) { + mf->AddDefinition("CMAKE_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", "GHSC"); + 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", "GHSCXX"); + mf->AddDefinition("CMAKE_CXX_COMPILER_FORCED", "TRUE"); + + if (ghsCompRoot.length() > 0) { + 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::string makeProgram = cmSystemTools::FindProgram("gbuild"); + if (makeProgram.empty()) { + makeProgram = "gbuild"; + } + 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\\Unin" + "stall\\" + "GreenHillsSoftwared771f1b4;InstallLocation", + output[0]); + cmsys::SystemTools::ReadRegistryValue( + "HKEY_LOCAL_" + "MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Unin" + "stall\\" + "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( + cmMakefile *const makefile) { + // Compute GHS MULTI's build file path. + std::string buildFilePath = + this->GetCMakeInstance()->GetHomeOutputDirectory(); + buildFilePath += "/"; + buildFilePath += "default"; + buildFilePath += FILE_EXTENSION; + + Open(std::string(""), buildFilePath, &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(trimQuotes(osDir)); + cmSystemTools::ReplaceString(fOSDir, "\\", "/"); + if (fOSDir.length() > 0 && ('c' == fOSDir[0] || 'C' == fOSDir[0])) { + OSDirRelative = false; + } else { + 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(trimQuotes(bspName)); + cmSystemTools::ReplaceString(fBspName, "\\", "/"); + WriteMacros(); + WriteHighLevelDirectives(); + + GhsMultiGpj::WriteGpjTag(GhsMultiGpj::Types::PROJECT, GetBuildFileStream()); + WriteDisclaimer(GetBuildFileStream()); + *GetBuildFileStream() << "# Top Level Project File" << std::endl; + if (fBspName.length() > 0) { + *GetBuildFileStream() << " -bsp " << fBspName << std::endl; + } + WriteCompilerOptions(fOSDir); +} + +void cmGlobalGhsMultiGenerator::CloseBuildFileStream( + cmGeneratedFileStream **filestream) { + if (filestream) { + delete *filestream; + *filestream = NULL; + } else { + cmSystemTools::Error("Build file stream was not open."); + } +} + +void cmGlobalGhsMultiGenerator::Generate() { + this->cmGlobalGenerator::Generate(); + + if (this->LocalGenerators.size() > 0) { + cmLocalGenerator *sampLG = this->LocalGenerators[0]; + this->OpenBuildFileStream(sampLG->GetMakefile()); + + // Build all the folder build files + for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i) { + cmLocalGhsMultiGenerator *lg = + static_cast<cmLocalGhsMultiGenerator *>(this->LocalGenerators[i]); + cmGeneratorTargetsType tgts = lg->GetMakefile()->GetGeneratorTargets(); + UpdateBuildFiles(tgts); + } + } +} + +void cmGlobalGhsMultiGenerator::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)); + + 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) { + *GetBuildFileStream() << "macro " << *expandedListI << std::endl; + } + } +} + +void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives() { + *GetBuildFileStream() << "primaryTarget=arm_integrity.tgt" << std::endl; + char const *const customization = + this->GetCMakeInstance()->GetCacheDefinition("GHS_CUSTOMIZATION"); + if (NULL != customization && strlen(customization) > 0) { + *GetBuildFileStream() << "customization=" << trimQuotes(customization) + << std::endl; + this->GetCMakeInstance()->MarkCliAsUsed("GHS_CUSTOMIZATION"); + } +} + +void cmGlobalGhsMultiGenerator::WriteCompilerOptions( + std::string const &fOSDir) { + *GetBuildFileStream() << " -os_dir=\"" << fOSDir << "\"" << std::endl; + *GetBuildFileStream() << " --link_once_templates" << std::endl; +} + +void cmGlobalGhsMultiGenerator::WriteDisclaimer(std::ostream *os) { + (*os) << "#" << std::endl + << "# CMAKE generated file: DO NOT EDIT!" << std::endl + << "# Generated by \"" << GetActualName() << "\"" + << " Generator, CMake Version " << cmVersion::GetMajorVersion() << "." + << cmVersion::GetMinorVersion() << std::endl + << "#" << std::endl; +} + +void cmGlobalGhsMultiGenerator::AddFilesUpToPath( + cmGeneratedFileStream *mainBuildFile, + std::map<std::string, cmsys::auto_ptr<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); + if (relPath.size() > 0 && '/' != relPath.back()) { + workingRelPath += "/"; + } + std::string pathUpTo; + for (std::vector<cmsys::String>::const_iterator splitPathI = + splitPath.begin(); + splitPath.end() != splitPathI; ++splitPathI) { + pathUpTo += *splitPathI; + if (targetFolderBuildStreams->end() == + targetFolderBuildStreams->find(pathUpTo)) { + AddFilesUpToPathNewBuildFile( + mainBuildFile, targetFolderBuildStreams, homeOutputDirectory, + pathUpTo, splitPath.begin() == splitPathI, workingRelPath, projType); + } + AddFilesUpToPathAppendNextFile(targetFolderBuildStreams, pathUpTo, + splitPathI, splitPath.end(), projType); + pathUpTo += "/"; + } +} + +void cmGlobalGhsMultiGenerator::Open( + std::string const &mapKeyName, std::string const &fileName, + std::map<std::string, cmsys::auto_ptr<cmGeneratedFileStream>> *fileMap) { + if (fileMap->end() == fileMap->find(fileName)) { + cmsys::auto_ptr<cmGeneratedFileStream> temp(new cmGeneratedFileStream); + temp->open(fileName.c_str()); + (*fileMap)[mapKeyName] = temp; + } +} + +void cmGlobalGhsMultiGenerator::AddFilesUpToPathNewBuildFile( + cmGeneratedFileStream *mainBuildFile, + std::map<std::string, cmsys::auto_ptr<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].get()); + GhsMultiGpj::WriteGpjTag(projType, + (*targetFolderBuildStreams)[pathUpTo].get()); + WriteDisclaimer((*targetFolderBuildStreams)[pathUpTo].get()); + + // Add to main build file + if (isFirst) { + *mainBuildFile << relFilename << " "; + GhsMultiGpj::WriteGpjTag(projType, mainBuildFile); + } +} + +void cmGlobalGhsMultiGenerator::AddFilesUpToPathAppendNextFile( + std::map<std::string, cmsys::auto_ptr<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].get()); + } +} + +std::string +cmGlobalGhsMultiGenerator::GetFileNameFromPath(std::string const &path) { + std::string output(path); + if (path.length() > 0) { + cmSystemTools::ConvertToUnixSlashes(output); + std::vector<cmsys::String> splitPath = cmSystemTools::SplitString(output); + output += "/" + splitPath.back() + FILE_EXTENSION; + } + return output; +} + +void cmGlobalGhsMultiGenerator::UpdateBuildFiles( + cmGeneratorTargetsType const &tgts) { + for (cmGeneratorTargetsType::const_iterator tgtsI = tgts.begin(); + tgtsI != tgts.end(); ++tgtsI) { + cmGhsMultiTargetGenerator gmtg(tgtsI->first); + if (gmtg.GetSources().size() > 0 && gmtg.IncludeThisTarget()) { + char const *rawFolderName = tgtsI->first->GetProperty("FOLDER"); + if (NULL == rawFolderName) { + rawFolderName = ""; + } + std::string folderName(rawFolderName); + if (TargetFolderBuildStreams.end() == + TargetFolderBuildStreams.find(folderName)) { + AddFilesUpToPath(GetBuildFileStream(), &TargetFolderBuildStreams, + this->GetCMakeInstance()->GetHomeOutputDirectory(), + folderName, GhsMultiGpj::Types::PROJECT); + } + std::vector<cmsys::String> splitPath = + cmSystemTools::SplitString(gmtg.GetRelBuildFileName()); + std::string foldNameRelBuildFile(*(splitPath.end() - 2) + "/" + + splitPath.back()); + *TargetFolderBuildStreams[folderName] << foldNameRelBuildFile << " "; + GhsMultiGpj::WriteGpjTag(gmtg.GetGpjTag(), + TargetFolderBuildStreams[folderName].get()); + } + } +} + +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 0000000..cf699ae --- /dev/null +++ b/Source/cmGlobalGhsMultiGenerator.h @@ -0,0 +1,127 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2015 Geoffrey Viola <[email protected]> + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#ifndef 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(); + + 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 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 TargetFolderBuildStreams[""].get(); + } + + static void OpenBuildFileStream(std::string const &filepath, + cmGeneratedFileStream **filestream); + static void OpenBuildFileStream(cmGeneratedFileStream *filestream); + static void CloseBuildFileStream(cmGeneratedFileStream **filestream); + /// Write the common disclaimer text at the top of each build file. + static void WriteDisclaimer(std::ostream *os); + std::vector<std::string> GetLibDirs() { return LibDirs; } + + static void AddFilesUpToPath( + cmGeneratedFileStream *mainBuildFile, + std::map<std::string, cmsys::auto_ptr<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, cmsys::auto_ptr<cmGeneratedFileStream>> *fileMap); + + static std::string trimQuotes(std::string const &str); + inline bool IsOSDirRelative() { return 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(cmMakefile *makefile); + + void WriteMacros(); + void WriteHighLevelDirectives(); + void WriteCompilerOptions(std::string const &fOSDir); + + static void AddFilesUpToPathNewBuildFile( + cmGeneratedFileStream *mainBuildFile, + std::map<std::string, cmsys::auto_ptr<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, cmsys::auto_ptr<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 const &tgts); + + std::vector<cmGeneratedFileStream *> TargetSubProjects; + std::map<std::string, cmsys::auto_ptr<cmGeneratedFileStream>> + TargetFolderBuildStreams; + + std::vector<std::string> LibDirs; + + bool OSDirRelative; + bool GhsBuildCommandInitialized; + std::string GhsBuildCommand; +}; + +#endif diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index f74f1e0..2ade825 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 0000000..b700143 --- /dev/null +++ b/Source/cmLocalGhsMultiGenerator.cxx @@ -0,0 +1,48 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2015 Geoffrey Viola <[email protected]> + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#include "cmLocalGhsMultiGenerator.h" +#include "cmGlobalGhsMultiGenerator.h" +#include "cmGeneratorTarget.h" +#include "cmMakefile.h" +#include "cmGhsMultiTargetGenerator.h" +#include "cmGeneratedFileStream.h" + +cmLocalGhsMultiGenerator::cmLocalGhsMultiGenerator() {} + +cmLocalGhsMultiGenerator::~cmLocalGhsMultiGenerator() {} + +void cmLocalGhsMultiGenerator::Generate() { + cmGeneratorTargetsType tgts = this->GetMakefile()->GetGeneratorTargets(); + if (tgts.size() > 0) { + for (cmGeneratorTargetsType::iterator l = tgts.begin(); l != tgts.end(); + ++l) { + cmGhsMultiTargetGenerator tg(l->second->Target); + tg.Generate(); + } + } +} + +// Implemented in: +// cmLocalGenerator. +// Used in: +// Source/cmMakefile.cxx +// Source/cmGlobalGenerator.cxx +void cmLocalGhsMultiGenerator::Configure() { + // Compute the path to use when referencing the current output + // directory from the top output directory. + this->HomeRelativeOutputPath = + this->Convert(this->Makefile->GetStartOutputDirectory(), HOME_OUTPUT); + if (this->HomeRelativeOutputPath == ".") { + this->HomeRelativeOutputPath = ""; + } + this->cmLocalGenerator::Configure(); +} diff --git a/Source/cmLocalGhsMultiGenerator.h b/Source/cmLocalGhsMultiGenerator.h new file mode 100644 index 0000000..c97b03f --- /dev/null +++ b/Source/cmLocalGhsMultiGenerator.h @@ -0,0 +1,54 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2015 Geoffrey Viola <[email protected]> + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#ifndef cmLocalGhsMultiGenerator_h +#define cmLocalGhsMultiGenerator_h + +#include "cmLocalGenerator.h" + +class cmGeneratedFileStream; + +/** \class cmLocalGhsMultiGenerator + * \brief Write Green Hills MULTI project files. + * + * cmLocalGhsMultiGenerator produces a set of .gpj + * file for each target in its mirrored directory. + */ +class cmLocalGhsMultiGenerator : public cmLocalGenerator { +public: + cmLocalGhsMultiGenerator(); + + virtual ~cmLocalGhsMultiGenerator(); + + /// @returns the relative path between the HomeOutputDirectory and this + /// local generators StartOutputDirectory. + std::string GetHomeRelativeOutputPath() const { + return this->HomeRelativeOutputPath; + } + + /** + * Generate the makefile for this directory. + */ + virtual void Generate(); + + /// Overloaded methods. @see cmLocalGenerator::Configure() + virtual void Configure(); + const char *GetBuildFileName() { return BuildFileName.c_str(); } + +protected: + virtual bool CustomCommandUseLocal() const { return true; } + +private: + std::string BuildFileName; + std::string HomeRelativeOutputPath; +}; + +#endif diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 51df7f2..631397b 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" @@ -1841,6 +1842,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 49fd02b..87727c7 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1938,6 +1938,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 0000000..6e15ba9 --- /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 0000000..2adbd4e --- /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 0000000..1133834 --- /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 0000000..7bcc5f9 --- /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 0000000..9e22b5e --- /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 0000000..44c5de1 --- /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 0000000..224ec29 --- /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 0000000..9c822da --- /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 0000000..d7515d7 --- /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 0000000..00971b0 --- /dev/null +++ b/Tests/GhsMulti/ReturnNum/Lib/HelperFun.h @@ -0,0 +1 @@ +int giveNum(void); -- 2.1.4
-- Powered by www.kitware.com Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Kitware offers various services to support the CMake community. For more information on each offering, please visit: CMake Support: http://cmake.org/cmake/help/support.html CMake Consulting: http://cmake.org/cmake/help/consulting.html CMake Training Courses: http://cmake.org/cmake/help/training.html Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Follow this link to subscribe/unsubscribe: http://public.kitware.com/mailman/listinfo/cmake-developers
