diff options
20 files changed, 67 insertions, 3 deletions
diff --git a/docs/markdown/snippets/swift-parse-as-library.md b/docs/markdown/snippets/swift-parse-as-library.md new file mode 100644 index 000000000..5208899bc --- /dev/null +++ b/docs/markdown/snippets/swift-parse-as-library.md @@ -0,0 +1,8 @@ +## Top-level statement handling in Swift libraries + +The Swift compiler normally treats modules with a single source +file (and files named main.swift) to run top-level code at program +start. This emits a main symbol which is usually undesirable in a +library target. Meson now automatically passes the *-parse-as-library* +flag to the Swift compiler in case of single-file library targets to +disable this behavior unless the source file is called main.swift. diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index ba75ce737..82411b0e6 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -2288,6 +2288,13 @@ class NinjaBackend(backends.Backend): compile_args += swiftc.get_cxx_interoperability_args(target.compilers) compile_args += self.build.get_project_args(swiftc, target.subproject, target.for_machine) compile_args += self.build.get_global_args(swiftc, target.for_machine) + if isinstance(target, (build.StaticLibrary, build.SharedLibrary)): + # swiftc treats modules with a single source file, and the main.swift file in multi-source file modules + # as top-level code. This is undesirable in library targets since it emits a main function. Add the + # -parse-as-library option as necessary to prevent emitting the main function while keeping files explicitly + # named main.swift treated as the entrypoint of the module in case this is desired. + if len(abssrc) == 1 and os.path.basename(abssrc[0]) != 'main.swift': + compile_args += swiftc.get_library_args() for i in reversed(target.get_include_dirs()): basedir = i.get_curdir() for d in i.get_incdirs(): diff --git a/mesonbuild/compilers/swift.py b/mesonbuild/compilers/swift.py index 47d254be5..3fff7a1ff 100644 --- a/mesonbuild/compilers/swift.py +++ b/mesonbuild/compilers/swift.py @@ -159,6 +159,9 @@ class SwiftCompiler(Compiler): else: return ['-cxx-interoperability-mode=off'] + def get_library_args(self) -> T.List[str]: + return ['-parse-as-library'] + def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], build_dir: str) -> T.List[str]: for idx, i in enumerate(parameter_list): diff --git a/test cases/swift/14 single-file library/main.swift b/test cases/swift/14 single-file library/main.swift new file mode 100644 index 000000000..ccc8fb98b --- /dev/null +++ b/test cases/swift/14 single-file library/main.swift @@ -0,0 +1,3 @@ +import SingleFile + +callMe() diff --git a/test cases/swift/14 single-file library/meson.build b/test cases/swift/14 single-file library/meson.build new file mode 100644 index 000000000..8eda1d59d --- /dev/null +++ b/test cases/swift/14 single-file library/meson.build @@ -0,0 +1,4 @@ +project('single-file library', 'swift') + +lib = static_library('SingleFile', 'singlefile.swift') +executable('program', 'main.swift', link_with: [lib]) diff --git a/test cases/swift/14 single-file library/singlefile.swift b/test cases/swift/14 single-file library/singlefile.swift new file mode 100644 index 000000000..617952f4e --- /dev/null +++ b/test cases/swift/14 single-file library/singlefile.swift @@ -0,0 +1 @@ +public func callMe() {} diff --git a/test cases/swift/15 main in single-file library/main.swift b/test cases/swift/15 main in single-file library/main.swift new file mode 100644 index 000000000..0d95abbcf --- /dev/null +++ b/test cases/swift/15 main in single-file library/main.swift @@ -0,0 +1,3 @@ +import CProgram + +precondition(callMe() == 4) diff --git a/test cases/swift/15 main in single-file library/meson.build b/test cases/swift/15 main in single-file library/meson.build new file mode 100644 index 000000000..2e1202e34 --- /dev/null +++ b/test cases/swift/15 main in single-file library/meson.build @@ -0,0 +1,4 @@ +project('main in single-file library', 'swift', 'c') + +lib = static_library('Library', 'main.swift', include_directories: ['.']) +executable('program', 'program.c', link_with: [lib]) diff --git a/test cases/swift/15 main in single-file library/module.modulemap b/test cases/swift/15 main in single-file library/module.modulemap new file mode 100644 index 000000000..3c1817a32 --- /dev/null +++ b/test cases/swift/15 main in single-file library/module.modulemap @@ -0,0 +1,3 @@ +module CProgram [extern_c] { + header "program.h" +} diff --git a/test cases/swift/15 main in single-file library/program.c b/test cases/swift/15 main in single-file library/program.c new file mode 100644 index 000000000..8959daee5 --- /dev/null +++ b/test cases/swift/15 main in single-file library/program.c @@ -0,0 +1,5 @@ +#include "program.h" + +int callMe() { + return 4; +} diff --git a/test cases/swift/15 main in single-file library/program.h b/test cases/swift/15 main in single-file library/program.h new file mode 100644 index 000000000..5058be393 --- /dev/null +++ b/test cases/swift/15 main in single-file library/program.h @@ -0,0 +1 @@ +int callMe(void); diff --git a/test cases/swift/16 main in multi-file library/main.swift b/test cases/swift/16 main in multi-file library/main.swift new file mode 100644 index 000000000..3682e8d40 --- /dev/null +++ b/test cases/swift/16 main in multi-file library/main.swift @@ -0,0 +1,4 @@ +import CProgram + +precondition(callMe() == 4) +precondition(callMe2() == 6) diff --git a/test cases/swift/16 main in multi-file library/meson.build b/test cases/swift/16 main in multi-file library/meson.build new file mode 100644 index 000000000..4d287f3a3 --- /dev/null +++ b/test cases/swift/16 main in multi-file library/meson.build @@ -0,0 +1,4 @@ +project('main in multi-file library', 'swift', 'c') + +lib = static_library('Library', 'main.swift', 'more.swift', include_directories: ['.']) +executable('program', 'program.c', link_with: [lib]) diff --git a/test cases/swift/16 main in multi-file library/module.modulemap b/test cases/swift/16 main in multi-file library/module.modulemap new file mode 100644 index 000000000..3c1817a32 --- /dev/null +++ b/test cases/swift/16 main in multi-file library/module.modulemap @@ -0,0 +1,3 @@ +module CProgram [extern_c] { + header "program.h" +} diff --git a/test cases/swift/16 main in multi-file library/more.swift b/test cases/swift/16 main in multi-file library/more.swift new file mode 100644 index 000000000..716500f6f --- /dev/null +++ b/test cases/swift/16 main in multi-file library/more.swift @@ -0,0 +1,3 @@ +func callMe2() -> Int { + 6 +} diff --git a/test cases/swift/16 main in multi-file library/program.c b/test cases/swift/16 main in multi-file library/program.c new file mode 100644 index 000000000..8959daee5 --- /dev/null +++ b/test cases/swift/16 main in multi-file library/program.c @@ -0,0 +1,5 @@ +#include "program.h" + +int callMe() { + return 4; +} diff --git a/test cases/swift/16 main in multi-file library/program.h b/test cases/swift/16 main in multi-file library/program.h new file mode 100644 index 000000000..5058be393 --- /dev/null +++ b/test cases/swift/16 main in multi-file library/program.h @@ -0,0 +1 @@ +int callMe(void); diff --git a/test cases/swift/8 extra args/lib.swift b/test cases/swift/8 extra args/lib.swift new file mode 100644 index 000000000..f8167ad45 --- /dev/null +++ b/test cases/swift/8 extra args/lib.swift @@ -0,0 +1,3 @@ +public func callMe() { + print("test") +} diff --git a/test cases/swift/8 extra args/main.swift b/test cases/swift/8 extra args/main.swift deleted file mode 100644 index 1ff8e07c7..000000000 --- a/test cases/swift/8 extra args/main.swift +++ /dev/null @@ -1 +0,0 @@ -print("test") diff --git a/test cases/swift/8 extra args/meson.build b/test cases/swift/8 extra args/meson.build index ead2ff509..d243e3646 100644 --- a/test cases/swift/8 extra args/meson.build +++ b/test cases/swift/8 extra args/meson.build @@ -2,8 +2,8 @@ project('extra args', 'swift') trace_fname = 'trace.json' -lib = static_library('main', - 'main.swift', +lib = static_library('lib', + 'lib.swift', swift_args: [ '-emit-loaded-module-trace', '-emit-loaded-module-trace-path', '../' + trace_fname |
