configs.py: Refine argparse to select build command type

To make configs.py more flexible, argparse is updated as below:
1. Use "--config_params" to list the build config variables of the
   input configuration.
2. Split the "build commands" into four types: "set_compiler",
   "cmake_config", "cmake_build" and "post_build". Only print the
   required type of commands.

Signed-off-by: Xinyu Zhang <xinyu.zhang@arm.com>
Change-Id: I550eb6218fdac34d2aa634e730aba8ccfb05dd52
diff --git a/build_helper/build_helper_configs.py b/build_helper/build_helper_configs.py
index 0137a8c..4acfc43 100755
--- a/build_helper/build_helper_configs.py
+++ b/build_helper/build_helper_configs.py
@@ -71,10 +71,10 @@
     "artifact_capture_rex": (r'%(_tbm_build_dir_)s/bin'
                              r'/(\w+\.(?:axf|bin|hex))$'),
 
-    # ALL commands will be executed for every build.
-    # Other keys will append extra commands when matching target_platform
-    "build_cmds": {"all": ["cmake --build ./ -- install"],
-                   "arm/musca_b1": [("srec_cat "
+    # CMake build commands will be executed for every build.
+    "cmake_build": "cmake --build ./ -- install",
+    # Keys will append extra commands when matching target_platform
+    "post_build": {"arm/musca_b1": ("srec_cat "
                                  "%(_tbm_build_dir_)s/bin/"
                                  "bl2.bin "
                                  "-Binary -offset 0xA000000 "
@@ -84,8 +84,8 @@
                                  "-Binary -offset 0xA020000 "
                                  "-fill 0xFF 0xA020000 0xA200000 "
                                  "-o %(_tbm_build_dir_)s/bin/"
-                                 "tfm.hex -Intel")],
-                   "arm/musca_s1": [("srec_cat "
+                                 "tfm.hex -Intel"),
+                   "arm/musca_s1": ("srec_cat "
                                  "%(_tbm_build_dir_)s/bin/"
                                  "bl2.bin "
                                  "-Binary -offset 0xA000000 "
@@ -95,20 +95,20 @@
                                  "-Binary -offset 0xA020000 "
                                  "-fill 0xFF 0xA020000 0xA200000 "
                                  "-o %(_tbm_build_dir_)s/bin/"
-                                 "tfm.hex -Intel")],
-                   "stm/stm32l562e_dk": [("echo 'STM32L562E-DK board post process';"
+                                 "tfm.hex -Intel"),
+                   "stm/stm32l562e_dk": ("echo 'STM32L562E-DK board post process';"
                                           "%(_tbm_build_dir_)s/postbuild.sh;"
                                           "pushd %(_tbm_build_dir_)s;"
                                           "BIN_FILES=$(grep -o '\/.*\.bin' TFM_UPDATE.sh | sed 's/^/bin/');"
                                           "tar jcf ./bin/stm32l562e-dk-tfm.tar.bz2 regression.sh TFM_UPDATE.sh ${BIN_FILES};"
-                                          "popd")],
-                   "stm/b_u585i_iot02a": [("echo 'STM32U5 board post process';"
+                                          "popd"),
+                   "stm/b_u585i_iot02a": ("echo 'STM32U5 board post process';"
                                           "%(_tbm_build_dir_)s/postbuild.sh;"
                                           "pushd %(_tbm_build_dir_)s;"
                                           "BIN_FILES=$(grep -o '\/.*\.bin' TFM_UPDATE.sh | sed 's/^/bin/');"
                                           "tar jcf ./bin/b_u585i_iot02a-tfm.tar.bz2 regression.sh TFM_UPDATE.sh ${BIN_FILES};"
-                                          "popd")],
-                  "nxp/lpcxpresso55s69": [("echo 'LPCXpresso55S69 board post process\n';"
+                                          "popd"),
+                  "nxp/lpcxpresso55s69": ("echo 'LPCXpresso55S69 board post process\n';"
                                             "if [ -f \"%(_tbm_build_dir_)s/bin/bl2.hex\" ]; then FLASH_FILE='flash_bl2_JLink.py'; else FLASH_FILE='flash_JLink.py'; fi;"
                                             "pushd %(_tbm_build_dir_)s/../platform/ext/target/nxp/lpcxpresso55s69/scripts;"
                                             "LN=$(grep -n 'JLinkExe' ${FLASH_FILE}|awk -F: '{print $1}');"
@@ -117,8 +117,8 @@
                                             "cd %(_tbm_build_dir_)s/bin;"
                                             "BIN_FILES=$(grep loadfile flash.jlink | awk '{print $2}');"
                                             "tar jcf lpcxpresso55s69-tfm.tar.bz2 flash.jlink ${BIN_FILES};"
-                                            "popd")],
-                   "cypress/psoc64": [("echo 'Sign binaries for Cypress PSoC64 platform';"
+                                            "popd"),
+                   "cypress/psoc64": ("echo 'Sign binaries for Cypress PSoC64 platform';"
                                        "pushd %(_tbm_build_dir_)s/..;"
                                        "sudo /usr/local/bin/cysecuretools "
                                        "--policy platform/ext/target/cypress/psoc64/security/policy/policy_multi_CM0_CM4_tfm.json "
@@ -134,7 +134,7 @@
                                        "--image-type BOOT --image-id 16;"
                                        "mv %(_tbm_build_dir_)s/bin/tfm_s.hex %(_tbm_build_dir_)s/bin/tfm_s_signed.hex;"
                                        "mv %(_tbm_build_dir_)s/bin/tfm_ns.hex %(_tbm_build_dir_)s/bin/tfm_ns_signed.hex;"
-                                       "popd")]
+                                       "popd")
                    },
 
     # (Optional) If set will fail if those artefacts are missing post build
diff --git a/configs.py b/configs.py
index 61fc4b2..faef7f2 100755
--- a/configs.py
+++ b/configs.py
@@ -44,16 +44,19 @@
     return build_manager.get_config()
 
 
-def print_config_environment(config, group=None, silence_stderr=False):
+def print_build_configs(config, group=None, silence_stderr=False):
     """Prints particular configuration environment variables"""
     build_manager = get_build_manager(group)
-    build_manager.print_config_environment(config, silence_stderr=silence_stderr)
+    params = build_manager.get_build_configs(config, silence_stderr=silence_stderr)
+    for name in params:
+        print("{}={}".format(name, params[name]))
 
 
-def print_build_commands(config, group=None, jobs=None):
-    """Prints particular configuration environment variables"""
+def print_build_commands(config, cmd_type, group=None, jobs=None):
+    """Prints particular commands to be run"""
     build_manager = get_build_manager(group)
-    build_manager.print_build_commands(config, silence_stderr=True, jobs=jobs)
+    cmd = build_manager.get_build_commands(config, silence_stderr=True, jobs=jobs)
+    print(cmd[cmd_type])
 
 
 if __name__ == "__main__":
@@ -70,9 +73,14 @@
         "-b",
         "--build_commands",
         default=None,
+        choices=['set_compiler', 'cmake_config', 'cmake_build', 'post_build'],
+        help="Print selected type of build commands to be run for current configuration."
+    )
+    PARSER.add_argument(
+        "--config_params",
+        default=None,
         action='store_true',
-        help="Instead of printing environment variables, print raw "
-        "build commands to be run."
+        help="List config parameters of current configuration."
     )
     PARSER.add_argument(
         "-g",
@@ -100,11 +108,12 @@
             all_configs.update(list_configs(group))
         else:
             try:
-                if not ARGS.build_commands:
-                    print_config_environment(ARGS.config, group=group, silence_stderr=True)
-                else:
-                    print_build_commands(ARGS.config, group=group, jobs=ARGS.jobs)
-                break
+                if ARGS.config_params:
+                    print_build_configs(ARGS.config, group=group, silence_stderr=True)
+                    break
+                if ARGS.build_commands:
+                    print_build_commands(ARGS.config, ARGS.build_commands, group=group, jobs=ARGS.jobs)
+                    break
             except (SystemExit, KeyError):
                 if group == ARGS.group[-1] or ARGS.group == []:
                     print(
diff --git a/eclair/utils_tfm.sh b/eclair/utils_tfm.sh
index 783e036..c2f4301 100644
--- a/eclair/utils_tfm.sh
+++ b/eclair/utils_tfm.sh
@@ -1,4 +1,4 @@
 eclair_tfm_set_toolchain_path() {
-    path_cmd=$(python3 tf-m-ci-scripts/configs.py -b -g all $CONFIG_NAME | head -n1)
+    path_cmd=$(python3 tf-m-ci-scripts/configs.py -b set_compiler $CONFIG_NAME)
     eval $path_cmd
 }
diff --git a/jenkins/ci.jpl b/jenkins/ci.jpl
index 7678e2b..a6c95c3 100644
--- a/jenkins/ci.jpl
+++ b/jenkins/ci.jpl
@@ -68,7 +68,7 @@
   def build_params = [:]
   build_config_params = sh(script:
     """
-    python3 ./tf-m-ci-scripts/configs.py ${config}\n
+    python3 ./tf-m-ci-scripts/configs.py --config_params ${config}\n
     """, returnStdout: true).trim()
   def lines = build_config_params.tokenize('\n')
   for (String line : lines) {
diff --git a/run-build.sh b/run-build.sh
index d3db1ff..f114702 100755
--- a/run-build.sh
+++ b/run-build.sh
@@ -16,10 +16,15 @@
 set -ex
 
 if [ -z "$CONFIG_NAME" ] ; then
-	echo "Set CONFIG_NAME to run a build."
-	exit 1
+    echo "Set CONFIG_NAME to run a build."
+    exit 1
 fi
 
+set_compiler_cmd=$(python3 tf-m-ci-scripts/configs.py -b set_compiler $CONFIG_NAME)
+cmake_config_cmd=$(python3 tf-m-ci-scripts/configs.py -b cmake_config $CONFIG_NAME)
+cmake_build_cmd=$(python3 tf-m-ci-scripts/configs.py -b cmake_build -j ${BUILD_JOBS:-2} $CONFIG_NAME)
+post_build_cmd=$(python3 tf-m-ci-scripts/configs.py -b post_build $CONFIG_NAME)
+
 set +e
 echo "output current build environment"
 cat /etc/issue
@@ -30,36 +35,41 @@
 make --version
 
 set -ex
-build_commands=$(python3 tf-m-ci-scripts/configs.py -b -g all -j ${BUILD_JOBS:-2} $CONFIG_NAME)
+eval $set_compiler_cmd
 
 if [ -n "$BUILD_TARGET" ]; then
-    build_commands=$(echo "$build_commands" | head -4)
-    build_commands=${build_commands/-- install/-- $BUILD_TARGET}
+    cmake_build_cmd=$(echo "$cmake_build_cmd" | head -4)
+    cmake_build_cmd=${cmake_build_cmd/-- install/-- $BUILD_TARGET}
 fi
 
 if [ $CODE_COVERAGE_EN = "TRUE" ] && [[ $CONFIG_NAME =~ "GCC" ]] ; then
-    build_commands=${build_commands/toolchain_GNUARM.cmake/toolchain_GNUARM.cmake -DTFM_CODE_COVERAGE=True}
+    cmake_config_cmd=${cmake_config_cmd/toolchain_GNUARM.cmake/toolchain_GNUARM.cmake -DTFM_CODE_COVERAGE=True}
     echo "Flag: Add compiler flag for build with code coverage supported."
-    echo $build_commands
+    echo $cmake_config_cmd
 fi
 
-if [ -z "$build_commands" ] ; then
-	echo "No build commands found."
-	exit 1
+if [ -z "$cmake_config_cmd" ] ; then
+    echo "No CMake config commands found."
+    exit 1
+fi
+
+if [ -z "$cmake_build_cmd" ] ; then
+    echo "No build image commands found."
+    exit 1
 fi
 
 cnt=$(ls trusted-firmware-m/lib/ext/mbedcrypto/*.patch 2> /dev/null | wc -l)
 if [ "$cnt" != "0" ] ; then
-	cd mbedtls
-	git apply ../trusted-firmware-m/lib/ext/mbedcrypto/*.patch
-	cd -
+    cd mbedtls
+    git apply ../trusted-firmware-m/lib/ext/mbedcrypto/*.patch
+    cd -
 fi
 
 cnt=$(ls trusted-firmware-m/lib/ext/psa_arch_tests/*.patch 2> /dev/null | wc -l)
 if [ "$cnt" != "0" ] ; then
-	cd psa-arch-tests
-	git apply ../trusted-firmware-m/lib/ext/psa_arch_tests/*.patch
-	cd -
+    cd psa-arch-tests
+    git apply ../trusted-firmware-m/lib/ext/psa_arch_tests/*.patch
+    cd -
 fi
 
 cd trusted-firmware-m
@@ -70,4 +80,4 @@
 mkdir trusted-firmware-m/build
 cd trusted-firmware-m/build
 
-eval "set -ex ; $build_commands"
+eval "set -ex ; $cmake_config_cmd; $cmake_build_cmd; $post_build_cmd"
diff --git a/tfm_ci_pylib/tfm_build_manager.py b/tfm_ci_pylib/tfm_build_manager.py
index de3cbce..53ef5c6 100644
--- a/tfm_ci_pylib/tfm_build_manager.py
+++ b/tfm_ci_pylib/tfm_build_manager.py
@@ -100,46 +100,33 @@
     def get_config(self):
             return list(self._tbm_build_cfg.keys())
 
-    def print_config_environment(self, config, silence_stderr=False):
+    def get_build_configs(self, config, silence_stderr=False):
         """
-        For a given build configuration from output of print_config
-        method, print environment variables to build.
+        Return build config variables needed by the input config.
         """
         if config not in self._tbm_build_cfg:
             if not silence_stderr:
                 print("Error: no such config {}".format(config), file=sys.stderr)
             sys.exit(1)
         config_details = self._tbm_build_cfg[config]
-        argument_list = [
-            "CONFIG_NAME={}",
-            "TFM_PLATFORM={}",
-            "COMPILER={}",
-            "ISOLATION_LEVEL={}",
-            "TEST_REGRESSION={}",
-            "TEST_PSA_API={}",
-            "CMAKE_BUILD_TYPE={}",
-            "BL2={}",
-            "PROFILE={}",
-            "EXTRA_PARAMS={}"
-        ]
-        print(
-            "\n".join(argument_list)
-            .format(
-                config,
-                config_details.tfm_platform,
-                config_details.compiler,
-                config_details.isolation_level,
-                config_details.test_regression,
-                config_details.test_psa_api,
-                config_details.cmake_build_type,
-                config_details.with_bl2,
-                "N.A" if not config_details.profile else config_details.profile,
-                "N.A" if not config_details.extra_params else config_details.extra_params,
-            )
-            .strip()
-        )
+        config_params = {
+            "CONFIG_NAME":      config,
+            "TFM_PLATFORM":     config_details.tfm_platform,
+            "COMPILER":         config_details.compiler,
+            "ISOLATION_LEVEL":  config_details.isolation_level,
+            "TEST_REGRESSION":  config_details.test_regression,
+            "TEST_PSA_API":     config_details.test_psa_api,
+            "CMAKE_BUILD_TYPE": config_details.cmake_build_type,
+            "BL2":              config_details.with_bl2,
+            "PROFILE":          "N.A" if not config_details.profile else config_details.profile,
+            "EXTRA_PARAMS":     "N.A" if not config_details.extra_params else config_details.extra_params,
+        }
+        return config_params
 
-    def print_build_commands(self, config, silence_stderr=False, jobs=None):
+    def get_build_commands(self, config, silence_stderr=False, jobs=None):
+        """
+        Return selected type of commands to be run to build the input config.
+        """
         config_details = self._tbm_build_cfg[config]
         codebase_dir = os.path.join(os.getcwd(),"trusted-firmware-m")
         build_dir=os.path.join(os.getcwd(),"trusted-firmware-m/build")
@@ -148,11 +135,13 @@
                                              build_dir=build_dir, \
                                              codebase_dir=codebase_dir, \
                                              jobs=jobs)
-        build_commands = [build_config["set_compiler_path"], \
-                          build_config["config_template"]]
-        for command in build_config["build_cmds"]:
-            build_commands.append(command)
-        print(" ;\n".join(build_commands))
+        build_commands = {
+            'set_compiler': build_config['set_compiler_path'],
+            'cmake_config': build_config['config_template'],
+            'cmake_build':  build_config['cmake_build'],
+            'post_build':   build_config['post_build']
+        }
+        return build_commands
 
     def pre_eval(self):
         """ Tests that need to be run in set-up state """
@@ -248,11 +237,10 @@
             build_cfg = deepcopy(self.tbm_common_cfg)
 
             # Extract the common for all elements of config
-            for key in ["build_cmds", "required_artefacts"]:
-                try:
-                    build_cfg[key] = build_cfg[key]["all"]
-                except KeyError:
-                    build_cfg[key] = []
+            try:
+                build_cfg["required_artefacts"] = build_cfg["required_artefacts"]["all"]
+            except KeyError:
+                build_cfg["required_artefacts"] = []
             name = build_cfg["config_type"]
 
             # Override _tbm_xxx paths in commands
@@ -263,7 +251,7 @@
                          "_tbm_code_dir_": build_cfg["codebase_root_dir"]}
 
             build_cfg = self.override_tbm_cfg_params(build_cfg,
-                                                     ["build_cmds",
+                                                     ["post_build",
                                                       "required_artefacts",
                                                       "artifact_capture_rex"],
                                                      **over_dict)
@@ -363,14 +351,13 @@
             # However, many things use this from build_cfg elsewhere
             build_cfg["codebase_root_dir"] = codebase_dir
         # Extract the common for all elements of config
-        for key in ["build_cmds", "required_artefacts"]:
-            try:
-                build_cfg[key] = deepcopy(self.tbm_common_cfg[key]
-                                          ["all"])
-            except KeyError as E:
-                build_cfg[key] = []
+        try:
+            build_cfg["required_artefacts"] = deepcopy(self.tbm_common_cfg["required_artefacts"]["all"])
+        except KeyError as E:
+            build_cfg["required_artefacts"] = []
+        build_cfg["post_build"] = ""
         # Extract the platform specific elements of config
-        for key in ["build_cmds", "required_artefacts"]:
+        for key in ["post_build", "required_artefacts"]:
             try:
                 if i.tfm_platform in self.tbm_common_cfg[key].keys():
                     build_cfg[key] += deepcopy(self.tbm_common_cfg[key]
@@ -387,7 +374,7 @@
                 jobs = os.cpu_count()
 
         thread_no = " -j {} ".format(jobs)
-        build_cfg["build_cmds"][0] += thread_no
+        build_cfg["cmake_build"] += thread_no
 
         # Overwrite command lines to set compiler
         build_cfg["set_compiler_path"] %= {"compiler": i.compiler}
@@ -414,9 +401,7 @@
         if i.tfm_platform == "arm/musca_b1":
             overwrite_params["test_psa_api"] += " -DOTP_NV_COUNTERS_RAM_EMULATION=ON"
         build_cfg["config_template"] %= overwrite_params
-        if len(build_cfg["build_cmds"]) > 1:
-            overwrite_build_dir = {"_tbm_build_dir_": build_dir}
-            build_cfg["build_cmds"][1] %= overwrite_build_dir
+        build_cfg["post_build"] %= {"_tbm_build_dir_": build_dir}
 
         return build_cfg