Add first version of CMake framework code

This commit adds the core elements of the framework and documentation:
 - Map utility: store key-value pairs.
 - Group utility: store build configuration options.
 - STGT API: describe the targets.
 - Compiler abstraction functions for GCC.
 - Other helper functions.
 - New CMake system type called "Embedded", using correct output file
   prefixes and extensions.
 - Sphinx based documentation which includes:
    - licensing information
    - version numbering policy
    - documentation on how-to build the documentation

In addition the following utility files are added:
  - .editorconfig
  - .gitignore

Change-Id: If19a171ef066775d3544fba82f1cc70a5fb0e7d7
Signed-off-by: Balint Dobszay <balint.dobszay@arm.com>
Co-authored-by: Gyorgy Szing <gyorgy.szing@arm.com>
Co-authored-by: Bence Szépkúti <bence.szepkuti@arm.com>
diff --git a/Common/Group.cmake b/Common/Group.cmake
new file mode 100644
index 0000000..a76eb1d
--- /dev/null
+++ b/Common/Group.cmake
@@ -0,0 +1,292 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+#[===[.rst:
+Group utility file
+------------------
+Group is an unordered collection of interrelated :cmake:module:`map`\s.
+
+The main purpose of this utility is to pack a set of coherent configuration data
+description into one unit, which can be applied on a target in one step. This
+means e.g. defines, compiler flags, include paths, etc.
+
+Internally the utility uses global properties and maps. Global property
+``GROUPS.<name of group>`` is defined to indicate that the group is defined, and
+for each element in the :cmake:variable:`GROUPS_VALID_TYPES`:
+
+  * a map is created, using ``<name of group>.<type>`` as name,
+  * a global property ``GROUPS.<name of group>.<type>`` is defined to indicate
+    that the type is valid in the group.
+
+.. todo:: Investigate alternatives to global properties (name collision possible).
+.. todo:: Investigate if import/export group functions would be necessary.
+
+#]===]
+
+include_guard(DIRECTORY)
+include(Common/Map)
+include(Common/Utils)
+
+#[===[.rst:
+.. cmake:variable:: GROUPS_VALID_TYPES
+
+  List of configuration data types that can be stored in a group. The
+  implementation of :cmake:command:`group_new` creates a map for each of these
+  types automatically.
+
+#]===]
+set(GROUPS_VALID_TYPES "CONFIG;DEFINE;CFLAG;ASFLAG;LDFLAG;INCLUDE")
+
+#[===[.rst:
+.. cmake:command:: group_new
+
+  .. code-block:: cmake
+
+    group_new(NAME foo)
+
+  Create a new group.
+
+  Inputs:
+
+  ``NAME``
+    Name of the new group, use |C identifier like string|. The name must be
+    unique within the global namespace, otherwise an error is generated.
+
+#]===]
+function(group_new)
+	set(_OPTIONS_ARGS)
+	set(_ONE_VALUE_ARGS NAME)
+	set(_MULTI_VALUE_ARGS)
+	cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN})
+
+	check_args(group_new NAME)
+
+	group_is_defined(NAME ${_MY_PARAMS_NAME} RET _is_defined)
+	if(_is_defined)
+		message(FATAL_ERROR "group_new(): '${_MY_PARAMS_NAME}' is already defined.")
+	endif()
+
+	set(_null " ")
+	define_property(GLOBAL PROPERTY GROUPS.${_MY_PARAMS_NAME} BRIEF_DOCS ${_null} FULL_DOCS ${_null})
+
+	foreach(_type IN LISTS GROUPS_VALID_TYPES)
+		define_property(GLOBAL PROPERTY GROUPS.${_MY_PARAMS_NAME}.${_type} BRIEF_DOCS ${_null} FULL_DOCS ${_null})
+		map_new(NAME ${_MY_PARAMS_NAME}.${_type})
+	endforeach()
+endfunction()
+
+#[===[.rst:
+.. cmake:command:: group_is_defined
+
+  .. code-block:: cmake
+
+    group_is_defined(NAME foo RET ret)
+
+  Helper function to check if a group has been defined.
+
+  Inputs:
+
+  ``NAME``
+    Name of the group.
+
+  Outputs:
+
+  ``RET``
+    Name of the variable in the parent scope, where the return value is written.
+
+#]===]
+function(group_is_defined)
+	set(_OPTIONS_ARGS)
+	set(_ONE_VALUE_ARGS NAME RET)
+	set(_MULTI_VALUE_ARGS)
+	cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN})
+
+	check_args(group_is_defined NAME RET)
+
+	get_property(_is_defined GLOBAL PROPERTY GROUPS.${_MY_PARAMS_NAME} DEFINED)
+	set(${_MY_PARAMS_RET} ${_is_defined} PARENT_SCOPE)
+endfunction()
+
+#[===[.rst:
+.. cmake:command:: group_add
+
+  .. code-block:: cmake
+
+    group_add(NAME foo TYPE type KEY one VAL 1)
+
+  Add new key-value pair to the map called ``type`` within a group. Multiple
+  types can be defined in one function call, the key-value pair will be added to
+  each of those types.
+
+  Inputs:
+
+  ``NAME``
+    Name of the group. Trying to add to a non-existing group generates an error.
+
+  ``TYPE`` (multi)
+    Type can be one or more of the values defined in
+    :cmake:variable:`GROUPS_VALID_TYPES`.
+
+  ``KEY``
+    New key to add. Same constraints apply as described in
+    :cmake:command:`map_add`.
+
+  ``VAL`` (optional)
+    Value for new key. Same constraints apply as described in
+    :cmake:command:`map_add`.
+
+#]===]
+function(group_add)
+	set(_OPTIONS_ARGS)
+	set(_ONE_VALUE_ARGS NAME KEY VAL)
+	set(_MULTI_VALUE_ARGS TYPE)
+	cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN})
+
+	check_args(group_add NAME TYPE KEY)
+
+	group_is_defined(NAME ${_MY_PARAMS_NAME} RET _is_group_defined)
+	if(NOT _is_group_defined)
+		message(FATAL_ERROR "group_add(): '${_MY_PARAMS_NAME}' group is not defined.")
+	endif()
+
+	if(DEFINED _MY_PARAMS_VAL)
+		if(DEFINED CFG_${_MY_PARAMS_KEY})
+			set(_val ${CFG_${_MY_PARAMS_KEY}})
+			message(STATUS "group_add(): '${_MY_PARAMS_KEY}' in group '${_MY_PARAMS_NAME}' is
+							overwritten by command line parameter.")
+		else()
+			set(_val ${_MY_PARAMS_VAL})
+		endif()
+	else()
+		set(_val " ")
+	endif()
+
+	foreach(_type IN LISTS _MY_PARAMS_TYPE)
+		get_property(_is_type_defined GLOBAL PROPERTY GROUPS.${_MY_PARAMS_NAME}.${_type} DEFINED)
+		if(NOT _is_type_defined)
+			message(FATAL_ERROR "group_add(): '${_type}' type is invalid.")
+		endif()
+
+		map_add(NAME ${_MY_PARAMS_NAME}.${_type} KEY ${_MY_PARAMS_KEY} VAL ${_val})
+	endforeach()
+endfunction()
+
+#[===[.rst:
+.. cmake:command:: group_apply
+
+  .. code-block:: cmake
+
+    group_apply(NAME foo TARGETS target1 target2)
+
+  Apply a group onto the selected target(s). All settings contained in the group
+  will be added to the targets. Use this function only for the build targets
+  created with :cmake:command:`stgt_create`.
+
+  Inputs:
+
+  ``NAME``
+    Name of the group.
+
+  ``TARGETS`` (multi)
+    Name of the targets.
+
+  .. todo:: Move this to STGT?
+  .. todo:: Revise implementation for INCLUDE type.
+
+#]===]
+function(group_apply)
+	set(_OPTIONS_ARGS)
+	set(_ONE_VALUE_ARGS NAME)
+	set(_MULTI_VALUE_ARGS TARGETS)
+	cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN})
+
+	check_args(group_apply NAME TARGETS)
+
+	group_is_defined(NAME ${_MY_PARAMS_NAME} RET _is_defined)
+	if(NOT _is_defined)
+		message(FATAL_ERROR "group_apply(): '${_MY_PARAMS_NAME}' group is not defined.")
+	endif()
+
+	foreach(_target IN LISTS _MY_PARAMS_TARGETS)
+		if(NOT TARGET ${_target})
+			message(FATAL_ERROR "group_apply(): target '${_target}' is not defined.")
+		endif()
+
+		map_read(NAME ${_MY_PARAMS_NAME}.CONFIG KEYS _keys VALS _vals)
+		if(_keys AND _vals)
+			list(LENGTH _keys _count)
+			math(EXPR _count "${_count}-1")
+
+			foreach(i RANGE ${_count})
+				list(GET _keys ${i} _key)
+				list(GET _vals ${i} _val)
+				set_property(TARGET ${_target} PROPERTY ${_key} ${_val})
+			endforeach()
+		endif()
+
+		map_read(NAME ${_MY_PARAMS_NAME}.DEFINE KEYS _keys VALS _vals)
+		if(_keys AND _vals)
+			map_to_list(KEYS ${_keys} VALS ${_vals} OUT _defines)
+			target_compile_definitions(${_target} PRIVATE ${_defines})
+		endif()
+
+		map_read(NAME ${_MY_PARAMS_NAME}.CFLAG KEYS _keys VALS _vals)
+		if(_keys AND _vals)
+			map_to_list(KEYS ${_keys} VALS ${_vals} OUT _cflags)
+			target_compile_options(${_target} PRIVATE ${_cflags})
+		endif()
+
+		map_read(NAME ${_MY_PARAMS_NAME}.ASFLAG KEYS _keys VALS _vals)
+		if(_keys AND _vals)
+			map_to_list(KEYS ${_keys} VALS ${_vals} OUT _asflags)
+			target_compile_options(${_target} PRIVATE $<$<COMPILE_LANGUAGE:ASM>:${_asflags}>)
+		endif()
+
+		map_read(NAME ${_MY_PARAMS_NAME}.LDFLAG KEYS _keys VALS _vals)
+		if(_keys AND _vals)
+			map_to_list(KEYS ${_keys} VALS ${_vals} OUT _ldflags)
+			target_link_options(${_target} PRIVATE ${_ldflags})
+		endif()
+
+		map_read(NAME ${_MY_PARAMS_NAME}.INCLUDE KEYS _keys VALS _vals)
+		if(_keys)
+			stgt_add_inc_param(NAME ${_target} KEY ARCH INC ${_keys})
+		endif()
+	endforeach()
+endfunction()
+
+#[===[.rst:
+.. cmake:command:: group_print
+
+  .. code-block:: cmake
+
+    group_print(NAME foo)
+
+  Print contents of the group, for debug purposes.
+
+  Inputs:
+
+  ``NAME``
+    Name of the group.
+
+#]===]
+function(group_print)
+	set(_OPTIONS_ARGS)
+	set(_ONE_VALUE_ARGS NAME)
+	set(_MULTI_VALUE_ARGS)
+	cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN})
+
+	if (NOT DEFINED _MY_PARAMS_NAME)
+		message(FATAL_ERROR "group_print(): mandatory parameter 'NAME' missing.")
+	endif()
+
+	message("\n====Group '${_MY_PARAMS_NAME}'====")
+	foreach(_type IN LISTS GROUPS_VALID_TYPES)
+		map_print(NAME ${_MY_PARAMS_NAME}.${_type})
+	endforeach()
+	message("====Group '${_MY_PARAMS_NAME}' end====\n")
+endfunction()
\ No newline at end of file