Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build Static Linux Executable from macOS #4852

Open
wants to merge 4 commits into
base: dev
Choose a base branch
from
Open
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
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ help:
@echo "test-rosetta-attach - attach onto the rosetta testing docker container for inspection"
@echo "linux_static - static build the harmony binary & bootnode along with the MCL & BLS libs (for linux)"
@echo "linux_static_quick - static build the harmony binary & bootnode more quickly without recompiling dependencies (for linux)"
@echo "linux_static_cross_build - cross-compile static Linux binaries for Harmony and Bootnode from macOS"
@echo "rpm_init - prepare the RPM build environment by creating directories, copying files, and generating the spec file and source tarball"
@echo "rpm_build - build an RPM package for x86_64 architecture using the spec file (<RPMBUILD>/SPECS/harmony.spec)"
@echo "rpm - build a harmony RPM pacakge"
Expand Down Expand Up @@ -166,6 +167,9 @@ linux_static:
linux_static_quick:
bash ./scripts/go_executable_build.sh -s

linux_static_cross_build:
bash ./scripts/linux_executable_from_macos.sh -s

deb_init:
rm -rf $(DEBBUILD)
mkdir -p $(DEBBUILD)/$(PKGNAME)-$(VERSION)-$(RELEASE)/{etc/systemd/system,usr/sbin,etc/sysctl.d,etc/harmony}
Expand Down
71 changes: 71 additions & 0 deletions scripts/linux_executable_from_macos.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#!/bin/bash
set -e # Exit on first error

# Define paths
SCRIPT_DIR=$(dirname "$0")
PROJECT_ROOT=$(realpath "$SCRIPT_DIR/..")
HARMONY_DIR="$PROJECT_ROOT"
DOCKER_IMAGE="harmony-one" # Name of the Docker image
OUTPUT_DIR="$HARMONY_DIR/bin/linux_static_bin" # Folder for generated binaries

echo "=== Paths ==="
echo "SCRIPT_DIR: $SCRIPT_DIR"
echo "PROJECT_ROOT: $PROJECT_ROOT"
echo "HARMONY_DIR: $HARMONY_DIR"
echo "OUTPUT_DIR: $OUTPUT_DIR"

# Ensure output directory exists and clean old binaries
mkdir -p "$OUTPUT_DIR"
rm -f "$OUTPUT_DIR/harmony" "$OUTPUT_DIR/bootnode"

# Check if Docker is running
if ! docker info > /dev/null 2>&1; then
echo "Docker is not running. Please start Docker and try again."
exit 1
fi

# Build Docker image if not found
if ! docker image inspect "$DOCKER_IMAGE" > /dev/null 2>&1; then
echo "Building Docker image '$DOCKER_IMAGE'..."
pushd "$PROJECT_ROOT/scripts/macos_docker"
docker build -t "$DOCKER_IMAGE" -f Dockerfile .
popd
else
echo "Docker image '$DOCKER_IMAGE' already exists. Skipping build."
fi

# Run the container in the background
echo "Running Docker container..."
CONTAINER_ID=$(docker run -d "$DOCKER_IMAGE" tail -f /dev/null)
trap 'docker stop "$CONTAINER_ID" > /dev/null; docker rm "$CONTAINER_ID" > /dev/null' EXIT # Ensure cleanup on exit

# Copy project files into the container
echo "Copying project files to Docker container..."
docker cp "$HARMONY_DIR/." "$CONTAINER_ID:/root/go/src/github.com/harmony-one/tmp"

# Build binaries inside the container
echo "Building Linux static binary..."
docker exec "$CONTAINER_ID" bash -c "
set -e
cd /root/go/src/github.com/harmony-one
echo 'Current Directory: ' && pwd
rm -rf harmony
mv tmp harmony
cd harmony/bin && rm -rf * # Clear previous binaries
cd ..
git config --global --add safe.directory /root/go/src/github.com/harmony-one/harmony
make linux_static
"

# Copy built binaries back to host machine
echo "Copying binaries to output directory..."
docker cp "$CONTAINER_ID:/root/go/src/github.com/harmony-one/harmony/bin/harmony" "$OUTPUT_DIR"
docker cp "$CONTAINER_ID:/root/go/src/github.com/harmony-one/harmony/bin/bootnode" "$OUTPUT_DIR"

# Validate build output
if [ "$(ls -A "$OUTPUT_DIR")" ]; then
echo "✅ Build completed successfully. Binaries are in '$OUTPUT_DIR'."
else
echo "❌ Build failed: No binaries found in '$OUTPUT_DIR'."
exit 1
fi
64 changes: 64 additions & 0 deletions scripts/macos_docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
FROM ubuntu:22.04

ARG TARGETARCH
ARG GOLANG_VERSION="1.22.5"

SHELL ["/bin/bash", "-c"]

ENV GOPATH=/root/go
ENV GO111MODULE=on
ENV HMY_PATH=${GOPATH}/src/github.com/harmony-one
ENV OPENSSL_DIR=/usr/lib/ssl
ENV MCL_DIR=${HMY_PATH}/mcl
ENV BLS_DIR=${HMY_PATH}/bls
ENV CGO_CFLAGS="-I${BLS_DIR}/include -I${MCL_DIR}/include"
ENV CGO_LDFLAGS="-L${BLS_DIR}/lib"
ENV LD_LIBRARY_PATH=${BLS_DIR}/lib:${MCL_DIR}/lib
ENV GIMME_GO_VERSION=${GOLANG_VERSION}
ENV PATH="/root/bin:${PATH}"

RUN apt update && apt upgrade -y && \
apt install libgmp-dev libssl-dev curl git \
psmisc dnsutils jq make gcc g++ bash tig tree sudo vim \
silversearcher-ag unzip emacs-nox nano bash-completion -y

RUN mkdir ~/bin && \
curl -sL -o ~/bin/gimme \
https://raw.githubusercontent.com/travis-ci/gimme/master/gimme && \
chmod +x ~/bin/gimme

RUN eval "$(~/bin/gimme ${GIMME_GO_VERSION})"

#RUN git clone https://github.com/harmony-one/harmony.git ${HMY_PATH}/harmony

RUN git clone https://github.com/harmony-one/mcl.git ${HMY_PATH}/mcl && \
echo "mcl repository cloned" && \
ls -la ${HMY_PATH}/mcl # List the contents of the mcl directory

RUN git clone https://github.com/harmony-one/bls.git ${HMY_PATH}/bls && \
echo "bls repository cloned" && \
ls -la ${HMY_PATH}/bls # List the contents of the bls directory

RUN git clone https://github.com/harmony-one/go-sdk.git ${HMY_PATH}/go-sdk

RUN cd ${HMY_PATH}/bls && make -j8 BLS_SWAP_G=1

RUN touch /root/.bash_profile && \
gimme ${GIMME_GO_VERSION} >> /root/.bash_profile && \
echo "GIMME_GO_VERSION='${GIMME_GO_VERSION}'" >> /root/.bash_profile && \
echo "GO111MODULE='on'" >> /root/.bash_profile && \
echo ". ~/.bash_profile" >> /root/.profile && \
echo ". ~/.bash_profile" >> /root/.bashrc

ENV PATH="/root/.gimme/versions/go${GIMME_GO_VERSION}.linux.${TARGETARCH:-amd64}/bin:${GOPATH}/bin:${PATH}"

RUN . ~/.bash_profile; \
go install golang.org/x/tools/cmd/goimports; \
go install golang.org/x/lint/golint ; \
go install github.com/rogpeppe/godef ; \
go install github.com/go-delve/delve/cmd/dlv; \
go install github.com/golang/mock/mockgen; \
go install github.com/stamblerre/gocode; \
go install golang.org/x/tools/...; \
go install honnef.co/go/tools/cmd/staticcheck/...