diff options
-rw-r--r-- | conf/machine-sdk/i686-mingw32.conf | 1 | ||||
-rw-r--r-- | conf/machine-sdk/include/mingw32-common.inc | 7 | ||||
-rw-r--r-- | conf/machine-sdk/x86_64-mingw32.conf | 1 | ||||
-rw-r--r-- | lib/oeqa/sdkmingw/__init__.py | 0 | ||||
-rw-r--r-- | lib/oeqa/sdkmingw/case.py | 87 | ||||
-rw-r--r-- | lib/oeqa/sdkmingw/cases/__init__.py | 0 | ||||
-rw-r--r-- | lib/oeqa/sdkmingw/context.py | 69 | ||||
-rw-r--r-- | lib/oeqa/sdkmingw/testsdk.py | 42 |
8 files changed, 207 insertions, 0 deletions
diff --git a/conf/machine-sdk/i686-mingw32.conf b/conf/machine-sdk/i686-mingw32.conf index 5090168..fef48b5 100644 --- a/conf/machine-sdk/i686-mingw32.conf +++ b/conf/machine-sdk/i686-mingw32.conf | |||
@@ -1,3 +1,4 @@ | |||
1 | SDK_ARCH = "i686" | 1 | SDK_ARCH = "i686" |
2 | TESTSDK_WINEARCH = "win32" | ||
2 | 3 | ||
3 | require conf/machine-sdk/include/mingw32-common.inc | 4 | require conf/machine-sdk/include/mingw32-common.inc |
diff --git a/conf/machine-sdk/include/mingw32-common.inc b/conf/machine-sdk/include/mingw32-common.inc index 733d092..9011ded 100644 --- a/conf/machine-sdk/include/mingw32-common.inc +++ b/conf/machine-sdk/include/mingw32-common.inc | |||
@@ -26,6 +26,9 @@ SDKPKGSUFFIX = "nativesdk-mingw32" | |||
26 | 26 | ||
27 | MACHINEOVERRIDES .= ":sdkmingw32" | 27 | MACHINEOVERRIDES .= ":sdkmingw32" |
28 | 28 | ||
29 | TESTSDK_CLASS_NAME = "oeqa.sdkmingw.testsdk.TestSDKMinGW" | ||
30 | TESTSDKEXT_CLASS_NAME = "" | ||
31 | |||
29 | WINDRES_mingw32 = "${HOST_PREFIX}windres --include-dir=${STAGING_INCDIR}" | 32 | WINDRES_mingw32 = "${HOST_PREFIX}windres --include-dir=${STAGING_INCDIR}" |
30 | RC_mingw32 = "${WINDRES}" | 33 | RC_mingw32 = "${WINDRES}" |
31 | 34 | ||
@@ -39,3 +42,7 @@ DISABLE_STATIC_mingw32 = "" | |||
39 | 42 | ||
40 | # disable security flags | 43 | # disable security flags |
41 | GCCPIE_mingw32 = "" | 44 | GCCPIE_mingw32 = "" |
45 | |||
46 | # wine and wineserver are required to test MinGW SDKs | ||
47 | HOSTTOOLS += "${@'wine wineserver' if (bb.utils.contains_any('IMAGE_CLASSES', 'testsdk', True, False, d) or any(x in (d.getVar("BBINCLUDED") or "") for x in ["testsdk.bbclass"])) else ''}" | ||
48 | |||
diff --git a/conf/machine-sdk/x86_64-mingw32.conf b/conf/machine-sdk/x86_64-mingw32.conf index fc53822..188debc 100644 --- a/conf/machine-sdk/x86_64-mingw32.conf +++ b/conf/machine-sdk/x86_64-mingw32.conf | |||
@@ -1,3 +1,4 @@ | |||
1 | SDK_ARCH = "x86_64" | 1 | SDK_ARCH = "x86_64" |
2 | TESTSDK_WINEARCH = "win64" | ||
2 | 3 | ||
3 | require conf/machine-sdk/include/mingw32-common.inc | 4 | require conf/machine-sdk/include/mingw32-common.inc |
diff --git a/lib/oeqa/sdkmingw/__init__.py b/lib/oeqa/sdkmingw/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/lib/oeqa/sdkmingw/__init__.py | |||
diff --git a/lib/oeqa/sdkmingw/case.py b/lib/oeqa/sdkmingw/case.py new file mode 100644 index 0000000..169c143 --- /dev/null +++ b/lib/oeqa/sdkmingw/case.py | |||
@@ -0,0 +1,87 @@ | |||
1 | # Copyright 2018 by Garmin Ltd. or its subsidiaries | ||
2 | # Released under the MIT license (see COPYING.MIT) | ||
3 | |||
4 | import subprocess | ||
5 | import os | ||
6 | import tempfile | ||
7 | import shutil | ||
8 | import bb | ||
9 | |||
10 | from oeqa.core.utils.path import remove_safe | ||
11 | from oeqa.sdk.case import OESDKTestCase | ||
12 | |||
13 | from oeqa.utils.subprocesstweak import errors_have_output | ||
14 | errors_have_output() | ||
15 | |||
16 | class OESDKMinGWTestCase(OESDKTestCase): | ||
17 | def setUp(self): | ||
18 | super().setUp() | ||
19 | |||
20 | self.test_dir = tempfile.mkdtemp(prefix=self.__class__.__name__ + '-', dir=self.tc.sdk_dir) | ||
21 | self.addCleanup(lambda: bb.utils.prunedir(self.test_dir)) | ||
22 | |||
23 | self.wine_test_dir = self.tc.wine_path(self.test_dir) | ||
24 | |||
25 | def copyTestFile(self, src, dest=None): | ||
26 | dest_path = dest or os.path.join(self.test_dir, os.path.basename(src)) | ||
27 | shutil.copyfile(src, dest_path) | ||
28 | self.addCleanup(lambda: remove_safe(dest_path)) | ||
29 | |||
30 | def fetch(self, url, destdir=None, dl_dir=None, archive=None): | ||
31 | if not destdir: | ||
32 | destdir = self.test_dir | ||
33 | |||
34 | if not dl_dir: | ||
35 | dl_dir = self.td.get('DL_DIR', None) | ||
36 | |||
37 | if not archive: | ||
38 | from urllib.parse import urlparse | ||
39 | archive = os.path.basename(urlparse(url).path) | ||
40 | |||
41 | if dl_dir: | ||
42 | tarball = os.path.join(dl_dir, archive) | ||
43 | if os.path.exists(tarball): | ||
44 | return tarball | ||
45 | |||
46 | tarball = os.path.join(destdir, archive) | ||
47 | subprocess.check_output(["wget", "-O", tarball, url]) | ||
48 | return tarball | ||
49 | |||
50 | |||
51 | def _run(self, cmd): | ||
52 | import shlex | ||
53 | |||
54 | def strip_quotes(s): | ||
55 | if s[0] == '"' and s[-1] == '"': | ||
56 | return s[1:-1] | ||
57 | return s | ||
58 | |||
59 | command = ['wine', 'cmd', '/c', self.tc.wine_sdk_env, '>', 'NUL', '&&', 'cd', self.wine_test_dir, '&&'] | ||
60 | |||
61 | # Perform some massaging so that commands can be written naturally in | ||
62 | # test cases. shlex.split() in Non-posix mode gets us most of the way | ||
63 | # there, but it leaves the quotes around a quoted argument, so we | ||
64 | # remove them manually. | ||
65 | command.extend(strip_quotes(s) for s in shlex.split(cmd, posix=False)) | ||
66 | |||
67 | return subprocess.check_output(command, env=self.tc.get_wine_env(), | ||
68 | stderr=subprocess.STDOUT, universal_newlines=True) | ||
69 | |||
70 | def assertIsTargetElf(self, path): | ||
71 | import oe.qa | ||
72 | import oe.elf | ||
73 | |||
74 | elf = oe.qa.ELFFile(path) | ||
75 | elf.open() | ||
76 | |||
77 | if not getattr(self, 'target_os', None): | ||
78 | output = self._run("echo %OECORE_TARGET_OS%:%OECORE_TARGET_ARCH%") | ||
79 | self.target_os, self.target_arch = output.strip().split(":") | ||
80 | |||
81 | machine_data = oe.elf.machine_dict(None)[self.target_os][self.target_arch] | ||
82 | (machine, osabi, abiversion, endian, bits) = machine_data | ||
83 | |||
84 | self.assertEqual(machine, elf.machine()) | ||
85 | self.assertEqual(bits, elf.abiSize()) | ||
86 | self.assertEqual(endian, elf.isLittleEndian()) | ||
87 | |||
diff --git a/lib/oeqa/sdkmingw/cases/__init__.py b/lib/oeqa/sdkmingw/cases/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/lib/oeqa/sdkmingw/cases/__init__.py | |||
diff --git a/lib/oeqa/sdkmingw/context.py b/lib/oeqa/sdkmingw/context.py new file mode 100644 index 0000000..edabcbd --- /dev/null +++ b/lib/oeqa/sdkmingw/context.py | |||
@@ -0,0 +1,69 @@ | |||
1 | # Copyright (C) 2018 by Garmin Ltd. or its subsidiaries | ||
2 | # Released under the MIT license (see COPYING.MIT) | ||
3 | import os | ||
4 | import subprocess | ||
5 | |||
6 | from oeqa.sdk.context import OESDKTestContext, OESDKTestContextExecutor | ||
7 | |||
8 | from oeqa.utils.subprocesstweak import errors_have_output | ||
9 | errors_have_output() | ||
10 | |||
11 | class OESDKMinGWTestContext(OESDKTestContext): | ||
12 | sdk_files_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "files") | ||
13 | |||
14 | def __init__(self, td=None, logger=None, sdk_dir=None, sdk_env=None, wine_prefix=None, | ||
15 | wine_arch=None, target_pkg_manifest=None, host_pkg_manifest=None): | ||
16 | super(OESDKMinGWTestContext, self).__init__(td, logger, sdk_dir, sdk_env, target_pkg_manifest, host_pkg_manifest) | ||
17 | self.wine_prefix = wine_prefix | ||
18 | self.wine_arch = wine_arch | ||
19 | self.wine_sdk_dir = self.wine_path(sdk_dir) | ||
20 | self.wine_sdk_env = self.wine_path(sdk_env) | ||
21 | |||
22 | def get_wine_env(self): | ||
23 | env = os.environ.copy() | ||
24 | |||
25 | # Turn off all Wine debug logging so it doesn't interfere with command output | ||
26 | env['WINEDEBUG'] = '-all' | ||
27 | |||
28 | env['WINEPREFIX'] = self.wine_prefix | ||
29 | env['WINEARCH'] = self.wine_arch | ||
30 | |||
31 | # Convenience variables to make test cases easier to write | ||
32 | env['SDK_DIR'] = getattr(self, 'wine_sdk_dir', '') | ||
33 | |||
34 | return env | ||
35 | |||
36 | def wine_path(self, p): | ||
37 | """ | ||
38 | Converts a host POSIX path to a path in Wine | ||
39 | """ | ||
40 | o = subprocess.check_output(['wine', 'winepath', '-w', p], env=self.get_wine_env()) | ||
41 | return o.decode('utf-8').rstrip() | ||
42 | |||
43 | |||
44 | class OESDKMinGWTestContextExecutor(OESDKTestContextExecutor): | ||
45 | _context_class = OESDKMinGWTestContext | ||
46 | |||
47 | name = 'sdk-mingw' | ||
48 | help = 'MinGW sdk test component' | ||
49 | description = 'executes MinGW sdk tests' | ||
50 | |||
51 | default_cases = [os.path.join(os.path.abspath(os.path.dirname(__file__)), | ||
52 | 'cases')] | ||
53 | |||
54 | def register_commands(self, logger, subparsers): | ||
55 | super(OESDKMinGWTestContextExecutor, self).register_commands(logger, subparsers) | ||
56 | |||
57 | wine_group = self.parser.add_argument_group('wine options') | ||
58 | wine_group.add_argument('--wine-prefix', action='store', | ||
59 | help='Wine prefix (bottle). Default is $SDK_DIR/.wine') | ||
60 | wine_group.add_argument('--wine-arch', action='store', choices=('win32', 'win64'), | ||
61 | default='win64', help='Wine architecture. Defaults to %(default)s') | ||
62 | |||
63 | def _process_args(self, logger, args): | ||
64 | super(OESDKMinGWTestContextExecutor, self)._process_args(logger, args) | ||
65 | self.tc_kwargs['init']['wine_prefix'] = args.wine_prefix or os.path.join(args.sdk_dir, '.wine') | ||
66 | self.tc_kwargs['init']['wine_arch'] = args.wine_arch | ||
67 | |||
68 | _executor_class = OESDKMinGWTestContextExecutor | ||
69 | |||
diff --git a/lib/oeqa/sdkmingw/testsdk.py b/lib/oeqa/sdkmingw/testsdk.py new file mode 100644 index 0000000..85fe3c6 --- /dev/null +++ b/lib/oeqa/sdkmingw/testsdk.py | |||
@@ -0,0 +1,42 @@ | |||
1 | # Copyright 2018 by Garmin Ltd. or its subsidiaries | ||
2 | # Released under the MIT license (see COPYING.MIT) | ||
3 | |||
4 | from oeqa.sdk.testsdk import TestSDK | ||
5 | from oeqa.sdkmingw.context import OESDKMinGWTestContext, OESDKMinGWTestContextExecutor | ||
6 | |||
7 | class TestSDKMinGW(TestSDK): | ||
8 | context_executor_class = OESDKMinGWTestContextExecutor | ||
9 | context_class = OESDKMinGWTestContext | ||
10 | |||
11 | def get_tcname(self, d): | ||
12 | """ | ||
13 | Get the name of the SDK file | ||
14 | """ | ||
15 | return d.expand("${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.tar.xz") | ||
16 | |||
17 | def extract_sdk(self, tcname, sdk_dir, d): | ||
18 | """ | ||
19 | Extract the SDK to the specified location | ||
20 | """ | ||
21 | import subprocess | ||
22 | |||
23 | try: | ||
24 | # TODO: It would be nice to try and extract the SDK in Wine to make | ||
25 | # sure it is well formed | ||
26 | subprocess.check_output(['tar', '-xf', tcname, '-C', sdk_dir]) | ||
27 | except subprocess.CalledProcessError as e: | ||
28 | bb.fatal("Couldn't install the SDK:\n%s" % e.output.decode("utf-8")) | ||
29 | |||
30 | def setup_context(self, d): | ||
31 | """ | ||
32 | Return a dictionary of additional arguments that should be passed to | ||
33 | the context_class on construction | ||
34 | """ | ||
35 | wine_prefix = d.getVar('TESTSDK_WINEPREFIX') or d.expand('${WORKDIR}/testimage-wine/') | ||
36 | bb.utils.remove(wine_prefix, True) | ||
37 | |||
38 | return { | ||
39 | 'wine_prefix': wine_prefix, | ||
40 | 'wine_arch': d.getVar('TESTSDK_WINEARCH') or 'win64' | ||
41 | } | ||
42 | |||