diff --git a/.appveyor.yml b/.appveyor.yml index 85ffe5ceddfb..e02c3e9d8151 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -1,9 +1,9 @@ -version: 3.3.2.{build} +version: 3.3.2.99.{build} image: Visual Studio 2015 platform: x64 configuration: # a trick to construct a build matrix with multiple Python versions - - 3.7 + - '3.7' # only build pull requests and # commits to 'master' @@ -27,11 +27,7 @@ install: - set PYTHON_VERSION=%CONFIGURATION% - set CONDA_ENV="test-env" - ps: | - switch ($env:PYTHON_VERSION) { - "3.6" {$env:MINICONDA = "C:\Miniconda36-x64"} - "3.7" {$env:MINICONDA = "C:\Miniconda37-x64"} - default {$env:MINICONDA = "C:\Miniconda37-x64"} - } + $env:MINICONDA = "C:\Miniconda3-x64" $env:PATH = "$env:MINICONDA;$env:MINICONDA\Scripts;$env:PATH" $env:BUILD_SOURCESDIRECTORY = "$env:APPVEYOR_BUILD_FOLDER" $env:LGB_VER = (Get-Content $env:APPVEYOR_BUILD_FOLDER\VERSION.txt).trim() @@ -39,5 +35,7 @@ install: build: false test_script: + - conda config --add channels conda-forge + - conda config --set channel_priority strict - conda init powershell - powershell.exe -ExecutionPolicy Bypass -File %APPVEYOR_BUILD_FOLDER%\.ci\test_windows.ps1 diff --git a/.ci/get_workflow_status.py b/.ci/get_workflow_status.py index 0572197c1ec2..34a910f0079f 100644 --- a/.ci/get_workflow_status.py +++ b/.ci/get_workflow_status.py @@ -33,15 +33,26 @@ def get_runs(trigger_phrase): pr_runs = [] if environ.get("GITHUB_EVENT_NAME", "") == "pull_request": pr_number = int(environ.get("GITHUB_REF").split('/')[-2]) - req = request.Request(url="{}/repos/microsoft/LightGBM/issues/{}/comments".format(environ.get("GITHUB_API_URL"), - pr_number), - headers={"Accept": "application/vnd.github.v3+json"}) - url = request.urlopen(req) - data = json.loads(url.read().decode('utf-8')) - url.close() - pr_runs = [i for i in data - if i['author_association'].lower() in {'owner', 'member', 'collaborator'} - and i['body'].startswith('/gha run {}'.format(trigger_phrase))] + page = 1 + while True: + req = request.Request( + url="{}/repos/microsoft/LightGBM/issues/{}/comments?page={}&per_page=100".format( + environ.get("GITHUB_API_URL"), + pr_number, + page + ), + headers={"Accept": "application/vnd.github.v3+json"} + ) + url = request.urlopen(req) + data = json.loads(url.read().decode('utf-8')) + url.close() + if not data: + break + runs_on_page = [i for i in data + if i['author_association'].lower() in {'owner', 'member', 'collaborator'} + and i['body'].startswith('/gha run {}'.format(trigger_phrase))] + pr_runs.extend(runs_on_page) + page += 1 return pr_runs[::-1] diff --git a/.ci/lint_r_code.R b/.ci/lint_r_code.R index cc83cb7c1cc9..54f94bb9a51d 100755 --- a/.ci/lint_r_code.R +++ b/.ci/lint_r_code.R @@ -8,7 +8,7 @@ SOURCE_DIR <- args[[1L]] FILES_TO_LINT <- list.files( path = SOURCE_DIR - , pattern = "\\.r$" + , pattern = "\\.r$|\\.rmd$" , all.files = TRUE , ignore.case = TRUE , full.names = TRUE @@ -29,28 +29,40 @@ interactive_text <- paste0( ) LINTERS_TO_USE <- list( - "absolute_path" = lintr::absolute_path_linter - , "assignment" = lintr::assignment_linter - , "closed_curly" = lintr::closed_curly_linter - , "commas" = lintr::commas_linter - , "equals_na" = lintr::equals_na_linter - , "function_left" = lintr::function_left_parentheses_linter - , "implicit_integers" = lintr::implicit_integer_linter - , "infix_spaces" = lintr::infix_spaces_linter + "absolute_path" = lintr::absolute_path_linter() + , "any_duplicated" = lintr::any_duplicated_linter() + , "any_is_na" = lintr::any_is_na_linter() + , "assignment" = lintr::assignment_linter() + , "braces" = lintr::brace_linter() + , "class_equals" = lintr::class_equals_linter() + , "commas" = lintr::commas_linter() + , "duplicate_argument" = lintr::duplicate_argument_linter() + , "equals_na" = lintr::equals_na_linter() + , "function_left" = lintr::function_left_parentheses_linter() + , "implicit_integers" = lintr::implicit_integer_linter() + , "infix_spaces" = lintr::infix_spaces_linter() + , "inner_combine" = lintr::inner_combine_linter() + , "literal_coercion" = lintr::literal_coercion_linter() , "long_lines" = lintr::line_length_linter(length = 120L) - , "no_tabs" = lintr::no_tab_linter - , "non_portable_path" = lintr::nonportable_path_linter - , "open_curly" = lintr::open_curly_linter - , "paren_brace_linter" = lintr::paren_brace_linter - , "semicolon" = lintr::semicolon_terminator_linter - , "seq" = lintr::seq_linter - , "single_quotes" = lintr::single_quotes_linter - , "spaces_inside" = lintr::spaces_inside_linter - , "spaces_left_parens" = lintr::spaces_left_parentheses_linter + , "missing_argument" = lintr::missing_argument_linter() + , "no_tabs" = lintr::no_tab_linter() + , "non_portable_path" = lintr::nonportable_path_linter() + , "numeric_leading_zero" = lintr::numeric_leading_zero_linter() + , "outer_negation" = lintr::outer_negation_linter() + , "package_hooks" = lintr::package_hooks_linter() + , "paste" = lintr::paste_linter() + , "regex_subset" = lintr::regex_subset_linter() + , "semicolon" = lintr::semicolon_linter() + , "seq" = lintr::seq_linter() + , "single_quotes" = lintr::single_quotes_linter() + , "spaces_inside" = lintr::spaces_inside_linter() + , "spaces_left_parens" = lintr::spaces_left_parentheses_linter() + , "sprintf" = lintr::sprintf_linter() + , "string_boundary" = lintr::string_boundary_linter() , "todo_comments" = lintr::todo_comment_linter(c("todo", "fixme", "to-do")) - , "trailing_blank" = lintr::trailing_blank_lines_linter - , "trailing_white" = lintr::trailing_whitespace_linter - , "true_false" = lintr::T_and_F_symbol_linter + , "trailing_blank" = lintr::trailing_blank_lines_linter() + , "trailing_white" = lintr::trailing_whitespace_linter() + , "true_false" = lintr::T_and_F_symbol_linter() , "undesirable_function" = lintr::undesirable_function_linter( fun = c( "cat" = "CRAN forbids the use of cat() in packages except in special cases. Use message() or warning()." @@ -58,8 +70,8 @@ LINTERS_TO_USE <- list( "cbind is an unsafe way to build up a data frame. merge() or direct " , "column assignment is preferred." ) - , "dyn.load" = "Directly loading/unloading .dll/.so files in package code should not be necessary." - , "dyn.unload" = "Directly loading/unloading .dll/.so files in package code should not be necessary." + , "dyn.load" = "Directly loading or unloading .dll or .so files in package code should not be necessary." + , "dyn.unload" = "Directly loading or unloading .dll or .so files in package code should not be necessary." , "help" = interactive_text , "ifelse" = "The use of ifelse() is dangerous because it will silently allow mixing types." , "install.packages" = interactive_text @@ -83,7 +95,9 @@ LINTERS_TO_USE <- list( , "??" = interactive_text ) ) - , "unneeded_concatenation" = lintr::unneeded_concatenation_linter + , "unneeded_concatenation" = lintr::unneeded_concatenation_linter() + , "unreachable_code" = lintr::unreachable_code_linter() + , "vector_logic" = lintr::vector_logic_linter() ) noquote(paste0(length(FILES_TO_LINT), " R files need linting")) diff --git a/.ci/setup.sh b/.ci/setup.sh index ef84a51cd587..c1e39b67d1a0 100755 --- a/.ci/setup.sh +++ b/.ci/setup.sh @@ -4,7 +4,7 @@ if [[ $OS_NAME == "macos" ]]; then if [[ $COMPILER == "clang" ]]; then brew install libomp if [[ $AZURE == "true" ]]; then - sudo xcode-select -s /Applications/Xcode_9.4.1.app/Contents/Developer || exit -1 + sudo xcode-select -s /Applications/Xcode_10.3.app/Contents/Developer || exit -1 fi else # gcc if [[ $TASK != "mpi" ]]; then @@ -17,8 +17,10 @@ if [[ $OS_NAME == "macos" ]]; then if [[ $TASK == "swig" ]]; then brew install swig fi - brew install graphviz - curl -sL -o conda.sh https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-x86_64.sh + curl \ + -sL \ + -o miniforge.sh \ + https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-MacOSX-x86_64.sh else # Linux if [[ $IN_UBUNTU_LATEST_CONTAINER == "true" ]]; then # fixes error "unable to initialize frontend: Dialog" @@ -42,9 +44,6 @@ else # Linux libicu66 \ libssl1.1 \ libunwind8 \ - libxau6 \ - libxext6 \ - libxrender1 \ locales \ netcat \ unzip \ @@ -72,25 +71,16 @@ else # Linux sudo apt-get install --no-install-recommends -y \ libboost1.74-dev \ ocl-icd-opencl-dev - cd $BUILD_DIRECTORY # to avoid permission errors - curl -sL -o AMD-APP-SDKInstaller.tar.bz2 https://github.com/microsoft/LightGBM/releases/download/v2.0.12/AMD-APP-SDKInstaller-v3.0.130.136-GA-linux64.tar.bz2 - tar -xjf AMD-APP-SDKInstaller.tar.bz2 - mkdir -p $OPENCL_VENDOR_PATH - mkdir -p $AMDAPPSDK_PATH - sh AMD-APP-SDK*.sh --tar -xf -C $AMDAPPSDK_PATH - mv $AMDAPPSDK_PATH/lib/x86_64/sdk/* $AMDAPPSDK_PATH/lib/x86_64/ - echo libamdocl64.so > $OPENCL_VENDOR_PATH/amdocl64.icd + if [[ $IN_UBUNTU_LATEST_CONTAINER == "true" ]]; then + sudo apt-get install --no-install-recommends -y \ + pocl-opencl-icd + fi fi - ARCH=$(uname -m) - if [[ $TASK == "cuda" ]]; then + if [[ $TASK == "cuda" || $TASK == "cuda_exp" ]]; then echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections apt-get update apt-get install --no-install-recommends -y \ curl \ - graphviz \ - libxau6 \ - libxext6 \ - libxrender1 \ lsb-release \ software-properties-common if [[ $COMPILER == "clang" ]]; then @@ -98,40 +88,24 @@ else # Linux clang \ libomp-dev fi - curl \ - -s \ - -L \ - --insecure \ - https://apt.kitware.com/keys/kitware-archive-latest.asc \ - | apt-key add - + curl -sL https://apt.kitware.com/keys/kitware-archive-latest.asc | apt-key add - apt-add-repository "deb https://apt.kitware.com/ubuntu/ $(lsb_release -cs) main" -y - apt-get --allow-unauthenticated upgrade -y - apt-get --allow-unauthenticated update -y + apt-get update apt-get install --no-install-recommends -y \ cmake - else - if [[ $ARCH != "x86_64" ]]; then - yum update -y - yum install -y \ - graphviz - else - sudo apt-get update - sudo apt-get install --no-install-recommends -y \ - graphviz - fi fi if [[ $SETUP_CONDA != "false" ]]; then - if [[ $ARCH == "x86_64" ]]; then - curl -sL -o conda.sh https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh - else - curl -sL -o conda.sh https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Linux-${ARCH}.sh - fi + ARCH=$(uname -m) + curl \ + -sL \ + -o miniforge.sh \ + https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Linux-${ARCH}.sh fi fi -if [[ "${TASK}" != "r-package" ]]; then +if [[ "${TASK}" != "r-package" ]] && [[ "${TASK}" != "r-rchk" ]]; then if [[ $SETUP_CONDA != "false" ]]; then - sh conda.sh -b -p $CONDA + sh miniforge.sh -b -p $CONDA fi conda config --set always_yes yes --set changeps1 no conda update -q -y conda diff --git a/.ci/test.sh b/.ci/test.sh index 00b2a3a38356..c75cf33d8565 100755 --- a/.ci/test.sh +++ b/.ci/test.sh @@ -36,13 +36,20 @@ cd $BUILD_DIRECTORY if [[ $TASK == "check-docs" ]] || [[ $TASK == "check-links" ]]; then cd $BUILD_DIRECTORY/docs - conda install -q -y -n $CONDA_ENV -c conda-forge doxygen rstcheck - pip install --user -r requirements.txt + conda env update \ + -n $CONDA_ENV \ + --file ./env.yml || exit -1 + conda install \ + -q \ + -y \ + -n $CONDA_ENV \ + doxygen \ + 'rstcheck>=6.0.0' || exit -1 # check reStructuredText formatting cd $BUILD_DIRECTORY/python-package - rstcheck --report warning $(find . -type f -name "*.rst") || exit -1 + rstcheck --report-level warning $(find . -type f -name "*.rst") || exit -1 cd $BUILD_DIRECTORY/docs - rstcheck --report warning --ignore-directives=autoclass,autofunction,doxygenfile $(find . -type f -name "*.rst") || exit -1 + rstcheck --report-level warning --ignore-directives=autoclass,autofunction,autosummary,doxygenfile $(find . -type f -name "*.rst") || exit -1 # build docs make html || exit -1 if [[ $TASK == "check-links" ]]; then @@ -62,16 +69,13 @@ fi if [[ $TASK == "lint" ]]; then conda install -q -y -n $CONDA_ENV \ + cmakelint \ + cpplint \ + isort \ + mypy \ pycodestyle \ pydocstyle \ - r-stringi # stringi needs to be installed separate from r-lintr to avoid issues like 'unable to load shared object stringi.so' - # r-xfun below has to be upgraded because lintr requires > 0.19 for that package - conda install -q -y -n $CONDA_ENV \ - -c conda-forge \ - libxml2 \ - "r-xfun>=0.19" \ - "r-lintr>=2.0" - pip install --user cmakelint cpplint isort mypy + "r-lintr>=3.0" echo "Linting Python code" pycodestyle --ignore=E501,W503 --exclude=./.nuget,./external_libs . || exit -1 pydocstyle --convention=numpy --add-ignore=D105 --match-dir="^(?!^external_libs|test|example).*" --match="(?!^test_|setup).*\.py" . || exit -1 @@ -82,7 +86,7 @@ if [[ $TASK == "lint" ]]; then echo "Linting C++ code" cpplint --filter=-build/c++11,-build/include_subdir,-build/header_guard,-whitespace/line_length --recursive ./src ./include ./R-package ./swig ./tests || exit -1 cmake_files=$(find . -name CMakeLists.txt -o -path "*/cmake/*.cmake") - cmakelint --linelength=120 ${cmake_files} || true + cmakelint --linelength=120 --filter=-convention/filename,-package/stdargs,-readability/wonkycase ${cmake_files} || exit -1 exit 0 fi @@ -114,15 +118,27 @@ if [[ $TASK == "swig" ]]; then exit 0 fi -# temporary fix for https://github.com/microsoft/LightGBM/issues/4769 -if [[ $PYTHON_VERSION == "3.6" ]]; then - DASK_DEPENDENCIES="dask distributed" +# temporary fix for https://github.com/microsoft/LightGBM/issues/5390 +if [[ $PYTHON_VERSION == "3.7" ]]; then + DEPENDENCIES="dask distributed" else - DASK_DEPENDENCIES="dask=2021.9.1 distributed=2021.9.1" + DEPENDENCIES="dask=2022.7.0 distributed=2022.7.0 scipy<1.9" fi -conda install -q -y -n $CONDA_ENV cloudpickle ${DASK_DEPENDENCIES} joblib matplotlib numpy pandas psutil pytest scikit-learn scipy -pip install graphviz # python-graphviz from Anaconda is not allowed to be installed with Python 3.9 +conda install -q -y -n $CONDA_ENV \ + cloudpickle \ + ${DEPENDENCIES} \ + joblib \ + matplotlib \ + numpy \ + pandas \ + psutil \ + pytest \ + scikit-learn || exit -1 + +# python-graphviz has to be installed separately to prevent conda from downgrading to pypy +conda install -q -y -n $CONDA_ENV \ + python-graphviz || exit -1 if [[ $OS_NAME == "macos" ]] && [[ $COMPILER == "clang" ]]; then # fix "OMP: Error #15: Initializing libiomp5.dylib, but found libomp.dylib already initialized." (OpenMP library conflict due to conda's MKL) @@ -140,7 +156,7 @@ if [[ $TASK == "sdist" ]]; then elif [[ $TASK == "bdist" ]]; then if [[ $OS_NAME == "macos" ]]; then cd $BUILD_DIRECTORY/python-package && python setup.py bdist_wheel --plat-name=macosx --python-tag py3 || exit -1 - mv dist/lightgbm-$LGB_VER-py3-none-macosx.whl dist/lightgbm-$LGB_VER-py3-none-macosx_10_14_x86_64.macosx_10_15_x86_64.macosx_11_0_x86_64.whl + mv dist/lightgbm-$LGB_VER-py3-none-macosx.whl dist/lightgbm-$LGB_VER-py3-none-macosx_10_15_x86_64.macosx_11_6_x86_64.macosx_12_0_x86_64.whl if [[ $PRODUCES_ARTIFACTS == "true" ]]; then cp dist/lightgbm-$LGB_VER-py3-none-macosx*.whl $BUILD_ARTIFACTSTAGINGDIRECTORY fi @@ -168,32 +184,52 @@ if [[ $TASK == "gpu" ]]; then grep -q 'std::string device_type = "gpu"' $BUILD_DIRECTORY/include/LightGBM/config.h || exit -1 # make sure that changes were really done if [[ $METHOD == "pip" ]]; then cd $BUILD_DIRECTORY/python-package && python setup.py sdist || exit -1 - pip install --user $BUILD_DIRECTORY/python-package/dist/lightgbm-$LGB_VER.tar.gz -v --install-option=--gpu --install-option="--opencl-include-dir=$AMDAPPSDK_PATH/include/" || exit -1 + pip install --user $BUILD_DIRECTORY/python-package/dist/lightgbm-$LGB_VER.tar.gz -v --install-option=--gpu || exit -1 pytest $BUILD_DIRECTORY/tests/python_package_test || exit -1 exit 0 elif [[ $METHOD == "wheel" ]]; then - cd $BUILD_DIRECTORY/python-package && python setup.py bdist_wheel --gpu --opencl-include-dir="$AMDAPPSDK_PATH/include/" || exit -1 + cd $BUILD_DIRECTORY/python-package && python setup.py bdist_wheel --gpu || exit -1 pip install --user $BUILD_DIRECTORY/python-package/dist/lightgbm-$LGB_VER*.whl -v || exit -1 pytest $BUILD_DIRECTORY/tests || exit -1 exit 0 elif [[ $METHOD == "source" ]]; then - cmake -DUSE_GPU=ON -DOpenCL_INCLUDE_DIR=$AMDAPPSDK_PATH/include/ .. + cmake -DUSE_GPU=ON .. + fi +elif [[ $TASK == "cuda" || $TASK == "cuda_exp" ]]; then + if [[ $TASK == "cuda" ]]; then + sed -i'.bak' 's/std::string device_type = "cpu";/std::string device_type = "cuda";/' $BUILD_DIRECTORY/include/LightGBM/config.h + grep -q 'std::string device_type = "cuda"' $BUILD_DIRECTORY/include/LightGBM/config.h || exit -1 # make sure that changes were really done + else + sed -i'.bak' 's/std::string device_type = "cpu";/std::string device_type = "cuda_exp";/' $BUILD_DIRECTORY/include/LightGBM/config.h + grep -q 'std::string device_type = "cuda_exp"' $BUILD_DIRECTORY/include/LightGBM/config.h || exit -1 # make sure that changes were really done + # by default ``gpu_use_dp=false`` for efficiency. change to ``true`` here for exact results in ci tests + sed -i'.bak' 's/gpu_use_dp = false;/gpu_use_dp = true;/' $BUILD_DIRECTORY/include/LightGBM/config.h + grep -q 'gpu_use_dp = true' $BUILD_DIRECTORY/include/LightGBM/config.h || exit -1 # make sure that changes were really done fi -elif [[ $TASK == "cuda" ]]; then - sed -i'.bak' 's/std::string device_type = "cpu";/std::string device_type = "cuda";/' $BUILD_DIRECTORY/include/LightGBM/config.h - grep -q 'std::string device_type = "cuda"' $BUILD_DIRECTORY/include/LightGBM/config.h || exit -1 # make sure that changes were really done if [[ $METHOD == "pip" ]]; then cd $BUILD_DIRECTORY/python-package && python setup.py sdist || exit -1 - pip install --user $BUILD_DIRECTORY/python-package/dist/lightgbm-$LGB_VER.tar.gz -v --install-option=--cuda || exit -1 + if [[ $TASK == "cuda" ]]; then + pip install --user $BUILD_DIRECTORY/python-package/dist/lightgbm-$LGB_VER.tar.gz -v --install-option=--cuda || exit -1 + else + pip install --user $BUILD_DIRECTORY/python-package/dist/lightgbm-$LGB_VER.tar.gz -v --install-option=--cuda-exp || exit -1 + fi pytest $BUILD_DIRECTORY/tests/python_package_test || exit -1 exit 0 elif [[ $METHOD == "wheel" ]]; then - cd $BUILD_DIRECTORY/python-package && python setup.py bdist_wheel --cuda || exit -1 + if [[ $TASK == "cuda" ]]; then + cd $BUILD_DIRECTORY/python-package && python setup.py bdist_wheel --cuda || exit -1 + else + cd $BUILD_DIRECTORY/python-package && python setup.py bdist_wheel --cuda-exp || exit -1 + fi pip install --user $BUILD_DIRECTORY/python-package/dist/lightgbm-$LGB_VER*.whl -v || exit -1 pytest $BUILD_DIRECTORY/tests || exit -1 exit 0 elif [[ $METHOD == "source" ]]; then - cmake -DUSE_CUDA=ON .. + if [[ $TASK == "cuda" ]]; then + cmake -DUSE_CUDA=ON .. + else + cmake -DUSE_CUDA_EXP=ON .. + fi fi elif [[ $TASK == "mpi" ]]; then if [[ $METHOD == "pip" ]]; then @@ -236,7 +272,11 @@ import matplotlib\ matplotlib.use\(\"Agg\"\)\ ' plot_example.py # prevent interactive window mode sed -i'.bak' 's/graph.render(view=True)/graph.render(view=False)/' plot_example.py - conda install -q -y -n $CONDA_ENV h5py ipywidgets notebook # requirements for examples + # requirements for examples + conda install -q -y -n $CONDA_ENV \ + h5py \ + ipywidgets \ + notebook for f in *.py **/*.py; do python $f || exit -1; done # run all examples cd $BUILD_DIRECTORY/examples/python-guide/notebooks sed -i'.bak' 's/INTERACTIVE = False/assert False, \\"Interactive mode disabled\\"/' interactive_plot_example.ipynb diff --git a/.ci/test_r_package.sh b/.ci/test_r_package.sh index a6656dfb83e6..c15b5c59df7b 100755 --- a/.ci/test_r_package.sh +++ b/.ci/test_r_package.sh @@ -1,7 +1,7 @@ #!/bin/bash # set up R environment -CRAN_MIRROR="https://cloud.r-project.org/" +CRAN_MIRROR="https://cran.rstudio.com" R_LIB_PATH=~/Rlib mkdir -p $R_LIB_PATH export R_LIBS=$R_LIB_PATH @@ -17,11 +17,13 @@ fi R_MAJOR_VERSION=( ${R_VERSION//./ } ) if [[ "${R_MAJOR_VERSION}" == "3" ]]; then export R_MAC_VERSION=3.6.3 + export R_MAC_PKG_URL=${CRAN_MIRROR}/bin/macosx/R-${R_MAC_VERSION}.pkg export R_LINUX_VERSION="3.6.3-1bionic" export R_APT_REPO="bionic-cran35/" elif [[ "${R_MAJOR_VERSION}" == "4" ]]; then - export R_MAC_VERSION=4.1.1 - export R_LINUX_VERSION="4.1.1-1.2004.0" + export R_MAC_VERSION=4.2.1 + export R_MAC_PKG_URL=${CRAN_MIRROR}/bin/macosx/base/R-${R_MAC_VERSION}.pkg + export R_LINUX_VERSION="4.2.1-1.2004.0" export R_APT_REPO="focal-cran40/" else echo "Unrecognized R version: ${R_VERSION}" @@ -38,7 +40,7 @@ if [[ $OS_NAME == "linux" ]]; then --keyserver keyserver.ubuntu.com \ --recv-keys E298A3A825C0D65DFD57CBB651716619E084DAB9 sudo add-apt-repository \ - "deb https://cloud.r-project.org/bin/linux/ubuntu ${R_APT_REPO}" + "deb ${CRAN_MIRROR}/bin/linux/ubuntu ${R_APT_REPO}" sudo apt-get update sudo apt-get install \ --no-install-recommends \ @@ -66,20 +68,33 @@ fi if [[ $OS_NAME == "macos" ]]; then brew update-reset && brew update if [[ $R_BUILD_TYPE == "cran" ]]; then - brew install automake + brew install automake || exit -1 fi brew install \ checkbashisms \ - qpdf - brew install --cask basictex + qpdf || exit -1 + brew install --cask basictex || exit -1 export PATH="/Library/TeX/texbin:$PATH" - sudo tlmgr --verify-repo=none update --self - sudo tlmgr --verify-repo=none install inconsolata helvetic + sudo tlmgr --verify-repo=none update --self || exit -1 + sudo tlmgr --verify-repo=none install inconsolata helvetic || exit -1 - curl -sL https://cran.r-project.org/bin/macosx/R-${R_MAC_VERSION}.pkg -o R.pkg + curl -sL ${R_MAC_PKG_URL} -o R.pkg || exit -1 sudo installer \ -pkg $(pwd)/R.pkg \ - -target / + -target / || exit -1 + + # Older R versions (<= 4.1.2) on newer macOS (>= 11.0.0) cannot create the necessary symlinks. + # See https://github.com/r-lib/actions/issues/412. + if [[ $(sw_vers -productVersion | head -c2) -ge "11" ]]; then + sudo ln \ + -sf \ + /Library/Frameworks/R.framework/Resources/bin/R \ + /usr/local/bin/R + sudo ln \ + -sf \ + /Library/Frameworks/R.framework/Resources/bin/Rscript \ + /usr/local/bin/Rscript + fi # Fix "duplicate libomp versions" issue on Mac # by replacing the R libomp.dylib with a symlink to the one installed with brew @@ -92,13 +107,13 @@ if [[ $OS_NAME == "macos" ]]; then fi fi -# Manually install Depends and Imports libraries + 'testthat' +# Manually install Depends and Imports libraries + 'knitr', 'RhpcBLASctl', 'rmarkdown', 'testthat' # to avoid a CI-time dependency on devtools (for devtools::install_deps()) # NOTE: testthat is not required when running rchk if [[ "${TASK}" == "r-rchk" ]]; then - packages="c('data.table', 'jsonlite', 'Matrix', 'R6')" + packages="c('data.table', 'jsonlite', 'knitr', 'Matrix', 'R6', 'RhpcBLASctl', 'rmarkdown')" else - packages="c('data.table', 'jsonlite', 'Matrix', 'R6', 'testthat')" + packages="c('data.table', 'jsonlite', 'knitr', 'Matrix', 'R6', 'RhpcBLASctl', 'rmarkdown', 'testthat')" fi compile_from_source="both" if [[ $OS_NAME == "macos" ]]; then @@ -112,7 +127,7 @@ cd ${BUILD_DIRECTORY} PKG_TARBALL="lightgbm_*.tar.gz" LOG_FILE_NAME="lightgbm.Rcheck/00check.log" if [[ $R_BUILD_TYPE == "cmake" ]]; then - Rscript build_r.R --skip-install || exit -1 + Rscript build_r.R -j4 --skip-install || exit -1 elif [[ $R_BUILD_TYPE == "cran" ]]; then # on Linux, we recreate configure in CI to test if diff --git a/.ci/test_r_package_valgrind.sh b/.ci/test_r_package_valgrind.sh index 80a2830b7422..9eddec2deed1 100755 --- a/.ci/test_r_package_valgrind.sh +++ b/.ci/test_r_package_valgrind.sh @@ -1,7 +1,9 @@ #!/bin/bash -RDscriptvalgrind -e "install.packages(c('R6', 'data.table', 'jsonlite', 'Matrix', 'testthat'), repos = 'https://cran.r-project.org', Ncpus = parallel::detectCores())" || exit -1 -sh build-cran-package.sh || exit -1 +RDscriptvalgrind -e "install.packages(c('R6', 'data.table', 'jsonlite', 'knitr', 'Matrix', 'RhpcBLASctl', 'rmarkdown', 'testthat'), repos = 'https://cran.rstudio.com', Ncpus = parallel::detectCores())" || exit -1 +sh build-cran-package.sh \ + --r-executable=RDvalgrind \ + || exit -1 RDvalgrind CMD INSTALL --preclean --install-tests lightgbm_*.tar.gz || exit -1 cd R-package/tests @@ -44,7 +46,7 @@ if [[ ${bytes_indirectly_lost} -gt 0 ]]; then fi # one error caused by a false positive between valgrind and openmp is allowed -# ==2063== 336 bytes in 1 blocks are possibly lost in loss record 153 of 2,709 +# ==2063== 352 bytes in 1 blocks are possibly lost in loss record 153 of 2,709 # ==2063== at 0x483DD99: calloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so) # ==2063== by 0x40149CA: allocate_dtv (dl-tls.c:286) # ==2063== by 0x40149CA: _dl_allocate_tls (dl-tls.c:532) @@ -66,7 +68,7 @@ bytes_possibly_lost=$( | tr -d "," ) echo "valgrind found ${bytes_possibly_lost} bytes possibly lost" -if [[ ${bytes_possibly_lost} -gt 336 ]]; then +if [[ ${bytes_possibly_lost} -gt 352 ]]; then exit -1 fi diff --git a/.ci/test_r_package_windows.ps1 b/.ci/test_r_package_windows.ps1 index 3c0f11ca58c6..c8f63b9c8b06 100644 --- a/.ci/test_r_package_windows.ps1 +++ b/.ci/test_r_package_windows.ps1 @@ -78,7 +78,7 @@ if ($env:R_MAJOR_VERSION -eq "3") { $env:RTOOLS_BIN = "$RTOOLS_INSTALL_PATH\usr\bin" $env:RTOOLS_MINGW_BIN = "$RTOOLS_INSTALL_PATH\mingw64\bin" $env:RTOOLS_EXE_FILE = "rtools40v2-x86_64.exe" - $env:R_WINDOWS_VERSION = "4.1.1" + $env:R_WINDOWS_VERSION = "4.1.3" } else { Write-Output "[ERROR] Unrecognized R version: $env:R_VERSION" Check-Output $false @@ -87,7 +87,7 @@ if ($env:R_MAJOR_VERSION -eq "3") { $env:R_LIB_PATH = "$env:BUILD_SOURCESDIRECTORY/RLibrary" -replace '[\\]', '/' $env:R_LIBS = "$env:R_LIB_PATH" $env:PATH = "$env:RTOOLS_BIN;" + "$env:RTOOLS_MINGW_BIN;" + "$env:R_LIB_PATH/R/bin/x64;" + "$env:R_LIB_PATH/miktex/texmfs/install/miktex/bin/x64;" + $env:PATH -$env:CRAN_MIRROR = "https://cloud.r-project.org/" +$env:CRAN_MIRROR = "https://cran.rstudio.com" $env:CTAN_MIRROR = "https://ctan.math.illinois.edu/systems/win32/miktex" $env:CTAN_PACKAGE_ARCHIVE = "$env:CTAN_MIRROR/tm/packages/" $env:MIKTEX_EXCEPTION_PATH = "$env:TEMP\miktex" @@ -109,7 +109,7 @@ tzutil /s "GMT Standard Time" # download R and RTools Write-Output "Downloading R and Rtools" -Download-File-With-Retries -url "https://cran.r-project.org/bin/windows/base/old/$env:R_WINDOWS_VERSION/R-$env:R_WINDOWS_VERSION-win.exe" -destfile "R-win.exe" +Download-File-With-Retries -url "$env:CRAN_MIRROR/bin/windows/base/old/$env:R_WINDOWS_VERSION/R-$env:R_WINDOWS_VERSION-win.exe" -destfile "R-win.exe" Download-File-With-Retries -url "https://github.com/microsoft/LightGBM/releases/download/v2.0.12/$env:RTOOLS_EXE_FILE" -destfile "Rtools.exe" # Install R @@ -122,7 +122,7 @@ Start-Process -FilePath Rtools.exe -NoNewWindow -Wait -ArgumentList "/VERYSILENT Write-Output "Done installing Rtools" Write-Output "Installing dependencies" -$packages = "c('data.table', 'jsonlite', 'Matrix', 'processx', 'R6', 'testthat'), dependencies = c('Imports', 'Depends', 'LinkingTo')" +$packages = "c('data.table', 'jsonlite', 'knitr', 'Matrix', 'processx', 'R6', 'RhpcBLASctl', 'rmarkdown', 'testthat'), dependencies = c('Imports', 'Depends', 'LinkingTo')" Run-R-Code-Redirect-Stderr "options(install.packages.check.source = 'no'); install.packages($packages, repos = '$env:CRAN_MIRROR', type = 'binary', lib = '$env:R_LIB_PATH', Ncpus = parallel::detectCores())" ; Check-Output $? # MiKTeX and pandoc can be skipped on non-MinGW builds, since we don't @@ -153,10 +153,10 @@ if ($env:COMPILER -ne "MSVC") { if ($env:R_BUILD_TYPE -eq "cmake") { if ($env:TOOLCHAIN -eq "MINGW") { Write-Output "Telling R to use MinGW" - $env:BUILD_R_FLAGS = "c('--skip-install', '--use-mingw')" + $env:BUILD_R_FLAGS = "c('--skip-install', '--use-mingw', '-j4')" } elseif ($env:TOOLCHAIN -eq "MSYS") { Write-Output "Telling R to use MSYS" - $env:BUILD_R_FLAGS = "c('--skip-install', '--use-msys2')" + $env:BUILD_R_FLAGS = "c('--skip-install', '--use-msys2', '-j4')" } elseif ($env:TOOLCHAIN -eq "MSVC") { $env:BUILD_R_FLAGS = "'--skip-install'" } else { @@ -165,7 +165,15 @@ if ($env:COMPILER -ne "MSVC") { } Run-R-Code-Redirect-Stderr "commandArgs <- function(...){$env:BUILD_R_FLAGS}; source('build_r.R')"; Check-Output $? } elseif ($env:R_BUILD_TYPE -eq "cran") { + # NOTE: gzip and tar are needed to create a CRAN package on Windows, but + # some flavors of tar.exe can fail in some settings on Windows. + # Putting the msys64 utilities at the beginning of PATH temporarily to be + # sure they're used for that purpose. + if ($env:R_MAJOR_VERSION -eq "3") { + $env:PATH = "C:\msys64\usr\bin;" + $env:PATH + } Run-R-Code-Redirect-Stderr "result <- processx::run(command = 'sh', args = 'build-cran-package.sh', echo = TRUE, windows_verbatim_args = FALSE, error_on_status = TRUE)" ; Check-Output $? + Remove-From-Path ".*msys64.*" # Test CRAN source .tar.gz in a directory that is not this repo or below it. # When people install.packages('lightgbm'), they won't have the LightGBM # git repo around. This is to protect against the use of relative paths @@ -275,7 +283,10 @@ if ($env:R_BUILD_TYPE -eq "cmake") { if ($env:COMPILER -eq "MSVC") { Write-Output "Running tests with testthat.R" cd R-package/tests - Run-R-Code-Redirect-Stderr "source('testthat.R')" ; Check-Output $? + # NOTE: using Rscript.exe intentionally here, instead of Run-R-Code-Redirect-Stderr, + # because something about the interaction between Run-R-Code-Redirect-Stderr + # and testthat results in failing tests not exiting with a non-0 exit code. + Rscript.exe --vanilla "testthat.R" ; Check-Output $? } Write-Output "No issues were found checking the R package" diff --git a/.ci/test_windows.ps1 b/.ci/test_windows.ps1 index 51488145dc17..6c0ffb8249f0 100644 --- a/.ci/test_windows.ps1 +++ b/.ci/test_windows.ps1 @@ -30,7 +30,7 @@ conda init powershell conda activate conda config --set always_yes yes --set changeps1 no conda update -q -y conda -conda create -q -y -n $env:CONDA_ENV python=$env:PYTHON_VERSION ; Check-Output $? +conda create -q -y -n $env:CONDA_ENV "python=$env:PYTHON_VERSION[build=*cpython]" ; Check-Output $? if ($env:TASK -ne "bdist") { conda activate $env:CONDA_ENV } @@ -50,7 +50,8 @@ if ($env:TASK -eq "swig") { Exit 0 } -conda install -q -y -n $env:CONDA_ENV joblib matplotlib numpy pandas psutil pytest python-graphviz scikit-learn scipy ; Check-Output $? +# re-including python=version[build=*cpython] to ensure that conda doesn't fall back to pypy +conda install -q -y -n $env:CONDA_ENV cloudpickle joblib matplotlib numpy pandas psutil pytest "python=$env:PYTHON_VERSION[build=*cpython]" python-graphviz scikit-learn scipy ; Check-Output $? if ($env:TASK -eq "regular") { mkdir $env:BUILD_SOURCESDIRECTORY/build; cd $env:BUILD_SOURCESDIRECTORY/build diff --git a/.github/workflows/cuda.yml b/.github/workflows/cuda.yml index 822ea2d44b82..a8d69ddcaa33 100644 --- a/.github/workflows/cuda.yml +++ b/.github/workflows/cuda.yml @@ -7,16 +7,16 @@ on: pull_request: branches: - master + - release/* env: github_actions: 'true' os_name: linux - task: cuda conda_env: test-env jobs: test: - name: cuda ${{ matrix.cuda_version }} ${{ matrix.method }} (linux, ${{ matrix.compiler }}, Python ${{ matrix.python_version }}) + name: ${{ matrix.task }} ${{ matrix.cuda_version }} ${{ matrix.method }} (linux, ${{ matrix.compiler }}, Python ${{ matrix.python_version }}) runs-on: [self-hosted, linux] timeout-minutes: 60 strategy: @@ -25,16 +25,29 @@ jobs: include: - method: source compiler: gcc - python_version: 3.7 - cuda_version: "11.4.2" + python_version: "3.8" + cuda_version: "11.7.1" + task: cuda - method: pip compiler: clang - python_version: 3.8 + python_version: "3.9" cuda_version: "10.0" + task: cuda - method: wheel compiler: gcc - python_version: 3.9 + python_version: "3.10" cuda_version: "9.0" + task: cuda + - method: source + compiler: gcc + python_version: "3.8" + cuda_version: "11.7.1" + task: cuda_exp + - method: pip + compiler: clang + python_version: "3.9" + cuda_version: "10.0" + task: cuda_exp steps: - name: Setup or update software on host machine run: | @@ -73,7 +86,7 @@ jobs: GITHUB_ACTIONS=${{ env.github_actions }} OS_NAME=${{ env.os_name }} COMPILER=${{ matrix.compiler }} - TASK=${{ env.task }} + TASK=${{ matrix.task }} METHOD=${{ matrix.method }} CONDA_ENV=${{ env.conda_env }} PYTHON_VERSION=${{ matrix.python_version }} @@ -81,7 +94,7 @@ jobs: LGB_VER=$(head -n 1 VERSION.txt) EOF cat > docker-script.sh <> tests.log 2>&1 || exit_code=1 + RDscript${{ matrix.r_customization }} testthat.R >> tests.log 2>&1 || exit_code=-1 cat ./tests.log exit ${exit_code} test-r-debian-clang: @@ -216,8 +220,11 @@ jobs: run: | apt-get update --allow-releaseinfo-change apt-get install --no-install-recommends -y git + - name: Trust git cloning LightGBM + run: | + git config --global --add safe.directory "${GITHUB_WORKSPACE}" - name: Checkout repository - uses: actions/checkout@v2.3.4 + uses: actions/checkout@v2.4.0 with: fetch-depth: 5 submodules: true @@ -225,7 +232,7 @@ jobs: shell: bash run: | export PATH=/opt/R-devel/bin/:${PATH} - Rscript -e "install.packages(c('R6', 'data.table', 'jsonlite', 'Matrix', 'testthat'), repos = 'https://cran.r-project.org', Ncpus = parallel::detectCores())" + Rscript -e "install.packages(c('R6', 'data.table', 'jsonlite', 'knitr', 'Matrix', 'RhpcBLASctl', 'rmarkdown', 'testthat'), repos = 'https://cran.rstudio.com', Ncpus = parallel::detectCores())" sh build-cran-package.sh R CMD check --as-cran --run-donttest lightgbm_*.tar.gz || exit -1 if grep -q -E "NOTE|WARNING|ERROR" lightgbm.Rcheck/00check.log; then diff --git a/.github/workflows/r_valgrind.yml b/.github/workflows/r_valgrind.yml index ff37c212a7eb..00d74f5c8f39 100644 --- a/.github/workflows/r_valgrind.yml +++ b/.github/workflows/r_valgrind.yml @@ -7,7 +7,7 @@ on: jobs: test-r-valgrind: name: r-package (ubuntu-latest, R-devel, valgrind) - timeout-minutes: 180 + timeout-minutes: 300 runs-on: ubuntu-latest container: wch1/r-debug env: @@ -19,10 +19,12 @@ jobs: apt-get update apt-get install --no-install-recommends -y \ curl \ - git \ jq + - name: Trust git cloning LightGBM + run: | + git config --global --add safe.directory "${GITHUB_WORKSPACE}" - name: Checkout repository - uses: actions/checkout@v2.3.4 + uses: actions/checkout@v2.4.0 with: fetch-depth: 5 submodules: true diff --git a/.github/workflows/static_analysis.yml b/.github/workflows/static_analysis.yml index cdc917903f46..9d83a9eefb56 100644 --- a/.github/workflows/static_analysis.yml +++ b/.github/workflows/static_analysis.yml @@ -9,13 +9,14 @@ on: pull_request: branches: - master + - release/* env: COMPILER: 'gcc' CONDA_ENV: test-env GITHUB_ACTIONS: 'true' OS_NAME: 'linux' - PYTHON_VERSION: 3.9 + PYTHON_VERSION: '3.10' jobs: test: @@ -30,7 +31,7 @@ jobs: - task: check-docs steps: - name: Checkout repository - uses: actions/checkout@v2.3.4 + uses: actions/checkout@v2.4.0 with: fetch-depth: 5 submodules: false @@ -39,7 +40,7 @@ jobs: run: | export TASK="${{ matrix.task }}" export BUILD_DIRECTORY="$GITHUB_WORKSPACE" - export CONDA=${HOME}/miniconda + export CONDA=${HOME}/miniforge export PATH=${CONDA}/bin:$HOME/.local/bin:${PATH} $GITHUB_WORKSPACE/.ci/setup.sh || exit -1 $GITHUB_WORKSPACE/.ci/test.sh || exit -1 @@ -49,15 +50,18 @@ jobs: runs-on: ubuntu-latest container: rocker/verse steps: + - name: Trust git cloning LightGBM + run: | + git config --global --add safe.directory "${GITHUB_WORKSPACE}" - name: Checkout repository - uses: actions/checkout@v2.3.4 + uses: actions/checkout@v2.4.0 with: fetch-depth: 5 submodules: true - name: Install packages shell: bash run: | - Rscript -e "install.packages(c('R6', 'data.table', 'jsonlite', 'Matrix', 'roxygen2', 'testthat'), repos = 'https://cran.r-project.org', Ncpus = parallel::detectCores())" + Rscript -e "install.packages(c('R6', 'data.table', 'jsonlite', 'knitr', 'Matrix', 'RhpcBLASctl', 'rmarkdown', 'roxygen2', 'testthat'), repos = 'https://cran.rstudio.com', Ncpus = parallel::detectCores())" sh build-cran-package.sh || exit -1 R CMD INSTALL --with-keep.source lightgbm_*.tar.gz || exit -1 - name: Test documentation diff --git a/.vsts-ci.yml b/.vsts-ci.yml index 059ebf9d35b4..0c6c9fc7af1d 100644 --- a/.vsts-ci.yml +++ b/.vsts-ci.yml @@ -7,19 +7,24 @@ trigger: - v* pr: - master +- release/* variables: AZURE: 'true' - PYTHON_VERSION: 3.9 + PYTHON_VERSION: '3.10' CONDA_ENV: test-env + runCodesignValidationInjection: false + skipComponentGovernanceDetection: true + DOTNET_CLI_TELEMETRY_OPTOUT: true + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true resources: containers: - container: ubuntu1404 image: lightgbm/vsts-agent:ubuntu-14.04 - container: ubuntu-latest - image: 'ubuntu:latest' + image: 'ubuntu:20.04' options: "--name ci-container -v /usr/bin/docker:/tmp/docker:ro" - container: rbase - image: rocker/r-base + image: wch1/r-debug jobs: ########################################### - job: Linux @@ -35,17 +40,19 @@ jobs: matrix: regular: TASK: regular + PYTHON_VERSION: '3.9' sdist: TASK: sdist - PYTHON_VERSION: 3.7 + PYTHON_VERSION: '3.7' bdist: TASK: bdist + PYTHON_VERSION: '3.8' inference: TASK: if-else mpi_source: TASK: mpi METHOD: source - PYTHON_VERSION: 3.8 + PYTHON_VERSION: '3.8' gpu_source: TASK: gpu METHOD: source @@ -56,12 +63,10 @@ jobs: echo "##vso[task.setvariable variable=BUILD_DIRECTORY]$BUILD_SOURCESDIRECTORY" echo "##vso[task.setvariable variable=LGB_VER]$(head -n 1 VERSION.txt)" echo "##vso[task.prependpath]$CONDA/bin" - AMDAPPSDK_PATH=$BUILD_SOURCESDIRECTORY/AMDAPPSDK - echo "##vso[task.setvariable variable=AMDAPPSDK_PATH]$AMDAPPSDK_PATH" - LD_LIBRARY_PATH=$AMDAPPSDK_PATH/lib/x86_64:$LD_LIBRARY_PATH - echo "##vso[task.setvariable variable=LD_LIBRARY_PATH]$LD_LIBRARY_PATH" - echo "##vso[task.setvariable variable=OPENCL_VENDOR_PATH]$AMDAPPSDK_PATH/etc/OpenCL/vendors" displayName: 'Set variables' + - script: | + echo '$(Build.SourceVersion)' > '$(Build.ArtifactStagingDirectory)/commit.txt' + displayName: 'Add commit hash to artifacts archive' - bash: $(Build.SourcesDirectory)/.ci/setup.sh displayName: Setup - bash: $(Build.SourcesDirectory)/.ci/test.sh @@ -87,12 +92,11 @@ jobs: matrix: regular: TASK: regular - PYTHON_VERSION: 3.6 sdist: TASK: sdist bdist: TASK: bdist - PYTHON_VERSION: 3.8 + PYTHON_VERSION: '3.8' inference: TASK: if-else mpi_source: @@ -101,22 +105,23 @@ jobs: mpi_pip: TASK: mpi METHOD: pip - PYTHON_VERSION: 3.8 + PYTHON_VERSION: '3.9' mpi_wheel: TASK: mpi METHOD: wheel - PYTHON_VERSION: 3.7 + PYTHON_VERSION: '3.7' gpu_source: TASK: gpu METHOD: source + PYTHON_VERSION: '3.9' gpu_pip: TASK: gpu METHOD: pip - PYTHON_VERSION: 3.6 + PYTHON_VERSION: '3.8' gpu_wheel: TASK: gpu METHOD: wheel - PYTHON_VERSION: 3.7 + PYTHON_VERSION: '3.7' cpp_tests: TASK: cpp-tests METHOD: with-sanitizers @@ -124,14 +129,9 @@ jobs: - script: | echo "##vso[task.setvariable variable=BUILD_DIRECTORY]$BUILD_SOURCESDIRECTORY" echo "##vso[task.setvariable variable=LGB_VER]$(head -n 1 VERSION.txt)" - CONDA=$HOME/miniconda + CONDA=$HOME/miniforge echo "##vso[task.setvariable variable=CONDA]$CONDA" echo "##vso[task.prependpath]$CONDA/bin" - AMDAPPSDK_PATH=$BUILD_SOURCESDIRECTORY/AMDAPPSDK - echo "##vso[task.setvariable variable=AMDAPPSDK_PATH]$AMDAPPSDK_PATH" - LD_LIBRARY_PATH=$AMDAPPSDK_PATH/lib/x86_64:$LD_LIBRARY_PATH - echo "##vso[task.setvariable variable=LD_LIBRARY_PATH]$LD_LIBRARY_PATH" - echo "##vso[task.setvariable variable=OPENCL_VENDOR_PATH]$AMDAPPSDK_PATH/etc/OpenCL/vendors" displayName: 'Set variables' # https://github.com/microsoft/azure-pipelines-agent/issues/2043#issuecomment-687983301 - script: | @@ -185,7 +185,7 @@ jobs: BUILD_ARTIFACTSTAGINGDIRECTORY=$BUILD_ARTIFACTSTAGINGDIRECTORY EOF cat > docker-script.sh < /dev/null 2>&1 + rm -f "${TARBALL_NAME}" + echo "done untarring ${TARBALL_NAME}" + + # Object files are left behind from compiling the library to generate vignettes. + # Approaches like using tar --exclude=*.so to exclude them are not portable + # (for example, don't work with some versions of tar on Windows). + # + # Removing them manually here removes the need to use tar --exclude. + # + # For background, see https://github.com/microsoft/LightGBM/pull/3946#pullrequestreview-799415812. + rm -f ./lightgbm/src/*.o + rm -f ./lightgbm/src/boosting/*.o + rm -f ./lightgbm/src/io/*.o + rm -f ./lightgbm/src/metric/*.o + rm -f ./lightgbm/src/network/*.o + rm -f ./lightgbm/src/objective/*.o + rm -f ./lightgbm/src/treelearner/*.o + + echo "re-tarring ${TARBALL_NAME}" + tar \ + -cz \ + -f "${TARBALL_NAME}" \ + lightgbm \ + > /dev/null 2>&1 + mv "${TARBALL_NAME}" ../ + cd .. + echo "Done creating ${TARBALL_NAME}" + + rm -rf ./_tmp +else + "${LGB_R_EXECUTABLE}" CMD build \ + --keep-empty-dirs \ + --no-build-vignettes \ + lightgbm_r +fi echo "Done building R package" diff --git a/build_r.R b/build_r.R index aa16c6fcdc6c..64ca29989db9 100644 --- a/build_r.R +++ b/build_r.R @@ -21,9 +21,12 @@ TEMP_SOURCE_DIR <- file.path(TEMP_R_DIR, "src") out_list <- list( "flags" = character(0L) , "keyword_args" = character(0L) + , "make_args" = character(0L) ) for (arg in args) { - if (any(grepl("=", arg))) { + if (any(grepl("^\\-j[0-9]+", arg))) { # nolint: non_portable_path + out_list[["make_args"]] <- arg + } else if (any(grepl("=", arg))) { split_arg <- strsplit(arg, "=")[[1L]] arg_name <- split_arg[[1L]] arg_value <- split_arg[[2L]] @@ -36,6 +39,7 @@ TEMP_SOURCE_DIR <- file.path(TEMP_R_DIR, "src") } parsed_args <- .parse_args(args) +SKIP_VIGNETTES <- "--no-build-vignettes" %in% parsed_args[["flags"]] USING_GPU <- "--use-gpu" %in% parsed_args[["flags"]] USING_MINGW <- "--use-mingw" %in% parsed_args[["flags"]] USING_MSYS2 <- "--use-msys2" %in% parsed_args[["flags"]] @@ -51,7 +55,8 @@ ARGS_TO_DEFINES <- c( ) recognized_args <- c( - "--skip-install" + "--no-build-vignettes" + , "--skip-install" , "--use-gpu" , "--use-mingw" , "--use-msys2" @@ -65,7 +70,7 @@ unrecognized_args <- setdiff(given_args, recognized_args) if (length(unrecognized_args) > 0L) { msg <- paste0( "Unrecognized arguments: " - , paste0(unrecognized_args, collapse = ", ") + , toString(unrecognized_args) ) stop(msg) } @@ -109,6 +114,20 @@ if (length(keyword_args) > 0L) { ) } +# if provided, set '-j' in 'make' commands in install.libs.R +if (length(parsed_args[["make_args"]]) > 0L) { + install_libs_content <- gsub( + pattern = "make_args_from_build_script <- character(0L)" + , replacement = paste0( + "make_args_from_build_script <- c(\"" + , paste0(parsed_args[["make_args"]], collapse = "\", \"") + , "\")" + ) + , x = install_libs_content + , fixed = TRUE + ) +} + # R returns FALSE (not a non-zero exit code) if a file copy operation # breaks. Let's fix that .handle_result <- function(res) { @@ -127,7 +146,7 @@ if (length(keyword_args) > 0L) { on_windows <- .Platform$OS.type == "windows" has_processx <- suppressMessages({ suppressWarnings({ - require("processx") # nolint + require("processx") # nolint: undesirable_function }) }) if (has_processx && on_windows) { @@ -385,7 +404,7 @@ dynlib_line <- grep( ) c_api_contents <- readLines(file.path(TEMP_SOURCE_DIR, "src", "lightgbm_R.h")) -c_api_contents <- c_api_contents[grepl("^LIGHTGBM_C_EXPORT", c_api_contents)] +c_api_contents <- c_api_contents[startsWith(c_api_contents, "LIGHTGBM_C_EXPORT")] c_api_contents <- gsub( pattern = "LIGHTGBM_C_EXPORT SEXP " , replacement = "" @@ -398,7 +417,7 @@ c_api_symbols <- gsub( ) dynlib_statement <- paste0( "useDynLib(lib_lightgbm, " - , paste0(c_api_symbols, collapse = ", ") + , toString(c_api_symbols) , ")" ) namespace_contents[dynlib_line] <- dynlib_statement @@ -407,7 +426,11 @@ writeLines(namespace_contents, NAMESPACE_FILE) # NOTE: --keep-empty-dirs is necessary to keep the deep paths expected # by CMake while also meeting the CRAN req to create object files # on demand -.run_shell_command("R", c("CMD", "build", TEMP_R_DIR, "--keep-empty-dirs")) +r_build_args <- c("CMD", "build", TEMP_R_DIR, "--keep-empty-dirs") +if (isTRUE(SKIP_VIGNETTES)) { + r_build_args <- c(r_build_args, "--no-build-vignettes") +} +.run_shell_command("R", r_build_args) # Install the package version <- gsub(