Browse Source

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.

Ignacio Etcheverry 7 years ago
parent
commit
ec6416d2b6
2 changed files with 56 additions and 20 deletions
  1. 26 16
      modules/mono/SCsub
  2. 30 4
      modules/mono/config.py

+ 26 - 16
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)

+ 30 - 4
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')