From ed917e359331663e98977e6532e3515343e0f577 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 7 Jan 2019 13:47:27 -0800 Subject: [PATCH] allow setting directory locations in a native file This allows the person running configure (either a developer, user, or distro maintainer) to keep a configuration of where various kinds of files should end up. --- docs/markdown/Native-environments.md | 15 +++++++++ docs/markdown/snippets/native-file-paths.md | 4 +++ mesonbuild/environment.py | 32 +++++++++++++++---- mesonbuild/interpreter.py | 28 ++++++++++++++++ mesonbuild/mconf.py | 19 ++++++++--- run_unittests.py | 11 +++++++ .../installed_files.txt | 1 + .../211 native file path override/main.cpp | 5 +++ .../211 native file path override/meson.build | 3 ++ .../nativefile.ini | 2 ++ .../unit/52 native file override/meson.build | 10 ++++++ .../52 native file override/meson_options.txt | 13 ++++++++ .../unit/52 native file override/nativefile | 16 ++++++++++ 13 files changed, 148 insertions(+), 11 deletions(-) create mode 100644 docs/markdown/snippets/native-file-paths.md create mode 100644 test cases/common/211 native file path override/installed_files.txt create mode 100644 test cases/common/211 native file path override/main.cpp create mode 100644 test cases/common/211 native file path override/meson.build create mode 100644 test cases/common/211 native file path override/nativefile.ini create mode 100644 test cases/unit/52 native file override/meson.build create mode 100644 test cases/unit/52 native file override/meson_options.txt create mode 100644 test cases/unit/52 native file override/nativefile diff --git a/docs/markdown/Native-environments.md b/docs/markdown/Native-environments.md index a9719a714923..f52c00cc5173 100644 --- a/docs/markdown/Native-environments.md +++ b/docs/markdown/Native-environments.md @@ -43,6 +43,21 @@ rust = '/usr/local/bin/rust' llvm-config = '/usr/local/llvm-svn/bin/llvm-config' ``` +### Paths and Directories + +As of 0.50.0 paths and directories such as libdir can be defined in the native +file in a paths section + +```ini +[paths] +libdir = 'mylibdir' +prefix = '/my prefix' +``` + +These will override default paths for native targets (executables, libraries, +etc), but not for cross targets. These values will be overwritten by command +line arguments, such as --libdir. + ## Loading multiple native files Unlike cross file, native files allow layering. More than one native file can be diff --git a/docs/markdown/snippets/native-file-paths.md b/docs/markdown/snippets/native-file-paths.md new file mode 100644 index 000000000000..62891f8edb89 --- /dev/null +++ b/docs/markdown/snippets/native-file-paths.md @@ -0,0 +1,4 @@ +### Native File Paths and Directories + +A new `[paths]` section has been added to the native file. This can be used to +set paths such a prefix and libdir in a persistent way. diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 42eda62ac2df..4bf1379f6b8b 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -350,6 +350,7 @@ def __init__(self, source_dir, build_dir, options): # Similar to coredata.compilers and build.compilers, but lower level in # that there is no meta data, only names/paths. self.binaries = PerMachineDefaultable() + # Just uses hard-coded defaults and environment variables. Might be # overwritten by a native file. self.binaries.build = BinaryTable({}) @@ -357,10 +358,16 @@ def __init__(self, source_dir, build_dir, options): # Misc other properties about each machine. self.properties = PerMachine(Properties(), Properties(), Properties()) + # Store paths for native and cross build files. There is no target + # machine information here because nothing is installed for the target + # architecture, just the build and host architectures + self.paths = PerMachine(Directories(), None, None) + if self.coredata.config_files is not None: config = MesonConfigFile.from_config_parser( coredata.load_configs(self.coredata.config_files)) self.binaries.build = BinaryTable(config.get('binaries', {})) + self.paths.build.update(config.get('paths', {})) if self.coredata.cross_file is not None: config = MesonConfigFile.parse_datafile(self.coredata.cross_file) @@ -1072,6 +1079,17 @@ def detect_static_linker(self, compiler): self._handle_exceptions(popen_exceptions, linkers, 'linker') raise EnvironmentException('Unknown static linker "%s"' % ' '.join(linkers)) + def get_install_path(self, name: str) -> str: + """Helper that checks the native file as well as command line options, + and defaults and resolve precidence. + """ + cd = self.coredata.builtins[name] + if cd.value_is_default: + conf = getattr(self.paths[MachineChoice.BUILD], name) + if conf: + return conf + return cd.value + def get_source_dir(self): return self.source_dir @@ -1103,25 +1121,25 @@ def get_object_suffix(self): return self.object_suffix def get_prefix(self): - return self.coredata.get_builtin_option('prefix') + return self.get_install_path('prefix') def get_libdir(self): - return self.coredata.get_builtin_option('libdir') + return self.get_install_path('libdir') def get_libexecdir(self): - return self.coredata.get_builtin_option('libexecdir') + return self.get_install_path('libexecdir') def get_bindir(self): - return self.coredata.get_builtin_option('bindir') + return self.get_install_path('bindir') def get_includedir(self): - return self.coredata.get_builtin_option('includedir') + return self.get_install_path('includedir') def get_mandir(self): - return self.coredata.get_builtin_option('mandir') + return self.get_install_path('mandir') def get_datadir(self): - return self.coredata.get_builtin_option('datadir') + return self.get_install_path('datadir') def get_compiler_system_dirs(self): for comp in self.coredata.compilers.values(): diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 9ebce7039fcd..373f484a960c 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -47,6 +47,23 @@ 'sources'}, } +# Set of options that are valid to get from a native file +NATIVE_OPTIONS = { + 'bindir', + 'datadir', + 'includedir', + 'infodir', + 'libdir', + 'libexecdir', + 'localedir', + 'localstatedir', + 'mandir', + 'prefix', + 'sbindir', + 'sharedstatedir', + 'sysconfdir', +} + def stringifyUserArguments(args): if isinstance(args, list): return '[%s]' % ', '.join([stringifyUserArguments(x) for x in args]) @@ -2439,6 +2456,17 @@ def do_subproject(self, dirname, kwargs): def get_option_internal(self, optname): # Some base options are not defined in some environments, return the # default value from compilers.base_options in that case. + if optname in NATIVE_OPTIONS: + core = self.coredata.builtins[optname] + conf = getattr(self.environment.paths[MachineChoice.BUILD], optname) + + if conf is not None and core.value_is_default: + # If there is a definition in a native file and the option + # wasn't passed on the command line, return the native file + # value + return conf + return core + for d in [self.coredata.base_options, compilers.base_options, self.coredata.builtins, self.coredata.compiler_options]: try: diff --git a/mesonbuild/mconf.py b/mesonbuild/mconf.py index 2863b0c0b6e5..a41036a23eff 100644 --- a/mesonbuild/mconf.py +++ b/mesonbuild/mconf.py @@ -102,14 +102,25 @@ def print_options(self, title, options): if not options: print(' No {}\n'.format(title.lower())) arr = [] - for k in sorted(options): - o = options[k] + for k, o in sorted(options.items()): d = o.description v = o.printable_value() c = o.choices arr.append({'name': k, 'descr': d, 'value': v, 'choices': c}) self.print_aligned(arr) + def print_list_options(self, title, olist): + print('\n{}:'.format(title)) + if not olist: + print(' No {}\n'.format(title.lower())) + arr = [] + for k, v in sorted(olist): + o = self.coredata.builtins[k] + d = o.description + c = o.choices + arr.append({'name': k, 'descr': d, 'value': v, 'choices': c}) + self.print_aligned(arr) + def print_conf(self): print('Core properties:') print(' Source dir', self.build.environment.source_dir) @@ -132,7 +143,7 @@ def print_conf(self): 'stdsplit'] core_option_names = [k for k in self.coredata.builtins if k not in dir_option_names + test_option_names] - dir_options = {k: o for k, o in self.coredata.builtins.items() if k in dir_option_names} + dir_options = [(k, self.build.environment.get_install_path(k)) for k in dir_option_names] test_options = {k: o for k, o in self.coredata.builtins.items() if k in test_option_names} core_options = {k: o for k, o in self.coredata.builtins.items() if k in core_option_names} @@ -140,7 +151,7 @@ def print_conf(self): self.print_options('Backend options', self.coredata.backend_options) self.print_options('Base options', self.coredata.base_options) self.print_options('Compiler options', self.coredata.compiler_options) - self.print_options('Directories', dir_options) + self.print_list_options('Directories', dir_options) self.print_options('Project options', self.coredata.user_options) self.print_options('Testing options', test_options) diff --git a/run_unittests.py b/run_unittests.py index f7737ab57cfa..30b5e6b6da1e 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -5240,6 +5240,17 @@ def test_swift_compiler(self): compiler = env.detect_swift_compiler() self.assertEqual(compiler.version, '1.2345') + def test_native_file_dirs(self): + testcase = os.path.join(self.unit_test_dir, '52 native file override') + self.init(testcase, default_args=False, + extra_args=['--native-file', os.path.join(testcase, 'nativefile')]) + + def test_native_file_dirs_overriden(self): + testcase = os.path.join(self.unit_test_dir, '52 native file override') + self.init(testcase, default_args=False, + extra_args=['--native-file', os.path.join(testcase, 'nativefile'), + '-Ddef_libdir=liblib', '-Dlibdir=liblib']) + def unset_envs(): # For unit tests we must fully control all command lines diff --git a/test cases/common/211 native file path override/installed_files.txt b/test cases/common/211 native file path override/installed_files.txt new file mode 100644 index 000000000000..5bc77dcfed86 --- /dev/null +++ b/test cases/common/211 native file path override/installed_files.txt @@ -0,0 +1 @@ +usr/custom_bindir/main diff --git a/test cases/common/211 native file path override/main.cpp b/test cases/common/211 native file path override/main.cpp new file mode 100644 index 000000000000..d65cab2120b7 --- /dev/null +++ b/test cases/common/211 native file path override/main.cpp @@ -0,0 +1,5 @@ +#include + +int main() { + std::cout << "Hello world!" << std::endl; +} diff --git a/test cases/common/211 native file path override/meson.build b/test cases/common/211 native file path override/meson.build new file mode 100644 index 000000000000..3fb2f7f2fc83 --- /dev/null +++ b/test cases/common/211 native file path override/meson.build @@ -0,0 +1,3 @@ +project('native file install dir override', 'cpp') + +executable('main', 'main.cpp', install : true) diff --git a/test cases/common/211 native file path override/nativefile.ini b/test cases/common/211 native file path override/nativefile.ini new file mode 100644 index 000000000000..1c295c7d4a3a --- /dev/null +++ b/test cases/common/211 native file path override/nativefile.ini @@ -0,0 +1,2 @@ +[paths] +bindir = 'custom_bindir' diff --git a/test cases/unit/52 native file override/meson.build b/test cases/unit/52 native file override/meson.build new file mode 100644 index 000000000000..8318abaefd36 --- /dev/null +++ b/test cases/unit/52 native file override/meson.build @@ -0,0 +1,10 @@ +project('native file overrides') + +foreach o : ['bindir', 'datadir', 'includedir', 'infodir', 'libdir', + 'libexecdir', 'localedir', 'localstatedir', 'mandir', 'prefix', + 'sbindir', 'sharedstatedir', 'sysconfdir'] + expected = get_option('def_' + o) + actual = get_option(o) + assert(expected == actual, + '@0@ should have been @1@, but was @2@!'.format(o, expected, actual)) +endforeach diff --git a/test cases/unit/52 native file override/meson_options.txt b/test cases/unit/52 native file override/meson_options.txt new file mode 100644 index 000000000000..4d2abf9c6692 --- /dev/null +++ b/test cases/unit/52 native file override/meson_options.txt @@ -0,0 +1,13 @@ +option('def_bindir', type: 'string', value : 'binfoo',) +option('def_datadir', type: 'string', value : 'datafoo',) +option('def_includedir', type: 'string', value : 'includefoo',) +option('def_infodir', type: 'string', value : 'infofoo',) +option('def_libdir', type: 'string', value : 'libfoo',) +option('def_libexecdir', type: 'string', value : 'libexecfoo',) +option('def_localedir', type: 'string', value : 'localefoo',) +option('def_localstatedir', type: 'string', value : 'localstatefoo',) +option('def_mandir', type: 'string', value : 'manfoo',) +option('def_prefix', type: 'string', value : '/prefix',) +option('def_sbindir', type: 'string', value : 'sbinfoo',) +option('def_sharedstatedir', type: 'string', value : 'sharedstatefoo',) +option('def_sysconfdir', type: 'string', value : 'sysconffoo',) diff --git a/test cases/unit/52 native file override/nativefile b/test cases/unit/52 native file override/nativefile new file mode 100644 index 000000000000..a39072579426 --- /dev/null +++ b/test cases/unit/52 native file override/nativefile @@ -0,0 +1,16 @@ +[paths] +bindir = 'binfoo' +datadir = 'datafoo' +includedir = 'includefoo' +infodir = 'infofoo' +libdir = 'libfoo' +libexecdir = 'libexecfoo' +localedir = 'localefoo' +localstatedir = 'localstatefoo' +mandir = 'manfoo' +prefix = '/prefix' +sbindir = 'sbinfoo' +sharedstatedir = 'sharedstatefoo' +sysconfdir = 'sysconffoo' + +; vim: ft=dosini