solution_builder.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. import os
  2. verbose = False
  3. def find_dotnet_cli():
  4. import os.path
  5. if os.name == "nt":
  6. windows_exts = os.environ["PATHEXT"]
  7. windows_exts = windows_exts.split(os.pathsep) if windows_exts else []
  8. for hint_dir in os.environ["PATH"].split(os.pathsep):
  9. hint_dir = hint_dir.strip('"')
  10. hint_path = os.path.join(hint_dir, "dotnet")
  11. if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
  12. return hint_path
  13. if os.path.isfile(hint_path + ".exe") and os.access(hint_path + ".exe", os.X_OK):
  14. return hint_path + ".exe"
  15. else:
  16. for hint_dir in os.environ["PATH"].split(os.pathsep):
  17. hint_dir = hint_dir.strip('"')
  18. hint_path = os.path.join(hint_dir, "dotnet")
  19. if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
  20. return hint_path
  21. def find_msbuild_unix():
  22. import os.path
  23. import sys
  24. hint_dirs = []
  25. if sys.platform == "darwin":
  26. hint_dirs[:0] = [
  27. "/Library/Frameworks/Mono.framework/Versions/Current/bin",
  28. "/usr/local/var/homebrew/linked/mono/bin",
  29. ]
  30. for hint_dir in hint_dirs:
  31. hint_path = os.path.join(hint_dir, "msbuild")
  32. if os.path.isfile(hint_path):
  33. return hint_path
  34. elif os.path.isfile(hint_path + ".exe"):
  35. return hint_path + ".exe"
  36. for hint_dir in os.environ["PATH"].split(os.pathsep):
  37. hint_dir = hint_dir.strip('"')
  38. hint_path = os.path.join(hint_dir, "msbuild")
  39. if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
  40. return hint_path
  41. if os.path.isfile(hint_path + ".exe") and os.access(hint_path + ".exe", os.X_OK):
  42. return hint_path + ".exe"
  43. return None
  44. def find_msbuild_windows(env):
  45. from .mono_reg_utils import find_mono_root_dir, find_msbuild_tools_path_reg
  46. mono_root = env["mono_prefix"] or find_mono_root_dir(env["bits"])
  47. if not mono_root:
  48. raise RuntimeError("Cannot find mono root directory")
  49. mono_bin_dir = os.path.join(mono_root, "bin")
  50. msbuild_mono = os.path.join(mono_bin_dir, "msbuild.bat")
  51. msbuild_tools_path = find_msbuild_tools_path_reg()
  52. if msbuild_tools_path:
  53. return (os.path.join(msbuild_tools_path, "MSBuild.exe"), {})
  54. if os.path.isfile(msbuild_mono):
  55. # The (Csc/Vbc/Fsc)ToolExe environment variables are required when
  56. # building with Mono's MSBuild. They must point to the batch files
  57. # in Mono's bin directory to make sure they are executed with Mono.
  58. mono_msbuild_env = {
  59. "CscToolExe": os.path.join(mono_bin_dir, "csc.bat"),
  60. "VbcToolExe": os.path.join(mono_bin_dir, "vbc.bat"),
  61. "FscToolExe": os.path.join(mono_bin_dir, "fsharpc.bat"),
  62. }
  63. return (msbuild_mono, mono_msbuild_env)
  64. return None
  65. def run_command(command, args, env_override=None, name=None):
  66. def cmd_args_to_str(cmd_args):
  67. return " ".join([arg if not " " in arg else '"%s"' % arg for arg in cmd_args])
  68. args = [command] + args
  69. if name is None:
  70. name = os.path.basename(command)
  71. if verbose:
  72. print("Running '%s': %s" % (name, cmd_args_to_str(args)))
  73. import subprocess
  74. try:
  75. if env_override is None:
  76. subprocess.check_call(args)
  77. else:
  78. subprocess.check_call(args, env=env_override)
  79. except subprocess.CalledProcessError as e:
  80. raise RuntimeError("'%s' exited with error code: %s" % (name, e.returncode))
  81. def build_solution(env, solution_path, build_config, extra_msbuild_args=[]):
  82. global verbose
  83. verbose = env["verbose"]
  84. msbuild_env = os.environ.copy()
  85. # Needed when running from Developer Command Prompt for VS
  86. if "PLATFORM" in msbuild_env:
  87. del msbuild_env["PLATFORM"]
  88. msbuild_args = []
  89. dotnet_cli = find_dotnet_cli()
  90. if dotnet_cli:
  91. msbuild_path = dotnet_cli
  92. msbuild_args += ["msbuild"] # `dotnet msbuild` command
  93. else:
  94. # Find MSBuild
  95. if os.name == "nt":
  96. msbuild_info = find_msbuild_windows(env)
  97. if msbuild_info is None:
  98. raise RuntimeError("Cannot find MSBuild executable")
  99. msbuild_path = msbuild_info[0]
  100. msbuild_env.update(msbuild_info[1])
  101. else:
  102. msbuild_path = find_msbuild_unix()
  103. if msbuild_path is None:
  104. raise RuntimeError("Cannot find MSBuild executable")
  105. print("MSBuild path: " + msbuild_path)
  106. # Build solution
  107. msbuild_args += [solution_path, "/restore", "/t:Build", "/p:Configuration=" + build_config]
  108. msbuild_args += extra_msbuild_args
  109. run_command(msbuild_path, msbuild_args, env_override=msbuild_env, name="msbuild")