Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,6 @@ check_path_for_excludes() {
warn "xz not found, excluding update tests"
EXCLUDES="${EXCLUDES} --exclude=xz"
fi
GCCVER="`cc -dumpversion`"
if [ ! -d "/usr/lib/gcc/x86_64-linux-gnu/${GCCVER%.*.*}/32" ] && [ ! -d "/usr/lib/gcc/x86_64-pc-linux-gnu/$GCCVER/32" ]; then
warn "32-bit gcc libraries not found, excluding cross-compile tests"
EXCLUDES="${EXCLUDES} --exclude=x86"
fi

echo $EXCLUDES
}

Expand Down
37 changes: 28 additions & 9 deletions test/cross_compile/BUILD
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
subinclude("//test/build_defs", "///cc//build_defs:c")
subinclude("//test/build_defs")

# A static link goes via the host C compiler, which can't handle objects for the architecture
# we're cross-compiling to. Go turns cgo off by itself when cross-compiling, so a dynamic link
# here is a pure-Go one and needs no C toolchain at all.
# N.B. Scoped to this package, so it can't affect the real cross-compiled builds of Please.
package(
go = {
"default_static": False,
},
)

genrule(
name = "record_arch",
Expand All @@ -24,23 +34,34 @@ plz_e2e_test(
cmd = "plz test -a test_x86 //test/cross_compile:test_arch",
)

c_binary(
go_binary(
name = "bin",
srcs = ["main.c"],
srcs = ["main.go"],
deps = ["//test/cross_compile/lib"],
)

sh_test(
name = "bin_test",
src = "bin_test.sh",
data = [":bin"],
)

# N.B. arch_checker is a test tool, not data, so that it's built for the host and can actually
# run here while :bin is built for the architecture we're testing.
gentest(
name = "cross_compiled_bin_test",
data = [":bin"],
labels = ["manual"],
no_test_output = True,
test_cmd = "$TOOL $(location :bin) EM_AARCH64",
test_tools = ["//test/cross_compile/arch_checker"],
)

# N.B. Go can cross-compile to any platform it supports without needing a toolchain installed,
# so unlike the C rules this used to use, this needs nothing set up to run.
plz_e2e_test(
name = "x86_test",
cmd = "plz test -a linux_x86 //test/cross_compile:bin_test",
labels = ["x86"],
name = "cross_compile_binary_test",
cmd = "plz test -a linux_arm64 //test/cross_compile:cross_compiled_bin_test",
)

# Test for #582
Expand All @@ -60,8 +81,7 @@ sh_test(

plz_e2e_test(
name = "location_cross_compile_test",
cmd = "plz test -a linux_x86 //test/cross_compile:location_test",
labels = ["x86"],
cmd = "plz test -a linux_arm64 //test/cross_compile:location_test",
)

config_setting(
Expand Down Expand Up @@ -104,5 +124,4 @@ sh_test(
plz_e2e_test(
name = "select_cross_compile_test",
cmd = "plz test -a linux_x86 //test/cross_compile:select_test",
labels = ["x86"],
)
11 changes: 8 additions & 3 deletions test/cross_compile/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
Example rules for testing cross-compiling.

One can test a simple binary with `plz build -a linux_x86 //test/cross_compile:bin`.
The configuration for that is stored in `.plzconfig_linux_x86` at the repo root.
This typically requires some additional packages to be installed; e.g. `gcc-multilib` or similar.
One can test a simple binary with `plz build -a linux_arm64 //test/cross_compile:bin`.

These use Go rather than C deliberately: the Go toolchain can produce binaries for any platform
it supports without anything extra being installed, whereas the C version of this needed a
cross-compiling gcc (e.g. `gcc-multilib`) which is often not present.

The `package()` call in the BUILD file turns off static linking for these rules; a static link
runs the host C compiler, which can't handle objects for the architecture we're targeting.
5 changes: 5 additions & 0 deletions test/cross_compile/arch_checker/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
go_binary(
name = "arch_checker",
srcs = ["main.go"],
visibility = ["//test/cross_compile:all"],
)
28 changes: 28 additions & 0 deletions test/cross_compile/arch_checker/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Binary arch_checker asserts that a binary was built for a particular machine architecture.
// It exists so the cross-compilation test doesn't have to shell out to `file`, which isn't
// present on all the images we build on.
package main

import (
"debug/elf"
"fmt"
"os"
)

func main() {
if len(os.Args) != 3 {
fmt.Fprintf(os.Stderr, "usage: %s <binary> <machine>\n", os.Args[0])
os.Exit(2)
}
path, expected := os.Args[1], os.Args[2]
f, err := elf.Open(path)
if err != nil {
fmt.Fprintf(os.Stderr, "couldn't read %s as an ELF binary: %s\n", path, err)
os.Exit(1)
}
defer f.Close()
if f.Machine.String() != expected {
fmt.Fprintf(os.Stderr, "%s was built for %s, expected %s\n", path, f.Machine, expected)
os.Exit(1)
}
}
8 changes: 3 additions & 5 deletions test/cross_compile/bin_test.sh
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
#!/bin/bash
# Checks that the binary built for the host architecture actually works, so that the
# cross-compiled test below is checking the architecture of something that isn't broken.
set -eu

if [ "`test/cross_compile/bin`" != "42" ]; then
echo "unexpected output"
exit 1
fi
if [ ! `file test/cross_compile/bin | grep 32-bit` ]; then
echo "unexpected architecture of binary"
echo "unexpected output: `test/cross_compile/bin`"
exit 1
fi
7 changes: 2 additions & 5 deletions test/cross_compile/lib/BUILD
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
# This contains an arbitrary set of rules intended to exercise
# aspects of the cross-compilation code.

subinclude("///cc//build_defs:c")

c_library(
go_library(
name = "lib",
srcs = ["lib.c"],
hdrs = ["lib.h"],
srcs = ["lib.go"],
visibility = ["//test/cross_compile:all"],
)
5 changes: 0 additions & 5 deletions test/cross_compile/lib/lib.c

This file was deleted.

8 changes: 8 additions & 0 deletions test/cross_compile/lib/lib.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Package lib exists to give the cross-compilation test something to build alongside the binary,
// so that we exercise cross-compiling a dependency and not just a single target.
package lib

// GetAnswer returns, as usual, the answer to Life, the Universe and Everything.
func GetAnswer() int {
return 42
}
2 changes: 0 additions & 2 deletions test/cross_compile/lib/lib.h

This file was deleted.

7 changes: 0 additions & 7 deletions test/cross_compile/lib/main.go

This file was deleted.

4 changes: 3 additions & 1 deletion test/cross_compile/location_test.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#!/bin/bash
# $DATA is arch_location.txt, whose contents are the $(location) of :record_arch. That must come
# out the same whether or not we're cross-compiling, which is what #582 was about.

if [ "`cat $DATA`" != "test/cross_compile/arch_location.txt" ]; then
if [ "`cat $DATA`" != "test/cross_compile/arch.txt" ]; then
echo "Unexpected contents of file: `cat $DATA`"
exit 1
fi
8 changes: 0 additions & 8 deletions test/cross_compile/main.c

This file was deleted.

11 changes: 11 additions & 0 deletions test/cross_compile/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package main

import (
"fmt"

"github.com/thought-machine/please/test/cross_compile/lib"
)

func main() {
fmt.Println(lib.GetAnswer())
}
Loading