Skip to content

Commit

Permalink
feat: Add kraftld
Browse files Browse the repository at this point in the history
This implements a `kraftld` linker shim acting as a gcc-style linker.

It accepts the same arguments and forwards them to `UK_LDFLAGS`.
It removes flags that are known to be incompatible.
Furthermore, it sanitizes relative paths for the Unikraft build system.

`kraftld` also extracts any file dependencies for `UK_LDEPS`.
Lastly, it parses `-o <OUTPUT>` and copies the KraftKit output image.
Currently, it assumes the `default_qemu-x86_64`.
Future versions of KraftKit will support an output option.
`kraftld` will then adapt that option instead.

`kraftld` is currently targeting the Rust compiler.
Other compilers may or may not work as well.

Signed-off-by: Martin Kröning <[email protected]>
GitHub-Closes: unikraft#612
  • Loading branch information
mkroening committed Oct 20, 2023
1 parent 52a660c commit 88d7e1d
Showing 1 changed file with 106 additions and 0 deletions.
106 changes: 106 additions & 0 deletions scripts/kraftld
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
#!/usr/bin/env bash

# The KraftKit linker (`kraftld`).
#
# This linker transparently encapsulates KraftKit and the Unikraft build system
# to include the provided object files in a Unikraft build.
# It is a drop-in replacement for the GNU linker (`ld`).
#
# A `Kraftfile` is required to configure the build process.
# If only one unnamed target configuration exists, this works out of the box.
# If the `Kraftfile` contains multiple targets, the current target has to be
# specified via environment variables:
# - `KRAFTKIT_TARGET` corresponds to `kraft build --target $KRAFTKIT_TARGET`
# - `KRAFTKIT_ARCH` corresponds to `kraft build --arch $KRAFTKIT_ARCH`
# - `KRAFTKIT_PLAT` corresponds to `kraft build --plat $KRAFTKIT_PLAT`


# Bash strict mode
set -euo pipefail
IFS=$'\n\t'


# Prepare `UK_LDFLAGS`
LDFLAGS="$*"

# Make all relative object paths absolute for make
# rel_path.o -> $PWD/rel_path.o
LDFLAGS=$(echo "$LDFLAGS" | sed -Ee 's,(^[^/].*\.o),'"$PWD"'\/\1,g' )

# Remove -nodefaultlibs
LDFLAGS=${LDFLAGS/-nodefaultlibs/}

export UK_LDFLAGS="$LDFLAGS"


# Extract `OUTPUT` and `FILES` from arguments
FILES=""
while [[ $# -gt 0 ]]; do
case $1 in
-o)
# Extract output path
OUTPUT="$2"
shift
shift
;;
-L)
# Ignore other options with arguments
shift
shift
;;
-*)
# Ignore other options without arguments
shift
;;
*)
# Collect input files for `UK_LDEPS`
# This creates a leading whitespace but that's okay
FILES+=" $1"
shift
;;
esac
done

export UK_LDEPS="$FILES"


# Parse target selection environment variables
if [[ -z "${KRAFTKIT_TARGET:-}" ]]; then
KRAFTKIT_ARG_TARG=()
KRAFTKIT_TARGET=workspace
else
KRAFTKIT_ARG_TARG=("--target=$KRAFTKIT_TARGET")
fi
if [[ -z "${KRAFTKIT_ARCH:-}" ]]; then
KRAFTKIT_ARCH='*'
KRAFTKIT_ARG_ARCH=()
else
KRAFTKIT_ARG_ARCH=("--arch=$KRAFTKIT_ARCH")
fi
if [[ -z "${KRAFTKIT_PLAT:-}" ]]; then
KRAFTKIT_PLAT='*'
KRAFTKIT_ARG_PLAT=()
else
KRAFTKIT_ARG_PLAT=("--plat=$KRAFTKIT_PLAT")
fi


# Finally, build the Unikraft image
kraft build --log-level debug --log-type basic --no-cache "${KRAFTKIT_ARG_TARG[@]}" "${KRAFTKIT_ARG_PLAT[@]}" "${KRAFTKIT_ARG_ARCH[@]}"


# Find KraftKit output image
# Don't match any files with extensions
mapfile -t kraft_output < <(find .unikraft/build -maxdepth 1 -type f ! -name "*.*" -name "${KRAFTKIT_TARGET}_${KRAFTKIT_PLAT}-${KRAFTKIT_ARCH}")

if [[ "${#kraft_output[@]}" -ne 1 ]]; then
echo "Cannot decide on kraft output file"
echo "Specify \$KRAFTKIT_TARGET, \$KRAFTKIT_ARCH, or \$KRAFTKIT_PLAT"
exit 1
fi

kraft_output="${kraft_output[0]}"


# Copy KraftKit output to linker output
cp "$kraft_output" "$OUTPUT"

0 comments on commit 88d7e1d

Please sign in to comment.