diff --git a/recipes/lightgbm/all/CMakeLists.txt b/recipes/lightgbm/all/CMakeLists.txt index 61f3d3b039e2b..d250cd86d5991 100644 --- a/recipes/lightgbm/all/CMakeLists.txt +++ b/recipes/lightgbm/all/CMakeLists.txt @@ -1,7 +1,20 @@ -cmake_minimum_required(VERSION 3.1) -project(cmake_wrapper) +cmake_minimum_required(VERSION 3.15) +project(cmake_wrapper LANGUAGES CXX) -include(conanbuildinfo.cmake) -conan_basic_setup(KEEP_RPATHS) +find_package(Eigen3 REQUIRED CONFIG) +find_package(fast_double_parser REQUIRED CONFIG) +find_package(fmt REQUIRED CONFIG) -add_subdirectory("source_subfolder") +add_subdirectory(src) + +if(_MAJOR_VERSION GREATER_EQUAL 4) + set(TARGETS lightgbm_objs lightgbm_capi_objs) + set(VISIBILITY PRIVATE) +else() + set(TARGETS lightgbm _lightgbm) + set(VISIBILITY "") +endif() + +foreach(target ${TARGETS}) + target_link_libraries(${target} ${VISIBILITY} Eigen3::Eigen fast_double_parser::fast_double_parser fmt::fmt) +endforeach() diff --git a/recipes/lightgbm/all/conandata.yml b/recipes/lightgbm/all/conandata.yml index 2fac2e54523aa..5c29f9403b5ce 100644 --- a/recipes/lightgbm/all/conandata.yml +++ b/recipes/lightgbm/all/conandata.yml @@ -1,18 +1,23 @@ sources: - "3.3.2": - url: "https://github.com/microsoft/LightGBM/archive/refs/tags/v3.3.2.tar.gz" - sha256: "d7c0f842e94165578d5a0c046ca942838d1574149f98c84400ce511239d17b9f" + "4.1.0": + url: "https://github.com/microsoft/LightGBM/archive/refs/tags/v4.1.0.tar.gz" + sha256: "eb896dc21c7afec95d10327777f6e77163b5bcd35f6ce5d152e6feefbe3328a5" "3.3.5": url: "https://github.com/microsoft/LightGBM/archive/refs/tags/v3.3.5.tar.gz" sha256: "16fb9e299ced37be5ac69dd510e7323337e623019c9c578628c43b285f764be7" -patches: "3.3.2": - - patch_file: "patches/0001-fix-includes.patch" - base_path: "source_subfolder" - - patch_file: "patches/0002-fix-openmp-clang.patch" - base_path: "source_subfolder" + url: "https://github.com/microsoft/LightGBM/archive/refs/tags/v3.3.2.tar.gz" + sha256: "d7c0f842e94165578d5a0c046ca942838d1574149f98c84400ce511239d17b9f" +patches: + "4.1.0": + - patch_file: "patches/4.1.0-0001-fix-openmp-clang.patch" + patch_type: "portability" + patch_description: "Fix OpenMP support for Clang" "3.3.5": - - patch_file: "patches/0001-fix-includes.patch" - base_path: "source_subfolder" - - patch_file: "patches/0003-fix-openmp-clang.patch" - base_path: "source_subfolder" + - patch_file: "patches/3.3.5-0001-fix-openmp-clang.patch" + patch_type: "portability" + patch_description: "Fix OpenMP support for Clang" + "3.3.2": + - patch_file: "patches/3.3.2-0001-fix-openmp-clang.patch" + patch_type: "portability" + patch_description: "Fix OpenMP support for Clang" diff --git a/recipes/lightgbm/all/conanfile.py b/recipes/lightgbm/all/conanfile.py index d00e21c352364..cae89a9218102 100644 --- a/recipes/lightgbm/all/conanfile.py +++ b/recipes/lightgbm/all/conanfile.py @@ -1,82 +1,107 @@ -from conans import CMake, ConanFile, tools +import os + +from conan import ConanFile, conan_version +from conan.tools.apple import is_apple_os +from conan.tools.build import check_min_cppstd +from conan.tools.cmake import CMake, CMakeDeps, CMakeToolchain, cmake_layout +from conan.tools.files import copy, get, replace_in_file, export_conandata_patches, apply_conandata_patches from conan.tools.microsoft import is_msvc -import functools +from conan.tools.scm import Version -required_conan_version = ">=1.33.0" +required_conan_version = ">=1.53.0" class LightGBMConan(ConanFile): name = "lightgbm" - description = "A fast, distributed, high performance gradient boosting (GBT, GBDT, GBRT, GBM or MART) framework based on decision tree algorithms, used for ranking, classification and many other machine learning tasks." - topics = ("machine-learning", "boosting") + description = ( + "A fast, distributed, high performance gradient boosting " + "(GBT, GBDT, GBRT, GBM or MART) framework based on decision tree algorithms, " + "used for ranking, classification and many other machine learning tasks." + ) + license = "MIT" url = "https://github.com/conan-io/conan-center-index" homepage = "https://github.com/microsoft/LightGBM" - license = "MIT" + topics = ("machine-learning", "boosting") + package_type = "library" settings = "os", "arch", "compiler", "build_type" - exports_sources = ["CMakeLists.txt", "patches/**"] - generators = "cmake", "cmake_find_package" options = { "shared": [True, False], "fPIC": [True, False], - "with_openmp": [True, False] + "with_openmp": [True, False], } default_options = { "shared": False, "fPIC": True, - "with_openmp": True + "with_openmp": True, } - @property - def _source_subfolder(self): - return "source_subfolder" + def export_sources(self): + copy(self, "CMakeLists.txt", self.recipe_folder, self.export_sources_folder) + export_conandata_patches(self) def config_options(self): if self.settings.os == "Windows": del self.options.fPIC + if conan_version.major == 1 and self.settings.compiler == "apple-clang": + # https://github.com/conan-io/conan-center-index/pull/18759#issuecomment-1817470331 + del self.options.with_openmp def configure(self): if self.options.shared: - del self.options.fPIC + self.options.rm_safe("fPIC") + + def layout(self): + cmake_layout(self, src_folder="src") def requirements(self): self.requires("eigen/3.4.0") - self.requires("fast_double_parser/0.6.0") - self.requires("fmt/9.0.0") - if self.options.with_openmp and self.settings.compiler in ("clang", "apple-clang"): - self.requires("llvm-openmp/11.1.0") + self.requires("fast_double_parser/0.7.0", transitive_headers=True, transitive_libs=True) + self.requires("fmt/10.1.1", transitive_headers=True, transitive_libs=True) + if self.options.get_safe("with_openmp") and self.settings.compiler in ["clang", "apple-clang"]: + self.requires("llvm-openmp/17.0.4", transitive_headers=True, transitive_libs=True) def validate(self): if self.settings.compiler.get_safe("cppstd"): - tools.check_min_cppstd(self, 11) + check_min_cppstd(self, 11) def source(self): - tools.get(**self.conan_data["sources"][self.version], - destination=self._source_subfolder, strip_root=True) + get(self, **self.conan_data["sources"][self.version], strip_root=True) + + def generate(self): + tc = CMakeToolchain(self) + tc.cache_variables["BUILD_STATIC_LIB"] = not self.options.shared + tc.cache_variables["USE_DEBUG"] = self.settings.build_type in ["Debug", "RelWithDebInfo"] + tc.cache_variables["USE_OPENMP"] = self.options.get_safe("with_openmp", False) + tc.cache_variables["BUILD_CLI"] = False + if is_apple_os(self): + tc.cache_variables["APPLE_OUTPUT_DYLIB"] = True + tc.variables["_MAJOR_VERSION"] = Version(self.version).major + tc.generate() + tc = CMakeDeps(self) + tc.generate() def _patch_sources(self): - for patch in self.conan_data.get("patches", {}).get(self.version, []): - tools.patch(**patch) - - @functools.lru_cache(1) - def _configure_cmake(self): - cmake = CMake(self) - cmake.definitions["BUILD_STATIC_LIB"] = not self.options.shared - cmake.definitions["USE_DEBUG"] = self.settings.build_type == "Debug" - cmake.definitions["USE_OPENMP"] = self.options.with_openmp - if self.settings.os == "Macos": - cmake.definitions["APPLE_OUTPUT_DYLIB"] = True - cmake.configure() - return cmake + apply_conandata_patches(self) + # Fix vendored dependency includes + common_h = os.path.join(self.source_folder, "include", "LightGBM", "utils", "common.h") + for lib in ["fmt", "fast_double_parser"]: + replace_in_file(self, common_h, f"../../../external_libs/{lib}/include/", "") + # Unvendor Eigen3 + replace_in_file(self, os.path.join(self.source_folder, "CMakeLists.txt"), + "include_directories(${EIGEN_DIR})", "") def build(self): self._patch_sources() - cmake = self._configure_cmake() + cmake = CMake(self) + cmake.configure(build_script_folder=self.source_path.parent) cmake.build() def package(self): - self.copy("LICENSE", dst="licenses", src=self._source_subfolder) - cmake = self._configure_cmake() + copy(self, "LICENSE", + dst=os.path.join(self.package_folder, "licenses"), + src=self.source_folder) + cmake = CMake(self) cmake.install() def package_info(self): @@ -90,16 +115,19 @@ def package_info(self): self.cpp_info.libs = ["lib_lightgbm"] if is_msvc(self) else ["_lightgbm"] if self.settings.os == "Windows": self.cpp_info.system_libs.extend(["ws2_32", "iphlpapi"]) - elif self.settings.os == "Linux": + elif self.settings.os in ["Linux", "FreeBSD"]: self.cpp_info.system_libs.append("pthread") - if not self.options.shared and self.options.with_openmp: + + # OpenMP preprocessor directives are used in a number of public headers, such as: + # https://github.com/microsoft/LightGBM/blob/master/include/LightGBM/tree.h#L188 + if self.options.get_safe("with_openmp"): + openmp_flags = [] if is_msvc(self): openmp_flags = ["-openmp"] elif self.settings.compiler == "gcc": openmp_flags = ["-fopenmp"] - elif self.settings.compiler in ("clang", "apple-clang"): + elif self.settings.compiler in ["clang", "apple-clang"]: openmp_flags = ["-Xpreprocessor", "-fopenmp"] - else: - openmp_flags = [] + self.cpp_info.cxxflags.extend(openmp_flags) self.cpp_info.exelinkflags.extend(openmp_flags) self.cpp_info.sharedlinkflags.extend(openmp_flags) diff --git a/recipes/lightgbm/all/patches/0001-fix-includes.patch b/recipes/lightgbm/all/patches/0001-fix-includes.patch deleted file mode 100644 index 13fa0fe43a998..0000000000000 --- a/recipes/lightgbm/all/patches/0001-fix-includes.patch +++ /dev/null @@ -1,16 +0,0 @@ -diff --git a/include/LightGBM/utils/common.h b/include/LightGBM/utils/common.h -index af981062..097f20d4 100644 ---- a/include/LightGBM/utils/common.h -+++ b/include/LightGBM/utils/common.h -@@ -33,9 +33,9 @@ - - #if (!((defined(sun) || defined(__sun)) && (defined(__SVR4) || defined(__svr4__)))) - #define FMT_HEADER_ONLY --#include "../../../external_libs/fmt/include/fmt/format.h" -+#include - #endif --#include "../../../external_libs/fast_double_parser/include/fast_double_parser.h" -+#include - - #ifdef _MSC_VER - #include diff --git a/recipes/lightgbm/all/patches/0002-fix-openmp-clang.patch b/recipes/lightgbm/all/patches/3.3.2-0001-fix-openmp-clang.patch similarity index 100% rename from recipes/lightgbm/all/patches/0002-fix-openmp-clang.patch rename to recipes/lightgbm/all/patches/3.3.2-0001-fix-openmp-clang.patch diff --git a/recipes/lightgbm/all/patches/0003-fix-openmp-clang.patch b/recipes/lightgbm/all/patches/3.3.5-0001-fix-openmp-clang.patch similarity index 100% rename from recipes/lightgbm/all/patches/0003-fix-openmp-clang.patch rename to recipes/lightgbm/all/patches/3.3.5-0001-fix-openmp-clang.patch diff --git a/recipes/lightgbm/all/patches/4.1.0-0001-fix-openmp-clang.patch b/recipes/lightgbm/all/patches/4.1.0-0001-fix-openmp-clang.patch new file mode 100644 index 0000000000000..4de5b0a2d1c8e --- /dev/null +++ b/recipes/lightgbm/all/patches/4.1.0-0001-fix-openmp-clang.patch @@ -0,0 +1,11 @@ +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -526,7 +526,7 @@ + endif() + + if(USE_OPENMP) +- if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") ++ if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang|AppleClang") + target_link_libraries(lightgbm_objs PUBLIC OpenMP::OpenMP_CXX) + # c_api headers also includes OpenMP headers, thus compiling + # lightgbm_capi_objs needs include directory for OpenMP. diff --git a/recipes/lightgbm/all/test_package/CMakeLists.txt b/recipes/lightgbm/all/test_package/CMakeLists.txt index 12b8a397ff5d3..1fc3dbaef1eaa 100644 --- a/recipes/lightgbm/all/test_package/CMakeLists.txt +++ b/recipes/lightgbm/all/test_package/CMakeLists.txt @@ -1,10 +1,7 @@ -cmake_minimum_required(VERSION 3.1) -project(test_package) +cmake_minimum_required(VERSION 3.15) +project(test_package LANGUAGES CXX) -include("${CMAKE_BINARY_DIR}/conanbuildinfo.cmake") -conan_basic_setup(TARGETS) - -find_package(LightGBM CONFIG REQUIRED) +find_package(LightGBM REQUIRED CONFIG) add_executable(${PROJECT_NAME} test_package.cpp) target_link_libraries(${PROJECT_NAME} LightGBM::LightGBM) diff --git a/recipes/lightgbm/all/test_package/conanfile.py b/recipes/lightgbm/all/test_package/conanfile.py index 746d011e4501a..ef5d7042163ec 100644 --- a/recipes/lightgbm/all/test_package/conanfile.py +++ b/recipes/lightgbm/all/test_package/conanfile.py @@ -1,10 +1,19 @@ -from conans import ConanFile, CMake, tools +from conan import ConanFile +from conan.tools.build import can_run +from conan.tools.cmake import cmake_layout, CMake import os -class LightGBMTestConan(ConanFile): - settings = "os", "compiler", "build_type", "arch" - generators = "cmake", "cmake_find_package_multi" +class TestPackageConan(ConanFile): + settings = "os", "arch", "compiler", "build_type" + generators = "CMakeDeps", "CMakeToolchain", "VirtualRunEnv" + test_type = "explicit" + + def requirements(self): + self.requires(self.tested_reference_str) + + def layout(self): + cmake_layout(self) def build(self): cmake = CMake(self) @@ -12,6 +21,6 @@ def build(self): cmake.build() def test(self): - if not tools.cross_building(self): - bin_path = os.path.join("bin", "test_package") - self.run(bin_path, run_environment=True) + if can_run(self): + bin_path = os.path.join(self.cpp.build.bindir, "test_package") + self.run(bin_path, env="conanrun") diff --git a/recipes/lightgbm/all/test_v1_package/CMakeLists.txt b/recipes/lightgbm/all/test_v1_package/CMakeLists.txt new file mode 100644 index 0000000000000..91630d79f4abb --- /dev/null +++ b/recipes/lightgbm/all/test_v1_package/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.15) +project(test_package) + +include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) +conan_basic_setup(TARGETS) + +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../test_package/ + ${CMAKE_CURRENT_BINARY_DIR}/test_package/) diff --git a/recipes/lightgbm/all/test_v1_package/conanfile.py b/recipes/lightgbm/all/test_v1_package/conanfile.py new file mode 100644 index 0000000000000..746d011e4501a --- /dev/null +++ b/recipes/lightgbm/all/test_v1_package/conanfile.py @@ -0,0 +1,17 @@ +from conans import ConanFile, CMake, tools +import os + + +class LightGBMTestConan(ConanFile): + settings = "os", "compiler", "build_type", "arch" + generators = "cmake", "cmake_find_package_multi" + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def test(self): + if not tools.cross_building(self): + bin_path = os.path.join("bin", "test_package") + self.run(bin_path, run_environment=True) diff --git a/recipes/lightgbm/config.yml b/recipes/lightgbm/config.yml index 185a3ba9f96e0..eba2ef0bbf4fd 100644 --- a/recipes/lightgbm/config.yml +++ b/recipes/lightgbm/config.yml @@ -1,5 +1,7 @@ versions: - "3.3.2": + "4.1.0": folder: all "3.3.5": folder: all + "3.3.2": + folder: all