diff options
-rw-r--r-- | mesonbuild/backend/backends.py | 29 | ||||
-rw-r--r-- | mesonbuild/backend/vs2010backend.py | 49 | ||||
-rw-r--r-- | mesonbuild/build.py | 24 | ||||
-rw-r--r-- | mesonbuild/dependencies.py | 187 | ||||
-rw-r--r-- | mesonbuild/environment.py | 3 | ||||
-rw-r--r-- | mesonbuild/interpreter.py | 17 | ||||
-rw-r--r-- | mesonbuild/mesonmain.py | 9 | ||||
-rw-r--r-- | mesonbuild/modules/windows.py | 2 | ||||
-rw-r--r-- | test cases/common/115 spaces backslash/asm output/meson.build | 2 | ||||
-rw-r--r-- | test cases/common/115 spaces backslash/comparer-end-notstring.c | 20 | ||||
-rw-r--r-- | test cases/common/115 spaces backslash/comparer-end.c | 16 | ||||
-rw-r--r-- | test cases/common/115 spaces backslash/comparer.c | 16 | ||||
-rw-r--r-- | test cases/common/115 spaces backslash/include/comparer.h | 4 | ||||
-rw-r--r-- | test cases/common/115 spaces backslash/meson.build | 28 | ||||
-rw-r--r-- | test cases/failing/24 backslash/comparer.c | 10 | ||||
-rw-r--r-- | test cases/failing/24 backslash/meson.build | 3 | ||||
-rw-r--r-- | test cases/windows/9 find program/meson.build | 4 | ||||
-rw-r--r-- | test cases/windows/9 find program/test-script | 3 | ||||
-rwxr-xr-x | tools/ac_converter.py | 1 |
19 files changed, 307 insertions, 120 deletions
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index d2693b2..1f1c3ca 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -296,6 +296,33 @@ class Backend(): args = includeargs + args return args + @staticmethod + def escape_extra_args(compiler, args): + # No extra escaping/quoting needed when not running on Windows + if not mesonlib.is_windows(): + return args + extra_args = [] + # Compiler-specific escaping is needed for -D args but not for any others + if compiler.get_id() == 'msvc': + # MSVC needs escaping when a -D argument ends in \ or \" + for arg in args: + if arg.startswith('-D') or arg.startswith('/D'): + # Without extra escaping for these two, the next character + # gets eaten + if arg.endswith('\\'): + arg += '\\' + elif arg.endswith('\\"'): + arg = arg[:-2] + '\\\\"' + extra_args.append(arg) + else: + # MinGW GCC needs all backslashes in defines to be doubly-escaped + # FIXME: Not sure about Cygwin or Clang + for arg in args: + if arg.startswith('-D') or arg.startswith('/D'): + arg = arg.replace('\\', '\\\\') + extra_args.append(arg) + return extra_args + def generate_basic_compiler_args(self, target, compiler): commands = [] commands += self.get_cross_stdlib_args(target, compiler) @@ -304,7 +331,7 @@ class Backend(): commands += compiler.get_option_compile_args(self.environment.coredata.compiler_options) commands += self.build.get_global_args(compiler) commands += self.environment.coredata.external_args[compiler.get_language()] - commands += target.get_extra_args(compiler.get_language()) + commands += self.escape_extra_args(compiler, target.get_extra_args(compiler.get_language())) commands += compiler.get_buildtype_args(self.environment.coredata.get_builtin_option('buildtype')) if self.environment.coredata.get_builtin_option('werror'): commands += compiler.get_werror_args() diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index f7eb147..669bcf8 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -436,9 +436,30 @@ class Vs2010Backend(backends.Backend): # they are part of the CustomBuildStep Outputs. return - @classmethod - def quote_define_cmdline(cls, arg): - return re.sub(r'^([-/])D(.*?)="(.*)"$', r'\1D\2=\"\3\"', arg) + @staticmethod + def escape_preprocessor_define(define): + # See: https://msdn.microsoft.com/en-us/library/bb383819.aspx + table = str.maketrans({'%': '%25', '$': '%24', '@': '%40', + "'": '%27', ';': '%3B', '?': '%3F', '*': '%2A', + # We need to escape backslash because it'll be un-escaped by + # Windows during process creation when it parses the arguments + # Basically, this converts `\` to `\\`. + '\\': '\\\\'}) + return define.translate(table) + + @staticmethod + def escape_additional_option(option): + # See: https://msdn.microsoft.com/en-us/library/bb383819.aspx + table = str.maketrans({'%': '%25', '$': '%24', '@': '%40', + "'": '%27', ';': '%3B', '?': '%3F', '*': '%2A', ' ': '%20',}) + option = option.translate(table) + # Since we're surrounding the option with ", if it ends in \ that will + # escape the " when the process arguments are parsed and the starting + # " will not terminate. So we escape it if that's the case. I'm not + # kidding, this is how escaping works for process args on Windows. + if option.endswith('\\'): + option += '\\' + return '"{}"'.format(option) @staticmethod def split_link_args(args): @@ -633,7 +654,7 @@ class Vs2010Backend(backends.Backend): # so filter them out if needed d_compile_args = compiler.unix_compile_flags_to_native(d.get_compile_args()) for arg in d_compile_args: - if arg.startswith('-I'): + if arg.startswith('-I') or arg.startswith('/I'): inc_dir = arg[2:] # De-dup if inc_dir not in inc_dirs: @@ -641,8 +662,24 @@ class Vs2010Backend(backends.Backend): else: general_args.append(arg) + defines = [] + # Split preprocessor defines and include directories out of the list of + # all extra arguments. The rest go into %(AdditionalOptions). for l, args in extra_args.items(): - extra_args[l] = [Vs2010Backend.quote_define_cmdline(x) for x in args] + extra_args[l] = [] + for arg in args: + if arg.startswith('-D') or arg.startswith('/D'): + define = self.escape_preprocessor_define(arg[2:]) + # De-dup + if define not in defines: + defines.append(define) + elif arg.startswith('-I') or arg.startswith('/I'): + inc_dir = arg[2:] + # De-dup + if inc_dir not in inc_dirs: + inc_dirs.append(inc_dir) + else: + extra_args[l].append(self.escape_additional_option(arg)) languages += gen_langs has_language_specific_args = any(l != extra_args['c'] for l in extra_args.values()) @@ -669,7 +706,7 @@ class Vs2010Backend(backends.Backend): inc_dirs.append('%(AdditionalIncludeDirectories)') ET.SubElement(clconf, 'AdditionalIncludeDirectories').text = ';'.join(inc_dirs) - preproc = ET.SubElement(clconf, 'PreprocessorDefinitions') + ET.SubElement(clconf, 'PreprocessorDefinitions').text = ';'.join(defines) rebuild = ET.SubElement(clconf, 'MinimalRebuild') rebuild.text = 'true' funclink = ET.SubElement(clconf, 'FunctionLevelLinking') diff --git a/mesonbuild/build.py b/mesonbuild/build.py index b610bb8..6a4f375 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -50,28 +50,6 @@ known_shlib_kwargs.update({'version' : True, 'name_suffix' : True, 'vs_module_defs' : True}) -backslash_explanation = \ -'''Compiler arguments have a backslash "\\" character. This is unfortunately not -permitted. The reason for this is that backslash is a shell quoting character -that behaves differently across different systems. Because of this is it not -possible to make it work reliably across all the platforms Meson needs to -support. - -There are several different ways of working around this issue. Most of the time -you are using this to provide a -D define to your compiler. Try instead to -create a config.h file and put all of your definitions in it using -configure_file(). - -Another approach is to move the backslashes into the source and have the other -bits in the def. So you would have an arg -DPLAIN_TEXT="foo" and then in your -C sources something like this: - -const char *fulltext = "\\\\" PLAIN_TEXT; - -We are fully aware that these are not really usable or pleasant ways to do -this but it's the best we can do given the way shell quoting works. -''' - def sources_are_suffix(sources, suffix): for source in sources: if source.endswith('.' + suffix): @@ -606,8 +584,6 @@ class BuildTarget(): for a in args: if not isinstance(a, (str, File)): raise InvalidArguments('A non-string passed to compiler args.') - if isinstance(a, str) and '\\' in a: - raise InvalidArguments(backslash_explanation) if language in self.extra_args: self.extra_args[language] += args else: diff --git a/mesonbuild/dependencies.py b/mesonbuild/dependencies.py index 2b77706..b4f825b 100644 --- a/mesonbuild/dependencies.py +++ b/mesonbuild/dependencies.py @@ -122,56 +122,66 @@ class PkgConfigDependency(Dependency): if self.required: raise DependencyException('%s dependency %s not found.' % (self.type_string, name)) self.modversion = 'none' + return + self.modversion = out.decode().strip() + found_msg = ['%s dependency' % self.type_string, mlog.bold(name), 'found:'] + self.version_requirement = kwargs.get('version', None) + if self.version_requirement is None: + self.is_found = True else: - self.modversion = out.decode().strip() - mlog.log('%s dependency' % self.type_string, mlog.bold(name), 'found:', - mlog.green('YES'), self.modversion) - self.version_requirement = kwargs.get('version', None) - if self.version_requirement is None: - self.is_found = True - else: - if not isinstance(self.version_requirement, str): - raise DependencyException('Version argument must be string.') - self.is_found = mesonlib.version_compare(self.modversion, self.version_requirement) - if not self.is_found and self.required: + if not isinstance(self.version_requirement, str): + raise DependencyException('Version argument must be string.') + self.is_found = mesonlib.version_compare(self.modversion, self.version_requirement) + if not self.is_found: + found_msg += [mlog.red('NO'), 'found {!r}'.format(self.modversion), + 'but need {!r}'.format(self.version_requirement)] + mlog.log(*found_msg) + if self.required: raise DependencyException( 'Invalid version of a dependency, needed %s %s found %s.' % (name, self.version_requirement, self.modversion)) - if not self.is_found: return - p = subprocess.Popen([pkgbin, '--cflags', name], stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - out = p.communicate()[0] - if p.returncode != 0: - raise DependencyException('Could not generate cargs for %s:\n\n%s' % \ - (name, out.decode(errors='ignore'))) - self.cargs = out.decode().split() - - libcmd = [pkgbin, '--libs'] - if self.static: - libcmd.append('--static') - p = subprocess.Popen(libcmd + [name], stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - out = p.communicate()[0] - if p.returncode != 0: - raise DependencyException('Could not generate libs for %s:\n\n%s' % \ - (name, out.decode(errors='ignore'))) - self.libs = [] - for lib in out.decode().split(): - if lib.endswith(".la"): - shared_libname = self.extract_libtool_shlib(lib) - shared_lib = os.path.join(os.path.dirname(lib), shared_libname) - if not os.path.exists(shared_lib): - shared_lib = os.path.join(os.path.dirname(lib), ".libs", shared_libname) - - if not os.path.exists(shared_lib): - raise DependencyException('Got a libtools specific "%s" dependencies' - 'but we could not compute the actual shared' - 'library path' % lib) - lib = shared_lib - self.is_libtool = True - - self.libs.append(lib) + found_msg += [mlog.green('YES'), self.modversion] + mlog.log(*found_msg) + # Fetch cargs to be used while using this dependency + self._set_cargs() + # Fetch the libraries and library paths needed for using this + self._set_libs() + + def _set_cargs(self): + p = subprocess.Popen([self.pkgbin, '--cflags', self.name], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out = p.communicate()[0] + if p.returncode != 0: + raise DependencyException('Could not generate cargs for %s:\n\n%s' % \ + (name, out.decode(errors='ignore'))) + self.cargs = out.decode().split() + + def _set_libs(self): + libcmd = [self.pkgbin, '--libs'] + if self.static: + libcmd.append('--static') + p = subprocess.Popen(libcmd + [self.name], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out = p.communicate()[0] + if p.returncode != 0: + raise DependencyException('Could not generate libs for %s:\n\n%s' % \ + (name, out.decode(errors='ignore'))) + self.libs = [] + for lib in out.decode().split(): + if lib.endswith(".la"): + shared_libname = self.extract_libtool_shlib(lib) + shared_lib = os.path.join(os.path.dirname(lib), shared_libname) + if not os.path.exists(shared_lib): + shared_lib = os.path.join(os.path.dirname(lib), ".libs", shared_libname) + + if not os.path.exists(shared_lib): + raise DependencyException('Got a libtools specific "%s" dependencies' + 'but we could not compute the actual shared' + 'library path' % lib) + lib = shared_lib + self.is_libtool = True + self.libs.append(lib) def get_variable(self, variable_name): p = subprocess.Popen([self.pkgbin, '--variable=%s' % variable_name, self.name], @@ -343,37 +353,13 @@ class WxDependency(Dependency): class ExternalProgram(): def __init__(self, name, fullpath=None, silent=False, search_dir=None): self.name = name - self.fullpath = None if fullpath is not None: if not isinstance(fullpath, list): self.fullpath = [fullpath] else: self.fullpath = fullpath else: - self.fullpath = [shutil.which(name)] - if self.fullpath[0] is None and search_dir is not None: - trial = os.path.join(search_dir, name) - suffix = os.path.splitext(trial)[-1].lower()[1:] - if mesonlib.is_windows() and (suffix == 'exe' or suffix == 'com'\ - or suffix == 'bat'): - self.fullpath = [trial] - elif not mesonlib.is_windows() and os.access(trial, os.X_OK): - self.fullpath = [trial] - else: - # Now getting desperate. Maybe it is a script file that is a) not chmodded - # executable or b) we are on windows so they can't be directly executed. - try: - first_line = open(trial).readline().strip() - if first_line.startswith('#!'): - commands = first_line[2:].split('#')[0].strip().split() - if mesonlib.is_windows(): - # Windows does not have /usr/bin. - commands[0] = commands[0].split('/')[-1] - if commands[0] == 'env': - commands = commands[1:] - self.fullpath = commands + [trial] - except Exception: - pass + self.fullpath = self._search(name, search_dir) if not silent: if self.found(): mlog.log('Program', mlog.bold(name), 'found:', mlog.green('YES'), @@ -381,6 +367,67 @@ class ExternalProgram(): else: mlog.log('Program', mlog.bold(name), 'found:', mlog.red('NO')) + @staticmethod + def _shebang_to_cmd(script): + """ + Windows does not understand shebangs, so we check if the file has a + shebang and manually parse it to figure out the interpreter to use + """ + try: + first_line = open(script).readline().strip() + if first_line.startswith('#!'): + commands = first_line[2:].split('#')[0].strip().split() + if mesonlib.is_windows(): + # Windows does not have /usr/bin. + commands[0] = commands[0].split('/')[-1] + if commands[0] == 'env': + commands = commands[1:] + return commands + [script] + except Exception: + pass + return False + + @staticmethod + def _is_executable(path): + suffix = os.path.splitext(path)[-1].lower()[1:] + if mesonlib.is_windows(): + if suffix == 'exe' or suffix == 'com' or suffix == 'bat': + return True + elif os.access(path, os.X_OK): + return True + return False + + def _search_dir(self, name, search_dir): + if search_dir is None: + return False + trial = os.path.join(search_dir, name) + if not os.path.exists(trial): + return False + if self._is_executable(trial): + return [trial] + # Now getting desperate. Maybe it is a script file that is a) not chmodded + # executable or b) we are on windows so they can't be directly executed. + return self._shebang_to_cmd(trial) + + def _search(self, name, search_dir): + commands = self._search_dir(name, search_dir) + if commands: + return commands + # Do a standard search in PATH + fullpath = shutil.which(name) + if fullpath or not mesonlib.is_windows(): + # On UNIX-like platforms, the standard PATH search is enough + return [fullpath] + # 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 found(self): return self.fullpath[0] is not None diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 6375938..404ed3e 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -171,9 +171,10 @@ class Environment(): def is_cross_build(self): return self.cross_info is not None - def dump_coredata(self): + def dump_coredata(self, mtime): cdf = os.path.join(self.get_build_dir(), Environment.coredata_file) coredata.save(self.coredata, cdf) + os.utime(cdf, times=(mtime, mtime)) def get_script_dir(self): import mesonbuild.scripts diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 51c40c9..5201be2 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -1683,21 +1683,29 @@ class Interpreter(): dep = dependencies.find_external_dependency(name, self.environment, kwargs) except dependencies.DependencyException: if 'fallback' in kwargs: - dep = self.dependency_fallback(kwargs) + dep = self.dependency_fallback(name, kwargs) self.coredata.deps[identifier] = dep.held_object return dep raise self.coredata.deps[identifier] = dep return DependencyHolder(dep) - def dependency_fallback(self, kwargs): + def dependency_fallback(self, name, kwargs): fbinfo = kwargs['fallback'] check_stringlist(fbinfo) if len(fbinfo) != 2: raise InterpreterException('Fallback info must have exactly two items.') dirname, varname = fbinfo - self.do_subproject(dirname, {}) + try: + self.do_subproject(dirname, {}) + except: + mlog.log('Also couldn\'t find a fallback subproject in', + mlog.bold(os.path.join(self.subproject_dir, dirname)), + 'for the dependency', mlog.bold(name)) + raise dep = self.subprojects[dirname].get_variable_method([varname], {}) + if not isinstance(dep, (DependencyHolder, InternalDependencyHolder)): + raise InterpreterException('Fallback variable is not a dependency object.') # Check if the version of the declared dependency matches what we want if 'version' in kwargs: wanted = kwargs['version'] @@ -1705,6 +1713,9 @@ class Interpreter(): if found == 'undefined' or not mesonlib.version_compare(found, wanted): m = 'Subproject "{0}" dependency "{1}" version is "{2}" but "{3}" is required.' raise InterpreterException(m.format(dirname, varname, found, wanted)) + mlog.log('Found a', mlog.green('fallback'), 'subproject', + mlog.bold(os.path.join(self.subproject_dir, dirname)), 'for', + mlog.bold(name)) return dep def func_executable(self, node, args, kwargs): diff --git a/mesonbuild/mesonmain.py b/mesonbuild/mesonmain.py index e61c602..e002d9a 100644 --- a/mesonbuild/mesonmain.py +++ b/mesonbuild/mesonmain.py @@ -15,7 +15,7 @@ # limitations under the License. import sys, stat, traceback, pickle, argparse -import datetime +import time, datetime import os.path from . import environment, interpreter, mesonlib from . import build @@ -164,6 +164,7 @@ itself as required.''' mlog.log('Build machine cpu family:', mlog.bold(intr.builtin['build_machine'].cpu_family_method([], {}))) mlog.log('Build machine cpu:', mlog.bold(intr.builtin['build_machine'].cpu_method([], {}))) intr.run() + coredata_mtime = time.time() g.generate(intr) g.run_postconf_scripts() dumpfile = os.path.join(env.get_scratch_dir(), 'build.dat') @@ -173,7 +174,11 @@ itself as required.''' # that pops up during generation, post-conf scripts, etc to cause us to # incorrectly signal a successful meson run which will cause an error # about an already-configured build directory when the user tries again. - env.dump_coredata() + # + # However, we set the mtime to an earlier value to ensure that doing an + # mtime comparison between the coredata dump and other build files + # shows the build files to be newer, not older. + env.dump_coredata(coredata_mtime) def run_script_command(args): cmdname = args[0] diff --git a/mesonbuild/modules/windows.py b/mesonbuild/modules/windows.py index 7bf0319..cd4e343 100644 --- a/mesonbuild/modules/windows.py +++ b/mesonbuild/modules/windows.py @@ -38,6 +38,8 @@ class WindowsModule: rescomp = dependencies.ExternalProgram(rescomp_name, silent=True) res_args = extra_args + ['@INPUT@', '@OUTPUT@'] suffix = 'o' + if not rescomp.found(): + raise MesonException('Could not find Windows resource compiler %s.' % ' '.join(rescomp.get_command())) res_files = mesonlib.stringlistify(args) res_kwargs = {'output' : '@BASENAME@.' + suffix, 'arguments': res_args} diff --git a/test cases/common/115 spaces backslash/asm output/meson.build b/test cases/common/115 spaces backslash/asm output/meson.build new file mode 100644 index 0000000..b5f13f5 --- /dev/null +++ b/test cases/common/115 spaces backslash/asm output/meson.build @@ -0,0 +1,2 @@ +configure_file(output : 'blank.txt', configuration : configuration_data()) + diff --git a/test cases/common/115 spaces backslash/comparer-end-notstring.c b/test cases/common/115 spaces backslash/comparer-end-notstring.c new file mode 100644 index 0000000..65bf8bc --- /dev/null +++ b/test cases/common/115 spaces backslash/comparer-end-notstring.c @@ -0,0 +1,20 @@ +#include "comparer.h" + +#ifndef COMPARER_INCLUDED +#error "comparer.h not included" +#endif + +/* This converts foo\\\\bar\\\\ to "foo\\bar\\" (string literal) */ +#define Q(x) #x +#define QUOTE(x) Q(x) + +#define COMPARE_WITH "foo\\bar\\" /* This is the literal `foo\bar\` */ + +int main(int argc, char **argv) { + if(strcmp(QUOTE(DEF_WITH_BACKSLASH), COMPARE_WITH)) { + printf("Arg string is quoted incorrectly: %s instead of %s\n", + QUOTE(DEF_WITH_BACKSLASH), COMPARE_WITH); + return 1; + } + return 0; +} diff --git a/test cases/common/115 spaces backslash/comparer-end.c b/test cases/common/115 spaces backslash/comparer-end.c new file mode 100644 index 0000000..fef25a5 --- /dev/null +++ b/test cases/common/115 spaces backslash/comparer-end.c @@ -0,0 +1,16 @@ +#include "comparer.h" + +#ifndef COMPARER_INCLUDED +#error "comparer.h not included" +#endif + +#define COMPARE_WITH "foo\\bar\\" /* This is `foo\bar\` */ + +int main (int argc, char **argv) { + if (strcmp (DEF_WITH_BACKSLASH, COMPARE_WITH)) { + printf ("Arg string is quoted incorrectly: %s vs %s\n", + DEF_WITH_BACKSLASH, COMPARE_WITH); + return 1; + } + return 0; +} diff --git a/test cases/common/115 spaces backslash/comparer.c b/test cases/common/115 spaces backslash/comparer.c new file mode 100644 index 0000000..937cb47 --- /dev/null +++ b/test cases/common/115 spaces backslash/comparer.c @@ -0,0 +1,16 @@ +#include "comparer.h" + +#ifndef COMPARER_INCLUDED +#error "comparer.h not included" +#endif + +#define COMPARE_WITH "foo\\bar" /* This is the literal `foo\bar` */ + +int main (int argc, char **argv) { + if (strcmp (DEF_WITH_BACKSLASH, COMPARE_WITH)) { + printf ("Arg string is quoted incorrectly: %s instead of %s\n", + DEF_WITH_BACKSLASH, COMPARE_WITH); + return 1; + } + return 0; +} diff --git a/test cases/common/115 spaces backslash/include/comparer.h b/test cases/common/115 spaces backslash/include/comparer.h new file mode 100644 index 0000000..624d96c --- /dev/null +++ b/test cases/common/115 spaces backslash/include/comparer.h @@ -0,0 +1,4 @@ +#include <string.h> +#include <stdio.h> + +#define COMPARER_INCLUDED diff --git a/test cases/common/115 spaces backslash/meson.build b/test cases/common/115 spaces backslash/meson.build new file mode 100644 index 0000000..bf614e8 --- /dev/null +++ b/test cases/common/115 spaces backslash/meson.build @@ -0,0 +1,28 @@ +project('comparer', 'c') + +# Added manually as a c_arg to test handling of include paths with backslashes +# and spaces. This is especially useful on Windows in vcxproj files since it +# stores include directories in a separate element that has its own +# context-specific escaping/quoting. +include_dir = meson.current_source_dir() + '/include' +default_c_args = ['-I' + include_dir] + +if meson.get_compiler('c').get_id() == 'msvc' + default_c_args += ['/Faasm output\\'] + # Hack to create the 'asm output' directory in the builddir + subdir('asm output') +endif + +# Path can contain \. Here we're sending `"foo\bar"`. +test('backslash quoting', + executable('comparer', 'comparer.c', + c_args : default_c_args + ['-DDEF_WITH_BACKSLASH="foo\\bar"'])) +# Path can end in \ without any special quoting. Here we send `"foo\bar\"`. +test('backslash end quoting', + executable('comparer-end', 'comparer-end.c', + c_args : default_c_args + ['-DDEF_WITH_BACKSLASH="foo\\bar\\"'])) +# Path can (really) end in \ if we're not passing a string literal without any +# special quoting. Here we're sending `foo\bar\`. +test('backslash end quoting when not a string literal', + executable('comparer-end-notstring', 'comparer-end-notstring.c', + c_args : default_c_args + ['-DDEF_WITH_BACKSLASH=foo\\bar\\'])) diff --git a/test cases/failing/24 backslash/comparer.c b/test cases/failing/24 backslash/comparer.c deleted file mode 100644 index f562f5e..0000000 --- a/test cases/failing/24 backslash/comparer.c +++ /dev/null @@ -1,10 +0,0 @@ -#include<string.h> -#include<stdio.h> - -int main(int argc, char **argv) { - if(strcmp(DEF_WITH_BACKSLASH, "foo\\bar")) { - printf("Arg string is quoted incorrectly: %s\n", DEF_WITH_BACKSLASH); - return 1; - } - return 0; -} diff --git a/test cases/failing/24 backslash/meson.build b/test cases/failing/24 backslash/meson.build deleted file mode 100644 index dba891e..0000000 --- a/test cases/failing/24 backslash/meson.build +++ /dev/null @@ -1,3 +0,0 @@ -project('comparer', 'c') - -test('backslash quoting', executable('comparer', 'comparer.c', c_args : '-DDEF_WITH_BACKSLASH="foo\\bar"')) diff --git a/test cases/windows/9 find program/meson.build b/test cases/windows/9 find program/meson.build new file mode 100644 index 0000000..ef34586 --- /dev/null +++ b/test cases/windows/9 find program/meson.build @@ -0,0 +1,4 @@ +project('find program', 'c') + +prog = find_program('test-script') +test('script', prog) diff --git a/test cases/windows/9 find program/test-script b/test cases/windows/9 find program/test-script new file mode 100644 index 0000000..d105a81 --- /dev/null +++ b/test cases/windows/9 find program/test-script @@ -0,0 +1,3 @@ +#!/usr/bin/env python + +print('1') diff --git a/tools/ac_converter.py b/tools/ac_converter.py index c7dbd37..2f1b4c3 100755 --- a/tools/ac_converter.py +++ b/tools/ac_converter.py @@ -116,6 +116,7 @@ function_data = \ 'HAVE_READLINK': ('readlink', 'unistd.h'), 'HAVE_RES_INIT': ('res_init', 'resolv.h'), 'HAVE_SENDMMSG': ('sendmmsg', 'sys/socket.h'), + 'HAVE_SOCKET' : ('socket',' sys/socket.h'), 'HAVE_GETENV': ('getenv', 'stdlib.h'), 'HAVE_SETENV': ('setenv', 'stdlib.h'), 'HAVE_PUTENV': ('putenv', 'stdlib.h'), |