From fc547ad05e5a8e650ae5bc2ecc7d40e4dbcc9f0f Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 20 Nov 2017 10:20:27 -0800 Subject: [PATCH 1/4] haiku: do not add pthread arguments Haiku has pthreads, but they are part of the standard C library, and do not need either special compiler or linker flags. --- mesonbuild/backend/backends.py | 2 +- mesonbuild/backend/ninjabackend.py | 2 +- mesonbuild/compilers/c.py | 22 ++++++++++++++-------- mesonbuild/linkers.py | 4 ++-- mesonbuild/mesonlib.py | 12 ++++++++++++ 5 files changed, 30 insertions(+), 12 deletions(-) diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 067b71936..f899735ba 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -509,7 +509,7 @@ class Backend: # For 'automagic' deps: Boost and GTest. Also dependency('threads'). # pkg-config puts the thread flags itself via `Cflags:` if dep.need_threads(): - commands += compiler.thread_flags() + commands += compiler.thread_flags(self.environment) # Fortran requires extra include directives. if compiler.language == 'fortran': for lt in target.link_targets: diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index bcda603ed..954ead5f2 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -2430,7 +2430,7 @@ rule FORTRAN_DEP_HACK # pkg-config puts the thread flags itself via `Cflags:` for d in target.external_deps: if d.need_threads(): - commands += linker.thread_link_flags() + commands += linker.thread_link_flags(self.environment) # Only non-static built targets need link args and link dependencies if not isinstance(target, build.StaticLibrary): commands += target.link_args diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index 0f92e7880..9c1d1fcad 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -16,9 +16,11 @@ import subprocess, os.path, tempfile from .. import mlog from .. import coredata -from ..mesonlib import EnvironmentException, version_compare, Popen_safe, listify -from ..mesonlib import for_windows, for_darwin, for_cygwin from . import compilers +from ..mesonlib import ( + EnvironmentException, version_compare, Popen_safe, listify, + for_windows, for_darwin, for_cygwin, for_haiku, +) from .compilers import ( GCC_MINGW, @@ -281,12 +283,12 @@ class CCompiler(Compiler): # Add compile flags needed by dependencies args += d.get_compile_args() if d.need_threads(): - args += self.thread_flags() + args += self.thread_flags(env) if mode == 'link': # Add link flags needed to find dependencies args += d.get_link_args() if d.need_threads(): - args += self.thread_link_flags() + args += self.thread_link_flags(env) # Select a CRT if needed since we're linking if mode == 'link': args += self.get_linker_debug_crt_args() @@ -781,10 +783,14 @@ class CCompiler(Compiler): return [trial] return None - def thread_flags(self): + def thread_flags(self, env): + if for_haiku(self.is_cross, env): + return [] return ['-pthread'] - def thread_link_flags(self): + def thread_link_flags(self, env): + if for_haiku(self.is_cross, env): + return [] return ['-pthread'] def has_multi_arguments(self, args, env): @@ -1005,10 +1011,10 @@ class VisualStudioCCompiler(CCompiler): return [] # FIXME, no idea what these should be. - def thread_flags(self): + def thread_flags(self, env): return [] - def thread_link_flags(self): + def thread_link_flags(self, env): return [] def get_options(self): diff --git a/mesonbuild/linkers.py b/mesonbuild/linkers.py index de788b7b6..2333e272b 100644 --- a/mesonbuild/linkers.py +++ b/mesonbuild/linkers.py @@ -48,7 +48,7 @@ class VisualStudioLinker(StaticLinker): def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath): return [] - def thread_link_flags(self): + def thread_link_flags(self, env): return [] def get_option_link_args(self, options): @@ -100,7 +100,7 @@ class ArLinker(StaticLinker): def get_always_args(self): return [] - def thread_link_flags(self): + def thread_link_flags(self, env): return [] def get_option_link_args(self, options): diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py index 09b5d9273..f10a1381e 100644 --- a/mesonbuild/mesonlib.py +++ b/mesonbuild/mesonlib.py @@ -292,6 +292,18 @@ def for_darwin(is_cross, env): return env.cross_info.config['host_machine']['system'] == 'darwin' return False +def for_haiku(is_cross, env): + """ + Host machine is Haiku? + + Note: 'host' is the machine on which compiled binaries will run + """ + if not is_cross: + return is_haiku() + elif env.cross_info.has_host(): + return env.cross_info.config['host_machine']['system'] == 'haiku' + return False + def exe_exists(arglist): try: p = subprocess.Popen(arglist, stdout=subprocess.PIPE, stderr=subprocess.PIPE) From b56450f9b25a02462164d0b6a0e47faa1c730c74 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 20 Nov 2017 16:58:11 -0800 Subject: [PATCH 2/4] tests: Add haiku to get define test --- test cases/common/140 get define/meson.build | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test cases/common/140 get define/meson.build b/test cases/common/140 get define/meson.build index 9342340af..e23b7dedb 100644 --- a/test cases/common/140 get define/meson.build +++ b/test cases/common/140 get define/meson.build @@ -16,6 +16,9 @@ foreach lang : ['c', 'cpp'] elif host_system == 'cygwin' d = cc.get_define('__CYGWIN__') assert(d == '1', '__CYGWIN__ value is @0@ instead of 1'.format(d)) + elif host_system == 'haiku' + d = cc.get_define('__HAIKU__') + assert(d == '1', '__HAIKU__ value is @0@ instead of 1'.format(d)) else error('Please report a bug and help us improve support for this platform') endif From 75bc95bd66159c2dfaf720362c5eaca28cd90c28 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 20 Nov 2017 16:59:21 -0800 Subject: [PATCH 3/4] docs: Add haiku to reference table --- docs/markdown/Reference-tables.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/markdown/Reference-tables.md b/docs/markdown/Reference-tables.md index ff286624b..8e048dc14 100644 --- a/docs/markdown/Reference-tables.md +++ b/docs/markdown/Reference-tables.md @@ -56,6 +56,7 @@ These are provided by the `.system()` method call. | darwin | Either OSX or iOS | | windows | Any version of Windows | | cygwin | The Cygwin environment for Windows | +| haiku | | Any string not listed above is not guaranteed to remain stable in -future releases. \ No newline at end of file +future releases. From 5a1d294b5e27cd77b1ca4ae5d403abd005e20ea9 Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Sat, 9 Dec 2017 21:10:11 +0530 Subject: [PATCH 4/4] dependencies: Handle /usr/bin/env shebangs on Haiku /usr/bin/env does not exist on Haiku since there's no /usr. The actual location is /bin/env. Detect that case and directly use the interpreter being passed to `env` in the shebang. Also reorganize the Windows special cases which does the same thing. --- mesonbuild/dependencies/base.py | 85 +++++++++++++++++++++------------ 1 file changed, 54 insertions(+), 31 deletions(-) diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index f8469c527..6d83ea5d5 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -626,9 +626,20 @@ class ExternalProgram: # Windows does not ship python3.exe, but we know the path to it if len(commands) > 0 and commands[0] == 'python3': commands = mesonlib.python_command + commands[1:] + elif mesonlib.is_haiku(): + # Haiku does not have /usr, but a lot of scripts assume that + # /usr/bin/env always exists. Detect that case and run the + # script with the interpreter after it. + if commands[0] == '/usr/bin/env': + commands = commands[1:] + # We know what python3 is, we're running on it + if len(commands) > 0 and commands[0] == 'python3': + commands = mesonlib.python_command + commands[1:] return commands + [script] - except Exception: + except Exception as e: + mlog.debug(e) pass + mlog.debug('Unusable script {!r}'.format(script)) return False def _is_executable(self, path): @@ -659,21 +670,17 @@ class ExternalProgram: return [trial_ext] return False - def _search(self, name, search_dir): + def _search_windows_special_cases(self, name, command): ''' - Search in the specified dir for the specified executable by name - and if not found search in PATH + Lots of weird Windows quirks: + 1. PATH search for @name returns files with extensions from PATHEXT, + but only self.windows_exts are executable without an interpreter. + 2. @name might be an absolute path to an executable, but without the + extension. This works inside MinGW so people use it a lot. + 3. The script is specified without an extension, in which case we have + to manually search in PATH. + 4. More special-casing for the shebang inside the script. ''' - commands = self._search_dir(name, search_dir) - if commands: - return commands - # Do a standard search in PATH - command = shutil.which(name) - if not mesonlib.is_windows(): - # On UNIX-like platforms, shutil.which() is enough to find - # all executables whether in PATH or with an absolute path - return [command] - # HERE BEGINS THE TERROR OF WINDOWS if command: # On Windows, even if the PATH search returned a full path, we can't be # sure that it can be run directly if it's not a native executable. @@ -687,25 +694,41 @@ class ExternalProgram: commands = self._shebang_to_cmd(command) if commands: return commands - else: - # Maybe the name is an absolute path to a native Windows - # executable, but without the extension. This is technically wrong, - # but many people do it because it works in the MinGW shell. - if os.path.isabs(name): - for ext in self.windows_exts: - command = '{}.{}'.format(name, ext) - if os.path.exists(command): - return [command] - # On Windows, interpreted scripts must have an extension otherwise they - # cannot be found by a standard PATH search. So we do a custom search - # where we manually search for a script with a shebang in PATH. - search_dirs = os.environ.get('PATH', '').split(';') - for search_dir in search_dirs: - commands = self._search_dir(name, search_dir) - if commands: - return commands + return [None] + # Maybe the name is an absolute path to a native Windows + # executable, but without the extension. This is technically wrong, + # but many people do it because it works in the MinGW shell. + if os.path.isabs(name): + for ext in self.windows_exts: + command = '{}.{}'.format(name, ext) + if os.path.exists(command): + return [command] + # On Windows, interpreted scripts must have an extension otherwise they + # cannot be found by a standard PATH search. So we do a custom search + # where we manually search for a script with a shebang in PATH. + search_dirs = os.environ.get('PATH', '').split(';') + for search_dir in search_dirs: + commands = self._search_dir(name, search_dir) + if commands: + return commands return [None] + def _search(self, name, search_dir): + ''' + Search in the specified dir for the specified executable by name + and if not found search in PATH + ''' + commands = self._search_dir(name, search_dir) + if commands: + return commands + # Do a standard search in PATH + command = shutil.which(name) + if mesonlib.is_windows(): + return self._search_windows_special_cases(name, command) + # On UNIX-like platforms, shutil.which() is enough to find + # all executables whether in PATH or with an absolute path + return [command] + def found(self): return self.command[0] is not None