cmake: use object library to avoid duplicate compilation. (#4489)

* cmake: use object library to avoid duplicate compilation.

* debug: verbose make log for building r package.

* Include /usr/local/include for AppleClang.

* Revert "debug: verbose make log for building r package."

* update cmake comment and fix indentation

* debug cmake USE_DEBUG.

* Revert "debug cmake USt E_DEBUG."

* Add -fPIC for building shared library.

* Always set -fPIC for non MSVC compiler.

* debug: print exception in setup.py

* debug: print cmake output for vs build.

* debug: set opencl related target_xxx on lightgbm_objs.

* Define compile definitions, link libraries on lightgbm_objs.

* Add PUBLIC to target_link_libraries to expose library dependency.

* Use target_link_libraries on object library.

This should propagate usage requirements.

* Fix CUDA linking.

Linking object library (lightgbm_objs) to object library (histograms)
does not linked objects.

* Use PUBLIC link for lightgbm lib.

* Set cuda related properties on final targets.

* Remove debugging changes.

Revert "debug: print exception in setup.py"
Revert "debug: print cmake output for vs build."
etc.

* Remove -D_lightgbm_EXPORTS.

* Revert to add -fPIC only for NOT USE_DEBUG.

* Enable PIC for shared lib.

* Fix enable PIC.

* Use -fPIC for shared lib.

* testlightgbm depends only on object files.

* tweak build for R.

* Try to remove OpenMP related include dir settings.

* link with openmp for capi object library.

* Use PUBLIC for _lightgbm target_link_libraries.

* Try removing exports definition.

* fix typo

Co-authored-by: Nikita Titov <nekit94-08@mail.ru>

* fix typo

Co-authored-by: Nikita Titov <nekit94-08@mail.ru>

* Add some comments for cmake code.

* Try to fix cmake warnings CUDA.

* revert accidentally commited R-package path change.

* Try to fix cmake CUDA warnings, set for _lightgbm target.

* Try to fix cmake CUDA warnings, set for lightgbm target.

* empty commit to trigger ci

Co-authored-by: Nikita Titov <nekit94-08@mail.ru>
This commit is contained in:
Chen Yufei 2021-11-10 09:45:21 +08:00 коммит произвёл GitHub
Родитель 7152c49a76
Коммит 15a63696c0
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
1 изменённых файлов: 59 добавлений и 43 удалений

Просмотреть файл

@ -317,8 +317,11 @@ if(MSVC)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /O2 /Ob2 /Oi /Ot /Oy") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /O2 /Ob2 /Oi /Ot /Oy")
endif() endif()
else() else()
if(NOT BUILD_STATIC_LIB)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
endif()
if(NOT USE_DEBUG) if(NOT USE_DEBUG)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -funroll-loops") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -funroll-loops")
endif() endif()
endif(MSVC) endif(MSVC)
@ -353,20 +356,28 @@ if(USE_CUDA)
endif(USE_CUDA) endif(USE_CUDA)
) )
add_executable(lightgbm src/main.cpp src/application/application.cpp ${SOURCES}) add_library(lightgbm_objs OBJECT ${SOURCES})
list(APPEND SOURCES "src/c_api.cpp")
add_executable(lightgbm src/main.cpp src/application/application.cpp)
target_link_libraries(lightgbm PRIVATE lightgbm_objs)
set(API_SOURCES "src/c_api.cpp")
# Only build the R part of the library if building for # Only build the R part of the library if building for
# use with the R package # use with the R package
if(__BUILD_FOR_R) if(__BUILD_FOR_R)
list(APPEND SOURCES "src/lightgbm_R.cpp") list(APPEND API_SOURCES "src/lightgbm_R.cpp")
endif(__BUILD_FOR_R) endif(__BUILD_FOR_R)
add_library(lightgbm_capi_objs OBJECT ${API_SOURCES})
if(BUILD_STATIC_LIB) if(BUILD_STATIC_LIB)
add_library(_lightgbm STATIC ${SOURCES}) add_library(_lightgbm STATIC)
else() else()
add_library(_lightgbm SHARED ${SOURCES}) add_library(_lightgbm SHARED)
endif(BUILD_STATIC_LIB) endif(BUILD_STATIC_LIB)
# LightGBM headers include openmp, cuda, R etc. headers,
# thus PUBLIC is required for building _lightgbm_swig target.
target_link_libraries(_lightgbm PUBLIC lightgbm_capi_objs lightgbm_objs)
if(MSVC) if(MSVC)
set_target_properties(_lightgbm PROPERTIES OUTPUT_NAME "lib_lightgbm") set_target_properties(_lightgbm PROPERTIES OUTPUT_NAME "lib_lightgbm")
@ -410,70 +421,75 @@ if(USE_SWIG)
endif(USE_SWIG) endif(USE_SWIG)
if(USE_MPI) if(USE_MPI)
TARGET_LINK_LIBRARIES(lightgbm ${MPI_CXX_LIBRARIES}) target_link_libraries(lightgbm_objs PUBLIC ${MPI_CXX_LIBRARIES})
TARGET_LINK_LIBRARIES(_lightgbm ${MPI_CXX_LIBRARIES})
endif(USE_MPI) endif(USE_MPI)
if(USE_OPENMP) if(USE_OPENMP)
if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
TARGET_LINK_LIBRARIES(lightgbm OpenMP::OpenMP_CXX) target_link_libraries(lightgbm_objs PUBLIC OpenMP::OpenMP_CXX)
TARGET_LINK_LIBRARIES(_lightgbm OpenMP::OpenMP_CXX) # c_api headers also includes OpenMP headers, thus compiling
# lightgbm_capi_objs needs include directory for OpenMP.
# Specifying OpenMP in target_link_libraries will get include directory
# requirements for compilation.
# This uses CMake's Transitive Usage Requirements. Refer to CMake doc:
# https://cmake.org/cmake/help/v3.16/manual/cmake-buildsystem.7.html#transitive-usage-requirements
target_link_libraries(lightgbm_capi_objs PUBLIC OpenMP::OpenMP_CXX)
endif() endif()
endif(USE_OPENMP) endif(USE_OPENMP)
if(USE_GPU) if(USE_GPU)
TARGET_LINK_LIBRARIES(lightgbm ${OpenCL_LIBRARY} ${Boost_LIBRARIES}) target_link_libraries(lightgbm_objs PUBLIC ${OpenCL_LIBRARY} ${Boost_LIBRARIES})
TARGET_LINK_LIBRARIES(_lightgbm ${OpenCL_LIBRARY} ${Boost_LIBRARIES})
endif(USE_GPU) endif(USE_GPU)
if(__INTEGRATE_OPENCL) if(__INTEGRATE_OPENCL)
# targets OpenCL and Boost are added in IntegratedOpenCL.cmake # targets OpenCL and Boost are added in IntegratedOpenCL.cmake
add_dependencies(lightgbm OpenCL Boost) add_dependencies(lightgbm_objs OpenCL Boost)
add_dependencies(_lightgbm OpenCL Boost)
# variables INTEGRATED_OPENCL_* are set in IntegratedOpenCL.cmake # variables INTEGRATED_OPENCL_* are set in IntegratedOpenCL.cmake
target_include_directories(lightgbm PRIVATE ${INTEGRATED_OPENCL_INCLUDES}) target_include_directories(lightgbm_objs PRIVATE ${INTEGRATED_OPENCL_INCLUDES})
target_include_directories(_lightgbm PRIVATE ${INTEGRATED_OPENCL_INCLUDES}) target_compile_definitions(lightgbm_objs PRIVATE ${INTEGRATED_OPENCL_DEFINITIONS})
target_compile_definitions(lightgbm PRIVATE ${INTEGRATED_OPENCL_DEFINITIONS}) target_link_libraries(lightgbm_objs PUBLIC ${INTEGRATED_OPENCL_LIBRARIES})
target_compile_definitions(_lightgbm PRIVATE ${INTEGRATED_OPENCL_DEFINITIONS})
target_link_libraries(lightgbm PRIVATE ${INTEGRATED_OPENCL_LIBRARIES})
target_link_libraries(_lightgbm PRIVATE ${INTEGRATED_OPENCL_LIBRARIES})
endif() endif()
if(USE_CUDA) if(USE_CUDA)
set_target_properties(lightgbm PROPERTIES CUDA_RESOLVE_DEVICE_SYMBOLS ON) # Disable cmake warning about policy CMP0104. Refer to issue #3754 and PR #4268.
set_target_properties(lightgbm PROPERTIES CUDA_ARCHITECTURES OFF) # Custom target properties does not propagate, thus we need to specify for
TARGET_LINK_LIBRARIES( # each target that contains or depends on cuda source.
lightgbm set_target_properties(lightgbm_objs PROPERTIES CUDA_ARCHITECTURES OFF)
${histograms}
)
set_target_properties(_lightgbm PROPERTIES CUDA_RESOLVE_DEVICE_SYMBOLS ON)
set_target_properties(_lightgbm PROPERTIES CUDA_ARCHITECTURES OFF) set_target_properties(_lightgbm PROPERTIES CUDA_ARCHITECTURES OFF)
TARGET_LINK_LIBRARIES( set_target_properties(lightgbm PROPERTIES CUDA_ARCHITECTURES OFF)
_lightgbm
${histograms} # Device linking is not supported for object libraries.
) # Thus we have to specify them on final targets.
set_target_properties(lightgbm PROPERTIES CUDA_RESOLVE_DEVICE_SYMBOLS ON)
set_target_properties(_lightgbm PROPERTIES CUDA_RESOLVE_DEVICE_SYMBOLS ON)
# histograms are list of object libraries. Linking object library to other
# object libraries only gets usage requirements, the linked objects won't be
# used. Thus we have to call target_link_libraries on final targets here.
target_link_libraries(lightgbm PRIVATE ${histograms})
target_link_libraries(_lightgbm PRIVATE ${histograms})
endif(USE_CUDA) endif(USE_CUDA)
if(USE_HDFS) if(USE_HDFS)
TARGET_LINK_LIBRARIES(lightgbm ${HDFS_CXX_LIBRARIES}) target_link_libraries(lightgbm_objs PUBLIC ${HDFS_CXX_LIBRARIES})
TARGET_LINK_LIBRARIES(_lightgbm ${HDFS_CXX_LIBRARIES})
endif(USE_HDFS) endif(USE_HDFS)
if(WIN32) if(WIN32)
if(MINGW OR CYGWIN) if(MINGW OR CYGWIN)
TARGET_LINK_LIBRARIES(lightgbm Ws2_32) target_link_libraries(lightgbm_objs PUBLIC Ws2_32 IPHLPAPI)
TARGET_LINK_LIBRARIES(_lightgbm Ws2_32)
TARGET_LINK_LIBRARIES(lightgbm IPHLPAPI)
TARGET_LINK_LIBRARIES(_lightgbm IPHLPAPI)
endif(MINGW OR CYGWIN) endif(MINGW OR CYGWIN)
endif(WIN32) endif(WIN32)
if(__BUILD_FOR_R) if(__BUILD_FOR_R)
# utils/log.h and capi uses R headers, thus both object libraries need to link
# with R lib.
if(MSVC) if(MSVC)
TARGET_LINK_LIBRARIES(_lightgbm ${LIBR_MSVC_CORE_LIBRARY}) set(R_LIB ${LIBR_MSVC_CORE_LIBRARY})
else() else()
TARGET_LINK_LIBRARIES(_lightgbm ${LIBR_CORE_LIBRARY}) set(R_LIB ${LIBR_CORE_LIBRARY})
endif(MSVC) endif(MSVC)
target_link_libraries(lightgbm_objs PUBLIC ${R_LIB})
target_link_libraries(lightgbm_capi_objs PUBLIC ${R_LIB})
endif(__BUILD_FOR_R) endif(__BUILD_FOR_R)
#-- Google C++ tests #-- Google C++ tests
@ -505,8 +521,8 @@ if(BUILD_CPP_TEST)
string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}") string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}")
endforeach() endforeach()
endif(MSVC) endif(MSVC)
add_executable(testlightgbm ${CPP_TEST_SOURCES} ${SOURCES}) add_executable(testlightgbm ${CPP_TEST_SOURCES})
target_link_libraries(testlightgbm PRIVATE GTest::GTest) target_link_libraries(testlightgbm PRIVATE lightgbm_objs GTest::GTest)
endif() endif()
install(TARGETS lightgbm _lightgbm install(TARGETS lightgbm _lightgbm