From cbc5064a67b2e7ff1a69d40f65c84e3d55fe2a66 Mon Sep 17 00:00:00 2001 From: Jon Turney Date: Fri, 24 Mar 2017 18:23:04 +0000 Subject: [PATCH 01/17] Don't use -fPIC on Cygwin, either Identify Cygwin-targetted gcc as sui generis (don't use -fPIC, but don't link with standard Windows libraries, either) Update tests appropriately --- mesonbuild/compilers.py | 7 ++++--- mesonbuild/environment.py | 3 ++- mesonbuild/mesonlib.py | 4 ++++ run_unittests.py | 4 +++- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py index 6f08d98bd..e6be8b1b2 100644 --- a/mesonbuild/compilers.py +++ b/mesonbuild/compilers.py @@ -2309,6 +2309,7 @@ class VisualStudioCPPCompiler(VisualStudioCCompiler, CPPCompiler): GCC_STANDARD = 0 GCC_OSX = 1 GCC_MINGW = 2 +GCC_CYGWIN = 3 CLANG_STANDARD = 0 CLANG_OSX = 1 @@ -2324,7 +2325,7 @@ def get_gcc_soname_args(gcc_type, prefix, shlib_name, suffix, path, soversion, i sostr = '' else: sostr = '.' + soversion - if gcc_type == GCC_STANDARD or gcc_type == GCC_MINGW: + if gcc_type in (GCC_STANDARD, GCC_MINGW, GCC_CYGWIN): # Might not be correct for mingw but seems to work. return ['-Wl,-soname,%s%s.%s%s' % (prefix, shlib_name, suffix, sostr)] elif gcc_type == GCC_OSX: @@ -2398,7 +2399,7 @@ class GnuCompiler: return self.defines[define] def get_pic_args(self): - if self.gcc_type in (GCC_MINGW, GCC_OSX): + if self.gcc_type in (GCC_CYGWIN, GCC_MINGW, GCC_OSX): return [] # On Window and OS X, pic is always on. return ['-fPIC'] @@ -2796,7 +2797,7 @@ class FortranCompiler(Compiler): return ' '.join(self.exelist) def get_pic_args(self): - if self.gcc_type in (GCC_MINGW, GCC_OSX): + if self.gcc_type in (GCC_CYGWIN, GCC_MINGW, GCC_OSX): return [] # On Window and OS X, pic is always on. return ['-fPIC'] diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index cb6250671..7ae53fca6 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -368,7 +368,8 @@ class Environment: return GCC_OSX elif '__MINGW32__' in defines or '__MINGW64__' in defines: return GCC_MINGW - # We ignore Cygwin for now, and treat it as a standard GCC + elif '__CYGWIN__' in defines: + return GCC_CYGWIN return GCC_STANDARD def _get_compilers(self, lang, evar, want_cross): diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py index ba52219db..291eb68fc 100644 --- a/mesonbuild/mesonlib.py +++ b/mesonbuild/mesonlib.py @@ -212,6 +212,10 @@ def is_windows(): platname = platform.system().lower() return platname == 'windows' or 'mingw' in platname +def is_cygwin(): + platname = platform.system().lower() + return platname.startswith('cygwin') + def is_debianlike(): return os.path.isfile('/etc/debian_version') diff --git a/run_unittests.py b/run_unittests.py index 53abef75e..14badc2b2 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -24,7 +24,7 @@ from pathlib import PurePath import mesonbuild.compilers import mesonbuild.environment import mesonbuild.mesonlib -from mesonbuild.mesonlib import is_windows, is_osx +from mesonbuild.mesonlib import is_windows, is_osx, is_cygwin from mesonbuild.environment import detect_ninja, Environment from mesonbuild.dependencies import PkgConfigDependency, ExternalProgram @@ -833,6 +833,8 @@ class AllPlatformTests(BasePlatformTests): self.assertEqual(cc.gcc_type, mesonbuild.compilers.GCC_OSX) elif is_windows(): self.assertEqual(cc.gcc_type, mesonbuild.compilers.GCC_MINGW) + elif is_cygwin(): + self.assertEqual(cc.gcc_type, mesonbuild.compilers.GCC_CYGWIN) else: self.assertEqual(cc.gcc_type, mesonbuild.compilers.GCC_STANDARD) if isinstance(cc, clang): From 600f16f9f834f14ff411b477674b6112cbac33d1 Mon Sep 17 00:00:00 2001 From: Jon Turney Date: Mon, 27 Mar 2017 14:52:34 +0100 Subject: [PATCH 02/17] Use extra_paths on Cygwin Cygwin executables are still loaded by the Windows PE loader, so PATH needs to include any extra directories where required DLLs can be found. Cygwin uses a unix style ':'-separated PATH. os.pathsep is used correctly on extra_paths in meson_exe.py, but not in mesontest.py --- mesonbuild/backend/backends.py | 4 ++-- mesonbuild/backend/ninjabackend.py | 2 +- mesontest.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 5517fbd99..80cf0ee63 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -252,7 +252,7 @@ class Backend: exe_wrapper = self.environment.cross_info.config['binaries'].get('exe_wrapper', None) else: exe_wrapper = None - if mesonlib.is_windows(): + if mesonlib.is_windows() or mesonlib.is_cygwin(): extra_paths = self.determine_windows_extra_paths(exe) else: extra_paths = [] @@ -481,7 +481,7 @@ class Backend: exe_wrapper = self.environment.cross_info.config['binaries'].get('exe_wrapper', None) else: exe_wrapper = None - if mesonlib.is_windows(): + if mesonlib.is_windows() or mesonlib.is_cygwin(): extra_paths = self.determine_windows_extra_paths(exe) else: extra_paths = [] diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index bc51ace8f..31439707c 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -492,7 +492,7 @@ int dummy; # the project, we need to set PATH so the DLLs are found. We use # a serialized executable wrapper for that and check if the # CustomTarget command needs extra paths first. - if target.capture or (mesonlib.is_windows() and + if target.capture or ((mesonlib.is_windows() or mesonlib.is_cygwin()) and self.determine_windows_extra_paths(target.command[0])): exe_data = self.serialise_executable(target.command[0], cmd[1:], # All targets are built from the build dir diff --git a/mesontest.py b/mesontest.py index a1708e386..d626ba738 100755 --- a/mesontest.py +++ b/mesontest.py @@ -202,7 +202,7 @@ class TestHarness: child_env.update(test.env) if len(test.extra_paths) > 0: - child_env['PATH'] += ';'.join([''] + test.extra_paths) + child_env['PATH'] += os.pathsep.join([''] + test.extra_paths) # If MALLOC_PERTURB_ is not set, or if it is set to an empty value, # (i.e., the test or the environment don't explicitly set it), set From 5af98a5ee8e8065932e9ebcaa45dd6fd42a54bdf Mon Sep 17 00:00:00 2001 From: Jon Turney Date: Tue, 4 Apr 2017 12:35:24 +0100 Subject: [PATCH 03/17] Use correct shared library naming for Cygwin Use correct shared library naming for Cygwin when building and installing --- mesonbuild/build.py | 14 ++++++++++- mesonbuild/environment.py | 24 ++++++++++++++++++- run_project_tests.py | 21 ++++++++++------ .../installed_files.txt | 8 +++---- 4 files changed, 54 insertions(+), 13 deletions(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 1246f3e7d..895cc7fc6 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -21,7 +21,7 @@ from . import mlog from .mesonlib import File, MesonException from .mesonlib import flatten, stringlistify, classify_unity_sources from .mesonlib import get_filenames_templates_dict, substitute_values -from .environment import for_windows, for_darwin +from .environment import for_windows, for_darwin, for_cygwin from .compilers import is_object, clike_langs, sort_clike, lang_suffixes known_basic_kwargs = {'install': True, @@ -1120,6 +1120,18 @@ class SharedLibrary(BuildTarget): self.filename_tpl = '{0.prefix}{0.name}-{0.soversion}.{0.suffix}' else: self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}' + elif for_cygwin(is_cross, env): + suffix = 'dll' + self.gcc_import_filename = 'lib{0}.dll.a'.format(self.name) + # Shared library is of the form cygfoo.dll + # (ld --dll-search-prefix=cyg is the default) + prefix = 'cyg' + # Import library is called libfoo.dll.a + self.import_filename = self.gcc_import_filename + if self.soversion: + self.filename_tpl = '{0.prefix}{0.name}-{0.soversion}.{0.suffix}' + else: + self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}' elif for_darwin(is_cross, env): prefix = 'lib' suffix = 'dylib' diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 7ae53fca6..7861612eb 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -158,7 +158,10 @@ def detect_cpu(compilers): return trial def detect_system(): - return platform.system().lower() + system = platform.system().lower() + if system.startswith('cygwin'): + return 'cygwin' + return system def for_windows(is_cross, env): @@ -173,6 +176,20 @@ def for_windows(is_cross, env): return env.cross_info.config['host_machine']['system'] == 'windows' return False + +def for_cygwin(is_cross, env): + """ + Host machine is cygwin? + + Note: 'host' is the machine on which compiled binaries will run + """ + if not is_cross: + return mesonlib.is_cygwin() + elif env.cross_info.has_host(): + return env.cross_info.config['host_machine']['system'] == 'cygwin' + return False + + def for_darwin(is_cross, env): """ Host machine is Darwin (iOS/OS X)? @@ -257,6 +274,11 @@ class Environment: self.exe_suffix = 'exe' self.object_suffix = 'obj' self.win_libdir_layout = True + elif (not cross and mesonlib.is_cygwin()) \ + or (cross and self.cross_info.has_host() and self.cross_info.config['host_machine']['system'] == 'cygwin'): + self.exe_suffix = 'exe' + self.object_suffix = 'o' + self.win_libdir_layout = True else: self.exe_suffix = '' self.object_suffix = 'o' diff --git a/run_project_tests.py b/run_project_tests.py index 28de638b6..a6cada3a5 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -31,6 +31,7 @@ import xml.etree.ElementTree as ET import time import multiprocessing import concurrent.futures as conc +import re from mesonbuild.coredata import backendlist @@ -208,12 +209,18 @@ def get_relative_files_list_from_dir(fromdir): paths.append(path) return paths -def platform_fix_exe_name(fname): - if not fname.endswith('?exe'): - return fname - fname = fname[:-4] - if mesonlib.is_windows(): - return fname + '.exe' +def platform_fix_name(fname): + if '?lib' in fname: + if mesonlib.is_cygwin(): + fname = re.sub(r'\?lib(.*)\.dll$', r'cyg\1.dll', fname) + else: + fname = re.sub(r'\?lib', 'lib', fname) + + if fname.endswith('?exe'): + fname = fname[:-4] + if mesonlib.is_windows(): + return fname + '.exe' + return fname def validate_install(srcdir, installdir): @@ -230,7 +237,7 @@ def validate_install(srcdir, installdir): elif os.path.exists(info_file): with open(info_file) as f: for line in f: - expected[platform_fix_exe_name(line.strip())] = False + expected[platform_fix_name(line.strip())] = False # Check if expected files were found for fname in expected: if os.path.exists(os.path.join(installdir, fname)): diff --git a/test cases/windows/7 mingw dll versioning/installed_files.txt b/test cases/windows/7 mingw dll versioning/installed_files.txt index ebad9e422..661005c4a 100644 --- a/test cases/windows/7 mingw dll versioning/installed_files.txt +++ b/test cases/windows/7 mingw dll versioning/installed_files.txt @@ -1,8 +1,8 @@ -usr/bin/libsome-0.dll +usr/bin/?libsome-0.dll usr/lib/libsome.dll.a -usr/bin/libnoversion.dll +usr/bin/?libnoversion.dll usr/lib/libnoversion.dll.a -usr/bin/libonlyversion-1.dll +usr/bin/?libonlyversion-1.dll usr/lib/libonlyversion.dll.a -usr/bin/libonlysoversion-5.dll +usr/bin/?libonlysoversion-5.dll usr/lib/libonlysoversion.dll.a From fd47ef3a274e85f4391808f7bbade2a807ab53df Mon Sep 17 00:00:00 2001 From: Jon Turney Date: Tue, 4 Apr 2017 11:39:09 +0100 Subject: [PATCH 04/17] Use '.exe' extension for executables for Cygwin Use '.exe' extension for executables for Cygwin when building and installing --- mesonbuild/build.py | 3 ++- mesonbuild/scripts/meson_exe.py | 6 +++++- mesonbuild/scripts/meson_install.py | 2 +- mesontest.py | 6 +++++- run_project_tests.py | 2 +- run_unittests.py | 2 +- test cases/failing/19 target clash/meson.build | 2 +- 7 files changed, 16 insertions(+), 7 deletions(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 895cc7fc6..537c91bde 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -997,7 +997,8 @@ class Executable(BuildTarget): self.prefix = '' if not hasattr(self, 'suffix'): # Executable for Windows or C#/Mono - if for_windows(is_cross, environment) or 'cs' in self.compilers: + if (for_windows(is_cross, environment) or + for_cygwin(is_cross, environment) or 'cs' in self.compilers): self.suffix = 'exe' else: self.suffix = '' diff --git a/mesonbuild/scripts/meson_exe.py b/mesonbuild/scripts/meson_exe.py index 5c5c31776..643e1af7b 100644 --- a/mesonbuild/scripts/meson_exe.py +++ b/mesonbuild/scripts/meson_exe.py @@ -29,8 +29,12 @@ def is_windows(): platname = platform.system().lower() return platname == 'windows' or 'mingw' in platname +def is_cygwin(): + platname = platform.system().lower() + return 'cygwin' in platname + def run_with_mono(fname): - if fname.endswith('.exe') and not is_windows(): + if fname.endswith('.exe') and not (is_windows() or is_cygwin()): return True return False diff --git a/mesonbuild/scripts/meson_install.py b/mesonbuild/scripts/meson_install.py index 8fb9e0403..af84f6463 100644 --- a/mesonbuild/scripts/meson_install.py +++ b/mesonbuild/scripts/meson_install.py @@ -193,7 +193,7 @@ def run_install_script(d): def is_elf_platform(): platname = platform.system().lower() - if platname == 'darwin' or platname == 'windows': + if platname == 'darwin' or platname == 'windows' or platname == 'cygwin': return False return True diff --git a/mesontest.py b/mesontest.py index d626ba738..c4d1178f5 100755 --- a/mesontest.py +++ b/mesontest.py @@ -36,6 +36,10 @@ def is_windows(): platname = platform.system().lower() return platname == 'windows' or 'mingw' in platname +def is_cygwin(): + platname = platform.system().lower() + return 'cygwin' in platname + def determine_worker_count(): varname = 'MESON_TESTTHREADS' if varname in os.environ: @@ -150,7 +154,7 @@ def write_json_log(jsonlogfile, test_name, result): jsonlogfile.write(json.dumps(jresult) + '\n') def run_with_mono(fname): - if fname.endswith('.exe') and not is_windows(): + if fname.endswith('.exe') and not (is_windows() or is_cygwin()): return True return False diff --git a/run_project_tests.py b/run_project_tests.py index a6cada3a5..302ca3605 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -218,7 +218,7 @@ def platform_fix_name(fname): if fname.endswith('?exe'): fname = fname[:-4] - if mesonlib.is_windows(): + if mesonlib.is_windows() or mesonlib.is_cygwin(): return fname + '.exe' return fname diff --git a/run_unittests.py b/run_unittests.py index 14badc2b2..1b24d087d 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -28,7 +28,7 @@ from mesonbuild.mesonlib import is_windows, is_osx, is_cygwin from mesonbuild.environment import detect_ninja, Environment from mesonbuild.dependencies import PkgConfigDependency, ExternalProgram -if is_windows(): +if is_windows() or is_cygwin(): exe_suffix = '.exe' else: exe_suffix = '' diff --git a/test cases/failing/19 target clash/meson.build b/test cases/failing/19 target clash/meson.build index 070631bf2..fbc757c8c 100644 --- a/test cases/failing/19 target clash/meson.build +++ b/test cases/failing/19 target clash/meson.build @@ -7,7 +7,7 @@ project('clash', 'c') # This test might fail to work on different backends or when # output location is redirected. -if host_machine.system() == 'windows' +if host_machine.system() == 'windows' or host_machine.system() == 'cygwin' error('This is expected.') endif From 3194ab9420de8a593229d28e3a66ed6b0e4a8061 Mon Sep 17 00:00:00 2001 From: Jon Turney Date: Thu, 6 Apr 2017 11:56:46 +0100 Subject: [PATCH 05/17] Add myself to authors.txt --- authors.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/authors.txt b/authors.txt index 72fe935c4..50c032b2c 100644 --- a/authors.txt +++ b/authors.txt @@ -76,3 +76,4 @@ melak47 Philipp Ittershagen Dylan Baker Aaron Plattner +Jon Turney From 205b3757236538977aeef663c63ba4c4ec7ffbe0 Mon Sep 17 00:00:00 2001 From: Jon Turney Date: Tue, 28 Mar 2017 13:04:18 +0100 Subject: [PATCH 06/17] Cygwin uses the msabi calling convention on x86_64 Fix test cases/common/126 and 135 on Cygwin/x86_64 Cygwin also uses the msabi calling convention on x86_64, not the sysvabi calling convention. --- test cases/common/126 llvm ir and assembly/square-x86_64.S | 4 ++-- test cases/common/135 generated assembly/square-x86_64.S.in | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test cases/common/126 llvm ir and assembly/square-x86_64.S b/test cases/common/126 llvm ir and assembly/square-x86_64.S index 4adc31e14..1452f476e 100644 --- a/test cases/common/126 llvm ir and assembly/square-x86_64.S +++ b/test cases/common/126 llvm ir and assembly/square-x86_64.S @@ -19,12 +19,12 @@ END .text .globl SYMBOL_NAME(square_unsigned) -# ifdef _WIN32 /* MinGW */ +# if defined(_WIN32) || defined(__CYGWIN__) /* msabi */ SYMBOL_NAME(square_unsigned): imull %ecx, %ecx movl %ecx, %eax retq -# else /* Linux and OS X */ +# else /* sysvabi */ SYMBOL_NAME(square_unsigned): imull %edi, %edi movl %edi, %eax diff --git a/test cases/common/135 generated assembly/square-x86_64.S.in b/test cases/common/135 generated assembly/square-x86_64.S.in index b6d7fb002..0834f1662 100644 --- a/test cases/common/135 generated assembly/square-x86_64.S.in +++ b/test cases/common/135 generated assembly/square-x86_64.S.in @@ -23,12 +23,12 @@ END .type square_unsigned,@function # endif -# ifdef _WIN32 /* MinGW */ +# if defined(_WIN32) || defined(__CYGWIN__) /* msabi */ SYMBOL_NAME(square_unsigned): imull %ecx, %ecx movl %ecx, %eax retq -# else /* Linux and OS X */ +# else /* sysvabi */ SYMBOL_NAME(square_unsigned): imull %edi, %edi movl %edi, %eax From 4ef4a659f20635d0345dc829772e199cbfb16fbe Mon Sep 17 00:00:00 2001 From: Jon Turney Date: Tue, 28 Mar 2017 17:01:30 +0100 Subject: [PATCH 07/17] Fix test cases/common/37 on Cygwin Including newlib's brings in a '#define __has_include 0', so using -U__has_include on the command line isn't going to remove it (so the fallback doesn't happen and the test fails) Instead use a '#undef __has_include' at the end of the prefix to excerise this. (newlib's is derived from FreeBSD, so the same problem will probably be seen there) --- test cases/common/37 has header/meson.build | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test cases/common/37 has header/meson.build b/test cases/common/37 has header/meson.build index 4299ce580..b53849c78 100644 --- a/test cases/common/37 has header/meson.build +++ b/test cases/common/37 has header/meson.build @@ -11,19 +11,19 @@ configure_file(input : non_existant_header, # Test that the fallback to __has_include also works on all compilers if host_system != 'darwin' - args = [[], ['-U__has_include']] + fallbacks = ['', '\n#undef __has_include'] else # On Darwin's clang you can't redefine builtin macros so the above doesn't work - args = [[]] + fallbacks = [''] endif -foreach arg : args +foreach fallback : fallbacks foreach comp : [meson.get_compiler('c'), meson.get_compiler('cpp')] - assert(comp.has_header('stdio.h', args : arg), 'Stdio missing.') + assert(comp.has_header('stdio.h', prefix : fallback), 'Stdio missing.') # stdio.h doesn't actually need stdlib.h, but just test that setting the # prefix does not result in an error. - assert(comp.has_header('stdio.h', prefix : '#include ', args : arg), + assert(comp.has_header('stdio.h', prefix : '#include ' + fallback), 'Stdio missing.') # XInput.h should not require type definitions from windows.h, but it does @@ -32,9 +32,9 @@ foreach arg : args # We only do this check on MSVC because MinGW often defines its own wrappers # that pre-include windows.h if comp.get_id() == 'msvc' - assert(comp.has_header('XInput.h', prefix : '#include ', args : arg), + assert(comp.has_header('XInput.h', prefix : '#include ' + fallback), 'XInput.h should not be missing on Windows') - assert(comp.has_header('XInput.h', prefix : '#define _X86_', args : arg), + assert(comp.has_header('XInput.h', prefix : '#define _X86_' + fallback), 'XInput.h should not need windows.h') endif @@ -42,13 +42,13 @@ foreach arg : args # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80005 # https://github.com/mesonbuild/meson/issues/1458 if host_system == 'linux' - assert(comp.has_header('linux/if.h', args : arg), + assert(comp.has_header('linux/if.h', prefix : fallback), 'Could not find ') endif # This header exists in the source and the builddir, but we still must not # find it since we are looking in the system directories. - assert(not comp.has_header(non_existant_header, args : arg), + assert(not comp.has_header(non_existant_header, prefix : fallback), 'Found non-existant header.') endforeach endforeach From 45a3bd8661210aae1d1baeffbd8ca2b3e8ae0900 Mon Sep 17 00:00:00 2001 From: Jon Turney Date: Thu, 6 Apr 2017 20:20:30 +0100 Subject: [PATCH 08/17] Skip objc/nsstring test on Cygwin GNUstep isn't packaged for Cygwin --- test cases/objc/2 nsstring/meson.build | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test cases/objc/2 nsstring/meson.build b/test cases/objc/2 nsstring/meson.build index ec496a2ae..a877d7465 100644 --- a/test cases/objc/2 nsstring/meson.build +++ b/test cases/objc/2 nsstring/meson.build @@ -2,6 +2,8 @@ project('nsstring', 'objc') if host_machine.system() == 'darwin' dep = dependency('appleframeworks', modules : 'foundation') +elif host_machine.system() == 'cygwin' + error('MESON_SKIP_TEST GNUstep is not packaged for Cygwin.') else dep = dependency('gnustep') if host_machine.system() == 'linux' and meson.get_compiler('objc').get_id() == 'clang' From 90a483fa74434b0ed25bd960eb0535e06f641d69 Mon Sep 17 00:00:00 2001 From: Jon Turney Date: Wed, 5 Apr 2017 23:22:39 +0100 Subject: [PATCH 09/17] Skip some linuxlike tests which don't work on Cygwin --- test cases/linuxlike/10 large file support/meson.build | 4 ++++ test cases/linuxlike/7 library versions/meson.build | 4 ++++ test cases/linuxlike/8 subproject library install/meson.build | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/test cases/linuxlike/10 large file support/meson.build b/test cases/linuxlike/10 large file support/meson.build index aa4eccf95..66833456c 100644 --- a/test cases/linuxlike/10 large file support/meson.build +++ b/test cases/linuxlike/10 large file support/meson.build @@ -1,5 +1,9 @@ project('trivial test', 'c') +if host_machine.system() == 'cygwin' + error('MESON_SKIP_TEST _FILE_OFFSET_BITS not yet supported on Cygwin.') +endif + cc = meson.get_compiler('c') size = cc.sizeof('off_t') diff --git a/test cases/linuxlike/7 library versions/meson.build b/test cases/linuxlike/7 library versions/meson.build index 48b75ad35..451e42ef1 100644 --- a/test cases/linuxlike/7 library versions/meson.build +++ b/test cases/linuxlike/7 library versions/meson.build @@ -1,5 +1,9 @@ project('library versions', 'c') +if host_machine.system() == 'cygwin' + error('MESON_SKIP_TEST linuxlike soversions not supported on Cygwin.') +endif + some = shared_library('some', 'lib.c', version : '1.2.3', soversion : '0', diff --git a/test cases/linuxlike/8 subproject library install/meson.build b/test cases/linuxlike/8 subproject library install/meson.build index 63e57cfd7..ff5579947 100644 --- a/test cases/linuxlike/8 subproject library install/meson.build +++ b/test cases/linuxlike/8 subproject library install/meson.build @@ -2,5 +2,9 @@ project('subproj lib install', 'c', version : '2.3.4', license : 'mylicense') +if host_machine.system() == 'cygwin' + error('MESON_SKIP_TEST linuxlike soversions not supported on Cygwin.') +endif + # Test that the subproject library gets installed subproject('sublib', version : '1.0.0') From 6c9260c47f62656e81a9af08121d3e1c592d9f7b Mon Sep 17 00:00:00 2001 From: Jon Turney Date: Wed, 29 Mar 2017 20:07:37 +0100 Subject: [PATCH 10/17] Run test cases/windows/ tests on Cygwin Also, always run 'test cases/windows/5 resources' on Cygwin since it can handle args containing spaces correctly. --- run_project_tests.py | 2 +- test cases/windows/5 resources/meson.build | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/run_project_tests.py b/run_project_tests.py index 302ca3605..4a4101a18 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -444,7 +444,7 @@ def detect_tests_to_run(): all_tests.append(('prebuilt', gather_tests('test cases/prebuilt'), False)) all_tests.append(('platform-osx', gather_tests('test cases/osx'), False if mesonlib.is_osx() else True)) - all_tests.append(('platform-windows', gather_tests('test cases/windows'), False if mesonlib.is_windows() else True)) + all_tests.append(('platform-windows', gather_tests('test cases/windows'), False if mesonlib.is_windows() or mesonlib.is_cygwin() else True)) all_tests.append(('platform-linux', gather_tests('test cases/linuxlike'), False if not (mesonlib.is_osx() or mesonlib.is_windows()) else True)) all_tests.append(('framework', gather_tests('test cases/frameworks'), False if not mesonlib.is_osx() and not mesonlib.is_windows() else True)) all_tests.append(('java', gather_tests('test cases/java'), False if using_backend('ninja') and not mesonlib.is_osx() and have_java() else True)) diff --git a/test cases/windows/5 resources/meson.build b/test cases/windows/5 resources/meson.build index e92a43c1e..ddb7d6e8a 100644 --- a/test cases/windows/5 resources/meson.build +++ b/test cases/windows/5 resources/meson.build @@ -3,7 +3,7 @@ project('winmain', 'c') # MinGW windres has a bug due to which it doesn't parse args with space properly: # https://github.com/mesonbuild/meson/pull/1346 # https://sourceware.org/bugzilla/show_bug.cgi?id=4933 -if meson.get_compiler('c').get_id() == 'gcc' +if meson.get_compiler('c').get_id() == 'gcc' and host_machine.system() == 'windows' # Construct build_to_src and skip this test if it has spaces # because then the -I flag to windres will also have spaces # and we know the test will fail From 320490cd00ee651fb41869bc974cd58d572ee784 Mon Sep 17 00:00:00 2001 From: Jon Turney Date: Mon, 3 Apr 2017 19:16:57 +0100 Subject: [PATCH 11/17] Ignore install as non-existent user or group 'test cases/common/12 data' and 'test cases/common/66 install subdir' both try to install something as 'root'. This user doesn't exist on Cygwin. Perhaps we should automatically convert this to some other user, but it's not clear which. For real projects, it's possibly better for the meson.build to explicitly handle this... 'test cases/common/12 data' also tries to install something with GID 0. There's no guarantee this group exists. --- mesonbuild/scripts/meson_install.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/mesonbuild/scripts/meson_install.py b/mesonbuild/scripts/meson_install.py index af84f6463..e1720322f 100644 --- a/mesonbuild/scripts/meson_install.py +++ b/mesonbuild/scripts/meson_install.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -import sys, pickle, os, shutil, subprocess, gzip, platform +import sys, pickle, os, shutil, subprocess, gzip, platform, errno from glob import glob from . import depfixer from . import destdir_join @@ -34,6 +34,15 @@ def set_mode(path, mode): except PermissionError as e: msg = '{!r}: Unable to set owner {!r} and group {!r}: {}, ignoring...' print(msg.format(path, mode.owner, mode.group, e.strerror)) + except LookupError as e: + msg = '{!r}: Non-existent owner {!r} or group {!r}: ignoring...' + print(msg.format(path, mode.owner, mode.group)) + except OSError as e: + if e.errno == errno.EINVAL: + msg = '{!r}: Non-existent numeric owner {!r} or group {!r}: ignoring...' + print(msg.format(path, mode.owner, mode.group)) + else: + raise # Must set permissions *after* setting owner/group otherwise the # setuid/setgid bits will get wiped by chmod # NOTE: On Windows you can set read/write perms; the rest are ignored From 8a2699acd0c8b157e46cbdbb6e48a4f0442df9d8 Mon Sep 17 00:00:00 2001 From: Jon Turney Date: Mon, 3 Apr 2017 21:54:25 +0100 Subject: [PATCH 12/17] Fix test cases/common/135 on Cygwin I don't really know how to explain this briefly... If you don't decorate this with dllimport, then a Cygwin runtime relocation is used (a so called 'pseudo-reloc'). As the relocation offset is only 32 bits, this can fail on x86_64 if the DLL happens to be loaded more than 2GB away from the reference. If you decorate with dllimport, then access is indirected via a pointer, imp_square_unsigned, which is fixed up by the loader. --- test cases/common/135 generated assembly/main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test cases/common/135 generated assembly/main.c b/test cases/common/135 generated assembly/main.c index 97fe723e3..b669cba27 100644 --- a/test cases/common/135 generated assembly/main.c +++ b/test cases/common/135 generated assembly/main.c @@ -1,5 +1,8 @@ #include +#if defined(_WIN32) || defined(__CYGWIN__) + __declspec(dllimport) +#endif unsigned square_unsigned (unsigned a); int From b4b55c3022305701090caaa6706e4d187ca59161 Mon Sep 17 00:00:00 2001 From: Jon Turney Date: Wed, 5 Apr 2017 22:47:23 +0100 Subject: [PATCH 13/17] Teach test cases/common/140 of the existence of Cygwin --- 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 7a0969fc2..5ce4b366b 100644 --- a/test cases/common/140 get define/meson.build +++ b/test cases/common/140 get define/meson.build @@ -13,6 +13,9 @@ foreach lang : ['c', 'cpp'] elif host_system == 'windows' d = cc.get_define('_WIN32') assert(d == '1', '_WIN32 value is @0@ instead of 1'.format(d)) + elif host_system == 'cygwin' + d = cc.get_define('__CYGWIN__') + assert(d == '1', '__CYGWIN__ value is @0@ instead of 1'.format(d)) else error('Please report a bug and help us improve support for this platform') endif From 16ad5508721300fc5afab6dff61d650c799a35ac Mon Sep 17 00:00:00 2001 From: Jon Turney Date: Mon, 3 Apr 2017 22:43:54 +0100 Subject: [PATCH 14/17] Fix test cases/common/125 on Cygwin --- test cases/common/125 shared module/meson.build | 3 ++- test cases/common/125 shared module/module.c | 17 ++++++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/test cases/common/125 shared module/meson.build b/test cases/common/125 shared module/meson.build index 7c15bccd2..d96d8fcae 100644 --- a/test cases/common/125 shared module/meson.build +++ b/test cases/common/125 shared module/meson.build @@ -5,7 +5,8 @@ l = shared_library('runtime', 'runtime.c') # Do NOT link the module with the runtime library. This # is a common approach for plugins that are only used # with dlopen. Any symbols are resolved dynamically -# at runtime +# at runtime. This requires extra help on Windows, so +# should be avoided unless really neccessary. m = shared_module('mymodule', 'module.c') e = executable('prog', 'prog.c', link_with : l, dependencies : dl) test('import test', e, args : m) diff --git a/test cases/common/125 shared module/module.c b/test cases/common/125 shared module/module.c index 56078c565..181b760ff 100644 --- a/test cases/common/125 shared module/module.c +++ b/test cases/common/125 shared module/module.c @@ -9,14 +9,24 @@ #endif #endif -#ifdef _WIN32 +#if defined(_WIN32) || defined(__CYGWIN__) #include -#include -#include typedef int (*fptr) (void); +#ifdef __CYGWIN__ + +#include + +fptr find_any_f (const char *name) { + return (fptr) dlsym(RTLD_DEFAULT, name); +} +#else /* _WIN32 */ + +#include +#include + /* Unlike Linux and OS X, when a library is loaded, all the symbols aren't * loaded into a single namespace. You must fetch the symbol by iterating over * all loaded modules. Code for finding the function from any of the loaded @@ -45,6 +55,7 @@ fptr find_any_f (const char *name) { CloseHandle (snapshot); return f; } +#endif int DLL_PUBLIC func() { fptr f; From 85f989f74476f4cc02434cb34a27b8581023f8e3 Mon Sep 17 00:00:00 2001 From: Jon Turney Date: Thu, 6 Apr 2017 20:21:55 +0100 Subject: [PATCH 15/17] Don't run framework tests on Cygwin --- run_project_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run_project_tests.py b/run_project_tests.py index 4a4101a18..cbf8f083a 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -446,7 +446,7 @@ def detect_tests_to_run(): all_tests.append(('platform-osx', gather_tests('test cases/osx'), False if mesonlib.is_osx() else True)) all_tests.append(('platform-windows', gather_tests('test cases/windows'), False if mesonlib.is_windows() or mesonlib.is_cygwin() else True)) all_tests.append(('platform-linux', gather_tests('test cases/linuxlike'), False if not (mesonlib.is_osx() or mesonlib.is_windows()) else True)) - all_tests.append(('framework', gather_tests('test cases/frameworks'), False if not mesonlib.is_osx() and not mesonlib.is_windows() else True)) + all_tests.append(('framework', gather_tests('test cases/frameworks'), False if not mesonlib.is_osx() and not mesonlib.is_windows() and not mesonlib.is_cygwin() else True)) all_tests.append(('java', gather_tests('test cases/java'), False if using_backend('ninja') and not mesonlib.is_osx() and have_java() else True)) all_tests.append(('C#', gather_tests('test cases/csharp'), False if using_backend('ninja') and shutil.which('mcs') else True)) all_tests.append(('vala', gather_tests('test cases/vala'), False if using_backend('ninja') and shutil.which('valac') else True)) From 2930d3bda64ef02d9baaee2165690e3eb4ad9455 Mon Sep 17 00:00:00 2001 From: Jon Turney Date: Tue, 4 Apr 2017 00:11:53 +0100 Subject: [PATCH 16/17] Ignore missing .pdb files when not using MSVS This fixes 'test cases/windows/1 basic' on Cygwin --- run_project_tests.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/run_project_tests.py b/run_project_tests.py index cbf8f083a..dc05524df 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -244,6 +244,9 @@ def validate_install(srcdir, installdir): expected[fname] = True for (fname, found) in expected.items(): if not found: + # Ignore missing PDB files if we aren't using cl + if fname.endswith('.pdb') and compiler != 'cl': + continue ret_msg += 'Expected file {0} missing.\n'.format(fname) # Check if there are any unexpected files found = get_relative_files_list_from_dir(installdir) From 44c54affda4526a90e20d457786fa6fc2d3cbe06 Mon Sep 17 00:00:00 2001 From: Jon Turney Date: Thu, 6 Apr 2017 00:26:11 +0100 Subject: [PATCH 17/17] Add Cygwin/x86_64 to AppVeyor CI matrix Install ninja and packages needed for tests Don't bother with x86 for speed and reliability reasons --- .appveyor.yml | 15 +++++++++++++-- ci/appveyor-install.bat | 11 +++++++++++ ci/appveyor-test.sh | 6 ++++++ 3 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 ci/appveyor-install.bat create mode 100755 ci/appveyor-test.sh diff --git a/.appveyor.yml b/.appveyor.yml index 9264f493f..c79e2509d 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -38,6 +38,10 @@ environment: compiler: msys2-mingw backend: ninja + - arch: x64 + compiler: cygwin + backend: ninja + platform: - x64 @@ -55,15 +59,22 @@ install: - cmd: if %compiler%==msvc2015 ( call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" %arch% ) - cmd: if %compiler%==msvc2017 ( call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\Tools\VsDevCmd.bat" -arch=%arch% ) - cmd: if %compiler%==msys2-mingw (if %arch%==x86 (set "PATH=C:\msys64\mingw32\bin;%PATH%") else (set "PATH=C:\msys64\mingw64\bin;%PATH%")) + - cmd: if %compiler%==cygwin ( call ci\appveyor-install.bat ) build_script: - cmd: echo No build step. - - cmd: if %backend%==ninja ( ninja.exe --version ) else ( MSBuild /version & echo. ) + - cmd: if not %compiler%==cygwin if %backend%==ninja ( ninja.exe --version ) else ( MSBuild /version & echo. ) test_script: - cmd: echo Running tests for %arch% and %compiler% with the %backend% backend - - cmd: PATH=%cd%;%MESON_PYTHON_PATH%;%PATH%; && python run_tests.py --backend=%backend% + - cmd: set "ORIG_PATH=%PATH%" + - cmd: if %compiler%==cygwin ( set "PATH=%CYGWIN_ROOT%\bin;%SYSTEMROOT%\system32" && bash -lc "cd $APPVEYOR_BUILD_FOLDER && ci/appveyor-test.sh" ) + - cmd: if not %compiler%==cygwin ( set "PATH=%cd%;%MESON_PYTHON_PATH%;%PATH%;" && python run_tests.py --backend=%backend% ) on_finish: + - set "PATH=%ORIG_PATH%" - appveyor PushArtifact meson-test-run.txt -DeploymentName "Text test logs" - appveyor PushArtifact meson-test-run.xml -DeploymentName "XML test logs" + +cache: + - C:\cache diff --git a/ci/appveyor-install.bat b/ci/appveyor-install.bat new file mode 100644 index 000000000..0c1ce440b --- /dev/null +++ b/ci/appveyor-install.bat @@ -0,0 +1,11 @@ +set CACHE=C:\cache +set CYGWIN_MIRROR="http://cygwin.mirror.constant.com" + +if _%arch%_ == _x64_ set SETUP=setup-x86_64.exe && set CYGWIN_ROOT=C:\cygwin64 +if _%arch%_ == _x86_ set SETUP=setup-x86.exe && set CYGWIN_ROOT=C:\cygwin + +if not exist %CACHE% mkdir %CACHE% + +echo Updating Cygwin and installing ninja and test prerequisites +%CYGWIN_ROOT%\%SETUP% -qnNdO -R "%CYGWIN_ROOT%" -s "%CYGWIN_MIRROR%" -l "%CACHE%" -g -P "ninja,gcc-objc,gcc-objc++,libglib2.0-devel,zlib-devel" +echo Install done diff --git a/ci/appveyor-test.sh b/ci/appveyor-test.sh new file mode 100755 index 000000000..2f2963054 --- /dev/null +++ b/ci/appveyor-test.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +echo ninja $(ninja --version) +python3 --version -V + +python3 run_tests.py --backend=${backend}