From d83c2894428104188cd5f75565ee7bd2b4fdcd54 Mon Sep 17 00:00:00 2001 From: Matthias Klumpp Date: Tue, 29 Aug 2017 04:57:06 +0200 Subject: d: Add easy way to use D-specific features Of course D compilers have different flags to set some important D-specific settings. This adds a simple method to change these flags in a compiler-agnostic way in Meson. This replaces the previous `unittest_args` method with a more generic variant. --- mesonbuild/compilers/d.py | 55 ++++++++++++++++++++++++++++++--- mesonbuild/interpreter.py | 17 +++++++--- test cases/d/9 features/app.d | 51 ++++++++++++++++++++++++++++++ test cases/d/9 features/data/food.txt | 6 ++++ test cases/d/9 features/data/people.txt | 5 +++ test cases/d/9 features/meson.build | 28 +++++++++++++++++ 6 files changed, 153 insertions(+), 9 deletions(-) create mode 100644 test cases/d/9 features/app.d create mode 100644 test cases/d/9 features/data/food.txt create mode 100644 test cases/d/9 features/data/people.txt create mode 100644 test cases/d/9 features/meson.build diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py index a989704..7fc21cc 100644 --- a/mesonbuild/compilers/d.py +++ b/mesonbuild/compilers/d.py @@ -27,6 +27,20 @@ from .compilers import ( CompilerArgs, ) +d_feature_args = {'gcc': {'unittest': '-funittest', + 'version': '-fversion', + 'import_dir': '-J' + }, + 'llvm': {'unittest': '-unittest', + 'version': '-d-version', + 'import_dir': '-J' + }, + 'dmd': {'unittest': '-unittest', + 'version': '-version', + 'import_dir': '-J' + } + } + class DCompiler(Compiler): def __init__(self, exelist, version, is_cross): self.language = 'd' @@ -79,8 +93,42 @@ class DCompiler(Compiler): # FIXME: Make this work for Windows, MacOS and cross-compiling return get_gcc_soname_args(GCC_STANDARD, prefix, shlib_name, suffix, path, soversion, is_shared_module) - def get_unittest_args(self): - return ['-unittest'] + def get_feature_args(self, args, kwargs): + res = [] + if 'unittest' in kwargs: + unittest = kwargs.pop('unittest') + unittest_arg = d_feature_args[self.id]['unittest'] + if not unittest_arg: + raise EnvironmentException('D compiler %s does not support the "unittest" feature.' % self.name_string()) + if unittest: + res.append(unittest_arg) + + if 'versions' in kwargs: + versions = kwargs.pop('versions') + if not isinstance(versions, list): + versions = [versions] + + version_arg = d_feature_args[self.id]['version'] + if not version_arg: + raise EnvironmentException('D compiler %s does not support the "feature versions" feature.' % self.name_string()) + for v in versions: + res.append('{0}={1}'.format(version_arg, v)) + + if 'import_dirs' in kwargs: + import_dirs = kwargs.pop('import_dirs') + if not isinstance(import_dirs, list): + import_dirs = [import_dirs] + + import_dir_arg = d_feature_args[self.id]['import_dir'] + if not import_dir_arg: + raise EnvironmentException('D compiler %s does not support the "string import directories" feature.' % self.name_string()) + for d in import_dirs: + res.append('{0}{1}'.format(import_dir_arg, d)) + + if kwargs: + raise EnvironmentException('Unknown D compiler feature(s) selected: %s' % ', '.join(kwargs.keys())) + + return res def get_buildtype_linker_args(self, buildtype): return [] @@ -217,9 +265,6 @@ class GnuDCompiler(DCompiler): def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath): return self.build_unix_rpath_args(build_dir, from_dir, rpath_paths, build_rpath, install_rpath) - def get_unittest_args(self): - return ['-funittest'] - class LLVMDCompiler(DCompiler): def __init__(self, exelist, version, is_cross): diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 2bcf198..c6cface 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -655,6 +655,7 @@ class CompilerHolder(InterpreterObject): 'get_supported_arguments': self.get_supported_arguments_method, 'first_supported_argument': self.first_supported_argument_method, 'unittest_args': self.unittest_args_method, + 'feature_args': self.feature_args_method, 'symbols_have_underscore_prefix': self.symbols_have_underscore_prefix_method, }) @@ -751,11 +752,19 @@ class CompilerHolder(InterpreterObject): ''' return self.compiler.symbols_have_underscore_prefix(self.environment) - def unittest_args_method(self, args, kwargs): + def feature_args_method(self, args, kwargs): # At time, only D compilers have this feature. - if not hasattr(self.compiler, 'get_unittest_args'): - raise InterpreterException('This {} compiler has no unittest arguments.'.format(self.compiler.get_display_language())) - return self.compiler.get_unittest_args() + if not hasattr(self.compiler, 'get_feature_args'): + raise InterpreterException('This {} compiler has no feature arguments.'.format(self.compiler.get_display_language())) + return self.compiler.get_feature_args(args, kwargs) + + def unittest_args_method(self, args, kwargs): + ''' + This function is deprecated and should not be used. + ''' + if not hasattr(self.compiler, 'get_feature_args'): + raise InterpreterException('This {} compiler has no feature arguments.'.format(self.compiler.get_display_language())) + return self.compiler.get_feature_args(args, {'unittest': 'true'}) def has_member_method(self, args, kwargs): if len(args) != 2: diff --git a/test cases/d/9 features/app.d b/test cases/d/9 features/app.d new file mode 100644 index 0000000..37cc1dd --- /dev/null +++ b/test cases/d/9 features/app.d @@ -0,0 +1,51 @@ + +import std.stdio; +import std.array : split; +import std.string : strip; + +auto getMenu () +{ + auto foods = import ("food.txt").strip.split ("\n"); + return foods; +} + +auto getPeople () +{ + return import ("people.txt").strip.split ("\n"); +} + +void main (string[] args) +{ + import std.array : join; + import core.stdc.stdlib : exit; + + immutable request = args[1]; + if (request == "menu") { + version (No_Menu) { + } else { + writeln ("On the menu: ", getMenu.join (", ")); + exit (0); + } + } + + version (With_People) { + if (request == "people") { + writeln ("People: ", getPeople.join (", ")); + exit (0); + } + } + + // we fail here + exit (1); +} + +unittest +{ + writeln ("TEST"); + import core.stdc.stdlib : exit; + + writeln(getMenu); + assert (getMenu () == ["Spam", "Eggs", "Spam", "Baked Beans", "Spam", "Spam"]); + + exit (0); +} diff --git a/test cases/d/9 features/data/food.txt b/test cases/d/9 features/data/food.txt new file mode 100644 index 0000000..8275dd0 --- /dev/null +++ b/test cases/d/9 features/data/food.txt @@ -0,0 +1,6 @@ +Spam +Eggs +Spam +Baked Beans +Spam +Spam diff --git a/test cases/d/9 features/data/people.txt b/test cases/d/9 features/data/people.txt new file mode 100644 index 0000000..abbae06 --- /dev/null +++ b/test cases/d/9 features/data/people.txt @@ -0,0 +1,5 @@ +Rick +Morty +Summer +Beth +Jerry diff --git a/test cases/d/9 features/meson.build b/test cases/d/9 features/meson.build new file mode 100644 index 0000000..9fda3bd --- /dev/null +++ b/test cases/d/9 features/meson.build @@ -0,0 +1,28 @@ +project('D Features', 'd') +dc = meson.get_compiler('d') + +# directory for data +data_dir = join_paths(meson.current_source_dir(), 'data') + +# test string import dirs only +dfeatures_simple = dc.feature_args(import_dirs: [data_dir]) + +e_plain = executable('dapp_menu', 'app.d', d_args: dfeatures_simple) +test('dapp_menu_t_fail', e_plain, should_fail: true) +test('dapp_menu_t', e_plain, args: ['menu']) + +# test feature versions and string imports +dfeatures_version = dc.feature_args(import_dirs: [data_dir], versions: ['No_Menu', 'With_People']) +e_versions = executable('dapp_versions', 'app.d', d_args: dfeatures_version) +test('dapp_versions_t_fail', e_versions, args: ['menu'], should_fail: true) +test('dapp_versions_t', e_versions, args: ['people']) + +# test everything and unittests +dfeatures_test = dc.feature_args( + import_dirs: [data_dir], + versions: ['No_Menu', 'With_People'], + unittest: true +) +e_test = executable('dapp_test', 'app.d', + d_args: dfeatures_test) +test('dapp_test', e_test) -- cgit v1.1 From 6cd3f066b4c4e9ffbe7c8af6a183a6ebe39925dc Mon Sep 17 00:00:00 2001 From: Matthias Klumpp Date: Tue, 12 Sep 2017 14:29:23 +0200 Subject: d: Implement specific properties for D features --- mesonbuild/build.py | 20 +++++++++++++++++++- mesonbuild/compilers/d.py | 2 +- mesonbuild/interpreter.py | 8 ++++++-- test cases/d/9 features/meson.build | 27 ++++++++++++++------------- 4 files changed, 40 insertions(+), 17 deletions(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 89689d7..2e27153 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -36,6 +36,9 @@ known_basic_kwargs = {'install': True, 'vala_args': True, 'fortran_args': True, 'd_args': True, + 'd_feature_import_dirs': True, + 'd_feature_unittest': True, + 'd_feature_versions': True, 'java_args': True, 'rust_args': True, 'link_args': True, @@ -351,11 +354,11 @@ class BuildTarget(Target): # 1. Pre-existing objects provided by the user with the `objects:` kwarg # 2. Compiled objects created by and extracted from another target self.process_objectlist(objects) + self.process_compilers() self.process_kwargs(kwargs, environment) self.check_unknown_kwargs(kwargs) if not self.sources and not self.generated and not self.objects: raise InvalidArguments('Build target %s has no sources.' % name) - self.process_compilers() self.validate_sources() self.validate_cross_install(environment) @@ -669,8 +672,23 @@ class BuildTarget(Target): self.vala_header = kwargs.get('vala_header', self.name + '.h') self.vala_vapi = kwargs.get('vala_vapi', self.name + '.vapi') self.vala_gir = kwargs.get('vala_gir', None) + dlist = stringlistify(kwargs.get('d_args', [])) self.add_compiler_args('d', dlist) + dfeatures = dict() + dfeature_unittest = kwargs.get('d_feature_unittest', False) + if dfeature_unittest: + dfeatures['unittest'] = dfeature_unittest + dfeature_versions = kwargs.get('d_feature_versions', None) + if dfeature_versions: + dfeatures['versions'] = dfeature_versions + dfeature_import_dirs = kwargs.get('d_feature_import_dirs', None) + if dfeature_import_dirs: + dfeatures['import_dirs'] = dfeature_import_dirs + if dfeatures: + if 'd' in self.compilers: + self.add_compiler_args('d', self.compilers['d'].get_feature_args(dfeatures)) + self.link_args = flatten(kwargs.get('link_args', [])) for i in self.link_args: if not isinstance(i, str): diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py index 7fc21cc..9739f28 100644 --- a/mesonbuild/compilers/d.py +++ b/mesonbuild/compilers/d.py @@ -93,7 +93,7 @@ class DCompiler(Compiler): # FIXME: Make this work for Windows, MacOS and cross-compiling return get_gcc_soname_args(GCC_STANDARD, prefix, shlib_name, suffix, path, soversion, is_shared_module) - def get_feature_args(self, args, kwargs): + def get_feature_args(self, kwargs): res = [] if 'unittest' in kwargs: unittest = kwargs.pop('unittest') diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index c6cface..c72fa3f 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -756,15 +756,16 @@ class CompilerHolder(InterpreterObject): # At time, only D compilers have this feature. if not hasattr(self.compiler, 'get_feature_args'): raise InterpreterException('This {} compiler has no feature arguments.'.format(self.compiler.get_display_language())) - return self.compiler.get_feature_args(args, kwargs) + return self.compiler.get_feature_args(kwargs) def unittest_args_method(self, args, kwargs): ''' This function is deprecated and should not be used. + It can be removed in a future version of Meson. ''' if not hasattr(self.compiler, 'get_feature_args'): raise InterpreterException('This {} compiler has no feature arguments.'.format(self.compiler.get_display_language())) - return self.compiler.get_feature_args(args, {'unittest': 'true'}) + return self.compiler.get_feature_args({'unittest': 'true'}) def has_member_method(self, args, kwargs): if len(args) != 2: @@ -1258,6 +1259,9 @@ pch_kwargs = set(['c_pch', 'cpp_pch']) lang_arg_kwargs = set(['c_args', 'cpp_args', 'd_args', + 'd_feature_import_dirs', + 'd_feature_unittest', + 'd_feature_versions', 'fortran_args', 'java_args', 'objc_args', diff --git a/test cases/d/9 features/meson.build b/test cases/d/9 features/meson.build index 9fda3bd..1d36b9d 100644 --- a/test cases/d/9 features/meson.build +++ b/test cases/d/9 features/meson.build @@ -1,28 +1,29 @@ project('D Features', 'd') -dc = meson.get_compiler('d') # directory for data data_dir = join_paths(meson.current_source_dir(), 'data') -# test string import dirs only -dfeatures_simple = dc.feature_args(import_dirs: [data_dir]) - -e_plain = executable('dapp_menu', 'app.d', d_args: dfeatures_simple) +e_plain = executable('dapp_menu', + 'app.d', + d_feature_import_dirs: [data_dir] +) test('dapp_menu_t_fail', e_plain, should_fail: true) test('dapp_menu_t', e_plain, args: ['menu']) # test feature versions and string imports -dfeatures_version = dc.feature_args(import_dirs: [data_dir], versions: ['No_Menu', 'With_People']) -e_versions = executable('dapp_versions', 'app.d', d_args: dfeatures_version) +e_versions = executable('dapp_versions', + 'app.d', + d_feature_import_dirs: [data_dir], + d_feature_versions: ['No_Menu', 'With_People'] +) test('dapp_versions_t_fail', e_versions, args: ['menu'], should_fail: true) test('dapp_versions_t', e_versions, args: ['people']) # test everything and unittests -dfeatures_test = dc.feature_args( - import_dirs: [data_dir], - versions: ['No_Menu', 'With_People'], - unittest: true +e_test = executable('dapp_test', + 'app.d', + d_feature_import_dirs: [data_dir], + d_feature_versions: ['No_Menu', 'With_People'], + d_feature_unittest: true ) -e_test = executable('dapp_test', 'app.d', - d_args: dfeatures_test) test('dapp_test', e_test) -- cgit v1.1 From 75fdf413e46b490c16eed834bd1c08e56bebe0f9 Mon Sep 17 00:00:00 2001 From: Matthias Klumpp Date: Tue, 12 Sep 2017 17:27:14 +0200 Subject: Drop feature_args call in favor of letting pkgconfig do this directly --- mesonbuild/interpreter.py | 7 ------- mesonbuild/modules/pkgconfig.py | 8 +++++++- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index c72fa3f..acc54c3 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -655,7 +655,6 @@ class CompilerHolder(InterpreterObject): 'get_supported_arguments': self.get_supported_arguments_method, 'first_supported_argument': self.first_supported_argument_method, 'unittest_args': self.unittest_args_method, - 'feature_args': self.feature_args_method, 'symbols_have_underscore_prefix': self.symbols_have_underscore_prefix_method, }) @@ -752,12 +751,6 @@ class CompilerHolder(InterpreterObject): ''' return self.compiler.symbols_have_underscore_prefix(self.environment) - def feature_args_method(self, args, kwargs): - # At time, only D compilers have this feature. - if not hasattr(self.compiler, 'get_feature_args'): - raise InterpreterException('This {} compiler has no feature arguments.'.format(self.compiler.get_display_language())) - return self.compiler.get_feature_args(kwargs) - def unittest_args_method(self, args, kwargs): ''' This function is deprecated and should not be used. diff --git a/mesonbuild/modules/pkgconfig.py b/mesonbuild/modules/pkgconfig.py index 0a0498c..594dd86 100644 --- a/mesonbuild/modules/pkgconfig.py +++ b/mesonbuild/modules/pkgconfig.py @@ -121,7 +121,7 @@ class PkgConfigModule(ExtensionModule): @permittedKwargs({'libraries', 'version', 'name', 'description', 'filebase', 'subdirs', 'requires', 'requires_private', 'libraries_private', - 'install_dir', 'extra_cflags', 'variables', 'url'}) + 'install_dir', 'extra_cflags', 'variables', 'url', 'd_feature_versions'}) def generate(self, state, args, kwargs): if len(args) > 0: raise mesonlib.MesonException('Pkgconfig_gen takes no positional arguments.') @@ -148,6 +148,12 @@ class PkgConfigModule(ExtensionModule): conflicts = mesonlib.stringlistify(kwargs.get('conflicts', [])) extra_cflags = mesonlib.stringlistify(kwargs.get('extra_cflags', [])) + dversions = kwargs.get('d_feature_versions', None) + if dversions: + compiler = state.environment.coredata.compilers.get('d') + if compiler: + extra_cflags.extend(compiler.get_feature_args({'versions': dversions})) + def parse_variable_list(stringlist): reserved = ['prefix', 'libdir', 'includedir'] variables = [] -- cgit v1.1 From 61db415d7fbdb0c3d897e75e91644947525365da Mon Sep 17 00:00:00 2001 From: Matthias Klumpp Date: Sun, 17 Sep 2017 17:21:06 +0200 Subject: d: Make feature names less verbose --- mesonbuild/build.py | 12 ++++++------ mesonbuild/interpreter.py | 6 +++--- mesonbuild/modules/pkgconfig.py | 4 ++-- test cases/d/9 features/meson.build | 12 ++++++------ 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 2e27153..5bf2874 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -36,9 +36,9 @@ known_basic_kwargs = {'install': True, 'vala_args': True, 'fortran_args': True, 'd_args': True, - 'd_feature_import_dirs': True, - 'd_feature_unittest': True, - 'd_feature_versions': True, + 'd_import_dirs': True, + 'd_unittest': True, + 'd_module_versions': True, 'java_args': True, 'rust_args': True, 'link_args': True, @@ -676,13 +676,13 @@ class BuildTarget(Target): dlist = stringlistify(kwargs.get('d_args', [])) self.add_compiler_args('d', dlist) dfeatures = dict() - dfeature_unittest = kwargs.get('d_feature_unittest', False) + dfeature_unittest = kwargs.get('d_unittest', False) if dfeature_unittest: dfeatures['unittest'] = dfeature_unittest - dfeature_versions = kwargs.get('d_feature_versions', None) + dfeature_versions = kwargs.get('d_module_versions', None) if dfeature_versions: dfeatures['versions'] = dfeature_versions - dfeature_import_dirs = kwargs.get('d_feature_import_dirs', None) + dfeature_import_dirs = kwargs.get('d_import_dirs', None) if dfeature_import_dirs: dfeatures['import_dirs'] = dfeature_import_dirs if dfeatures: diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index acc54c3..9a1bb84 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -1252,9 +1252,9 @@ pch_kwargs = set(['c_pch', 'cpp_pch']) lang_arg_kwargs = set(['c_args', 'cpp_args', 'd_args', - 'd_feature_import_dirs', - 'd_feature_unittest', - 'd_feature_versions', + 'd_import_dirs', + 'd_unittest', + 'd_module_versions', 'fortran_args', 'java_args', 'objc_args', diff --git a/mesonbuild/modules/pkgconfig.py b/mesonbuild/modules/pkgconfig.py index 594dd86..a7a35d5 100644 --- a/mesonbuild/modules/pkgconfig.py +++ b/mesonbuild/modules/pkgconfig.py @@ -121,7 +121,7 @@ class PkgConfigModule(ExtensionModule): @permittedKwargs({'libraries', 'version', 'name', 'description', 'filebase', 'subdirs', 'requires', 'requires_private', 'libraries_private', - 'install_dir', 'extra_cflags', 'variables', 'url', 'd_feature_versions'}) + 'install_dir', 'extra_cflags', 'variables', 'url', 'd_module_versions'}) def generate(self, state, args, kwargs): if len(args) > 0: raise mesonlib.MesonException('Pkgconfig_gen takes no positional arguments.') @@ -148,7 +148,7 @@ class PkgConfigModule(ExtensionModule): conflicts = mesonlib.stringlistify(kwargs.get('conflicts', [])) extra_cflags = mesonlib.stringlistify(kwargs.get('extra_cflags', [])) - dversions = kwargs.get('d_feature_versions', None) + dversions = kwargs.get('d_module_versions', None) if dversions: compiler = state.environment.coredata.compilers.get('d') if compiler: diff --git a/test cases/d/9 features/meson.build b/test cases/d/9 features/meson.build index 1d36b9d..9e63710 100644 --- a/test cases/d/9 features/meson.build +++ b/test cases/d/9 features/meson.build @@ -5,7 +5,7 @@ data_dir = join_paths(meson.current_source_dir(), 'data') e_plain = executable('dapp_menu', 'app.d', - d_feature_import_dirs: [data_dir] + d_import_dirs: [data_dir] ) test('dapp_menu_t_fail', e_plain, should_fail: true) test('dapp_menu_t', e_plain, args: ['menu']) @@ -13,8 +13,8 @@ test('dapp_menu_t', e_plain, args: ['menu']) # test feature versions and string imports e_versions = executable('dapp_versions', 'app.d', - d_feature_import_dirs: [data_dir], - d_feature_versions: ['No_Menu', 'With_People'] + d_import_dirs: [data_dir], + d_module_versions: ['No_Menu', 'With_People'] ) test('dapp_versions_t_fail', e_versions, args: ['menu'], should_fail: true) test('dapp_versions_t', e_versions, args: ['people']) @@ -22,8 +22,8 @@ test('dapp_versions_t', e_versions, args: ['people']) # test everything and unittests e_test = executable('dapp_test', 'app.d', - d_feature_import_dirs: [data_dir], - d_feature_versions: ['No_Menu', 'With_People'], - d_feature_unittest: true + d_import_dirs: [data_dir], + d_module_versions: ['No_Menu', 'With_People'], + d_unittest: true ) test('dapp_test', e_test) -- cgit v1.1 From c3c37fac38dcea1f00cb6750722b39704ef8fc10 Mon Sep 17 00:00:00 2001 From: Matthias Klumpp Date: Sun, 17 Sep 2017 21:36:23 +0200 Subject: docs: Document the D support --- docs/markdown/D.md | 89 +++++++++++++++++++++++++++++++++++++++ docs/markdown/Pkgconfig-module.md | 2 + docs/markdown/Reference-manual.md | 6 ++- docs/markdown/index.md | 2 +- docs/sitemap.txt | 1 + 5 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 docs/markdown/D.md diff --git a/docs/markdown/D.md b/docs/markdown/D.md new file mode 100644 index 0000000..7b0d485 --- /dev/null +++ b/docs/markdown/D.md @@ -0,0 +1,89 @@ +--- +title: D +short-description: Compiling D sources +... + +# Compiling D applications + +Meson has support for compiling D programs. A minimal `meson.build` file for D looks like this: + +```meson +project('myapp', 'd') + +executable('myapp', 'app.d') +``` + +## Compiling different versions + +If you are using the [version()](https://dlang.org/spec/version.html) feature for conditional compilation, you can use it using the `d_module_versions` +target property: +```meson +project('myapp', 'd') +executable('myapp', 'app.d', d_module_versions: ['Demo', 'FeatureA']) +``` + +## Using embedded unittests + +If you are using embedded [unittest functions](https://dlang.org/spec/unittest.html), your source code needs to be compiled twice, once in regular +mode, and once with unittests active. This is done by setting the `d_unittest` target property to `true`. +Meson will only ever pass the respective compiler's `-unittest` flag, and never have the compiler generate an empty main function. +If you need that feature in a portable way, create an empty `main()` function for unittests yourself, since the GNU D compiler +does not have this feature. + +This is an example for using D unittests with Meson: +```meson +project('myapp_tested', 'd') + +myapp_src = ['app.d', 'alpha.d', 'beta.d'] +executable('myapp', myapp_src) + +test_exe = executable('myapp_test', myapp_src, d_unittest: true) +test('myapptest', test_exe) +``` + +# Compiling D libraries and installing them + +Building D libraries is a straightforward process, not different from how C libraries are built in Meson. You should generate a pkg-config file +and install it, in order to make other software on the system find the dependency once it is installed. + +This is an example on how to build a D shared library: +```meson +project('mylib', 'd', version: '1.2.0') + +project_soversion = 0 +glib_dep = dependency('glib-2.0') + +my_lib = library('mylib', + ['src/mylib/libfunctions.d'], + dependencies: [glib_dep], + install: true, + version: meson.project_version(), + soversion: project_soversion, + d_module_versions: ['FeatureA', 'featureB'] +) +pkgc.generate(name: 'mylib', + libraries: my_lib, + subdirs: 'd/mylib', + version: meson.project_version(), + description: 'A simple example D library.', + d_module_versions: ['FeatureA'] +) +install_subdir('src/mylib/', install_dir: 'include/d/mylib/') +``` + +It is important to make the D sources install in a subdirectory in the include path, in this case `/usr/include/d/mylib/mylib`. +All D compilers include the `/usr/include/d` directory by default, and if your library would be installed into `/usr/include/d/mylib`, there +is a high chance that, when you compile your project again on a machine where you installed it, the compiler will prefer the old installed include over +the new version in the source tree, leading to very confusing errors. + +This is an example of how to use the D library we just built and installed in an application: +```meson +project('myapp', 'd') + +mylib_dep = dependency('mylib', version: '>= 1.2.0') +myapp_src = ['app.d', 'alpha.d', 'beta.d'] +executable('myapp', myapp_src, dependencies: [mylib_dep]) +``` + +Please keep in mind that the library and executable would both need to be built with the exact same D compiler and D compiler version. The D ABI is not +stable across compilers and their versions, and mixing compilers will lead to problems. diff --git a/docs/markdown/Pkgconfig-module.md b/docs/markdown/Pkgconfig-module.md index 5a660fd..7f767f1 100644 --- a/docs/markdown/Pkgconfig-module.md +++ b/docs/markdown/Pkgconfig-module.md @@ -41,3 +41,5 @@ keyword arguments. e.g. `datadir=${prefix}/share`. The names `prefix`, `libdir` and `installdir` are reserved and may not be used. - `version` a string describing the version of this library +- `d_module_versions` a list of module version flags used when compiling + D sources referred to by this pkg-config file diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md index 34b473d..7c26d7c 100644 --- a/docs/markdown/Reference-manual.md +++ b/docs/markdown/Reference-manual.md @@ -424,6 +424,10 @@ be passed to [shared and static libraries](#library). - `override_options` takes an array of strings in the same format as `project`'s `default_options` overriding the values of these options for this target only, since 0.40.0 +- `d_import_dirs` list of directories to look in for string imports used + in the D programmling language +- `d_unittest`, when set to true, the D modules are compiled in debug mode +- `d_module_versions` list of module versions set when compiling D sources The list of `sources`, `objects`, and `dependencies` is always flattened, which means you can freely nest and add lists while @@ -835,7 +839,7 @@ This function prints its argument to stdout. The first argument to this function must be a string defining the name of this project. It is followed by programming languages that the project uses. Supported values for languages are `c`, `cpp` (for -`C++`), `objc`, `objcpp`, `fortran`, `java`, `cs` (for `C#`) and +`C++`), `d`, `objc`, `objcpp`, `fortran`, `java`, `cs` (for `C#`) and `vala`. In versions before `0.40.0` you must have at least one language listed. diff --git a/docs/markdown/index.md b/docs/markdown/index.md index 8e35a4d..2aba0d7 100644 --- a/docs/markdown/index.md +++ b/docs/markdown/index.md @@ -13,7 +13,7 @@ The main design point of Meson is that every moment a developer spends writing o ## Features * multiplatform support for Linux, OSX, Windows, GCC, Clang, Visual Studio and others -* supported languages include C, C++, Fortran, Java, Rust +* supported languages include C, C++, D, Fortran, Java, Rust * build definitions in a very readable and user friendly non-Turing complete DSL * cross compilation for many operating systems as well as bare metal * optimized for extremely fast full and incremental builds without sacrificing correctness diff --git a/docs/sitemap.txt b/docs/sitemap.txt index af8aede..cb1570a 100644 --- a/docs/sitemap.txt +++ b/docs/sitemap.txt @@ -38,6 +38,7 @@ index.md Windows-module.md Java.md Vala.md + D.md IDE-integration.md Custom-build-targets.md Build-system-converters.md -- cgit v1.1