macos_build_whl.sh 9.1 KB
Newer Older
1 2 3 4
#!/bin/bash -e

READLINK=readlink
OS=$(uname -s)
T
Tricster 已提交
5
USER=$(whoami)
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

if [ $OS = "Darwin" ];then
    READLINK=greadlink
else
    echo "ERR: only run at macos env"
    exit -1
fi

function err_env() {
    echo "check_env failed: pls refs ${SRC_DIR}/scripts/whl/BUILD_PYTHON_WHL_README.md"
    echo "try call ./scripts/whl/macos/macos_whl_env_prepare.sh to init env"
    exit -1
}

function append_path_env_and_check() {
    export PATH=/usr/local/opt/findutils/libexec/gnubin:$PATH
    export PATH=/usr/local/opt/binutils/bin:$PATH
    export PATH=/usr/local/opt/llvm/bin:$PATH
    export PATH=/Users/${USER}/megengine_use_cmake/install/bin:$PATH
    if [ ! -f "/usr/local/opt/llvm/bin/llvm-strip" ]; then
        err_env
    fi

    which cmake
    if [ ! -f "/Users/${USER}/megengine_use_cmake/install/bin/cmake" ]; then
        err_env
    fi
}

append_path_env_and_check

SRC_DIR=$($READLINK -f "`dirname $0`/../../../")
38 39
source ${SRC_DIR}/scripts/whl/utils/utils.sh

40
ALL_PYTHON=${ALL_PYTHON}
41
FULL_PYTHON_VER="3.6.10 3.7.7 3.8.3 3.9.4"
42 43 44
if [[ -z ${ALL_PYTHON} ]]
then
    ALL_PYTHON=${FULL_PYTHON_VER}
45 46
else
    check_python_version_is_valid "${ALL_PYTHON}" "${FULL_PYTHON_VER}"
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
fi

PYTHON_DIR=
PYTHON_LIBRARY=
PYTHON_INCLUDE_DIR=
MACOS_WHL_HOME=${SRC_DIR}/scripts/whl/macos/macos_whl_home
if [ -e "${MACOS_WHL_HOME}" ]; then
    echo "remove old macos whl file"
    rm -rf ${MACOS_WHL_HOME}
fi
mkdir -p ${MACOS_WHL_HOME}

function config_python_env() {
    PYTHON_DIR=/Users/${USER}/.pyenv/versions/$1/
    PYTHON_BIN=/Users/${USER}/.pyenv/versions/$1/bin
    if [ ! -f "$PYTHON_BIN/python3" ]; then
        echo "ERR: can not find $PYTHON_BIN , Invalid python package"
        echo "now support list: ${FULL_PYTHON_VER}"
        err_env
    else
        echo "put python3 to env..."
        export PATH=${PYTHON_BIN}:$PATH
        which python3
    fi
    echo ${ver}

73
    if [ "$1" = "3.6.10" ]; then
74
        PYTHON_INCLUDE_DIR=${PYTHON_DIR}include/python3.6m
75
        PYTHON_LIBRARY=${PYTHON_DIR}/lib/libpython3.6m.dylib
76 77
    elif [ "$1" = "3.7.7" ]; then
        PYTHON_INCLUDE_DIR=${PYTHON_DIR}include/python3.7m
78
        PYTHON_LIBRARY=${PYTHON_DIR}/lib/libpython3.7m.dylib
79 80
    elif [ "$1" = "3.8.3" ]; then
        PYTHON_INCLUDE_DIR=${PYTHON_DIR}include/python3.8
81
        PYTHON_LIBRARY=${PYTHON_DIR}/lib/libpython3.8.dylib
82 83 84 85 86 87
    elif [ "$1" = "3.9.4" ]; then
        PYTHON_INCLUDE_DIR=${PYTHON_DIR}include/python3.9
        PYTHON_LIBRARY=${PYTHON_DIR}/lib/libpython3.9.dylib
    elif [ "$1" = "3.10.1" ]; then
        PYTHON_INCLUDE_DIR=${PYTHON_DIR}include/python3.10
        PYTHON_LIBRARY=${PYTHON_DIR}/lib/libpython3.10.dylib
88 89 90 91 92 93 94
    else
        echo "ERR: DO NOT SUPPORT PYTHON VERSION"
        echo "now support list: ${FULL_PYTHON_VER}"
        exit -1
    fi
}

95
MEGENGINE_LIB="${SRC_DIR}/build_dir/host/MGE_WITH_CUDA_OFF/MGE_INFERENCE_ONLY_OFF/Release/build/src/libmegengine_shared.dylib"
96 97 98 99 100 101
function depend_real_copy() {
    REAL_DST=$1
    echo "real copy lib to $1"
    cp "${MEGENGINE_LIB}" ${REAL_DST}
}

102 103 104 105 106 107
BUILD_DIR=${SRC_DIR}/build_dir/host/MGE_WITH_CUDA_OFF/MGE_INFERENCE_ONLY_OFF/Release/build/

# here we just treat dnn/src/common/conv_bias.cpp should not in the increment build file list
INCREMENT_KEY_WORDS="conv_bias.cpp.o is dirty"
IS_IN_FIRST_LOOP=TRUE

108
ORG_EXTRA_CMAKE_FLAG=${EXTRA_CMAKE_FLAG}
109 110 111
function do_build() {
    for ver in ${ALL_PYTHON}
    do
112 113 114 115 116 117 118 119
        # we want run a full clean build at the first loop
        if [ ${IS_IN_FIRST_LOOP} = "TRUE" ]; then
            # TODO: may all cmake issue can be resolved after rm CMakeCache?
            # if YES, remove this to use old cache and speed up CI
            echo "warning: remove old build_dir for the first loop"
            rm -rf ${BUILD_DIR}
        fi

120 121 122 123
        #config
        config_python_env ${ver}

        #check env
124
        if [ ! -f "$PYTHON_LIBRARY" ]; then
125 126 127 128 129 130 131 132 133 134
            echo "ERR: can not find $PYTHON_LIBRARY , Invalid python package"
            err_env
        fi
        if [ ! -d "$PYTHON_INCLUDE_DIR" ]; then
            echo "ERR: can not find $PYTHON_INCLUDE_DIR , Invalid python package"
            err_env
        fi
        echo "PYTHON_LIBRARY: ${PYTHON_LIBRARY}"
        echo "PYTHON_INCLUDE_DIR: ${PYTHON_INCLUDE_DIR}"
        #config build type to RelWithDebInfo to enable MGB_ENABLE_DEBUG_UTIL etc
135
        export EXTRA_CMAKE_ARGS="${ORG_EXTRA_CMAKE_FLAG} -DCMAKE_BUILD_TYPE=RelWithDebInfo"
136
        export EXTRA_CMAKE_ARGS="${EXTRA_CMAKE_ARGS} -DMGE_WITH_CUSTOM_OP=ON"
137 138 139 140 141
        #append cmake args for config python
        export EXTRA_CMAKE_ARGS="${EXTRA_CMAKE_ARGS} -DPYTHON_EXECUTABLE=${PYTHON_DIR}/bin/python3"
        export EXTRA_CMAKE_ARGS="${EXTRA_CMAKE_ARGS} -DPYTHON_LIBRARY=${PYTHON_LIBRARY}"
        export EXTRA_CMAKE_ARGS="${EXTRA_CMAKE_ARGS} -DPYTHON_INCLUDE_DIR=${PYTHON_INCLUDE_DIR}"

142 143 144 145
        #we use std::visit in src, so set osx version minimum to 10.14, but 10.14 have objdump
        #issue, so we now config to 10.15, whl name to 10.14
        #TODO: can set to 10.12 after remove use std::visit
        export EXTRA_CMAKE_ARGS="${EXTRA_CMAKE_ARGS} -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 "
146

147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
        if [ -d "${BUILD_DIR}" ]; then
            # insure rm have args
            touch ${BUILD_DIR}/empty.so
            touch ${BUILD_DIR}/CMakeCache.txt
            find ${BUILD_DIR} -name "*.so" | xargs rm
            # as we now use increment build mode when switch python
            # But I do not known any more issue at CMakeLists.txt or not
            # so Force remove CMakeCache.txt
            find ${BUILD_DIR} -name CMakeCache.txt | xargs rm
        fi

        HOST_BUILD_ARGS="-t -s"

        # call ninja dry run and check increment is invalid or not
        if [ ${IS_IN_FIRST_LOOP} = "FALSE" ]; then
            ninja_dry_run_and_check_increment "${SRC_DIR}/scripts/cmake-build/host_build.sh" "${HOST_BUILD_ARGS}" "${INCREMENT_KEY_WORDS}"
        fi

        # call real build
        echo "host_build.sh HOST_BUILD_ARGS: ${HOST_BUILD_ARGS}"
        ${SRC_DIR}/scripts/cmake-build/host_build.sh ${HOST_BUILD_ARGS}
168

169
        # check python api call setup.py
170
        cd ${BUILD_DIR}
171
        check_build_ninja_python_api ${ver}
172

173
        rm -rf staging
174 175
        mkdir -p staging

176
        cp -a imperative/python/{megengine,setup.py,requires.txt,requires-style.txt,requires-test.txt} staging/
177
        cp -a ${SRC_DIR}/src/custom/include staging/megengine/core/include/
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
        cd ${BUILD_DIR}/staging/megengine/core
        rt_file=`ls _imperative_rt.*.so`
        echo "rt file is: ${rt_file}"
        if [[ -z ${rt_file} ]]
        then
            echo "ERR: can not find valid rt file"
            exit -1
        fi
        llvm-strip -s ${rt_file}
        mv ${rt_file} _imperative_rt.so
        echo "check so valid or not..."
        otool_out=`otool -L _imperative_rt.so`
        if [[ "${otool_out}" =~ "ython" ]]; then
            echo "ERR: invalid _imperative_rt.so which depend on python lib, detail: log"
            echo ${otool_out}
            exit -1
194
        else
195
            echo "valid..."
196
        fi
197

198
        #handle dlopen path
199
        install_name_tool -change @rpath/libmegengine_shared.dylib @loader_path/lib/libmegengine_shared.dylib _imperative_rt.so
200 201 202 203 204 205

        #copy megbrain_export lib
        DEPEND_LIB=${BUILD_DIR}/staging/megengine/core/lib/
        rm -rf ${DEPEND_LIB}
        mkdir ${DEPEND_LIB}
        depend_real_copy ${DEPEND_LIB}
206

207 208 209 210 211 212 213 214 215
        # handle megenginelite
        cd ${BUILD_DIR}
        mkdir -p staging/megenginelite
        cp ${SRC_DIR}/lite/pylite/megenginelite/* staging/megenginelite/
        mkdir -p ${BUILD_DIR}/staging/megenginelite/libs
        LITE_LIB=${BUILD_DIR}/staging/megenginelite/libs/liblite_shared_whl.so
        cp ${SRC_DIR}/build_dir/host/MGE_WITH_CUDA_OFF/MGE_INFERENCE_ONLY_OFF/Release/build/lite/liblite_shared_whl.dylib ${LITE_LIB}
        llvm-strip -s ${LITE_LIB}
        #handle dlopen path
216
        install_name_tool -change @rpath/libmegengine_shared.dylib @loader_path/../../megengine/core/lib/libmegengine_shared.dylib ${LITE_LIB}
217

218 219
        cd ${BUILD_DIR}/staging
        ${PYTHON_DIR}/bin/python3 setup.py bdist_wheel
220 221 222
        cd ${BUILD_DIR}/staging/dist/
        org_whl_name=`ls Meg*.whl`
        index=`awk -v a="${org_whl_name}" -v b="-macosx" 'BEGIN{print index(a,b)}'`
223
        compat_whl_name=`echo ${org_whl_name} |cut -b -$index`macosx_10_14_x86_64.whl
224 225 226
        echo "org whl name: ${org_whl_name}"
        echo "comapt whl name: ${compat_whl_name}"
        cp ${BUILD_DIR}/staging/dist/Meg*.whl ${MACOS_WHL_HOME}/${compat_whl_name}
227

228
        cd ${SRC_DIR}
229 230 231 232 233
        echo ""
        echo "##############################################################################################"
        echo "macos whl package location: ${MACOS_WHL_HOME}"
        ls ${MACOS_WHL_HOME}
        echo "##############################################################################################"
234
        IS_IN_FIRST_LOOP=FALSE
235 236 237
    done
}

238
function third_party_prepare() {
239 240 241 242
    echo "init third_party..."
    ${SRC_DIR}/third_party/prepare.sh

    if [[ -z ${ALREADY_INSTALL_MKL} ]]
243 244 245 246
    then
        echo "init third_party..."
        ${SRC_DIR}/third_party/install-mkl.sh
    else
247
        echo "skip init mkl internal"
248 249 250
    fi
}

251
######################
252
third_party_prepare
253
do_build