|
- #!/usr/bin/env python3
- # -*- coding: utf-8; mode: python; tab-width: 4; indent-tabs-mode: nil -*-
- # vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 fileencoding=utf-8
- #
- # THIS FILE IS PART OF adtools PROJECT
- #
- # DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
- # Version 2, December 2004
- #
- # Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
- #
- # Everyone is permitted to copy and distribute verbatim or modified
- # copies of this license document, and changing it is allowed as long
- # as the name is changed.
- #
- # DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
- # TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
- #
- # 0. You just DO WHAT THE FUCK YOU WANT TO.
-
- import os
- import sys
- import argparse
- import textwrap
- import re
- import inspect
- import traceback
- import glob
-
- import crayons
-
- from .__init__ import __version__
- from .adutil import AdUtil, Logger, WorkspaceHelper, TripletHelper, W, E, D
- from .adgit import AdGitHelper
-
- SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
-
-
- class VersionSourceWrapper:
- DEFAULT_VERSION_FILE = "version"
-
- def __init__(self, args):
- self._args = args
- self._file_content = None
- self._file_path = None
-
- def __enter__(self):
- if not self._args.gen_version:
- return
- else:
- gh = AdGitHelper()
- file_name = os.path.join(
- "source", "{}.cpp".format(VersionSourceWrapper.DEFAULT_VERSION_FILE)
- )
- self._file_path = os.path.join(self._args.dir, file_name)
- if not os.path.isfile(self._file_path):
- W(
- crayons.yellow(
- f"The required version definition file is missing: <{self._file_path}>"
- )
- )
- return
-
- version_info = gh.get_revision(cur_dir=self._args.dir)
- if not version_info:
- W(
- crayons.yellow(
- f"Failed to generate the version string for <{self._file_path}>"
- )
- )
- return
-
- if "short_commit" not in version_info:
- ver = f"{version_info['version']}-({version_info['commit']})"
- else:
- ver = f"{version_info['version']}-({version_info['short_commit']})"
-
- self._file_content = open(self._file_path).read()
- m = re.sub(
- r"(.*)std::string\s+VersionString(.*)",
- rf'\1std::string VersionString = "{ver}";',
- self._file_content,
- )
- open(self._file_path, "w+").write(m)
-
- def __exit__(self, exc_type, exc_val, traceback):
- # Recover the file content
- if self._file_content:
- open(self._file_path, "w+").write(self._file_content)
- return True
-
-
- class Command:
- def __init__(self):
- self.ws_helper = WorkspaceHelper()
- self.__build_dir_name = ".build"
- self.__package_dir_name = ".package"
-
- def help(self, *args) -> int:
- """Shows help for a specific command"""
- parser = argparse.ArgumentParser(
- description=self.help.__doc__, prog="admake help"
- )
- parser.add_argument("command", help="command", nargs="?")
- args = parser.parse_args(*args)
- if not args.command:
- self._show_help()
- return
-
- cmds = self._commands()
- if args.command in cmds:
- return cmds[args.command](["--help"])
- else:
- W(crayons.yellow(f"Command <{args.command}> is unsupported!"))
- return -1
-
- def _get_build_dirname(self, args):
- if not args.platform:
- args.platform = AdUtil.arch()
-
- base_dir = f"{args.os}_{args.platform}"
- build_dir = "{}{}{}".format(
- base_dir,
- "_release" if args.release else "_debug",
- "_test" if args.build_test else "",
- )
- return build_dir
-
- def _build_dir(self, args):
- build_dir = self._get_build_dirname(args)
- build_dir = os.path.join(self.__build_dir_name, build_dir)
-
- return os.path.join(os.path.abspath(args.dir), build_dir)
-
- def _pkg_dir(self, args):
- return os.path.join(os.path.abspath(args.dir), self.__package_dir_name).replace(
- "\\", "/"
- )
-
- def _construct_cmake_macros(self, unknown_args: list) -> list:
- # Construct unknown arguments as -D options for CMake
- other_cmake_macros = []
- unknown_args_len = len(unknown_args)
- if unknown_args_len > 0:
- idx = 0
- while idx < unknown_args_len:
- cur_arg = unknown_args[idx].strip()
- if cur_arg.startswith("--") and len(cur_arg) > 2 and cur_arg[2] != "-":
- cur_arg = cur_arg[2:].replace("-", "_").upper()
- opt = f"-DADMAKE_{cur_arg}"
- if idx + 1 < unknown_args_len:
- opt_cur_arg = unknown_args[idx + 1].strip()
- if not opt_cur_arg.startwith("-"):
- opt += f'="{opt_cur_arg}"'
- idx += 1
- else:
- opt += ":BOOL=ON"
- else:
- opt += ":BOOL=ON"
-
- other_cmake_macros.append(opt)
- idx += 1
- return other_cmake_macros
-
- def _do_build(self, cmd_name: str = "build", *args_) -> int:
- """
- Do build for build and rebuild
- """
- parser = argparse.ArgumentParser(
- description=self.build.__doc__
- if cmd_name == "build"
- else self.rebuild.__doc__,
- prog=f"admake {cmd_name}",
- )
- # TODO(donkey): *BSD, ChromeOS, iOS
- parser.add_argument(
- "-d",
- "--dir",
- default=".",
- help="Specify the directory contains the CMakeLists.txt",
- )
- parser.add_argument(
- "-v",
- "--verbose",
- action="store_true",
- default=False,
- help="Output the verbose information in the building progress",
- )
- parser.add_argument(
- "-o",
- "--os",
- default=AdUtil.SYSTEM.lower(),
- help="Target operating system. Supported operating systems : {}".format(
- ", ".join(
- ["windows", "linux", "android", "qnx", "darwin", "none", "unknonw"]
- )
- ),
- )
- parser.add_argument(
- "-p",
- "--platform",
- default="",
- help="The default value is different in different OSs.\n",
- )
- parser.add_argument(
- "-t",
- "--build-test",
- action="store_true",
- help="Build the test project with the static library.",
- )
- parser.add_argument(
- "-c",
- "--cc",
- default="",
- help="Specify the default compiling toolchain, such as: gcc, gcc-7, llvm, llvm-14, msvc, msvc-vs2019",
- )
- parser.add_argument(
- "--ccjson",
- action="store_true",
- help="Generate compile_commands.json in the project root directory.",
- )
- parser.add_argument(
- "-a",
- "--toolchain",
- default="",
- help="Specify the CMake TOOLCHAIN_FILE_PATH, if this option only contains a file name, admake will search it in CMAKE_MODULE_PATH.",
- )
- parser.add_argument(
- "-D",
- default=[],
- action="append",
- help="-D argument pass to CMake, e.g: -DENABLE_LOG -DTEST_BUILD=1",
- )
- parser.add_argument(
- "-r", "--release", action="store_true", help="Build release edition"
- )
- parser.add_argument(
- "-m",
- "--macro",
- default=[],
- action="append",
- help="C/C++ macros pass to compilers, e.g: -m BUILD_UNIT_TEST",
- )
- parser.add_argument(
- "-g",
- "--gen-version",
- action="store_true",
- default=False,
- help="Attempt to generate version information",
- )
- parser.add_argument(
- "--cmake-generator",
- default="",
- help="Specify the cmake generator, used by automatical derivation",
- )
-
- args, unknown_args = parser.parse_known_args(*args_)
-
- if args.verbose:
- Logger.get_instance().enable()
-
- args.dir = os.path.abspath(args.dir)
-
- with AdUtil.chdir(args.dir):
- if not os.path.isfile("CMakeLists.txt"):
- E(crayons.red("Required CMakeLists.txt is not existent!"))
- return -1
-
- other_cmake_macros = self._construct_cmake_macros(unknown_args)
- other_cmake_macros.extend([f"-D{d}" for d in args.D])
-
- th = TripletHelper(self.ws_helper, args.dir)
- tool = th.load(
- arch=args.platform,
- os=args.os,
- cc=args.cc,
- cmg=args.cmake_generator,
- toolchain=args.toolchain,
- )
- if not tool:
- E(crayons.red("Failed to load toolchain."))
- return -1
-
- build_dir = self._build_dir(args)
- cfg = "Release" if args.release else "Debug"
- rebuild = cmd_name == "rebuild"
-
- with AdUtil.chdir(args.dir):
- if rebuild:
- AdUtil.remove(build_dir)
-
- AdUtil.mkdirs(build_dir)
-
- cmake_macros_list = [
- f'-DADMAKE_BUILD_DIR="{build_dir}"',
- "-DADMAKE_BUILD_TEST:BOOL=ON" if args.build_test else "",
- f'-DADMAKE_OS="{args.os}"',
- f'-DADMAKE_PLATFORM="{args.platform}"',
- ]
-
- cmake_macros_list.extend(other_cmake_macros)
- cmake_macros = " ".join(cmake_macros_list)
-
- args.macro.append(f"OS_{args.os.upper()}")
-
- lang_macros = '-DCUSTOM_MACROS:LIST="{}"'.format(";".join(args.macro))
-
- pkg_dir = self._pkg_dir(args)
- cmake_cmd_list = [
- f'cmake --no-warn-unused-cli -S "{args.dir}"',
- f'-B "{build_dir}"',
- f'-DCMAKE_INSTALL_PREFIX="{pkg_dir}"',
- "-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON" if args.verbose else "",
- "-DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=ON" if args.ccjson else "",
- f"-DCMAKE_BUILD_TYPE={cfg}",
- '-DCMAKE_MODULE_PATH="{}/cmake"'.format(SCRIPT_DIR.replace("\\", "/")),
- cmake_macros,
- lang_macros,
- tool.additional,
- f'-G "{tool.generator}"',
- ]
-
- with VersionSourceWrapper(args):
- # Run `cmake`
- code, msg = AdUtil.run_command(cmake_cmd_list)
- if code != 0:
- E(crayons.red(f"Failed to call cmake\n{msg}"))
- return code
- else:
- # Run `make`
- code, msg = AdUtil.run_command(tool.make_command(build_dir, cfg))
- if code != 0:
- E(crayons.red(f"Failed to build target\n{msg}"))
- return code
-
- # For some editors, compile_commands.json is very useful,
- # so we attempt to create symbolic to compile_commands.json
- # if it exists.
- ccjson_path = os.path.join(build_dir, "compile_commands.json")
- if os.path.isfile(ccjson_path):
- # Delete the old symbolic link before create new one
- oldone = os.path.join(args.dir, "compile_commands.json")
- if os.path.exists(oldone):
- AdUtil.remove(oldone)
- AdUtil.mklink(ccjson_path, oldone)
- D(
- crayons.blue(
- f"Create symbolic link compile_commands.json -> {ccjson_path}"
- )
- )
-
- return 0
-
- def build(self, *args) -> int:
- """
- Build current project with the specific toolchain.
- """
- return self._do_build("build", *args)
-
- def coverage(self, *args_) -> int:
- """
- Generate coverage report for this project
- """
- parser = argparse.ArgumentParser(
- description=self.coverage.__doc__, prog=f"admake coverage"
- )
-
- parser.add_argument(
- "-d",
- "--dir",
- default=".",
- help="Specify the directory contains the CMakeLists.txt",
- )
- parser.add_argument(
- "-v",
- "--verbose",
- action="store_true",
- default=False,
- help="Output the verbose information in the building progress",
- )
- parser.add_argument(
- "-q",
- "--quiet",
- action="store_true",
- default=False,
- help="Do not print progress messages",
- )
- parser.add_argument(
- "-s",
- "--source",
- action="store_true",
- default=False,
- help="Generate the source pages",
- )
- parser.add_argument(
- "-o",
- "--os",
- default=AdUtil.SYSTEM.lower(),
- help="Target operating system. Supported operating systems : {}".format(
- ", ".join(
- ["windows", "linux", "android", "qnx", "darwin", "none", "unknonw"]
- )
- ),
- )
- parser.add_argument(
- "-p",
- "--platform",
- default="",
- help="The default value is different in different OSs.\n",
- )
- parser.add_argument(
- "-t", "--build-test", action="store_true", help="For the test project."
- )
- parser.add_argument(
- "-r", "--release", action="store_true", help="For the release version"
- )
- parser.add_argument(
- "--output",
- default="coverage-report",
- help="The output directory of the coverage-report, default: <PROJECT>/coverage-report",
- )
-
- args, unknown_args = parser.parse_known_args(*args_)
-
- if args.verbose:
- Logger.get_instance().enable()
-
- # TODO: LLVM support
- # Check programs
- for p in ["lcov", "genhtml"]:
- if not AdUtil.command_exists(p):
- print(crayons.red(f"The required command {p} is not existent!"))
- return -1
-
- args.dir = os.path.abspath(args.dir)
-
- build_dir = self._build_dir(args)
-
- title = os.path.basename(args.dir)
-
- with AdUtil.chdir(args.dir):
- output_dir = os.path.abspath(args.output)
- AdUtil.mkdirs(output_dir)
-
- cmd_list = [
- "lcov",
- "--quiet" if args.quiet else "",
- "--rc lcov_branch_coverage=1",
- "--no-external",
- f"--directory {build_dir}",
- f"--base-directory {args.dir}",
- # Ignore all the unit test cases
- "--exclude '*test/*'",
- "--capture",
- f"--output-file {output_dir}/{title}.info",
- ]
-
- code, r = AdUtil.run_command(cmd_list, True)
-
- if code != 0:
- print(crayons.red(f"Failed to run command lcov: {r}"))
- return -1
-
- cmd_list = [
- "genhtml",
- "--no-source" if not args.source else "",
- "--quiet" if args.quiet else "",
- "--branch-coverage",
- "--demangle-cpp",
- "--sort",
- "--highlight",
- "--legend",
- f"--title '{title}'",
- f"-o {output_dir}",
- f"{output_dir}/{title}.info",
- ]
-
- code, r = AdUtil.run_command(cmd_list)
-
- if code != 0:
- print(crayons.red(f"Failed to run command genhtml: {r}"))
- return -1
-
- return 0
-
- def rebuild(self, *args) -> int:
- """
- Rebuild the project
- """
- return self._do_build("rebuild", *args)
-
- def export(self, *args_) -> int:
- """
- Export current project as an independent project
- """
- parser = argparse.ArgumentParser(
- description=self.export.__doc__, prog="admake export"
- )
-
- parser.add_argument(
- "-d", "--dir", default=".", help="Specify the project root directory"
- )
-
- args = parser.parse_args(*args_)
-
- # Collect all the dependencies, pack as thirdparty libraries
- return 0
-
- def publish(self, *args_) -> int:
- """
- Publish the project to a specific NEXUS 3 server
- """
- parser = argparse.ArgumentParser(
- description=self.export.__doc__, prog="admake publish"
- )
-
- parser.add_argument(
- "-d",
- "--dir",
- default=".",
- help="Specify the directory contains the CMakeLists.txt.",
- )
-
- parser.add_argument(
- "-n", "--name", help="Specify the output name of your package."
- )
-
- parser.add_argument(
- "-o",
- "--os",
- default=AdUtil.SYSTEM.lower(),
- help="Target operating system. Supported operating systems : {}".format(
- ", ".join(
- ["windows", "linux", "android", "qnx", "darwin", "none", "unknonw"]
- )
- ),
- )
- parser.add_argument(
- "-p",
- "--platform",
- default="",
- help="The default value is different in different OSs.\n",
- )
- parser.add_argument(
- "-r", "--release", action="store_true", help="Build release edition"
- )
- parser.add_argument(
- "-t",
- "--build-test",
- action="store_true",
- help="Build the test project with the static library.",
- )
- parser.add_argument(
- "-l",
- "--other",
- default="",
- help="Publish to the local 3rd-party repository with a specific name.",
- )
- parser.add_argument(
- "-m",
- "--module",
- default="",
- help="Publish to the local module repository with a specific name.",
- )
-
- args = parser.parse_args(*args_)
- args.dir = os.path.abspath(args.dir)
-
- build_dir = self._build_dir(args).replace("\\", "/")
- cfg = "Release" if args.release else "Debug"
-
- # The same as "cmake --install <BUILD_DIR> --config <CONFIG>"
- code, msg = AdUtil.run_command(
- f'cmake --build "{build_dir}" --target install --config {cfg}'
- )
-
- if code != 0:
- E(crayons.red(f"Failed to run the install target.\n{msg}"))
- return -1
-
- pkg_dir = self._pkg_dir(args)
-
- if args.module:
- if self.ws_helper.add_to_ws(path=pkg_dir, alias=args.module):
- print(crayons.green(f"Append {args.module} to workspace"))
- else:
- print(crayons.red(f"Failed to append {args.other} to workspace"))
-
- if args.other:
- if self.ws_helper.add_to_thirdparty(pkg_dir, alias=args.other):
- print(crayons.green(f"Append {args.other} to 3rd-party"))
- else:
- print(crayons.red(f"Failed to append {args.other} to 3rd-party"))
-
- # Publish the library to NEXUS3
- return 0
-
- def ws(self, *args_) -> int:
- """
- Manages a workspace (a set of packages consumed from the user workspace that
- belongs to the same project).
- """
- parser = argparse.ArgumentParser(description=self.ws.__doc__, prog="admake ws")
- parser.add_argument(
- "-l", "--list", action="store_true", help="List all the available workspace"
- )
- parser.add_argument(
- "-x", "--switch", default="", help="Switch to specific workspace"
- )
- parser.add_argument("-c", "--create", nargs="+", help="Create a new workspace")
- parser.add_argument(
- "-r", "--remove", nargs="+", help="Remove the specific workspace"
- )
- parser.add_argument("-d", "--clear", nargs="+", help="Clear the workspace")
- parser.add_argument(
- "-t",
- "--tree",
- action="store_true",
- help="List all the modules in CURRENT workspace",
- )
- args = parser.parse_args(*args_)
-
- if len(*args_) == 0:
- parser.print_help()
- return 0
-
- if args.list:
- cur_ws_name = self.ws_helper.current_ws_name
- lw = self.ws_helper.list_all()
-
- print(crayons.blue("All available workspaces:"))
- for name in lw:
- if name == cur_ws_name:
- print(f" {name}", crayons.green("(CURRENT)"))
- else:
- print(f" {name}")
- return 0
-
- if args.switch:
- self.ws_helper.switchto(args.switch)
- return
-
- if args.tree:
- print(crayons.blue("Modules in CURRENT workspace:"))
- for m in self.ws_helper.list_children():
- print(crayons.green(f" {m}"))
- return
-
- if args.clear:
- for name in args.clear:
- self.ws_helper.clear_ws(name)
-
- if args.create:
- for name in args.create:
- self.ws_helper.create_ws(name)
-
- if args.remove:
- for name in args.remove:
- self.ws_helper.remove_ws(name)
-
- return 0
-
- def mark(self, *args_) -> int:
- """
- Modules and Thirdparty packages manager
- """
- parser = argparse.ArgumentParser(
- description=self.mark.__doc__, prog="admake mark"
- )
- parser.add_argument(
- "-w",
- "--ws",
- default="",
- help="Specify the target workspace, default: CURRENT",
- )
- parser.add_argument(
- "-l",
- "--list",
- action="store_true",
- help="List all the modules in specific workspace and 3rd-party",
- )
- parser.add_argument(
- "-d",
- "--directory",
- nargs="*",
- action="append",
- help="Specify the directory which sub-directories will should be marked as admake modules.",
- )
- parser.add_argument(
- "-m",
- "--module",
- nargs="*",
- action="append",
- help="Specify the directories which will should be marked as admake modules",
- )
- parser.add_argument(
- "-o",
- "--other",
- nargs="*",
- action="append",
- help="Specify the directories which will should be marked as admake 3rd-party modules",
- )
- parser.add_argument(
- "-x",
- "--remove",
- action="store_true",
- help="Remove existent admake modules/3rd-party modules",
- )
- args = parser.parse_args(*args_)
-
- if len(*args_) == 0:
- parser.print_help()
- return 0
-
- if args.remove and args.directory:
- print(
- crayons.red(
- "[ERROR] --remove and --directory can not be set at the same time."
- )
- )
- return -1
-
- ws_name = self.ws_helper.current_ws_name
- if args.ws:
- ws_name = args.ws
-
- if args.list:
- print(
- crayons.green("Modules in"),
- crayons.blue(ws_name),
- crayons.green("workspace:"),
- )
- for m in self.ws_helper.list_children(args.ws):
- print(crayons.blue(f" {m}"))
- print(crayons.cyan("\nTHirdparty modules:"))
- for m in self.ws_helper.list_thirdparty():
- print(crayons.green(f" {m}"))
- return 0
-
- modules = []
-
- if args.directory:
- for sdir in args.directory:
- for sub_dir in sdir:
- sub_dir = os.path.abspath(sub_dir)
- if not os.path.isdir(sub_dir):
- continue
- for ssdir in os.listdir(sub_dir):
- absdir = os.path.abspath(os.path.join(sub_dir, ssdir))
- if not os.path.isdir(absdir):
- continue
- modules.append(absdir)
-
- if args.module:
- for sub_mod in args.module:
- modules.extend(sub_mod)
-
- others = []
-
- if args.other:
- for sub_mod in args.other:
- others.extend(sub_mod)
-
- if args.remove:
- for m in modules:
- self.ws_helper.remove_from_ws(m, args.ws)
- print(
- crayons.yellow("Remove module"),
- crayons.green(os.path.basename(m)),
- crayons.yellow("from"),
- crayons.cyan(ws_name),
- )
-
- for m in others:
- self.ws_helper.remove_from_thirdparty(m)
- else:
- for m in modules:
- self.ws_helper.add_to_ws(m, args.ws)
- print(
- crayons.blue("Add module"),
- crayons.green(os.path.basename(m)),
- crayons.blue("to"),
- crayons.cyan(ws_name),
- )
-
- for m in others:
- self.ws_helper.add_to_thirdparty(m)
-
- return 0
-
- def update(self, args_) -> int:
- """
- Update the depandences marked in CMakeLists.txt for current project.
- """
- parser = argparse.ArgumentParser(
- description=self.update.__doc__, prog="admake update"
- )
-
- parser.add_argument(
- "-d",
- "--dir",
- default=".",
- help="Specify the directory contains the CMakeLists.txt",
- )
-
- args = parser.parse_args(*args_)
-
- mh = AdMakeHelper(args.dir)
- gh = AdGitHelper()
-
- group_dir = self.ws_helper.current_ws_dir
-
- projects = mh.modules()
-
- projs_num = len(projects)
- projs_bit_num = len(str(projs_num))
- i = 0
- for p in projects:
- i += 1
- p_path = os.path.join(group_dir, p)
- print(
- crayons.yellow("[{:0>{}d}/{}] ".format(i, projs_bit_num, projs_num)),
- end="",
- )
- if os.path.exists(p_path):
- with AdUtil.chdir(p_path):
- print(crayons.green("Updating project: {: <20} ".format(p)))
- if gh.pull()[0] == 0:
- # If successfully, remove the built artifacts
- # clean_dist(fake_args, None)
- pass
- else:
- print(crayons.blue("Skipped, CMake will clone the project"))
- return 0
-
- def clean(self, *args_) -> int:
- """
- Cleanup the project for rebuilding.
- """
- parser = argparse.ArgumentParser(
- description=self.clean.__doc__, prog="admake clean"
- )
- parser.add_argument(
- "-a",
- "--all",
- action="store_true",
- help="Remove all the artifacts, it is DANGEROUS!",
- )
- parser.add_argument(
- "-o",
- "--os",
- default=AdUtil.SYSTEM.lower(),
- choices=("windows", "linux", "qnx", "macos", "none"),
- help="Target operating system. Supported operating systems : {}".format(
- ", ".join(["windows", "linux", "qnx", "macos", "none"])
- ),
- )
- parser.add_argument(
- "-p",
- "--platform",
- choices=("x64", "arm64"),
- default="x64",
- help="The default value is different in different OSs.\n",
- )
- parser.add_argument(
- "-r", "--release", action="store_true", help="Clean up the release edition"
- )
- parser.add_argument(
- "-t",
- "--build-test",
- action="store_true",
- help="Build the test project with the static library.",
- )
- args = parser.parse_args(*args_)
-
- if args.all:
- for d in ["lib", "bin", self.__build_dir_name]:
- AdUtil.remove(d)
- else:
- AdUtil.remove(
- os.path.join(self.__build_dir_name, self._get_build_dirname(args))
- )
-
- return 0
-
- def config(self, *args_) -> int:
- """
- Output some config information to stdout, so you can use it in scripts.
- """
- parser = argparse.ArgumentParser(
- description=self.clean.__doc__, prog="admake dirs"
- )
- parser.add_argument(
- "-c",
- "--cmake",
- action="store_true",
- help="Output the additional CMAKE_MOUDLE_PATH from admake",)
- parser.add_argument(
- "-d",
- "--docker",
- const=":",
- default="",
- type=str,
- nargs="?",
- help="Specify the docker container that you want to run, <name>:<tag>",)
-
- args = parser.parse_args(*args_)
-
- if args.cmake:
- print(os.path.join(SCRIPT_DIR, "cmake"))
-
- if args.docker:
- if ":" == args.docker:
- # Default name
- args.docker = "admake-cross-linux-x64:latest"
-
- tpl = ['docker run -it --rm --net=host',
- '-v `dirname ${HOME}/.admake`:/home/admake/.admake',
- '-v `dirname ${PWD}`:/workspace',
- '-w /workspace/`basename ${PWD}`',
- '--name build_{}'.format(AdUtil.random_str()),
- '-u $(id -u ${USER}):$(id -g ${USER})',
- '-v "/etc/passwd:/etc/passwd"',
- '-v "/etc/group:/etc/group"',
- '-e HOME="/home/admake"',
- '-e NEXUS_HOST=${NEXUS_HOST}',
- '-e NEXUS_USERNAME=${NEXUS_USERNAME}',
- '-e NEXUS_PASSWORD=${NEXUS_PASSWORD}',
- args.docker, '/bin/bash']
- print(' '.join(tpl))
-
- return 0
-
- def _show_help(self):
- """
- Prints a summary of all commands
- """
- cmds = [
- "build",
- "rebuild",
- "coverage",
- "export",
- "publish",
- "ws",
- "mark",
- "clean",
- "config",
- ]
- max_len = max((len(c) for c in cmds)) + 1
-
- commands = self._commands()
-
- for name in cmds:
- print(crayons.green(name), end="")
-
- # Help will be all the lines up to the first empty one
- docstring_lines = commands[name].__doc__.split("\n")
- start = False
- data = []
- for line in docstring_lines:
- line = line.strip()
- if not line:
- if start:
- break
- start = True
- continue
- data.append(line)
-
- txt = (" " * (max_len + 2 - len(name))) + textwrap.fill(
- " ".join(data), 80, subsequent_indent=" " * (max_len + 2)
- )
- print(txt)
-
- def _commands(self) -> dict:
- """Returns a list of available commands."""
- result = {}
- for m in inspect.getmembers(self, predicate=inspect.ismethod):
- method_name = m[0]
- if not method_name.startswith("_"):
- method = m[1]
- if method.__doc__ and not method.__doc__.startswith("HIDDEN"):
- result[method_name] = method
- return result
-
- def run(self, *args) -> int:
- """HIDDEN: entry point for executing commands, dispatcher to class methods"""
- ret_code = 0
- try:
- try:
- command = args[0][1]
- except IndexError: # No parameters
- self._show_help()
- return 0
-
- cmds = self._commands()
- if command in cmds:
- ret_code = cmds[command](args[0][2:])
- else:
- if command in ["-v", "--version"]:
- print(__version__)
- return 0
-
- if command in ["-h", "--help"]:
- self._show_help()
- return 0
- except Exception:
- print(traceback.format_exc())
- return -1
-
- return ret_code
-
-
- if __name__ == "__main__":
- cmd = Command()
- sys.exit(cmd.run(sys.argv))
|