From ec6416d2b6126af209a92a0dc60b8bef17a725e0 Mon Sep 17 00:00:00 2001 From: Ignacio Etcheverry Date: Thu, 17 May 2018 23:40:22 +0200 Subject: [PATCH] Mono: Module build improvements - Add (Csc/Vbc/Fsc)ToolExe environment variables when running Mono's MSBuild. - Fix directory for the 'mono_assemblies_output_dir' argument being created with the '#' top level directory token as part of its name. - Allow to build with 'mono_static=yes' on Unix without specifying a mono prefix. The build script will try to find the mono prefix using the output from pkg-config. --- modules/mono/SCsub | 42 ++++++++++++++++++++++++++---------------- modules/mono/config.py | 34 ++++++++++++++++++++++++++++++---- 2 files changed, 56 insertions(+), 20 deletions(-) diff --git a/modules/mono/SCsub b/modules/mono/SCsub index a1dfcf63775..03e187e5b08 100644 --- a/modules/mono/SCsub +++ b/modules/mono/SCsub @@ -127,15 +127,24 @@ def find_msbuild_windows(): if not mono_root: raise RuntimeError('Cannot find mono root directory') + framework_path = os.path.join(mono_root, 'lib', 'mono', '4.5') + + mono_bin_dir = os.path.join(mono_root, 'bin') + + msbuild_mono = os.path.join(mono_bin_dir, 'msbuild.bat') + + if os.path.isfile(msbuild_mono): + mono_msbuild_env = { + 'CscToolExe': os.path.join(mono_bin_dir, 'csc.bat'), + 'VbcToolExe': os.path.join(mono_bin_dir, 'vbc.bat'), + 'FscToolExe': os.path.join(mono_bin_dir, 'fsharpc.bat') + } + return (msbuild_mono, framework_path, mono_msbuild_env) + msbuild_tools_path = monoreg.find_msbuild_tools_path_reg() if msbuild_tools_path: - return (os.path.join(msbuild_tools_path, 'MSBuild.exe'), os.path.join(mono_root, 'lib', 'mono', '4.5')) - else: - msbuild_mono = os.path.join(mono_root, 'bin', 'msbuild.bat') - - if os.path.isfile(msbuild_mono): - return (msbuild_mono, '') + return (os.path.join(msbuild_tools_path, 'MSBuild.exe'), framework_path, {}) return None @@ -145,14 +154,21 @@ def mono_build_solution(source, target, env): import mono_reg_utils as monoreg from shutil import copyfile - framework_path_override = '' + framework_path = '' + + msbuild_env = os.environ.copy() + + # Needed when running from Developer Command Prompt for VS + if 'PLATFORM' in msbuild_env: + del msbuild_env['PLATFORM'] if os.name == 'nt': msbuild_info = find_msbuild_windows() if msbuild_info is None: raise RuntimeError('Cannot find MSBuild executable') msbuild_path = msbuild_info[0] - framework_path_override = msbuild_info[1] + framework_path = msbuild_info[1] + msbuild_env.update(msbuild_info[2]) else: msbuild_path = find_msbuild_unix('msbuild') if msbuild_path is None: @@ -183,14 +199,8 @@ def mono_build_solution(source, target, env): '/p:Configuration=' + build_config, ] - if framework_path_override: - msbuild_args += ['/p:FrameworkPathOverride=' + framework_path_override] - - msbuild_env = os.environ.copy() - - # Needed when running from Developer Command Prompt for VS - if 'PLATFORM' in msbuild_env: - del msbuild_env['PLATFORM'] + if framework_path: + msbuild_args += ['/p:FrameworkPathOverride=' + framework_path] try: subprocess.check_call(msbuild_args, env=msbuild_env) diff --git a/modules/mono/config.py b/modules/mono/config.py index 18d9c67795c..d653a7222ee 100644 --- a/modules/mono/config.py +++ b/modules/mono/config.py @@ -4,7 +4,7 @@ import os import sys import subprocess -from SCons.Script import BoolVariable, Dir, Environment, PathVariable, Variables +from SCons.Script import BoolVariable, Dir, Environment, File, PathVariable, SCons, Variables monoreg = imp.load_source('mono_reg_utils', 'modules/mono/mono_reg_utils.py') @@ -42,13 +42,24 @@ def copy_file(src_dir, dst_dir, name): copyfile(src_path, dst_path) +def custom_path_is_dir_create(key, val, env): + """Validator to check if Path is a directory, creating it if it does not exist. + Similar to PathIsDirCreate, except it uses SCons.Script.Dir() and + SCons.Script.File() in order to support the '#' top level directory token. + """ + # Dir constructor will throw an error if the path points to a file + fsDir = Dir(val) + if not fsDir.exists: + os.makedirs(fsDir.abspath) + + def configure(env): env.use_ptrcall = True env.add_module_version_string("mono") envvars = Variables() envvars.Add(BoolVariable('mono_static', 'Statically link mono', False)) - envvars.Add(PathVariable('mono_assemblies_output_dir', 'Path to the assemblies output directory', '#bin', PathVariable.PathIsDirCreate)) + envvars.Add(PathVariable('mono_assemblies_output_dir', 'Path to the assemblies output directory', '#bin', custom_path_is_dir_create)) envvars.Update(env) bits = env['bits'] @@ -128,6 +139,22 @@ def configure(env): if os.getenv('MONO64_PREFIX'): mono_root = os.getenv('MONO64_PREFIX') + # We can't use pkg-config to link mono statically, + # but we can still use it to find the mono root directory + if not mono_root and mono_static: + def pkgconfig_try_find_mono_root(): + tmpenv = Environment() + tmpenv.AppendENVPath('PKG_CONFIG_PATH', os.getenv('PKG_CONFIG_PATH')) + tmpenv.ParseConfig('pkg-config monosgen-2 --libs-only-L') + for hint_dir in tmpenv['LIBPATH']: + name_found = find_file_in_dir(hint_dir, mono_lib_names, prefix='lib', extension=sharedlib_ext) + if name_found and os.path.isdir(os.path.join(hint_dir, '..', 'include', 'mono-2.0')): + return os.path.join(hint_dir, '..') + return '' + mono_root = pkgconfig_try_find_mono_root() + if not mono_root: + raise RuntimeError('Building with mono_static=yes, but failed to find the mono prefix with pkg-config. Specify one manually') + if mono_root: mono_lib_path = os.path.join(mono_root, 'lib') @@ -168,8 +195,7 @@ def configure(env): copy_file(os.path.join(mono_lib_path, 'mono', '4.5'), assemblies_output_dir, 'mscorlib.dll') else: - if mono_static: - raise RuntimeError('mono-static: Not supported with pkg-config. Specify a mono prefix manually') + assert not mono_static env.ParseConfig('pkg-config monosgen-2 --cflags --libs')