Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Buildsystem improvements for the Mono module #12388

Merged
merged 1 commit into from
Oct 29, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 110 additions & 29 deletions modules/mono/SCsub
Original file line number Diff line number Diff line change
Expand Up @@ -53,68 +53,149 @@ if env['tools']:

vars = Variables()
vars.Add(BoolVariable('mono_glue', 'Build with the mono glue sources', True))
vars.Add(BoolVariable('xbuild_fallback', 'If MSBuild is not found, fallback to xbuild', False))
vars.Update(env)

# Glue sources
if env['mono_glue']:
env.add_source_files(env.modules_sources, 'glue/*.cpp')
else:
env.Append(CPPDEFINES = [ 'MONO_GLUE_DISABLED' ])
env.Append(CPPDEFINES=['MONO_GLUE_DISABLED'])

if ARGUMENTS.get('yolo_copy', False):
env.Append(CPPDEFINES = [ 'YOLO_COPY' ])
env.Append(CPPDEFINES=['YOLO_COPY'])


# Build GodotSharpTools solution


import os
import subprocess
import mono_reg_utils as monoreg


def find_msbuild_unix(filename):
import os.path
import sys

hint_dirs = ['/opt/novell/mono/bin']
if sys.platform == "darwin":
hint_dirs = ['/Library/Frameworks/Mono.framework/Versions/Current/bin'] + hint_dirs

for hint_dir in hint_dirs:
hint_path = os.path.join(hint_dir, filename)
if os.path.isfile(hint_path):
return hint_path

for hint_dir in os.environ["PATH"].split(os.pathsep):
hint_dir = hint_dir.strip('"')
hint_path = os.path.join(hint_dir, filename)
if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
return hint_path

return None


def find_msbuild_windows():
import mono_reg_utils as monoreg

msbuild_tools_path = monoreg.find_msbuild_tools_path_reg()

if msbuild_tools_path:
return (os.path.join(msbuild_tools_path, 'MSBuild.exe'), '')
else:
bits = env['bits']

if bits == '32':
if os.getenv('MONO32_PREFIX'):
mono_root = os.getenv('MONO32_PREFIX')
else:
mono_root = monoreg.find_mono_root_dir(bits)
else:
if os.getenv('MONO64_PREFIX'):
mono_root = os.getenv('MONO64_PREFIX')
else:
mono_root = monoreg.find_mono_root_dir(bits)

if mono_root:
msbuild_mono = os.path.join(mono_root, 'bin', 'msbuild.bat')

if os.path.isfile(msbuild_mono):
return (msbuild_mono, os.path.join(mono_root, 'lib', 'mono', '4.5'))

return None


def mono_build_solution(source, target, env):
import subprocess
import mono_reg_utils as monoreg
from shutil import copyfile

framework_path_override = ''

if os.name == 'nt':
msbuild_tools_path = monoreg.find_msbuild_tools_path_reg()
if not msbuild_tools_path:
raise RuntimeError('Cannot find MSBuild Tools Path in the registry')
msbuild_path = os.path.join(msbuild_tools_path, 'MSBuild.exe')
msbuild_info = find_msbuild_windows()
if msbuild_info is None:
raise RuntimeError('Cannot find MSBuild executable')
msbuild_path = msbuild_windows[0]
framework_path_override = msbuild_windows[1]
else:
msbuild_path = 'msbuild'
msbuild_path = find_msbuild_unix('msbuild')
if msbuild_path is None:
xbuild_fallback = env['xbuild_fallback']

if xbuild_fallback and os.name == 'nt':
print("Option 'xbuild_fallback' not supported on Windows")
xbuild_fallback = False

if xbuild_fallback:
print('Cannot find MSBuild executable, trying with xbuild')
print('Warning: xbuild is deprecated')

msbuild_path = find_msbuild_unix('xbuild')

if msbuild_path is None:
raise RuntimeError('Cannot find xbuild executable')
else:
raise RuntimeError('Cannot find MSBuild executable')

print('MSBuild path: ' + msbuild_path)

output_path = os.path.abspath(os.path.join(str(target[0]), os.pardir))
build_config = 'Release'

msbuild_args = [
msbuild_path,
os.path.abspath(str(source[0])),
'/p:Configuration=Release',
'/p:OutputPath=' + output_path
'/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']

msbuild_alt_paths = [ 'xbuild' ]

while True:
try:
subprocess.check_call(msbuild_args, env = msbuild_env)
break
except subprocess.CalledProcessError:
raise RuntimeError('GodotSharpTools build failed')
except OSError:
if os.name != 'nt':
if not msbuild_alt_paths:
raise RuntimeError('Could not find commands msbuild or xbuild')
# Try xbuild
msbuild_args[0] = msbuild_alt_paths.pop(0)
else:
raise RuntimeError('Could not find command MSBuild.exe')
try:
subprocess.check_call(msbuild_args, env=msbuild_env)
except subprocess.CalledProcessError:
raise RuntimeError('GodotSharpTools build failed')

src_dir = os.path.abspath(os.path.join(str(source[0]), os.pardir, 'bin', build_config))
dst_dir = os.path.abspath(os.path.join(str(target[0]), os.pardir))

if not os.path.isdir(dst_dir):
if os.path.exists(dst_dir):
raise RuntimeError('Target directory is a file')
os.makedirs(dst_dir)

asm_file = 'GodotSharpTools.dll'

copyfile(os.path.join(src_dir, asm_file), os.path.join(dst_dir, asm_file))


mono_sln_builder = Builder(action = mono_build_solution)
env.Append(BUILDERS = { 'MonoBuildSolution' : mono_sln_builder })
env.Append(BUILDERS={'MonoBuildSolution': mono_sln_builder})
env.MonoBuildSolution(
os.path.join(Dir('#bin').abspath, 'GodotSharpTools.dll'),
'editor/GodotSharpTools/GodotSharpTools.sln'
Expand Down
80 changes: 58 additions & 22 deletions modules/mono/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import imp
import os
import sys
from shutil import copyfile

from SCons.Script import BoolVariable, Environment, Variables

Expand All @@ -16,8 +15,7 @@ def find_file_in_dir(directory, files, prefix='', extension=''):
for curfile in files:
if os.path.isfile(os.path.join(directory, prefix + curfile + extension)):
return curfile

return None
return ''


def can_build(platform):
Expand All @@ -31,13 +29,31 @@ def is_enabled():
return False


def copy_file_no_replace(src_dir, dst_dir, name):
from shutil import copyfile

src_path = os.path.join(src_dir, name)
dst_path = os.path.join(dst_dir, name)
need_copy = True

if not os.path.isdir(dst_dir):
os.mkdir(dst_dir)
elif os.path.exists(dst_path):
need_copy = False

if need_copy:
copyfile(src_path, dst_path)


def configure(env):
env.use_ptrcall = True

envvars = Variables()
envvars.Add(BoolVariable('mono_static', 'Statically link mono', False))
envvars.Update(env)

bits = env['bits']

mono_static = env['mono_static']

mono_lib_names = ['mono-2.0-sgen', 'monosgen-2.0']
Expand All @@ -46,18 +62,18 @@ def configure(env):
if mono_static:
raise RuntimeError('mono-static: Not supported on Windows')

if env['bits'] == '32':
if bits == '32':
if os.getenv('MONO32_PREFIX'):
mono_root = os.getenv('MONO32_PREFIX')
elif os.name == 'nt':
mono_root = monoreg.find_mono_root_dir()
mono_root = monoreg.find_mono_root_dir(bits)
else:
if os.getenv('MONO64_PREFIX'):
mono_root = os.getenv('MONO64_PREFIX')
elif os.name == 'nt':
mono_root = monoreg.find_mono_root_dir()
mono_root = monoreg.find_mono_root_dir(bits)

if mono_root is None:
if not mono_root:
raise RuntimeError('Mono installation directory not found')

mono_lib_path = os.path.join(mono_root, 'lib')
Expand All @@ -67,7 +83,7 @@ def configure(env):

mono_lib_name = find_file_in_dir(mono_lib_path, mono_lib_names, extension='.lib')

if mono_lib_name is None:
if not mono_lib_name:
raise RuntimeError('Could not find mono library in: ' + mono_lib_path)

if os.getenv('VCINSTALLDIR'):
Expand All @@ -79,36 +95,31 @@ def configure(env):

mono_dll_name = find_file_in_dir(mono_bin_path, mono_lib_names, extension='.dll')

mono_dll_src = os.path.join(mono_bin_path, mono_dll_name + '.dll')
mono_dll_dst = os.path.join('bin', mono_dll_name + '.dll')
copy_mono_dll = True

if not os.path.isdir('bin'):
os.mkdir('bin')
elif os.path.exists(mono_dll_dst):
copy_mono_dll = False
if not mono_dll_name:
raise RuntimeError('Could not find mono shared library in: ' + mono_bin_path)

if copy_mono_dll:
copyfile(mono_dll_src, mono_dll_dst)
copy_file_no_replace(mono_bin_path, 'bin', mono_dll_name + '.dll')
else:
mono_root = None
sharedlib_ext = '.dylib' if sys.platform == 'darwin' else '.so'

if env['bits'] == '32':
mono_root = ''

if bits == '32':
if os.getenv('MONO32_PREFIX'):
mono_root = os.getenv('MONO32_PREFIX')
else:
if os.getenv('MONO64_PREFIX'):
mono_root = os.getenv('MONO64_PREFIX')

if mono_root is not None:
if mono_root:
mono_lib_path = os.path.join(mono_root, 'lib')

env.Append(LIBPATH=mono_lib_path)
env.Append(CPPPATH=os.path.join(mono_root, 'include', 'mono-2.0'))

mono_lib = find_file_in_dir(mono_lib_path, mono_lib_names, prefix='lib', extension='.a')

if mono_lib is None:
if not mono_lib:
raise RuntimeError('Could not find mono library in: ' + mono_lib_path)

env.Append(CPPFLAGS=['-D_REENTRANT'])
Expand All @@ -130,12 +141,37 @@ def configure(env):
elif sys.platform == "linux" or sys.platform == "linux2":
env.Append(LIBS=['m', 'rt', 'dl', 'pthread'])

if not mono_static:
mono_so_name = find_file_in_dir(mono_lib_path, mono_lib_names, prefix='lib', extension=sharedlib_ext)

if not mono_so_name:
raise RuntimeError('Could not find mono shared library in: ' + mono_lib_path)

copy_file_no_replace(mono_lib_path, 'bin', 'lib' + mono_so_name + sharedlib_ext)
else:
if mono_static:
raise RuntimeError('mono-static: Not supported with pkg-config. Specify a mono prefix manually')

env.ParseConfig('pkg-config monosgen-2 --cflags --libs')

mono_lib_path = ''
mono_so_name = ''

tmpenv = Environment()
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:
mono_lib_path = hint_dir
mono_so_name = name_found
break

if not mono_so_name:
raise RuntimeError('Could not find mono shared library in: ' + str(tmpenv['LIBPATH']))

copy_file_no_replace(mono_lib_path, 'bin', 'lib' + mono_so_name + sharedlib_ext)

env.Append(LINKFLAGS='-rdynamic')


Expand Down
Loading