go plugin: cross-compilation support #1253

Closed
wants to merge 44 commits into
from
Commits
Jump to file or symbol
Failed to load files and symbols.
+650 −84
Split
@@ -18,6 +18,7 @@
import subprocess
import integration_tests
+import snapcraft
class GoPluginTestCase(integration_tests.TestCase):
@@ -33,3 +34,10 @@ def test_stage_go_plugin(self):
def test_building_multiple_main_packages(self):
self.run_snapcraft('stage', 'go-with-multiple-main-packages')
+
+ def test_cross_compiling(self):
+ if snapcraft.ProjectOptions().deb_arch != 'amd64':
+ self.skipTest('The test only handles amd64 to armhf')
+
+ arch = 'armhf'
+ self.run_snapcraft('stage', 'go-cgo', '--target={}'.format(arch))
@@ -0,0 +1,44 @@
+// -*- Mode: Go; indent-tabs-mode: t -*-
+
+/*
+ * Copyright (C) 2017 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package main
+
+/*
+#cgo pkg-config: glib-2.0
+#cgo LDFLAGS: -lm
+#include <math.h>
+#include <glib.h>
+
+*/
+import "C"
+
+import (
+ "fmt"
+ "os/user"
+)
+
+func main() {
+ u, err := user.Current()
+ if err != nil {
+ panic(err)
+ }
+ fmt.Println("user according to go:", u.Username)
+ fmt.Println("user according to glib:", C.GoString((*C.char)(C.g_get_user_name())))
+ fmt.Println("more or less 1:", C.sin(3.14/2))
+}
@@ -0,0 +1,14 @@
+name: go-cgo
+version: 0.1
+summary: A go project using libraries written in C.
+description: |
+ This is a basic go snap that uses cgo to access C APIs.
+ The name of the binary will be that of the directory containing it,
+ just like it is seen when using `go build` or `go install`.
+confinement: strict
+
+parts:
+ go-cgo:
+ plugin: go
+ source: .
+ build-packages: [libglib2.0-dev]
@@ -31,6 +31,4 @@ def test_bad_multiarch_stage_packages(self):
self.assertThat(
exception.output, Contains(
"Error downloading stage packages for part 'my-part': The "
- "package 'hello:fake-arch' was not found.\n"
- 'You may need to add support for this architecture with '
- "'dpkg --add-architecture fake-arch'"))
+ "package 'hello:fake-arch' was not found.\n"))
@@ -124,7 +124,7 @@ def test_error_with_unexistent_build_package(self):
subprocess.CalledProcessError, self.run_snapcraft, 'snap')
expected = (
"Could not find a required package in 'build-packages': "
- '"The cache has no package named \'inexistent-package\'"\n')
+ 'inexistent-package\n')
self.assertThat(exception.output, EndsWith(expected))
def test_snap_with_exposed_files(self):
View
@@ -33,7 +33,8 @@
'deb': 'armhf',
'uts_machine': 'arm',
'cross-compiler-prefix': 'arm-linux-gnueabihf-',
- 'cross-build-packages': ['gcc-arm-linux-gnueabihf'],
+ 'cross-build-packages': ['gcc-arm-linux-gnueabihf',
+ 'libc6-dev-armhf-cross'],
'triplet': 'arm-linux-gnueabihf',
'core-dynamic-linker': 'lib/ld-linux-armhf.so.3',
},
@@ -42,7 +43,8 @@
'deb': 'arm64',
'uts_machine': 'aarch64',
'cross-compiler-prefix': 'aarch64-linux-gnu-',
- 'cross-build-packages': ['gcc-aarch64-linux-gnu'],
+ 'cross-build-packages': ['gcc-aarch64-linux-gnu',
+ 'libc6-dev-arm64-cross'],
'triplet': 'aarch64-linux-gnu',
'core-dynamic-linker': 'lib/ld-linux-aarch64.so.1',
},
@@ -57,7 +59,8 @@
'deb': 'ppc64el',
'uts_machine': 'ppc64el',
'cross-compiler-prefix': 'powerpc64le-linux-gnu-',
- 'cross-build-packages': ['gcc-powerpc64le-linux-gnu'],
+ 'cross-build-packages': ['gcc-powerpc64le-linux-gnu',
+ 'libc6-dev-ppc64el-cross'],
'triplet': 'powerpc64le-linux-gnu',
'core-dynamic-linker': '/lib64/ld64.so.2',
},
@@ -66,7 +69,8 @@
'deb': 'powerpc',
'uts_machine': 'powerpc',
'cross-compiler-prefix': 'powerpc-linux-gnu-',
- 'cross-build-packages': ['gcc-powerpc-linux-gnu'],
+ 'cross-build-packages': ['gcc-powerpc-linux-gnu',
+ 'libc6-dev-powerpc-cross'],
'triplet': 'powerpc-linux-gnu',
},
'x86_64': {
@@ -81,7 +85,8 @@
'deb': 's390x',
'uts_machine': 's390x',
'cross-compiler-prefix': 's390x-linux-gnu-',
- 'cross-build-packages': ['gcc-s390x-linux-gnu'],
+ 'cross-build-packages': ['gcc-s390x-linux-gnu',
+ 'libc6-dev-s390x-cross'],
'triplet': 's390x-linux-gnu',
'core-dynamic-linker': '/lib/ld64.so.1',
}
@@ -145,8 +150,8 @@ def cross_compiler_prefix(self):
def additional_build_packages(self):
packages = []
if self.is_cross_compiling:
- packages.extend(self.__machine_info.get(
- 'cross-build-packages', []))
+ for package in self.__machine_info.get('cross-build-packages', []):
+ packages.append('{}:native'.format(package))
return packages
@property
@@ -108,7 +108,8 @@ def execute(step, project_options, part_names=None):
:returns: A dict with the snap name, version, type and architectures.
"""
config = snapcraft.internal.load_config(project_options)
- repo.Repo.install_build_packages(config.build_tools)
+ repo.Repo.install_build_packages(config.build_tools,
+ project_options.deb_arch)
if (os.environ.get('SNAPCRAFT_SETUP_CORE') and
config.data['confinement'] == 'classic'):
@@ -356,6 +356,10 @@ def _build_env(root, snap_name, confinement, arch_triplet,
env.append(formatting_utils.format_path_variable(
'PKG_CONFIG_PATH', paths, prepend='', separator=':'))
+ paths = common.get_pkg_config_paths('/', arch_triplet)
+ env.append(formatting_utils.format_path_variable(
+ 'PKG_CONFIG_PATH', paths, prepend='', separator=':'))
+
return env
@@ -34,11 +34,19 @@ def check_for_command(command):
def get_pkg_name_parts(pkg_name):
- """Break package name into base parts"""
+ """Break package name:arch=version into base parts"""
name = pkg_name
version = None
with contextlib.suppress(ValueError):
name, version = pkg_name.split('=')
- return name, version
+ arch = ''
+ if ':' in name:
+ name, arch = name.rsplit(':', 1)
+ if arch == 'any':
+ arch = ''
+ else:
+ arch = ':' + arch
+
+ return name, arch, version
@@ -90,11 +90,12 @@ def get_packages_for_source_type(cls, source_type):
raise NotImplementedError()
@classmethod
- def install_build_packages(cls, package_names):
+ def install_build_packages(cls, package_names, arch):
"""Install packages on the host required to build.
:param package_names: a list of package names to install.
:type package_names: a list of strings.
+ :param str arch: the target architecture.
:raises snapcraft.repo.errors.BuildPackageNotFoundError:
if one of the package_names cannot be installed.
"""
Oops, something went wrong.