Skip to content

Commit

Permalink
feat(make): build ooniprobe for windows and linux
Browse files Browse the repository at this point in the history
In ooni/probe#1466, a user is asking
about arm64 builds for Debian. We already had some code for that
in #311. Let us adapt the
code to the `./make` script to have arm64 builds.
  • Loading branch information
bassosimone committed May 5, 2021
1 parent 5738c07 commit e8eaf8f
Show file tree
Hide file tree
Showing 2 changed files with 170 additions and 15 deletions.
12 changes: 12 additions & 0 deletions CLI/linux/build
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/bin/sh
set -e
if [ "$GOARCH" = "" ]; then
echo 'fatal: $GOARCH is not set' 1>&2
exit 1
fi
set -x
apk update
apk upgrade
apk add --no-progress gcc git linux-headers musl-dev
CGO_ENABLED=1 GOOS=linux go build -o ./CLI/linux/$GOARCH/ \
-ldflags='-s -w -extldflags "-static"' "$@" ./cmd/ooniprobe
173 changes: 158 additions & 15 deletions make
Original file line number Diff line number Diff line change
Expand Up @@ -1094,6 +1094,19 @@ class MiniOONILinux:
engine.run(cmdline)


# MINIOONI_TARGETS contains all miniooni targets
MINIOONI_TARGETS: List[Target] = [
MiniOONIDarwinOrWindows("darwin", "amd64"),
MiniOONIDarwinOrWindows("darwin", "arm64"),
MiniOONILinux("386"),
MiniOONILinux("amd64"),
MiniOONILinux("arm"),
MiniOONILinux("arm64"),
MiniOONIDarwinOrWindows("windows", "386"),
MiniOONIDarwinOrWindows("windows", "amd64"),
]


class MiniOONI:
"""MiniOONI is the top-level 'miniooni' target."""

Expand All @@ -1103,31 +1116,161 @@ class MiniOONI:
return self.__name

def build(self, engine: Engine, options: Options) -> None:
for builder in (
MiniOONIDarwinOrWindows("darwin", "amd64"),
MiniOONIDarwinOrWindows("darwin", "arm64"),
MiniOONILinux("386"),
MiniOONILinux("amd64"),
MiniOONILinux("arm"),
MiniOONILinux("arm64"),
MiniOONIDarwinOrWindows("windows", "386"),
MiniOONIDarwinOrWindows("windows", "amd64"),
):
builder.build(engine, options)


TARGETS: List[Target] = [
for target in MINIOONI_TARGETS:
target.build(engine, options)


class OONIProbeLinux:
"""OONIProbeLinux builds ooniprobe for Linux."""

def __init__(self, goarch: str):
self.__name = os.path.join(".", "CLI", "linux", goarch, "ooniprobe")
self.__arch = goarch

def name(self) -> str:
return self.__name

def build(self, engine: Engine, options: Options) -> None:
if os.path.isfile(self.__name) and not options.dry_run():
log("./make: {}: already built".format(self.__name))
return
ooprivate = OONIProbePrivate()
ooprivate.build(engine, options)
ooprivate.copyfiles(engine, options)
log("./make: building {}...".format(self.__name))
engine.require("docker")
# make sure we have the latest version of the container image
engine.run(
[
"docker",
"pull",
"--platform",
"linux/{}".format(self.__arch),
"golang:{}-alpine".format(goversion()),
]
)
# then run the build inside the container
cmdline = [
"docker",
"run",
"--platform",
"linux/{}".format(self.__arch),
"-e",
"GOARCH={}".format(self.__arch),
"-it",
"-v",
"{}:/ooni".format(os.getcwd()),
"-w",
"/ooni",
"golang:{}-alpine".format(goversion()),
os.path.join(".", "CLI", "linux", "build"),
]
if options.debugging():
cmdline.append("-x")
if options.verbose():
cmdline.append("-v")
if not options.disable_embedding_psiphon_config():
cmdline.append("-tags=ooni_psiphon_config,netgo")
else:
cmdline.append("-tags=netgo")
engine.run(cmdline)


class OONIProbeWindows:
"""OONIProbeWindows builds ooniprobe for Windows."""

def __init__(self, goarch: str):
self.__name = os.path.join(".", "CLI", "windows", goarch, "ooniprobe.exe")
self.__arch = goarch

def name(self) -> str:
return self.__name

def _gcc(self) -> str:
if self.__arch == "amd64":
return "x86_64-w64-mingw32-gcc"
if self.__arch == "386":
return "i686-w64-mingw32-gcc"
raise NotImplementedError

def build(self, engine: Engine, options: Options) -> None:
if os.path.isfile(self.__name) and not options.dry_run():
log("./make: {}: already built".format(self.__name))
return
ooprivate = OONIProbePrivate()
ooprivate.build(engine, options)
ooprivate.copyfiles(engine, options)
gogo = SDKGolangGo()
gogo.build(engine, options)
log("./make: building {}...".format(self.__name))
engine.setenv("CGO_ENABLED", "1")
engine.setenv("GOOS", "windows")
engine.setenv("GOARCH", self.__arch)
engine.setenv("CC", self._gcc())
# TODO(bassosimone): here we have the problem that we would
# actually like to set the path before and see which is
# the golang executable that we're using.
engine.require(self._gcc(), "go")
cmdline = [
"go",
"build",
"-o",
os.path.join("CLI", "windows", self.__arch, "ooniprobe.exe"),
"-ldflags=-s -w",
]
if options.debugging():
cmdline.append("-x")
if options.verbose():
cmdline.append("-v")
if not options.disable_embedding_psiphon_config():
cmdline.append("-tags=ooni_psiphon_config")
cmdline.append("./cmd/ooniprobe")
engine.run(
cmdline,
extra_env={
"PATH": os.pathsep.join(
[
gogo.binpath(), # for golang/go
os.environ["PATH"], # original path
]
),
},
)
engine.unsetenv("GOARCH")
engine.unsetenv("GOOS")
engine.unsetenv("CGO_ENABLED")


# OONIPROBE_TARGETS contains all the ooniprobe targets
OONIPROBE_TARGETS: List[Target] = [
OONIProbeLinux("amd64"),
OONIProbeLinux("arm64"),
OONIProbeWindows("amd64"),
OONIProbeWindows("386"),
]

# MOBILE_TARGETS contains the top-level mobile targets.
MOBILE_TARGETS: List[Target] = [
Android(),
iOS(),
]

# EXTRA_TARGETS contains extra top-level targets.
EXTRA_TARGETS: List[Target] = [
MiniOONI(),
OONIMKAllAAR(),
OONIMKAllFrameworkZip(),
]

# VISIBLE_TARGETS contains all the visible-from-CLI targets
VISIBLE_TARGETS: List[Target] = (
OONIPROBE_TARGETS + MOBILE_TARGETS + EXTRA_TARGETS + MINIOONI_TARGETS
)


def main() -> None:
"""main function"""
toptargets: Dict[str, Target] = dict((t.name(), t) for t in TARGETS)
toptargets: Dict[str, Target] = dict((t.name(), t) for t in VISIBLE_TARGETS)
options = ConfigFromCLI.parse(list(toptargets.keys()))
engine = new_engine(options)
# note that we check whether the target is known in parse()
Expand Down

0 comments on commit e8eaf8f

Please sign in to comment.