windows_build_whl.sh 12.1 KB
Newer Older
1 2
#!/usr/bin/env bash
set -e
3 4 5 6 7 8 9 10 11

NT=$(echo `uname` | grep "NT")
echo $NT
if [ -z "$NT" ];then
    echo "only run at windows bash env"
    echo "pls consider install bash-like tools, eg MSYS or git-cmd, etc"
    exit -1
fi

12 13 14 15
SRC_DIR=$(READLINK -f "`dirname $0`/../../../")
source ${SRC_DIR}/scripts/whl/utils/utils.sh
source ${SRC_DIR}/scripts/whl/windows/config.sh

16
function err_env() {
17
    echo "check_env failed: pls call ${SRC_DIR}/scripts/whl/windows/env_prepare.sh to init env"
18 19
    exit -1
}
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58

SDK_NAME="unknown"
x86_64_support_version="cpu cu101 cu118"

if [[ -z ${IN_CI} ]]
then
    IN_CI="false"
fi

function usage() {
    echo "use -sdk sdk_version to specify sdk toolkit config!"
    echo "now x86_64 sdk_version support ${x86_64_support_version}"
}

while [ "$1" != "" ]; do
    case $1 in
        -sdk)
            shift
            SDK_NAME=$1
            shift
            ;;
        *)
            usage
            exit -1
    esac
done

is_valid_sdk="false"
all_sdk=""
machine=$(uname -m)
case ${machine} in
    x86_64) all_sdk=${x86_64_support_version} ;;
    *) echo "nonsupport env!!!";exit -1 ;;
esac

for i_sdk in ${all_sdk}
do
    if [ ${i_sdk} == ${SDK_NAME} ];then
        is_valid_sdk="true"
59
    fi
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
done
if [ ${is_valid_sdk} == "false" ];then
    echo "invalid sdk: ${SDK_NAME}"
    usage
    exit -1
fi

echo "Build with ${SDK_NAME}"

# export setup.py local version
export SDK_NAME=${SDK_NAME}

# TODO: Windows CI take a long time, we have no enough resource to test
# so only build one sm to speed build. after have enough resource, remove this
# now we test at 1080TI remote env, so config sm to 61
if [ ${IN_CI} = "true" ] ; then
    EXTRA_CMAKE_FLAG=" -DMGE_CUDA_GENCODE=\"-gencode arch=compute_61,code=sm_61\" "
fi

CUDA_LIBS="not_find"
CUDNN_LIBS="not_find"
TRT_LIBS="not_find"
MGE_EXPORT_DLL="${SRC_DIR}/build_dir/host/build/src/megengine_shared.dll"
MGE_EXPORT_LIB="${SRC_DIR}/build_dir/host/build/src/megengine_shared.lib"

if [ $SDK_NAME == "cu101" ];then
    REQUIR_CUDA_VERSION="10010"
    REQUIR_CUDNN_VERSION="7.6.5"
    REQUIR_TENSORRT_VERSION="6.0.1.5"
    REQUIR_CUBLAS_VERSION="10.1.0"
    CUDA_ROOT_DIR=${CUDA_ROOT_DIR_101}
    CUDNN_ROOT_DIR=${CUDNN_ROOT_DIR_101}
    TRT_ROOT_DIR=${TRT_ROOT_DIR_101}
    TENSORRT_ROOT_DIR=${TRT_ROOT_DIR}

    CUDA_LIBS="${CUDA_ROOT_DIR}/bin/cusolver64_10.dll:${CUDA_ROOT_DIR}/bin/cublas64_10.dll\
        :${CUDA_ROOT_DIR}/bin/curand64_10.dll:${CUDA_ROOT_DIR}/bin/cublasLt64_10.dll\
        :${CUDA_ROOT_DIR}/bin/cudart64_101.dll"

    CUDNN_LIBS="${CUDNN_ROOT_DIR}/bin/cudnn64_7.dll"

    TRT_LIBS="${TRT_ROOT_DIR}/lib/nvinfer.dll:${TRT_ROOT_DIR}/lib/nvinfer_plugin.dll"


elif [ $SDK_NAME == "cu118" ];then
    REQUIR_CUDA_VERSION="11080"
    REQUIR_CUDNN_VERSION="8.6.0"
    REQUIR_TENSORRT_VERSION="8.5.3.1"
    REQUIR_CUBLAS_VERSION="11.11.3.6"
    CUDA_ROOT_DIR=${CUDA_ROOT_DIR_118}
    CUDNN_ROOT_DIR=${CUDNN_ROOT_DIR_118}
    TRT_ROOT_DIR=${TRT_ROOT_DIR_118}
    TENSORRT_ROOT_DIR=${TRT_ROOT_DIR}

    CUDA_LIBS="${CUDA_ROOT_DIR}/bin/cusolver64_11.dll:${CUDA_ROOT_DIR}/bin/cublas64_11.dll\
        :${CUDA_ROOT_DIR}/bin/curand64_10.dll:${CUDA_ROOT_DIR}/bin/cublasLt64_11.dll\
        :${CUDA_ROOT_DIR}/bin/cudart64_110.dll:${CUDA_ROOT_DIR}/bin/nvrtc64_112_0.dll"

    CUDNN_LIBS="${CUDNN_ROOT_DIR}/bin/cudnn64_8.dll:${CUDNN_ROOT_DIR}/bin/cudnn_cnn_infer64_8.dll\
        :${CUDNN_ROOT_DIR}/bin/cudnn_ops_train64_8.dll:${CUDNN_ROOT_DIR}/bin/cudnn_adv_infer64_8.dll\
        :${CUDNN_ROOT_DIR}/bin/cudnn_cnn_train64_8.dll:${CUDNN_ROOT_DIR}/bin/cudnn_adv_train64_8.dll\
        :${CUDNN_ROOT_DIR}/bin/cudnn_ops_infer64_8.dll:${CUDNN_ROOT_DIR}/bin/zlibwapi.dll"

    # workround for CU118 depends on zlibwapi.dll
    if [[ ! -f ${CUDNN_ROOT_DIR}/bin/zlibwapi.dll ]]; then
        echo "can not find zlibwapi.dll, download from ${ZLIBWAPI_URL}"
        rm -rf tttttmp_1988
        mkdir -p tttttmp_1988
        cd tttttmp_1988
        curl -SL ${ZLIBWAPI_URL} --output zlib123dllx64.zip
        unzip -X zlib123dllx64.zip
        cp dll_x64/zlibwapi.dll ${CUDNN_ROOT_DIR}/bin/
        cd ..
        rm -rf tttttmp_1988
        # double check
        if [[ ! -f ${CUDNN_ROOT_DIR}/bin/zlibwapi.dll ]]; then
            echo "some issue happened when prepare zlibwapi.dll, please fix me!!!!"
            exit -1
        fi
139
    fi
140

141 142
    TRT_LIBS="${TRT_ROOT_DIR}/lib/nvinfer.dll:${TRT_ROOT_DIR}/lib/nvinfer_builder_resource.dll:\
        ${TRT_ROOT_DIR}/lib/nvinfer_plugin.dll"
143

144 145 146 147 148 149 150
elif [ $SDK_NAME == "cpu" ];then
    BUILD_WHL_CPU_ONLY="ON"
else
    echo "no support sdk ${SDK_NAME}"
    usage
    exit -1
fi
151

152
if [[ -z ${BUILD_WHL_CPU_ONLY} ]]
153
then
154 155 156 157 158
    BUILD_WHL_CPU_ONLY="OFF"
fi

if [ $SDK_NAME == "cpu" ];then
    echo "use $SDK_NAME without cuda support"
159
else
160 161 162 163 164 165 166
    echo "CUDA_LIBS: $CUDA_LIBS"
    echo "CUDNN_LIBS: $CUDNN_LIBS"
    echo "TRT_LIBS: $TRT_LIBS"
    # for utils.sh sub bash script, eg host_build.sh
    export CUDA_ROOT_DIR=${CUDA_ROOT_DIR}
    export CUDNN_ROOT_DIR=${CUDNN_ROOT_DIR}
    export TRT_ROOT_DIR=${TRT_ROOT_DIR}
167 168
fi

169 170 171
check_cuda_cudnn_trt_version
check_python_version_is_valid "${ALL_PYTHON}" "${FULL_PYTHON_VER}"

172 173 174
PYTHON_DIR=
PYTHON_LIBRARY=
PYTHON_INCLUDE_DIR=
175
WINDOWS_WHL_HOME=${SRC_DIR}/scripts/whl/windows/windows_whl_home/${SDK_NAME}
176 177 178 179 180 181 182
if [ -e "${WINDOWS_WHL_HOME}" ]; then
    echo "remove old windows whl file"
    rm -rf ${WINDOWS_WHL_HOME}
fi
mkdir -p ${WINDOWS_WHL_HOME}

function config_python_env() {
183
    PYTHON_DIR=${DFT_PYTHON_BIN}/../$1
184
    PYTHON_BIN=${PYTHON_DIR}
185
    if [ ! -f "${PYTHON_BIN}/python3.exe" ]; then
186 187 188 189
        echo "ERR: can not find $PYTHON_BIN , Invalid python package"
        echo "now support list: ${FULL_PYTHON_VER}"
        err_env
    else
190
        echo "put ${PYTHON_BIN}/python3.exe to env..."
191 192 193 194 195 196 197 198 199
        export PATH=${PYTHON_BIN}:$PATH
        which python3
    fi
    echo ${ver}

    PYTHON_LIBRARY=${PYTHON_DIR}/libs/python3.lib
    PYTHON_INCLUDE_DIR=${PYTHON_DIR}/include
}

200 201
BUILD_WHL_CPU_ONLY=${BUILD_WHL_CPU_ONLY}
if [[ -z ${BUILD_WHL_CPU_ONLY} ]]
202
then
203
    BUILD_WHL_CPU_ONLY="OFF"
204 205
fi

206 207 208
function depend_real_copy() {
    REAL_DST=$1
    echo "real copy lib to $1"
209
    cp "${MGE_EXPORT_DLL}" ${REAL_DST}
210 211 212 213
    cp "${MGE_EXPORT_LIB}" ${REAL_DST}

    if [ ${BUILD_WHL_CPU_ONLY} = "OFF" ]; then
        echo "copy nvidia lib...."
214 215 216

        IFS=: read -a lib_name_array <<<"$TRT_LIBS"
        for lib_name in ${lib_name_array[@]};
217
        do
218 219
            echo "Copy ${lib_name} to ${REAL_DST}"
            cp ${lib_name} ${REAL_DST}
220
        done
221 222 223

        IFS=: read -a lib_name_array <<<"$CUDNN_LIBS"
        for lib_name in ${lib_name_array[@]};
224
        do
225 226 227 228 229 230 231 232 233
            echo "Copy ${lib_name} to ${REAL_DST}"
            cp ${lib_name} ${REAL_DST}
        done

        IFS=: read -a lib_name_array <<<"$CUDA_LIBS"
        for lib_name in ${lib_name_array[@]};
        do
            echo "Copy ${lib_name} to ${REAL_DST}"
            cp ${lib_name} ${REAL_DST}
234
        done
235
    fi
236 237
}

238 239
function copy_more_dll() {
    # for python whl real use
240 241 242 243 244
    echo "config BUILD_IMPERATIVE core lib dir"
    CP_WHL_DST_IMP=${BUILD_DIR}/staging/megengine/core/lib
    rm -rf ${CP_WHL_DST_IMP}
    mkdir ${CP_WHL_DST_IMP}

245
    depend_real_copy ${CP_WHL_DST_IMP}
246
}
247 248

function lite_copy_more_dll() {
249 250 251 252 253
    if [ ${IN_CI} = "true" ]; then
        echo "copy lib for lite for ci test"
        IMP_TEST_DST=${SRC_DIR}/build_dir/host/build/lite/test/
        depend_real_copy ${IMP_TEST_DST}
        rm "${IMP_TEST_DST}/megengine_shared.dll"
254 255 256
    fi
}

257 258 259 260 261
BUILD_DIR=${SRC_DIR}/build_dir/host/build/

# here we just treat cu file should not in the increment build file list
INCREMENT_KEY_WORDS=".cu.obj is dirty"
IS_IN_FIRST_LOOP=TRUE
262

263
ORG_EXTRA_CMAKE_FLAG=${EXTRA_CMAKE_FLAG}
264 265 266
function do_build() {
    for ver in ${ALL_PYTHON}
    do
267 268 269 270 271 272 273 274 275
        # 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

        #config python3
276 277 278 279 280 281 282 283 284 285 286 287 288 289
        config_python_env ${ver}

        #check env
        if [ ! -f "$PYTHON_LIBRARY" ]; then
            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
290
        export EXTRA_CMAKE_ARGS="${ORG_EXTRA_CMAKE_FLAG} -DCMAKE_BUILD_TYPE=RelWithDebInfo "
291
        export EXTRA_CMAKE_ARGS="${EXTRA_CMAKE_ARGS} -DMGE_WITH_CUSTOM_OP=ON"
292 293

        #call build and install
294
        HOST_BUILD_ARGS=" -t -s"
295

296
        if [ ${BUILD_WHL_CPU_ONLY} = "OFF" ]; then
297
            echo "build windows whl with cuda"
298
            HOST_BUILD_ARGS="${HOST_BUILD_ARGS} -c "
299 300 301
        else
            echo "build windows whl with cpu only"
        fi
302

303 304 305 306 307 308 309 310 311 312 313 314 315
        if [ -d "${BUILD_DIR}" ]; then
            # insure rm have args
            touch ${BUILD_DIR}/empty.pyd
            touch ${BUILD_DIR}/CMakeCache.txt
            /usr/bin/find ${BUILD_DIR} -name "*.pyd" | xargs rm
            # ninja/cmake on windows will handle error if just export
            # PYTHON_LIBRARY/PYTHON_INCLUDE_DIR/PYTHON_EXECUTABLE
            # But after put python3.exe to HEAD of PATH by config_python_env
            # and force remove CMakeCache.txt, ninja/cmake will auto update
            # PYTHON_LIBRARY/PYTHON_INCLUDE_DIR/PYTHON_EXECUTABLE
            /usr/bin/find ${BUILD_DIR} -name CMakeCache.txt | xargs rm
        fi
        echo "host_build.sh HOST_BUILD_ARGS: ${HOST_BUILD_ARGS}"
316

317 318 319 320
        # 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
321

322 323
        #call real build
        ${SRC_DIR}/scripts/cmake-build/host_build.sh ${HOST_BUILD_ARGS}
324 325
        # remove megenginelite py develop soft link create by lite_shared:POST_BUILD @ lite/CMakeLists.txt
        rm -rf ${SRC_DIR}/lite/pylite/megenginelite/libs
326 327 328 329

        # check python api call setup.py
        cd ${BUILD_DIR}
        check_build_ninja_python_api ${ver}
330
        rm -rf staging
331
        mkdir -p staging
332
        cp -a imperative/python/{megengine,setup.py,requires.txt,requires-style.txt,requires-test.txt} staging/
333
        cp -a ${SRC_DIR}/src/custom/include/megbrain staging/megengine/core/include/
334 335 336 337 338 339 340
        cd ${BUILD_DIR}/staging/megengine/core
        rt_file=`ls _imperative_rt.*.pyd`
        echo "rt file is: ${rt_file}"
        if [[ -z ${rt_file} ]]
        then
            echo "ERR: can not find valid rt file"
            exit -1
341
        fi
342 343
        mv ${rt_file} _imperative_rt.pyd

344
        copy_more_dll
345

346 347
        # handle megenginelite
        cd ${BUILD_DIR}
348 349 350
        mkdir -p staging/megenginelite
        cp ${SRC_DIR}/lite/pylite/megenginelite/* staging/megenginelite/
        LITE_CORE_LIB_DIR=${BUILD_DIR}/staging/megenginelite/libs/
351 352
        mkdir -p ${LITE_CORE_LIB_DIR}
        cd ${LITE_CORE_LIB_DIR}
353
        cp ${BUILD_DIR}/lite/lite_shared_whl.dll liblite_shared_whl.pyd
354 355
        lite_copy_more_dll

356 357
        cd ${BUILD_DIR}/staging
        echo "call setup.py now"
358
        ${PYTHON_DIR}/python3 setup.py bdist_wheel
359
        cp ${BUILD_DIR}/staging/dist/Meg*.whl ${WINDOWS_WHL_HOME}/
360

361 362 363 364 365
        echo ""
        echo "##############################################################################################"
        echo "windows whl package location: ${WINDOWS_WHL_HOME}"
        ls ${WINDOWS_WHL_HOME}
        echo "##############################################################################################"
366
        IS_IN_FIRST_LOOP=FALSE
367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383
    done
}

function third_party_prepare() {
    echo "init third_party..."
    ${SRC_DIR}/third_party/prepare.sh

    if [[ -z ${ALREADY_INSTALL_MKL} ]]
    then
        echo "init third_party..."
        ${SRC_DIR}/third_party/install-mkl.sh
    else
        echo "skip init mkl internal"
    fi
}

######################
384
export ALREADY_CONFIG_PYTHON_VER="yes"
385
third_party_prepare
386
do_build