aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJussi Pakkanen <jpakkane@gmail.com>2015-12-12 01:08:11 +0200
committerJussi Pakkanen <jpakkane@gmail.com>2015-12-12 01:08:11 +0200
commit8d8e25118bb7cb811bc152d95489d721d6e03dcd (patch)
treeba5b20f899bcf3bc7452648b284a2be158aae360
parentba6191864d4a4461131081fef918796604a9ef28 (diff)
parent161d633f362a316e4711b8ab524d3688cd6847ef (diff)
downloadmeson-8d8e25118bb7cb811bc152d95489d721d6e03dcd.zip
meson-8d8e25118bb7cb811bc152d95489d721d6e03dcd.tar.gz
meson-8d8e25118bb7cb811bc152d95489d721d6e03dcd.tar.bz2
Merge pull request #330 from mesonbuild/swift
Added Swift support.
-rw-r--r--backends.py27
-rw-r--r--compilers.py104
-rwxr-xr-xdirchanger.py24
-rw-r--r--environment.py21
-rw-r--r--interpreter.py5
-rw-r--r--ninjabackend.py150
-rwxr-xr-xrun_tests.py1
-rw-r--r--test cases/swift/1 exe/meson.build3
-rw-r--r--test cases/swift/1 exe/prog.swift1
-rw-r--r--test cases/swift/2 multifile/libfile.swift3
-rw-r--r--test cases/swift/2 multifile/main.swift1
-rw-r--r--test cases/swift/2 multifile/meson.build3
-rw-r--r--test cases/swift/3 library/exe/main.swift7
-rw-r--r--test cases/swift/3 library/exe/meson.build2
-rw-r--r--test cases/swift/3 library/lib/datasource.swift3
-rw-r--r--test cases/swift/3 library/lib/meson.build1
-rw-r--r--test cases/swift/3 library/lib/othersource.swift3
-rw-r--r--test cases/swift/3 library/meson.build4
-rw-r--r--test cases/swift/4 generate/gen/main.swift10
-rw-r--r--test cases/swift/4 generate/gen/meson.build6
-rw-r--r--test cases/swift/4 generate/meson.build4
-rw-r--r--test cases/swift/4 generate/user/main.swift3
-rw-r--r--test cases/swift/4 generate/user/meson.build2
-rw-r--r--test cases/swift/5 mixed/main.swift3
-rw-r--r--test cases/swift/5 mixed/meson.build6
-rw-r--r--test cases/swift/5 mixed/mylib.c5
-rw-r--r--test cases/swift/5 mixed/mylib.h3
27 files changed, 394 insertions, 11 deletions
diff --git a/backends.py b/backends.py
index e0a9ec4..9abf02f 100644
--- a/backends.py
+++ b/backends.py
@@ -85,6 +85,13 @@ class Backend():
os.makedirs(os.path.join(self.environment.get_build_dir(), dirname), exist_ok=True)
return dirname
+ # Crap hack. The above was doing the wrong thing but too many thing use it to fix
+ # now. Get fixed once Swift works.
+ def get_target_private_dir_abs_v2(self, target):
+ dirname = os.path.join(self.environment.get_build_dir(), self.get_target_private_dir(target))
+ os.makedirs(dirname, exist_ok=True)
+ return dirname
+
def generate_unity_files(self, target, unity_src):
langlist = {}
abs_files = []
@@ -134,23 +141,23 @@ class Backend():
self.write_benchmark_file(datafile)
datafile.close()
- def has_vala(self, target):
+ def has_source_suffix(self, target, suffix):
for s in target.get_sources():
- if s.endswith('.vala'):
+ if s.endswith(suffix):
return True
return False
+ def has_vala(self, target):
+ return self.has_source_suffix(target, '.vala')
+
def has_rust(self, target):
- for s in target.get_sources():
- if s.endswith('.rs'):
- return True
- return False
+ return self.has_source_suffix(target, '.rs')
def has_cs(self, target):
- for s in target.get_sources():
- if s.endswith('.cs'):
- return True
- return False
+ return self.has_source_suffix(target, '.cs')
+
+ def has_swift(self, target):
+ return self.has_source_suffix(target, '.swift')
def determine_linker(self, target, src):
if isinstance(target, build.StaticLibrary):
diff --git a/compilers.py b/compilers.py
index 7907235..0567764 100644
--- a/compilers.py
+++ b/compilers.py
@@ -92,6 +92,11 @@ mono_buildtype_args = {'plain' : [],
'debugoptimized': ['-debug', '-optimize+'],
'release' : ['-optimize+']}
+swift_buildtype_args = {'plain' : [],
+ 'debug' : ['-g'],
+ 'debugoptimized': ['-g', '-O'],
+ 'release' : ['-O']}
+
gnu_winlibs = ['-lkernel32', '-luser32', '-lgdi32', '-lwinspool', '-lshell32',
'-lole32', '-loleaut32', '-luuid', '-lcomdlg32', '-ladvapi32']
@@ -210,6 +215,9 @@ class CCompiler(Compiler):
def get_dependency_gen_args(self, outtarget, outfile):
return ['-MMD', '-MQ', outtarget, '-MF', outfile]
+ def depfile_for_object(self, objfile):
+ return objfile + '.' + self.get_depfile_suffix()
+
def get_depfile_suffix(self):
return 'd'
@@ -948,6 +956,99 @@ class RustCompiler(Compiler):
def get_buildtype_args(self, buildtype):
return rust_buildtype_args[buildtype]
+class SwiftCompiler(Compiler):
+ def __init__(self, exelist, version):
+ super().__init__(exelist, version)
+ self.version = version
+ self.id = 'llvm'
+ self.language = 'swift'
+ self.is_cross = False
+
+ def get_id(self):
+ return self.id
+
+ def get_linker_exelist(self):
+ return self.exelist
+
+ def name_string(self):
+ return ' '.join(self.exelist)
+
+ def needs_static_linker(self):
+ return True
+
+ def get_exelist(self):
+ return self.exelist
+
+ def get_werror_args(self):
+ return ['--fatal-warnings']
+
+ def get_language(self):
+ return self.language
+
+ def get_dependency_gen_args(self, outtarget, outfile):
+ return ['-emit-dependencies']
+
+ def depfile_for_object(self, objfile):
+ return os.path.splitext(objfile)[0] + '.' + self.get_depfile_suffix()
+
+ def get_depfile_suffix(self):
+ return 'd'
+
+ def get_output_args(self, target):
+ return ['-o', target]
+
+ def get_linker_output_args(self, target):
+ return ['-o', target]
+
+ def get_header_import_args(self, headername):
+ return ['-import-objc-header', headername]
+
+ def get_warn_args(self, level):
+ return []
+
+ def get_buildtype_args(self, buildtype):
+ return swift_buildtype_args[buildtype]
+
+ def get_buildtype_linker_args(self, buildtype):
+ return []
+
+ def get_std_exe_link_args(self):
+ return ['-emit-executable']
+
+ def get_module_args(self, modname):
+ return ['-module-name', modname]
+
+ def get_mod_gen_args(self):
+ return ['-emit-module']
+
+ def build_rpath_args(self, *args):
+ return [] # FIXME
+
+ def get_include_args(self, dirname):
+ return ['-I' + dirname]
+
+ def get_compile_only_args(self):
+ return ['-c']
+
+ def sanity_check(self, work_dir):
+ src = 'swifttest.swift'
+ source_name = os.path.join(work_dir, src)
+ output_name = os.path.join(work_dir, 'swifttest')
+ ofile = open(source_name, 'w')
+ ofile.write('''1 + 2
+''')
+ ofile.close()
+ pc = subprocess.Popen(self.exelist + ['-emit-executable', '-o', output_name, src], cwd=work_dir)
+ pc.wait()
+ if pc.returncode != 0:
+ raise EnvironmentException('Swift compiler %s can not compile programs.' % self.name_string())
+ if subprocess.call(output_name) != 0:
+ raise EnvironmentException('Executables created by Swift compiler %s are not runnable.' % self.name_string())
+
+ def can_compile(self, filename):
+ suffix = filename.split('.')[-1]
+ return suffix in ('swift')
+
class VisualStudioCCompiler(CCompiler):
std_warn_args = ['/W3']
std_opt_args= ['/O2']
@@ -1476,6 +1577,9 @@ end program prog
def get_module_outdir_args(self, path):
return ['-J' + path]
+ def depfile_for_object(self, objfile):
+ return objfile + '.' + self.get_depfile_suffix()
+
def get_depfile_suffix(self):
return 'd'
diff --git a/dirchanger.py b/dirchanger.py
new file mode 100755
index 0000000..4cc863a
--- /dev/null
+++ b/dirchanger.py
@@ -0,0 +1,24 @@
+# Copyright 2015 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+'''CD into dir given as first argument and execute
+the command given in the rest of the arguments.'''
+
+import os, subprocess, sys
+
+dirname = sys.argv[1]
+command = sys.argv[2:]
+
+os.chdir(dirname)
+sys.exit(subprocess.call(command))
diff --git a/environment.py b/environment.py
index c92eb87..308a21c 100644
--- a/environment.py
+++ b/environment.py
@@ -19,6 +19,10 @@ import configparser
build_filename = 'meson.build'
+class EnvironmentException(coredata.MesonException):
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+
def find_coverage_tools():
gcovr_exe = 'gcovr'
lcov_exe = 'lcov'
@@ -457,6 +461,23 @@ class Environment():
return RustCompiler(exelist, version)
raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"')
+ def detect_swift_compiler(self):
+ exelist = ['swiftc']
+ try:
+ p = subprocess.Popen(exelist + ['-v'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ except OSError:
+ raise EnvironmentException('Could not execute Swift compiler "%s"' % ' '.join(exelist))
+ (_, err) = p.communicate()
+ err = err.decode()
+ vmatch = re.search(Environment.version_regex, err)
+ if vmatch:
+ version = vmatch.group(0)
+ else:
+ version = 'unknown version'
+ if 'Swift' in err:
+ return SwiftCompiler(exelist, version)
+ raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"')
+
def detect_static_linker(self, compiler):
if compiler.is_cross:
linker = self.cross_info.config['binaries']['ar']
diff --git a/interpreter.py b/interpreter.py
index a11f753..47ce716 100644
--- a/interpreter.py
+++ b/interpreter.py
@@ -1476,6 +1476,11 @@ class Interpreter():
comp = self.environment.detect_fortran_compiler(False)
if need_cross_compiler:
cross_comp = self.environment.detect_fortran_compiler(True)
+ elif lang == 'swift':
+ comp = self.environment.detect_swift_compiler()
+ if need_cross_compiler:
+ raise InterpreterException('Cross compilation with Swift is not working yet.')
+ #cross_comp = self.environment.detect_fortran_compiler(True)
else:
raise InvalidCode('Tried to use unknown language "%s".' % lang)
comp.sanity_check(self.environment.get_scratch_dir())
diff --git a/ninjabackend.py b/ninjabackend.py
index d837074..5c3a9e5 100644
--- a/ninjabackend.py
+++ b/ninjabackend.py
@@ -195,6 +195,9 @@ class NinjaBackend(backends.Backend):
return
if 'vala' in self.environment.coredata.compilers.keys() and self.has_vala(target):
gen_src_deps += self.generate_vala_compile(target, outfile)
+ if 'swift' in self.environment.coredata.compilers.keys() and self.has_swift(target):
+ self.generate_swift_target(target, outfile)
+ return
self.scan_fortran_module_outputs(target)
# The following deals with C/C++ compilation.
(gen_src, gen_other_deps) = self.process_dep_gens(outfile, target)
@@ -854,6 +857,134 @@ class NinjaBackend(backends.Backend):
element.write(outfile)
self.check_outputs(element)
+ def swift_module_file_name(self, target):
+ return os.path.join(self.get_target_private_dir(target),
+ self.target_swift_modulename(target) + '.swiftmodule')
+
+ def target_swift_modulename(self, target):
+ return target.name
+
+ def is_swift_target(self, target):
+ for s in target.sources:
+ if s.endswith('swift'):
+ return True
+ return False
+
+ def determine_swift_dep_modules(self, target):
+ result = []
+ for l in target.link_targets:
+ if self.is_swift_target(l):
+ result.append(self.swift_module_file_name(l))
+ return result
+
+ def determine_swift_dep_dirs(self, target):
+ result = []
+ for l in target.link_targets:
+ result.append(self.get_target_private_dir_abs_v2(l))
+ return result
+
+ def get_swift_link_deps(self, target):
+ result = []
+ for l in target.link_targets:
+ result.append(self.get_target_filename(l))
+ return result
+
+ def split_swift_generated_sources(self, target):
+ all_srcs = []
+ for genlist in target.get_generated_sources():
+ if isinstance(genlist, build.CustomTarget):
+ for ifile in genlist.get_filename():
+ rel = os.path.join(self.get_target_dir(genlist), ifile)
+ all_srcs.append(rel)
+ else:
+ for ifile in genlist.get_outfilelist():
+ rel = os.path.join(self.get_target_private_dir(target), ifile)
+ all_srcs.append(rel)
+ srcs = []
+ others = []
+ for i in all_srcs:
+ if i.endswith('.swift'):
+ srcs.append(i)
+ else:
+ others.append(i)
+ return (srcs, others)
+
+ def generate_swift_target(self, target, outfile):
+ module_name = self.target_swift_modulename(target)
+ swiftc = self.environment.coredata.compilers['swift']
+ abssrc = []
+ abs_headers = []
+ header_imports = []
+ for i in target.get_sources():
+ if swiftc.can_compile(i):
+ relsrc = i.rel_to_builddir(self.build_to_src)
+ abss = os.path.normpath(os.path.join(self.environment.get_build_dir(), relsrc))
+ abssrc.append(abss)
+ elif self.environment.is_header(i):
+ relh = i.rel_to_builddir(self.build_to_src)
+ absh = os.path.normpath(os.path.join(self.environment.get_build_dir(), relh))
+ abs_headers.append(absh)
+ header_imports += swiftc.get_header_import_args(absh)
+ else:
+ raise InvalidArguments('Swift target %s contains a non-swift source file.' % target.get_basename())
+ os.makedirs(os.path.join(self.get_target_private_dir_abs(target)), exist_ok=True)
+ compile_args = swiftc.get_compile_only_args()
+ compile_args += swiftc.get_module_args(module_name)
+ link_args = swiftc.get_output_args(os.path.join(self.environment.get_build_dir(), self.get_target_filename(target)))
+ rundir = self.get_target_private_dir(target)
+ out_module_name = self.swift_module_file_name(target)
+ in_module_files = self.determine_swift_dep_modules(target)
+ abs_module_dirs = self.determine_swift_dep_dirs(target)
+ module_includes = []
+ for x in abs_module_dirs:
+ module_includes += swiftc.get_include_args(x)
+ link_deps = self.get_swift_link_deps(target)
+ abs_link_deps = [os.path.join(self.environment.get_build_dir(), x) for x in link_deps]
+ (rel_generated, _) = self.split_swift_generated_sources(target)
+ abs_generated = [os.path.join(self.environment.get_build_dir(), x) for x in rel_generated]
+ # We need absolute paths because swiftc needs to be invoked in a subdir
+ # and this is the easiest way about it.
+ objects = [] # Relative to swift invocation dir
+ rel_objects = [] # Relative to build.ninja
+ for i in abssrc + abs_generated:
+ base = os.path.split(i)[1]
+ oname = os.path.splitext(base)[0] + '.o'
+ objects.append(oname)
+ rel_objects.append(os.path.join(self.get_target_private_dir(target), oname))
+
+ # Swiftc does not seem to be able to emit objects and module files in one go.
+ elem = NinjaBuildElement(rel_objects,
+ 'swift_COMPILER',
+ abssrc)
+ elem.add_dep(in_module_files + rel_generated)
+ elem.add_dep(abs_headers)
+ elem.add_item('ARGS', compile_args + header_imports + abs_generated + module_includes)
+ elem.add_item('RUNDIR', rundir)
+ elem.write(outfile)
+ self.check_outputs(elem)
+ elem = NinjaBuildElement(out_module_name,
+ 'swift_COMPILER',
+ abssrc)
+ elem.add_dep(in_module_files + rel_generated)
+ elem.add_item('ARGS', compile_args + abs_generated + module_includes + swiftc.get_mod_gen_args())
+ elem.add_item('RUNDIR', rundir)
+ elem.write(outfile)
+ self.check_outputs(elem)
+ if isinstance(target, build.StaticLibrary):
+ elem = self.generate_link(target, outfile, self.get_target_filename(target),
+ rel_objects, self.build.static_linker)
+ elem.write(outfile)
+ elif isinstance(target, build.Executable):
+ elem = NinjaBuildElement(self.get_target_filename(target), 'swift_COMPILER', [])
+ elem.add_dep(rel_objects)
+ elem.add_dep(link_deps)
+ elem.add_item('ARGS', link_args + swiftc.get_std_exe_link_args() + objects + abs_link_deps)
+ elem.add_item('RUNDIR', rundir)
+ elem.write(outfile)
+ self.check_outputs(elem)
+ else:
+ raise MesonException('Swift supports only executable and static library targets.')
+
def generate_static_link_rules(self, is_cross, outfile):
if self.build.has_language('java'):
if not is_cross:
@@ -991,6 +1122,19 @@ class NinjaBackend(backends.Backend):
outfile.write(depstyle)
outfile.write('\n')
+ def generate_swift_compile_rules(self, compiler, outfile):
+ rule = 'rule %s_COMPILER\n' % compiler.get_language()
+ full_exe = [sys.executable,
+ os.path.join(self.environment.get_script_dir(), 'dirchanger.py'),
+ '$RUNDIR'] + compiler.get_exelist()
+ invoc = ' '.join([ninja_quote(i) for i in full_exe])
+ command = ' command = %s $ARGS $in\n' % invoc
+ description = ' description = Compiling Swift source $in.\n'
+ outfile.write(rule)
+ outfile.write(command)
+ outfile.write(description)
+ outfile.write('\n')
+
def generate_fortran_dep_hack(self, outfile):
if mesonlib.is_windows():
cmd = 'cmd /C ""'
@@ -1024,6 +1168,10 @@ rule FORTRAN_DEP_HACK
if not is_cross:
self.generate_rust_compile_rules(compiler, outfile)
return
+ if langname == 'swift':
+ if not is_cross:
+ self.generate_swift_compile_rules(compiler, outfile)
+ return
if langname == 'fortran':
self.generate_fortran_dep_hack(outfile)
if is_cross:
@@ -1289,7 +1437,7 @@ rule FORTRAN_DEP_HACK
obj_basename = src_filename.replace('/', '_').replace('\\', '_')
rel_obj = os.path.join(self.get_target_private_dir(target), obj_basename)
rel_obj += '.' + self.environment.get_object_suffix()
- dep_file = rel_obj + '.' + compiler.get_depfile_suffix()
+ dep_file = compiler.depfile_for_object(rel_obj)
if self.environment.coredata.get_builtin_option('use_pch'):
pchlist = target.get_pch(compiler.language)
else:
diff --git a/run_tests.py b/run_tests.py
index e84d610..f07e066 100755
--- a/run_tests.py
+++ b/run_tests.py
@@ -254,6 +254,7 @@ def detect_tests_to_run():
all_tests.append(('rust', gather_tests('test cases/rust'), False if shutil.which('rustc') else True))
all_tests.append(('objective c', gather_tests('test cases/objc'), False if not mesonlib.is_windows() else True))
all_tests.append(('fortran', gather_tests('test cases/fortran'), False if shutil.which('gfortran') else True))
+ all_tests.append(('swift', gather_tests('test cases/swift'), False if shutil.which('swiftc') else True))
return all_tests
def run_tests(extra_args):
diff --git a/test cases/swift/1 exe/meson.build b/test cases/swift/1 exe/meson.build
new file mode 100644
index 0000000..f986e9a
--- /dev/null
+++ b/test cases/swift/1 exe/meson.build
@@ -0,0 +1,3 @@
+project('swift exe', 'swift')
+
+test('swifttest', executable('swifttest', 'prog.swift'))
diff --git a/test cases/swift/1 exe/prog.swift b/test cases/swift/1 exe/prog.swift
new file mode 100644
index 0000000..1b489de
--- /dev/null
+++ b/test cases/swift/1 exe/prog.swift
@@ -0,0 +1 @@
+print("Swift executable is working.")
diff --git a/test cases/swift/2 multifile/libfile.swift b/test cases/swift/2 multifile/libfile.swift
new file mode 100644
index 0000000..45f941c
--- /dev/null
+++ b/test cases/swift/2 multifile/libfile.swift
@@ -0,0 +1,3 @@
+func printSomething(text: String) {
+ print("Got this: \(text)")
+}
diff --git a/test cases/swift/2 multifile/main.swift b/test cases/swift/2 multifile/main.swift
new file mode 100644
index 0000000..61d67e2
--- /dev/null
+++ b/test cases/swift/2 multifile/main.swift
@@ -0,0 +1 @@
+printSomething("String from main")
diff --git a/test cases/swift/2 multifile/meson.build b/test cases/swift/2 multifile/meson.build
new file mode 100644
index 0000000..9012f3d
--- /dev/null
+++ b/test cases/swift/2 multifile/meson.build
@@ -0,0 +1,3 @@
+project('2 files', 'swift')
+
+test('2files', executable('twofiles', 'main.swift', 'libfile.swift'))
diff --git a/test cases/swift/3 library/exe/main.swift b/test cases/swift/3 library/exe/main.swift
new file mode 100644
index 0000000..c5de373
--- /dev/null
+++ b/test cases/swift/3 library/exe/main.swift
@@ -0,0 +1,7 @@
+import DataSource
+
+let data = getData()
+let data2 = getOther()
+
+print("String from module: \(data)")
+print("Other string: \(data2)")
diff --git a/test cases/swift/3 library/exe/meson.build b/test cases/swift/3 library/exe/meson.build
new file mode 100644
index 0000000..6c13957
--- /dev/null
+++ b/test cases/swift/3 library/exe/meson.build
@@ -0,0 +1,2 @@
+exe = executable('dataprog', 'main.swift', link_with : datasource)
+test('dataprog', exe)
diff --git a/test cases/swift/3 library/lib/datasource.swift b/test cases/swift/3 library/lib/datasource.swift
new file mode 100644
index 0000000..4ac7c2a
--- /dev/null
+++ b/test cases/swift/3 library/lib/datasource.swift
@@ -0,0 +1,3 @@
+public func getData() -> String {
+ return "String from module."
+}
diff --git a/test cases/swift/3 library/lib/meson.build b/test cases/swift/3 library/lib/meson.build
new file mode 100644
index 0000000..fc65556
--- /dev/null
+++ b/test cases/swift/3 library/lib/meson.build
@@ -0,0 +1 @@
+datasource = static_library('DataSource', 'datasource.swift', 'othersource.swift')
diff --git a/test cases/swift/3 library/lib/othersource.swift b/test cases/swift/3 library/lib/othersource.swift
new file mode 100644
index 0000000..fb668ba
--- /dev/null
+++ b/test cases/swift/3 library/lib/othersource.swift
@@ -0,0 +1,3 @@
+public func getOther() -> String {
+ return "String from other source."
+}
diff --git a/test cases/swift/3 library/meson.build b/test cases/swift/3 library/meson.build
new file mode 100644
index 0000000..d601721
--- /dev/null
+++ b/test cases/swift/3 library/meson.build
@@ -0,0 +1,4 @@
+project('linking', 'swift')
+
+subdir('lib')
+subdir('exe')
diff --git a/test cases/swift/4 generate/gen/main.swift b/test cases/swift/4 generate/gen/main.swift
new file mode 100644
index 0000000..2f2bd36
--- /dev/null
+++ b/test cases/swift/4 generate/gen/main.swift
@@ -0,0 +1,10 @@
+import Glibc
+
+let fname = Process.arguments[1]
+let code = "public func getGenerated() -> Int {\n return 42\n}\n"
+
+let f = fopen(fname, "w")
+
+fwrite(code, 1, Int(strlen(code)), f)
+print("Name: \(fname)")
+fclose(f)
diff --git a/test cases/swift/4 generate/gen/meson.build b/test cases/swift/4 generate/gen/meson.build
new file mode 100644
index 0000000..8cd7e04
--- /dev/null
+++ b/test cases/swift/4 generate/gen/meson.build
@@ -0,0 +1,6 @@
+gen = executable('gen', 'main.swift')
+
+srcs = custom_target('gensrc',
+ output : 'gen.swift',
+ command : [gen, '@OUTPUT@']
+)
diff --git a/test cases/swift/4 generate/meson.build b/test cases/swift/4 generate/meson.build
new file mode 100644
index 0000000..ccc7d5c
--- /dev/null
+++ b/test cases/swift/4 generate/meson.build
@@ -0,0 +1,4 @@
+project('swift generator', 'swift')
+
+subdir('gen')
+subdir('user')
diff --git a/test cases/swift/4 generate/user/main.swift b/test cases/swift/4 generate/user/main.swift
new file mode 100644
index 0000000..e6b46cd
--- /dev/null
+++ b/test cases/swift/4 generate/user/main.swift
@@ -0,0 +1,3 @@
+let generated = getGenerated()
+
+print("Generated number is: \(generated).")
diff --git a/test cases/swift/4 generate/user/meson.build b/test cases/swift/4 generate/user/meson.build
new file mode 100644
index 0000000..fc4722d
--- /dev/null
+++ b/test cases/swift/4 generate/user/meson.build
@@ -0,0 +1,2 @@
+user = executable('user', 'main.swift', srcs)
+test('User test', user)
diff --git a/test cases/swift/5 mixed/main.swift b/test cases/swift/5 mixed/main.swift
new file mode 100644
index 0000000..5574126
--- /dev/null
+++ b/test cases/swift/5 mixed/main.swift
@@ -0,0 +1,3 @@
+let num = getNumber()
+
+print("The number returned from C code is: \(num).")
diff --git a/test cases/swift/5 mixed/meson.build b/test cases/swift/5 mixed/meson.build
new file mode 100644
index 0000000..71cb99d
--- /dev/null
+++ b/test cases/swift/5 mixed/meson.build
@@ -0,0 +1,6 @@
+project('mixed', 'c', 'swift')
+
+lib = static_library('mylib', 'mylib.c')
+exe = executable('prog', 'main.swift', 'mylib.h',
+ link_with : lib)
+test('c interface', exe)
diff --git a/test cases/swift/5 mixed/mylib.c b/test cases/swift/5 mixed/mylib.c
new file mode 100644
index 0000000..e091836
--- /dev/null
+++ b/test cases/swift/5 mixed/mylib.c
@@ -0,0 +1,5 @@
+#include"mylib.h"
+
+int getNumber() {
+ return 42;
+}
diff --git a/test cases/swift/5 mixed/mylib.h b/test cases/swift/5 mixed/mylib.h
new file mode 100644
index 0000000..21bd9eb
--- /dev/null
+++ b/test cases/swift/5 mixed/mylib.h
@@ -0,0 +1,3 @@
+#pragma once
+
+int getNumber();