#!/bin/bash
set -e
set -x
CURRENT_DIR=$(cd $(dirname "$0"); pwd)
PROJECT_DIR=$(realpath "${CURRENT_DIR}")
BUILD_DIR=${PROJECT_DIR}/_build
THIRD_PARTY=${PROJECT_DIR}/third_party/
INSTALL_PATH=${PROJECT_DIR}/output/
BPF_DIR=${PROJECT_DIR}/pmu/bpf
LLVM_LIB_DIR=${PROJECT_DIR}/llvm-symbolizer/build/lib
BUILD_TYPE=Release
PYTHON=false
INCLUDE_TEST=false
GO=false
BPF=false
ASAN=false
UTRACE=false
JAVA_AGENT=false
JAVA_TRACE=false
source ${PROJECT_DIR}/build/common.sh
creat_dir "${BUILD_DIR}"
export CC=gcc
export CXX=g++
PYTHON_EXE=""
PYTHON_WHL=false
if [ -d "${THIRD_PARTY}/local" ];then
echo ${THIRD_PARTY}/local "is exist"
else
echo ${THIRD_PARTY}local "is not exist"
creat_dir ${THIRD_PARTY}/local
fi
for arg in "$@"; do
case "$arg" in
test=*)
INCLUDE_TEST="${arg#*=}"
;;
python=*)
PYTHON="${arg#*=}"
;;
install_path=*)
INSTALL_PATH="${arg#*=}"
;;
build_type=*)
BUILD_TYPE="${arg#*=}"
;;
whl=*)
WHL="${arg#*=}"
;;
python_exe=*)
PYTHON_EXE="${arg#*=}"
;;
go=*)
GO="${arg#*=}"
;;
bpf=*)
BPF="${arg#*=}"
;;
asan=*)
ASAN="${arg#*=}"
;;
elf_llvm=*)
ELF_LLVM="${arg#*=}"
;;
utrace=*)
UTRACE="${arg#*=}"
;;
java_agent=*)
JAVA_AGENT="${arg#*=}"
;;
java_trace=*)
JAVA_TRACE="${arg#*=}"
;;
esac
done
ARCH_TARGET="AArch64"
ARCH=$(uname -m)
case "$ARCH" in
x86_64|amd64) ARCH_TARGET="X86" ;;
aarch64|arm64) ARCH_TARGET="AArch64" ;;
esac
if [[ "$INCLUDE_TEST" == "true" ]]; then
build_googletest $THIRD_PARTY
fi
if [[ "$BPF" == "true" ]]; then
build_libbpf $THIRD_PARTY
build_skel_files $BPF_DIR $THIRD_PARTY
fi
if [[ "$UTRACE" == "true" ]]; then
build_capstone $THIRD_PARTY
fi
if [ "${JAVA_TRACE}" = "true" ];then
build_java_trace $INSTALL_PATH
if [ $? -ne 0 ]; then
echo "ERROR: failed to build java trace jar" >&2
exit 1
fi
fi
function build_elfin() {
local cmake_target_dir=$THIRD_PARTY/local/elfin-parser
rm -rf ${cmake_target_dir}
if [ -d "${cmake_target_dir}" ];then
echo ${cmake_target_dir} "is exist"
return
else
echo ${cmake_target_dir} "is not exist"
mkdir ${cmake_target_dir}
fi
cd "$THIRD_PARTY/elfin-parser"
rm -rf build
sed -i 's/-mcpu=tsv110//g' Common.cmake
sed -i 's/-mno-outline-atomics//g' Common.cmake
sed -i 's/-march=armv8.2-a//g' Common.cmake
if ! grep -q "^add_compile_options(-Wno-error=switch-enum)" CMakeLists.txt; then
sed -i '1i\add_compile_options(-Wno-error=switch-enum)' CMakeLists.txt
fi
mkdir build
cd build
cmake -DCMAKE_INSTALL_PREFIX=${cmake_target_dir} -DCMAKE_CXX_FLAGS="-fPIC" ..
make --silent -j ${cpu_core_num}
cp ./lib64/libdwarf++.a ./lib64/libelf++.a ${cmake_target_dir}
echo "install log path: $cmake_target_dir"
}
function build_symbolizer()
{
local cmake_target_dir=$PROJECT_DIR/llvm-symbolizer/build
rm -rf ${cmake_target_dir}
cd $PROJECT_DIR/llvm-symbolizer
mkdir build
cd build
cmake -DCMKAE_BUILD_TYPE=Release -DLLVM_TARGETS_TO_BUILD="${ARCH_TARGET}" ..
make -j ${cpu_core_num}
}
build_libkperf()
{
cd $BUILD_DIR
CMAKE_ARGS=()
CMAKE_ARGS+=(
"-DINCLUDE_TEST=${INCLUDE_TEST}"
"-DPYTHON=${PYTHON}"
"-DGO=${GO}"
"-DJAVA_AGENT=${JAVA_AGENT}"
"-DCMAKE_INSTALL_PREFIX=${INSTALL_PATH}"
"-DCMAKE_BUILD_TYPE=${BUILD_TYPE}"
"-DBPF=${BPF}"
"-DJAVA_TRACE=${JAVA_TRACE}"
"-DARCH_TARGET=${ARCH_TARGET}"
"-DELF_LLVM=${ELF_LLVM}"
)
if [ ! -z ${PYTHON_EXE} ];then
CMAKE_ARGS+=("-DPYTHON_KPERF=${PYTHON_EXE}")
fi
if [ "${PYTHON}" = "true" ];then
CMAKE_ARGS+=("-DPYTHON_WHL=${WHL}")
fi
if [ "${BPF}" = "true" ];then
CMAKE_ARGS+=(
"-DCMAKE_INSTALL_RPATH=${INSTALL_PATH}lib;${THIRD_PARTY}local/bpf/usr/lib64"
"-DCMAKE_INSTALL_RPATH_USE_LINK_PATH=TRUE"
)
fi
if [ "${ASAN}" = "true" ];then
CMAKE_ARGS+=(
"-DCMAKE_C_FLAGS=-fsanitize=address -fno-omit-frame-pointer"
"-DCAMKE_CXX_FLASG=-fsanitize=address -fno-omit-frame-pointer"
"-DCMAKE_EXE_LINKER_FLAGS=-fsanitize=address"
"-DCAMKE_SHARED_LINKPER_FLAGS=-fsanitize=address"
)
fi
if [ "${UTRACE}" = "true" ];then
CMAKE_ARGS+=("-DUTRACE=${UTRACE}")
fi
cmake "${CMAKE_ARGS[@]}" ..
make -j ${cpu_core_num}
make install
echo "build libkperf success"
}
function merge_libsym()
{
set +x
cd ${INSTALL_PATH}/lib
echo "CREATE libsym_bak.a" > merge.mri
if [ ! -f "${THIRD_PARTY}/local/elfin-parser/libelf.a" ];then
cp "${THIRD_PARTY}/local/elfin-parser/libelf++.a" "${THIRD_PARTY}/local/elfin-parser/libelf.a"
fi
echo "ADDLIB ${THIRD_PARTY}/local/elfin-parser/libelf.a" >> merge.mri
echo "ADDLIB ${INSTALL_PATH}/lib/libsym.a" >> merge.mri
echo "ADDLIB ${LLVM_LIB_DIR}/libLLVM${ARCH_TARGET}AsmPrinter.a" >> merge.mri
echo "ADDLIB ${LLVM_LIB_DIR}/libLLVM${ARCH_TARGET}AsmParser.a" >> merge.mri
echo "ADDLIB ${LLVM_LIB_DIR}/libLLVM${ARCH_TARGET}Desc.a" >> merge.mri
echo "ADDLIB ${LLVM_LIB_DIR}/libLLVM${ARCH_TARGET}Disassembler.a" >> merge.mri
echo "ADDLIB ${LLVM_LIB_DIR}/libLLVM${ARCH_TARGET}Info.a" >> merge.mri
echo "ADDLIB ${LLVM_LIB_DIR}/libLLVM${ARCH_TARGET}Utils.a" >> merge.mri
echo "ADDLIB ${LLVM_LIB_DIR}/libLLVMTarget.a" >> merge.mri
echo "ADDLIB ${LLVM_LIB_DIR}/libLLVMDebugInfoDWARF.a" >> merge.mri
echo "ADDLIB ${LLVM_LIB_DIR}/libLLVMDemangle.a" >> merge.mri
echo "ADDLIB ${LLVM_LIB_DIR}/libLLVMObject.a" >> merge.mri
echo "ADDLIB ${LLVM_LIB_DIR}/libLLVMOption.a" >> merge.mri
echo "ADDLIB ${LLVM_LIB_DIR}/libLLVMSupport.a" >> merge.mri
echo "ADDLIB ${LLVM_LIB_DIR}/libLLVMSymbolize.a" >> merge.mri
echo "ADDLIB ${LLVM_LIB_DIR}/libLLVMDebugInfoDWARF.a" >> merge.mri
echo "ADDLIB ${LLVM_LIB_DIR}/libLLVMObject.a" >> merge.mri
echo "ADDLIB ${LLVM_LIB_DIR}/libLLVMBitReader.a" >> merge.mri
echo "ADDLIB ${LLVM_LIB_DIR}/libLLVMCore.a" >> merge.mri
echo "ADDLIB ${LLVM_LIB_DIR}/libLLVMMCParser.a" >> merge.mri
echo "ADDLIB ${LLVM_LIB_DIR}/libLLVMMC.a" >> merge.mri
echo "ADDLIB ${LLVM_LIB_DIR}/libLLVMDebugInfoCodeView.a" >> merge.mri
echo "ADDLIB ${LLVM_LIB_DIR}/libLLVMBinaryFormat.a" >> merge.mri
echo "ADDLIB ${LLVM_LIB_DIR}/libLLVMSupport.a" >> merge.mri
echo "ADDLIB ${LLVM_LIB_DIR}/libLLVMDemangle.a" >> merge.mri
echo "ADDLIB ${LLVM_LIB_DIR}/libLLVMMCDisassembler.a" >> merge.mri
echo "SAVE" >> merge.mri
echo "END" >> merge.mri
ar -M < merge.mri
rm merge.mri
if [ ! -z libsym.a ];then
rm libsym.a
fi
mv libsym_bak.a libsym.a
if [ "${GO}" = "true" ];then
cp libsym.a ${PROJECT_DIR}/go/src/libkperf/static_lib/
fi
}
function build_test()
{
if [ "$INCLUDE_TEST" = "true" ]; then
execute_binary "$PROJECT_DIR"
fi
}
main() {
build_symbolizer
build_elfin
build_libkperf
build_test
merge_libsym
}
main $@