aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJussi Pakkanen <jpakkane@gmail.com>2018-02-25 14:03:02 +0200
committerGitHub <noreply@github.com>2018-02-25 14:03:02 +0200
commit8a68dc0179bc63303a8ef8c4a339cc01ca406084 (patch)
tree9ee89c663207c3f5cfd5e16f42ff24ea16727879
parentf1ce7af2d5866b5207c1f4036477a175f433655c (diff)
parent67f3f803620cdf5cbabd2757211cb4c969ccf41f (diff)
downloadmeson-8a68dc0179bc63303a8ef8c4a339cc01ca406084.zip
meson-8a68dc0179bc63303a8ef8c4a339cc01ca406084.tar.gz
meson-8a68dc0179bc63303a8ef8c4a339cc01ca406084.tar.bz2
Merge pull request #3132 from mesonbuild/csc
Visual Studio C# compiler support and some fixes
-rw-r--r--docs/markdown/snippets/csc.md4
-rw-r--r--mesonbuild/backend/ninjabackend.py19
-rw-r--r--mesonbuild/compilers/__init__.py3
-rw-r--r--mesonbuild/compilers/cs.py46
-rw-r--r--mesonbuild/environment.py35
-rwxr-xr-xrun_project_tests.py24
-rw-r--r--test cases/common/178 preserve gendir/base.inp (renamed from test cases/common/174 preserve gendir/base.inp)0
-rw-r--r--test cases/common/178 preserve gendir/com/mesonbuild/subbie.inp (renamed from test cases/common/174 preserve gendir/com/mesonbuild/subbie.inp)0
-rwxr-xr-xtest cases/common/178 preserve gendir/genprog.py (renamed from test cases/common/174 preserve gendir/genprog.py)0
-rw-r--r--test cases/common/178 preserve gendir/meson.build (renamed from test cases/common/174 preserve gendir/meson.build)0
-rw-r--r--test cases/common/178 preserve gendir/testprog.c (renamed from test cases/common/174 preserve gendir/testprog.c)0
-rw-r--r--test cases/csharp/1 basic/meson.build2
-rw-r--r--test cases/csharp/1 basic/prog.cs5
-rw-r--r--test cases/csharp/1 basic/text.cs7
-rw-r--r--test cases/csharp/4 external dep/meson.build7
-rw-r--r--test cases/csharp/4 pkgconfig/meson.build7
-rw-r--r--test cases/csharp/4 pkgconfig/test-lib.cs11
17 files changed, 123 insertions, 47 deletions
diff --git a/docs/markdown/snippets/csc.md b/docs/markdown/snippets/csc.md
new file mode 100644
index 0000000..90a6f7f
--- /dev/null
+++ b/docs/markdown/snippets/csc.md
@@ -0,0 +1,4 @@
+## Visual Studio C# compiler support
+
+In addition to the Mono C# compiler we also support Visual Studio's C#
+compiler. Currently this is only supported on the Ninja backend.
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index e8c8b39..8b616a6 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -103,7 +103,8 @@ class NinjaBuildElement:
# This is the only way I could find to make this work on all
# platforms including Windows command shell. Slash is a dir separator
# on Windows, too, so all characters are unambiguous and, more importantly,
- # do not require quoting.
+ # do not require quoting, unless explicitely specified, which is necessary for
+ # the csc compiler.
line = line.replace('\\', '/')
outfile.write(line)
@@ -988,7 +989,7 @@ int dummy;
outname_rel = os.path.join(self.get_target_dir(target), fname)
src_list = target.get_sources()
compiler = target.compilers['cs']
- rel_srcs = [s.rel_to_builddir(self.build_to_src) for s in src_list]
+ rel_srcs = [os.path.normpath(s.rel_to_builddir(self.build_to_src)) for s in src_list]
deps = []
commands = CompilerArgs(compiler, target.extra_args.get('cs', []))
commands += compiler.get_buildtype_args(buildtype)
@@ -1014,8 +1015,8 @@ int dummy;
for rel_src in generated_sources.keys():
dirpart, fnamepart = os.path.split(rel_src)
if rel_src.lower().endswith('.cs'):
- rel_srcs.append(rel_src)
- deps.append(rel_src)
+ rel_srcs.append(os.path.normpath(rel_src))
+ deps.append(os.path.normpath(rel_src))
for dep in target.get_external_deps():
commands.extend_direct(dep.get_link_args())
@@ -1588,7 +1589,15 @@ int dummy;
def generate_cs_compile_rule(self, compiler, outfile):
rule = 'rule %s_COMPILER\n' % compiler.get_language()
invoc = ' '.join([ninja_quote(i) for i in compiler.get_exelist()])
- command = ' command = %s $ARGS $in\n' % invoc
+
+ if mesonlib.is_windows():
+ command = ''' command = {executable} @$out.rsp
+ rspfile = $out.rsp
+ rspfile_content = $ARGS $in
+'''.format(executable=invoc)
+ else:
+ command = ' command = %s $ARGS $in\n' % invoc
+
description = ' description = Compiling C Sharp target $out.\n'
outfile.write(rule)
outfile.write(command)
diff --git a/mesonbuild/compilers/__init__.py b/mesonbuild/compilers/__init__.py
index f09f252..84c87fb 100644
--- a/mesonbuild/compilers/__init__.py
+++ b/mesonbuild/compilers/__init__.py
@@ -67,6 +67,7 @@ __all__ = [
'JavaCompiler',
'LLVMDCompiler',
'MonoCompiler',
+ 'VisualStudioCsCompiler',
'NAGFortranCompiler',
'ObjCCompiler',
'ObjCPPCompiler',
@@ -127,7 +128,7 @@ from .cpp import (
IntelCPPCompiler,
VisualStudioCPPCompiler,
)
-from .cs import MonoCompiler
+from .cs import MonoCompiler, VisualStudioCsCompiler
from .d import (
DCompiler,
DmdDCompiler,
diff --git a/mesonbuild/compilers/cs.py b/mesonbuild/compilers/cs.py
index dd7a433..f78e364 100644
--- a/mesonbuild/compilers/cs.py
+++ b/mesonbuild/compilers/cs.py
@@ -15,19 +15,26 @@
import os.path, subprocess
from ..mesonlib import EnvironmentException
+from ..mesonlib import is_windows
from .compilers import Compiler, mono_buildtype_args
-class MonoCompiler(Compiler):
- def __init__(self, exelist, version, **kwargs):
+class CsCompiler(Compiler):
+ def __init__(self, exelist, version, id, runner=None):
self.language = 'cs'
- super().__init__(exelist, version, **kwargs)
- self.id = 'mono'
- self.monorunner = 'mono'
+ super().__init__(exelist, version)
+ self.id = id
+ self.runner = runner
def get_display_language(self):
return 'C sharp'
+ def get_always_args(self):
+ return ['/nologo']
+
+ def get_linker_always_args(self):
+ return ['/nologo']
+
def get_output_args(self, fname):
return ['-out:' + fname]
@@ -92,11 +99,14 @@ class MonoCompiler(Compiler):
}
}
''')
- pc = subprocess.Popen(self.exelist + [src], cwd=work_dir)
+ pc = subprocess.Popen(self.exelist + self.get_always_args() + [src], cwd=work_dir)
pc.wait()
if pc.returncode != 0:
raise EnvironmentException('Mono compiler %s can not compile programs.' % self.name_string())
- cmdlist = [self.monorunner, obj]
+ if self.runner:
+ cmdlist = [self.runner, obj]
+ else:
+ cmdlist = [os.path.join(work_dir, obj)]
pe = subprocess.Popen(cmdlist, cwd=work_dir)
pe.wait()
if pe.returncode != 0:
@@ -107,3 +117,25 @@ class MonoCompiler(Compiler):
def get_buildtype_args(self, buildtype):
return mono_buildtype_args[buildtype]
+
+
+class MonoCompiler(CsCompiler):
+ def __init__(self, exelist, version):
+ super().__init__(exelist, version, 'mono',
+ 'mono')
+
+
+class VisualStudioCsCompiler(CsCompiler):
+ def __init__(self, exelist, version):
+ super().__init__(exelist, version, 'csc')
+
+ def get_buildtype_args(self, buildtype):
+ res = mono_buildtype_args[buildtype]
+ if not is_windows():
+ tmp = []
+ for flag in res:
+ if flag == '-debug':
+ flag = '-debug:portable'
+ tmp.append(flag)
+ res = tmp
+ return res
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
index e553423..ccd85d5 100644
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -54,6 +54,7 @@ from .compilers import (
IntelFortranCompiler,
JavaCompiler,
MonoCompiler,
+ VisualStudioCsCompiler,
NAGFortranCompiler,
Open64FortranCompiler,
PathScaleFortranCompiler,
@@ -275,6 +276,10 @@ class Environment:
else:
self.default_c = ['cc', 'gcc', 'clang']
self.default_cpp = ['c++', 'g++', 'clang++']
+ if mesonlib.is_windows():
+ self.default_cs = ['csc', 'mcs']
+ else:
+ self.default_cs = ['mcs', 'csc']
self.default_objc = ['cc']
self.default_objcpp = ['c++']
self.default_fortran = ['gfortran', 'g95', 'f95', 'f90', 'f77', 'ifort']
@@ -419,7 +424,7 @@ class Environment:
def _get_compilers(self, lang, evar, want_cross):
'''
The list of compilers is detected in the exact same way for
- C, C++, ObjC, ObjC++, Fortran so consolidate it here.
+ C, C++, ObjC, ObjC++, Fortran, CS so consolidate it here.
'''
if self.is_cross_build() and want_cross:
compilers = mesonlib.stringlistify(self.cross_info.config['binaries'][lang])
@@ -664,16 +669,24 @@ class Environment:
raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"')
def detect_cs_compiler(self):
- exelist = ['mcs']
- try:
- p, out, err = Popen_safe(exelist + ['--version'])
- except OSError:
- raise EnvironmentException('Could not execute C# compiler "%s"' % ' '.join(exelist))
- version = search_version(out)
- full_version = out.split('\n', 1)[0]
- if 'Mono' in out:
- return MonoCompiler(exelist, version, full_version=full_version)
- raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"')
+ compilers, ccache, is_cross, exe_wrap = self._get_compilers('cs', 'CSC', False)
+ popen_exceptions = {}
+ for comp in compilers:
+ if not isinstance(comp, list):
+ comp = [comp]
+ try:
+ p, out, err = Popen_safe(comp + ['--version'])
+ except OSError as e:
+ popen_exceptions[' '.join(comp + ['--version'])] = e
+ continue
+
+ version = search_version(out)
+ if 'Mono' in out:
+ return MonoCompiler(comp, version)
+ elif "Visual C#" in out:
+ return VisualStudioCsCompiler(comp, version)
+
+ self._handle_exceptions(popen_exceptions, compilers)
def detect_vala_compiler(self):
if 'VALAC' in os.environ:
diff --git a/run_project_tests.py b/run_project_tests.py
index c2c3efe..f9d4dbd 100755
--- a/run_project_tests.py
+++ b/run_project_tests.py
@@ -465,6 +465,28 @@ def skippable(suite, test):
# Other framework tests are allowed to be skipped on other platforms
return True
+def skip_csharp(backend):
+ if backend is not Backend.ninja:
+ return True
+ if not shutil.which('resgen'):
+ return True
+ if shutil.which('mcs'):
+ return False
+ if shutil.which('csc'):
+ # Only support VS2017 for now. Earlier versions fail
+ # under CI in mysterious ways.
+ try:
+ stdo = subprocess.check_output(['csc', '/version'])
+ except subprocess.CalledProcessError:
+ return True
+ # Having incrementing version numbers would be too easy.
+ # Microsoft reset the versioning back to 1.0 (from 4.x)
+ # when they got the Roslyn based compiler. Thus there
+ # is NO WAY to reliably do version number comparisons.
+ # Only support the version that ships with VS2017.
+ return not stdo.startswith(b'2.')
+ return True
+
def detect_tests_to_run():
# Name, subdirectory, skip condition.
all_tests = [
@@ -478,7 +500,7 @@ def detect_tests_to_run():
('platform-linux', 'linuxlike', mesonlib.is_osx() or mesonlib.is_windows()),
('java', 'java', backend is not Backend.ninja or mesonlib.is_osx() or not have_java()),
- ('C#', 'csharp', backend is not Backend.ninja or not shutil.which('mcs')),
+ ('C#', 'csharp', skip_csharp(backend)),
('vala', 'vala', backend is not Backend.ninja or not shutil.which('valac')),
('rust', 'rust', backend is not Backend.ninja or not shutil.which('rustc')),
('d', 'd', backend is not Backend.ninja or not have_d_compiler()),
diff --git a/test cases/common/174 preserve gendir/base.inp b/test cases/common/178 preserve gendir/base.inp
index df967b9..df967b9 100644
--- a/test cases/common/174 preserve gendir/base.inp
+++ b/test cases/common/178 preserve gendir/base.inp
diff --git a/test cases/common/174 preserve gendir/com/mesonbuild/subbie.inp b/test cases/common/178 preserve gendir/com/mesonbuild/subbie.inp
index df0f4e9..df0f4e9 100644
--- a/test cases/common/174 preserve gendir/com/mesonbuild/subbie.inp
+++ b/test cases/common/178 preserve gendir/com/mesonbuild/subbie.inp
diff --git a/test cases/common/174 preserve gendir/genprog.py b/test cases/common/178 preserve gendir/genprog.py
index 1e10998..1e10998 100755
--- a/test cases/common/174 preserve gendir/genprog.py
+++ b/test cases/common/178 preserve gendir/genprog.py
diff --git a/test cases/common/174 preserve gendir/meson.build b/test cases/common/178 preserve gendir/meson.build
index ce219f0..ce219f0 100644
--- a/test cases/common/174 preserve gendir/meson.build
+++ b/test cases/common/178 preserve gendir/meson.build
diff --git a/test cases/common/174 preserve gendir/testprog.c b/test cases/common/178 preserve gendir/testprog.c
index 46b4602..46b4602 100644
--- a/test cases/common/174 preserve gendir/testprog.c
+++ b/test cases/common/178 preserve gendir/testprog.c
diff --git a/test cases/csharp/1 basic/meson.build b/test cases/csharp/1 basic/meson.build
index 2ee6a4a..09e46c2 100644
--- a/test cases/csharp/1 basic/meson.build
+++ b/test cases/csharp/1 basic/meson.build
@@ -1,4 +1,4 @@
project('simple c#', 'cs')
-e = executable('prog', 'prog.cs', install : true)
+e = executable('prog', 'prog.cs', 'text.cs', install : true)
test('basic', e)
diff --git a/test cases/csharp/1 basic/prog.cs b/test cases/csharp/1 basic/prog.cs
index dfb2400..6ee47b0 100644
--- a/test cases/csharp/1 basic/prog.cs
+++ b/test cases/csharp/1 basic/prog.cs
@@ -1,7 +1,8 @@
using System;
-
+
public class Prog {
static public void Main () {
- Console.WriteLine("C# is working.");
+ TextGetter tg = new TextGetter();
+ Console.WriteLine(tg.getText());
}
}
diff --git a/test cases/csharp/1 basic/text.cs b/test cases/csharp/1 basic/text.cs
new file mode 100644
index 0000000..c83c424
--- /dev/null
+++ b/test cases/csharp/1 basic/text.cs
@@ -0,0 +1,7 @@
+using System;
+
+public class TextGetter {
+ public String getText() {
+ return "C# is working.";
+ }
+}
diff --git a/test cases/csharp/4 external dep/meson.build b/test cases/csharp/4 external dep/meson.build
index 004d25f..019d618 100644
--- a/test cases/csharp/4 external dep/meson.build
+++ b/test cases/csharp/4 external dep/meson.build
@@ -1,4 +1,9 @@
project('C# external library', 'cs')
-glib_sharp_2 = dependency('glib-sharp-2.0')
+glib_sharp_2 = dependency('glib-sharp-2.0', required : false)
+
+if not glib_sharp_2.found()
+ error('MESON_SKIP_TEST glib# not found.')
+endif
+
e = executable('prog', 'prog.cs', dependencies: glib_sharp_2, install : true)
test('libtest', e, args: [join_paths(meson.current_source_dir(), 'hello.txt')])
diff --git a/test cases/csharp/4 pkgconfig/meson.build b/test cases/csharp/4 pkgconfig/meson.build
deleted file mode 100644
index e2ba035..0000000
--- a/test cases/csharp/4 pkgconfig/meson.build
+++ /dev/null
@@ -1,7 +0,0 @@
-project('C# pkg-config', 'cs')
-
-nunit_dep = dependency('nunit')
-nunit_runner = find_program('nunit-console')
-
-test_lib = library('test_lib', 'test-lib.cs', dependencies: nunit_dep)
-test('nunit test', nunit_runner, args: test_lib)
diff --git a/test cases/csharp/4 pkgconfig/test-lib.cs b/test cases/csharp/4 pkgconfig/test-lib.cs
deleted file mode 100644
index 29f6795..0000000
--- a/test cases/csharp/4 pkgconfig/test-lib.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using NUnit.Framework;
-
-[TestFixture]
-public class NUnitTest
-{
- [Test]
- public void Test()
- {
- Assert.AreEqual(1 + 1, 2);
- }
-}