CMakeLists.txt 19.6 KB
Newer Older
1
2
3
4
5
6
7
option(USE_MPI "Enable MPI-based distributed learning" OFF)
option(USE_OPENMP "Enable OpenMP" ON)
option(USE_GPU "Enable GPU-accelerated training" OFF)
option(USE_SWIG "Enable SWIG to generate Java API" OFF)
option(USE_HDFS "Enable HDFS support (EXPERIMENTAL)" OFF)
option(USE_TIMETAG "Set to ON to output time costs" OFF)
option(USE_CUDA "Enable CUDA-accelerated training (EXPERIMENTAL)" OFF)
8
option(USE_CUDA_EXP "Enable CUDA-accelerated training with more acceleration (EXPERIMENTAL)" OFF)
9
10
11
option(USE_DEBUG "Set to ON for Debug mode" OFF)
option(USE_SANITIZER "Use santizer flags" OFF)
set(
12
13
14
15
16
17
18
  ENABLED_SANITIZERS
  "address" "leak" "undefined"
  CACHE
  STRING
  "Semicolon separated list of sanitizer names, e.g., 'address;leak'. \
Supported sanitizers are address, leak, undefined and thread."
)
19
20
21
22
option(BUILD_CPP_TEST "Build C++ tests with Google Test" OFF)
option(BUILD_STATIC_LIB "Build static library" OFF)
option(__BUILD_FOR_R "Set to ON if building lib_lightgbm for use with the R package" OFF)
option(__INTEGRATE_OPENCL "Set to ON if building LightGBM with the OpenCL ICD Loader and its dependencies included" OFF)
23

24
if(APPLE)
25
  option(APPLE_OUTPUT_DYLIB "Output dylib shared library" OFF)
26
endif()
27

28
29
30
if(__INTEGRATE_OPENCL)
  cmake_minimum_required(VERSION 3.11)
elseif(USE_GPU OR APPLE)
31
  cmake_minimum_required(VERSION 3.2)
32
elseif(USE_CUDA OR USE_CUDA_EXP)
33
  cmake_minimum_required(VERSION 3.16)
34
else()
35
  cmake_minimum_required(VERSION 3.0)
36
endif()
Guolin Ke's avatar
Guolin Ke committed
37

38
project(lightgbm LANGUAGES C CXX)
Guolin Ke's avatar
Guolin Ke committed
39

40
41
42
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/modules")

#-- Sanitizer
43
if(USE_SANITIZER)
44
45
  if(MSVC)
    message(FATAL_ERROR "Sanitizers are not supported with MSVC.")
46
  endif()
47
48
  include(cmake/Sanitizer.cmake)
  enable_sanitizers("${ENABLED_SANITIZERS}")
49
endif()
50

51
52
53
54
55
56
if(__INTEGRATE_OPENCL)
  set(__INTEGRATE_OPENCL ON CACHE BOOL "" FORCE)
  set(USE_GPU OFF CACHE BOOL "" FORCE)
  message(STATUS "Building library with integrated OpenCL components")
endif()

Qiwei Ye's avatar
Qiwei Ye committed
57
58
59
60
61
62
63
64
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
  if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.8.2")
    message(FATAL_ERROR "Insufficient gcc version")
  endif()
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
  if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "3.8")
    message(FATAL_ERROR "Insufficient Clang version")
  endif()
65
66
67
68
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
  if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "8.1.0")
    message(FATAL_ERROR "Insufficient AppleClang version")
  endif()
69
  cmake_minimum_required(VERSION 3.16)
70
71
elseif(MSVC)
  if(MSVC_VERSION LESS 1900)
72
73
74
75
    message(
      FATAL_ERROR
      "The compiler ${CMAKE_CXX_COMPILER} doesn't support required C++11 features. Please use a newer MSVC."
    )
76
77
  endif()
  cmake_minimum_required(VERSION 3.8)
78
endif()
Guolin Ke's avatar
Guolin Ke committed
79

80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
if(USE_SWIG)
  find_package(SWIG REQUIRED)
  find_package(Java REQUIRED)
  find_package(JNI REQUIRED)
  include(UseJava)
  include(UseSWIG)
  set(SWIG_CXX_EXTENSION "cxx")
  set(SWIG_EXTRA_LIBRARIES "")
  set(SWIG_JAVA_EXTRA_FILE_EXTENSIONS ".java" "JNI.java")
  set(SWIG_MODULE_JAVA_LANGUAGE "JAVA")
  set(SWIG_MODULE_JAVA_SWIG_LANGUAGE_FLAG "java")
  set(CMAKE_SWIG_OUTDIR "${CMAKE_CURRENT_BINARY_DIR}/java")
  include_directories(Java_INCLUDE_DIRS)
  include_directories(JNI_INCLUDE_DIRS)
  include_directories($ENV{JAVA_HOME}/include)
95
  if(WIN32)
96
      file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/com/microsoft/ml/lightgbm/windows/x86_64")
97
      include_directories($ENV{JAVA_HOME}/include/win32)
98
  elseif(APPLE)
99
      file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/com/microsoft/ml/lightgbm/osx/x86_64")
100
      include_directories($ENV{JAVA_HOME}/include/darwin)
101
  else()
102
      file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/com/microsoft/ml/lightgbm/linux/x86_64")
103
104
      include_directories($ENV{JAVA_HOME}/include/linux)
  endif()
105
endif()
106

107
set(EIGEN_DIR "${PROJECT_SOURCE_DIR}/external_libs/eigen")
108
109
include_directories(${EIGEN_DIR})

110
# See https://gitlab.com/libeigen/eigen/-/blob/master/COPYING.README
111
add_definitions(-DEIGEN_MPL2_ONLY)
112
add_definitions(-DEIGEN_DONT_PARALLELIZE)
113

114
if(__BUILD_FOR_R)
115
116
117
118
119
    find_package(LibR REQUIRED)
    message(STATUS "LIBR_EXECUTABLE: ${LIBR_EXECUTABLE}")
    message(STATUS "LIBR_INCLUDE_DIRS: ${LIBR_INCLUDE_DIRS}")
    message(STATUS "LIBR_CORE_LIBRARY: ${LIBR_CORE_LIBRARY}")
    include_directories(${LIBR_INCLUDE_DIRS})
120
    add_definitions(-DLGB_R_BUILD)
121
endif()
122

123
if(USE_TIMETAG)
124
    add_definitions(-DTIMETAG)
125
endif()
126

Guolin Ke's avatar
Guolin Ke committed
127
if(USE_DEBUG)
128
    add_definitions(-DDEBUG)
129
endif()
Guolin Ke's avatar
Guolin Ke committed
130

Guolin Ke's avatar
Guolin Ke committed
131
if(USE_MPI)
Guolin Ke's avatar
Guolin Ke committed
132
    find_package(MPI REQUIRED)
133
    add_definitions(-DUSE_MPI)
Guolin Ke's avatar
Guolin Ke committed
134
else()
135
    add_definitions(-DUSE_SOCKET)
136
endif()
Guolin Ke's avatar
Guolin Ke committed
137

138
if(USE_CUDA OR USE_CUDA_EXP)
139
    set(CMAKE_CUDA_HOST_COMPILER "${CMAKE_CXX_COMPILER}")
140
    enable_language(CUDA)
141
    set(USE_OPENMP ON CACHE BOOL "CUDA requires OpenMP" FORCE)
142
endif()
143

144
145
if(USE_OPENMP)
    find_package(OpenMP REQUIRED)
146
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
147
endif()
Guolin Ke's avatar
Guolin Ke committed
148

149
if(USE_GPU)
150
    set(BOOST_COMPUTE_HEADER_DIR ${PROJECT_SOURCE_DIR}/external_libs/compute/include)
151
    include_directories(${BOOST_COMPUTE_HEADER_DIR})
152
153
    find_package(OpenCL REQUIRED)
    include_directories(${OpenCL_INCLUDE_DIRS})
154
    message(STATUS "OpenCL include directory: " ${OpenCL_INCLUDE_DIRS})
155
    if(WIN32)
Guolin Ke's avatar
Guolin Ke committed
156
157
        set(Boost_USE_STATIC_LIBS ON)
    endif()
158
    find_package(Boost 1.56.0 COMPONENTS filesystem system REQUIRED)
159
    if(WIN32)
160
        # disable autolinking in boost
161
        add_definitions(-DBOOST_ALL_NO_LIB)
162
    endif()
Guolin Ke's avatar
Guolin Ke committed
163
    include_directories(${Boost_INCLUDE_DIRS})
164
    add_definitions(-DUSE_GPU)
165
endif()
166

167
168
if(__INTEGRATE_OPENCL)
    if(WIN32)
169
        include(cmake/IntegratedOpenCL.cmake)
170
        add_definitions(-DUSE_GPU)
171
172
    else()
        message(FATAL_ERROR "Integrated OpenCL build is available only for Windows")
173
174
    endif()
endif()
175

176
177
178
179
180
181
if(USE_CUDA OR USE_CUDA_EXP)
    if(USE_CUDA)
      find_package(CUDA 9.0 REQUIRED)
    else()
      find_package(CUDA 10.0 REQUIRED)
    endif()
182
    include_directories(${CUDA_INCLUDE_DIRS})
183
    set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcompiler=${OpenMP_CXX_FLAGS} -Xcompiler=-fPIC -Xcompiler=-Wall")
184
185
186
187
188

    set(CUDA_ARCHS "6.0" "6.1" "6.2" "7.0")
    if(CUDA_VERSION VERSION_GREATER_EQUAL "10.0")
        list(APPEND CUDA_ARCHS "7.5")
    endif()
189
190
191
192
193
194
    if(CUDA_VERSION VERSION_GREATER_EQUAL "11.0")
        list(APPEND CUDA_ARCHS "8.0")
    endif()
    if(CUDA_VERSION VERSION_GREATER_EQUAL "11.1")
        list(APPEND CUDA_ARCHS "8.6")
    endif()
195
196
    list(POP_BACK CUDA_ARCHS CUDA_LAST_SUPPORTED_ARCH)
    list(APPEND CUDA_ARCHS "${CUDA_LAST_SUPPORTED_ARCH}+PTX")
197
    cuda_select_nvcc_arch_flags(CUDA_ARCH_FLAGS ${CUDA_ARCHS})
198
    string(REPLACE ";" " " CUDA_ARCH_FLAGS "${CUDA_ARCH_FLAGS}")
199

200
    set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} ${CUDA_ARCH_FLAGS}")
201
    if(USE_DEBUG)
202
      set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -g")
203
    else()
204
      set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -O3 -lineinfo")
205
206
207
    endif()
    message(STATUS "CMAKE_CUDA_FLAGS: ${CMAKE_CUDA_FLAGS}")

208
209
210
211
212
213
    if(USE_CUDA)
      add_definitions(-DUSE_CUDA)
    elseif(USE_CUDA_EXP)
      add_definitions(-DUSE_CUDA_EXP)
    endif()

214
    if(NOT DEFINED CMAKE_CUDA_STANDARD)
215
216
217
218
      set(CMAKE_CUDA_STANDARD 11)
      set(CMAKE_CUDA_STANDARD_REQUIRED ON)
    endif()

219
220
221
222
    set(
      BASE_DEFINES
      -DPOWER_FEATURE_WORKGROUPS=12
      -DUSE_CONSTANT_BUF=0
223
    )
224
225
226
227
    set(
      ALLFEATS_DEFINES
      ${BASE_DEFINES}
      -DENABLE_ALL_FEATURES
228
    )
229
230
231
232
    set(
      FULLDATA_DEFINES
      ${ALLFEATS_DEFINES}
      -DIGNORE_INDICES
233
234
235
236
237
238
239
240
    )

    message(STATUS "ALLFEATS_DEFINES: ${ALLFEATS_DEFINES}")
    message(STATUS "FULLDATA_DEFINES: ${FULLDATA_DEFINES}")

    function(add_histogram hsize hname hadd hconst hdir)
      add_library(histo${hsize}${hname} OBJECT src/treelearner/kernels/histogram${hsize}.cu)
      set_target_properties(histo${hsize}${hname} PROPERTIES CUDA_SEPARABLE_COMPILATION ON)
241
      set_target_properties(histo${hsize}${hname} PROPERTIES CUDA_ARCHITECTURES OFF)
242
243
244
245
246
      if(hadd)
        list(APPEND histograms histo${hsize}${hname})
        set(histograms ${histograms} PARENT_SCOPE)
      endif()
      target_compile_definitions(
247
248
        histo${hsize}${hname}
        PRIVATE
249
250
251
252
253
        -DCONST_HESSIAN=${hconst}
        ${hdir}
      )
    endfunction()

254
    foreach(hsize _16_64_256)
255
256
257
258
259
260
261
      add_histogram("${hsize}" "_sp_const" "True" "1" "${BASE_DEFINES}")
      add_histogram("${hsize}" "_sp" "True" "0" "${BASE_DEFINES}")
      add_histogram("${hsize}" "-allfeats_sp_const" "False" "1" "${ALLFEATS_DEFINES}")
      add_histogram("${hsize}" "-allfeats_sp" "False" "0" "${ALLFEATS_DEFINES}")
      add_histogram("${hsize}" "-fulldata_sp_const" "True" "1" "${FULLDATA_DEFINES}")
      add_histogram("${hsize}" "-fulldata_sp" "True" "0" "${FULLDATA_DEFINES}")
    endforeach()
262
endif()
263

264
265
266
267
268
if(USE_HDFS)
    find_package(JNI REQUIRED)
    find_path(HDFS_INCLUDE_DIR hdfs.h REQUIRED)
    find_library(HDFS_LIB NAMES hdfs REQUIRED)
    include_directories(${HDFS_INCLUDE_DIR})
269
270
    add_definitions(-DUSE_HDFS)
    set(HDFS_CXX_LIBRARIES ${HDFS_LIB} ${JAVA_JVM_LIBRARY})
271
endif()
272

273
274
275
276
277
278
279
280
281
282
283
include(CheckCXXSourceCompiles)
check_cxx_source_compiles("
#include <xmmintrin.h>
int main() {
  int a = 0;
  _mm_prefetch(&a, _MM_HINT_NTA);
  return 0;
}
" MM_PREFETCH)

if(${MM_PREFETCH})
284
  message(STATUS "Using _mm_prefetch")
285
  add_definitions(-DMM_PREFETCH)
286
287
endif()

288
289
290
291
292
293
294
295
296
297
298
include(CheckCXXSourceCompiles)
check_cxx_source_compiles("
#include <mm_malloc.h>
int main() {
  char *a = (char*)_mm_malloc(8, 16);
  _mm_free(a);
  return 0;
}
" MM_MALLOC)

if(${MM_MALLOC})
299
  message(STATUS "Using _mm_malloc")
300
  add_definitions(-DMM_MALLOC)
301
302
endif()

Guolin Ke's avatar
Guolin Ke committed
303
if(UNIX OR MINGW OR CYGWIN)
304
  set(
305
306
307
308
    CMAKE_CXX_FLAGS
    "${CMAKE_CXX_FLAGS} -std=c++11 -pthread -Wextra -Wall -Wno-ignored-attributes -Wno-unknown-pragmas -Wno-return-type"
  )
  if(USE_DEBUG)
309
      set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0")
310
  else()
311
      set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
312
313
  endif()
  if(USE_SWIG)
314
      set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-strict-aliasing")
315
316
  endif()
  if(NOT USE_OPENMP)
317
      set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unknown-pragmas -Wno-unused-private-field")
318
319
  endif()
  if(__BUILD_FOR_R AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
320
      set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-cast-function-type")
321
  endif()
Guolin Ke's avatar
Guolin Ke committed
322
323
endif()

Nikita Titov's avatar
Nikita Titov committed
324
if(WIN32 AND MINGW)
325
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libstdc++")
Nikita Titov's avatar
Nikita Titov committed
326
327
endif()

328
329
330
331
332
333
334
335
336
337
338
339
# Check if inet_pton is already available, to avoid conflicts with the implementation in LightGBM.
# As of 2022, MinGW started including a definition of inet_pton.
if(WIN32)
  include(CheckSymbolExists)
  list(APPEND CMAKE_REQUIRED_LIBRARIES "ws2_32")
  check_symbol_exists(inet_pton "ws2tcpip.h" WIN_INET_PTON_FOUND)
  if(WIN_INET_PTON_FOUND)
    add_definitions(-DWIN_HAS_INET_PTON)
  endif()
  list(REMOVE_ITEM CMAKE_REQUIRED_LIBRARIES "ws2_32")
endif()

Guolin Ke's avatar
Guolin Ke committed
340
if(MSVC)
341
    set(
342
      variables
Guolin Ke's avatar
Guolin Ke committed
343
344
345
346
347
348
349
350
351
        CMAKE_C_FLAGS_DEBUG
        CMAKE_C_FLAGS_MINSIZEREL
        CMAKE_C_FLAGS_RELEASE
        CMAKE_C_FLAGS_RELWITHDEBINFO
        CMAKE_CXX_FLAGS_DEBUG
        CMAKE_CXX_FLAGS_MINSIZEREL
        CMAKE_CXX_FLAGS_RELEASE
        CMAKE_CXX_FLAGS_RELWITHDEBINFO
    )
352
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4 /MP")
Guolin Ke's avatar
Guolin Ke committed
353
    if(USE_DEBUG)
354
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Od")
Guolin Ke's avatar
Guolin Ke committed
355
    else()
356
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /O2 /Ob2 /Oi /Ot /Oy")
Guolin Ke's avatar
Guolin Ke committed
357
    endif()
Guolin Ke's avatar
Guolin Ke committed
358
else()
359
360
361
    if(NOT BUILD_STATIC_LIB)
      set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
    endif()
Guolin Ke's avatar
Guolin Ke committed
362
    if(NOT USE_DEBUG)
363
      set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -funroll-loops")
Guolin Ke's avatar
Guolin Ke committed
364
    endif()
365
endif()
Guolin Ke's avatar
Guolin Ke committed
366

367
set(LightGBM_HEADER_DIR ${PROJECT_SOURCE_DIR}/include)
Guolin Ke's avatar
Guolin Ke committed
368

369
370
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR})
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR})
Guolin Ke's avatar
Guolin Ke committed
371

372
include_directories(${LightGBM_HEADER_DIR})
Guolin Ke's avatar
Guolin Ke committed
373
374

if(APPLE)
375
  if(APPLE_OUTPUT_DYLIB)
376
    set(CMAKE_SHARED_LIBRARY_SUFFIX ".dylib")
377
  else()
378
    set(CMAKE_SHARED_LIBRARY_SUFFIX ".so")
379
  endif()
380
endif()
Guolin Ke's avatar
Guolin Ke committed
381
382
383

if(USE_MPI)
  include_directories(${MPI_CXX_INCLUDE_PATH})
384
endif()
Guolin Ke's avatar
Guolin Ke committed
385

386
387
388
389
390
391
392
393
394
file(
    GLOB
    SOURCES
      src/boosting/*.cpp
      src/io/*.cpp
      src/metric/*.cpp
      src/objective/*.cpp
      src/network/*.cpp
      src/treelearner/*.cpp
395
if(USE_CUDA OR USE_CUDA_EXP)
396
      src/treelearner/*.cu
397
endif()
398
if(USE_CUDA_EXP)
399
400
      src/boosting/cuda/*.cpp
      src/boosting/cuda/*.cu
401
402
403
404
405
406
407
      src/treelearner/cuda/*.cpp
      src/treelearner/cuda/*.cu
      src/io/cuda/*.cu
      src/io/cuda/*.cpp
      src/cuda/*.cpp
      src/cuda/*.cu
endif()
Guolin Ke's avatar
Guolin Ke committed
408
409
)

410
411
412
413
add_library(lightgbm_objs OBJECT ${SOURCES})

add_executable(lightgbm src/main.cpp src/application/application.cpp)
target_link_libraries(lightgbm PRIVATE lightgbm_objs)
414

415
set(API_SOURCES "src/c_api.cpp")
416
417
# Only build the R part of the library if building for
# use with the R package
418
if(__BUILD_FOR_R)
419
  list(APPEND API_SOURCES "src/lightgbm_R.cpp")
420
endif()
421

422
423
add_library(lightgbm_capi_objs OBJECT ${API_SOURCES})

424
if(BUILD_STATIC_LIB)
425
  add_library(_lightgbm STATIC)
426
else()
427
  add_library(_lightgbm SHARED)
428
endif()
429
# LightGBM headers include openmp, cuda, R etc. headers,
430
431
# thus PUBLIC is required for building _lightgbm_swig target.
target_link_libraries(_lightgbm PUBLIC lightgbm_capi_objs lightgbm_objs)
432

433
if(MSVC)
434
  set_target_properties(_lightgbm PROPERTIES OUTPUT_NAME "lib_lightgbm")
435
endif()
436

437
438
if(USE_SWIG)
  set_property(SOURCE swig/lightgbmlib.i PROPERTY CPLUSPLUS ON)
439
  list(APPEND swig_options -package com.microsoft.ml.lightgbm)
440
441
442
  set_property(SOURCE swig/lightgbmlib.i PROPERTY SWIG_FLAGS "${swig_options}")
  swig_add_module(_lightgbm_swig java swig/lightgbmlib.i)
  swig_link_libraries(_lightgbm_swig _lightgbm)
443
  # needed to ensure Linux build does not have lib prefix specified twice, e.g. liblib_lightgbm_swig
444
  set_target_properties(_lightgbm_swig PROPERTIES PREFIX "")
445
  # needed in some versions of CMake for VS and MinGW builds to ensure output dll has lib prefix
446
447
448
  set_target_properties(_lightgbm_swig PROPERTIES OUTPUT_NAME "lib_lightgbm_swig")
  if(WIN32)
    if(MINGW OR CYGWIN)
449
450
451
        add_custom_command(
            TARGET _lightgbm_swig
            POST_BUILD
452
            COMMAND "${Java_JAVAC_EXECUTABLE}" -d . java/*.java
453
454
455
456
457
458
459
460
461
462
463
464
465
466
            COMMAND
              "${CMAKE_COMMAND}"
              -E
              copy_if_different
              "${PROJECT_SOURCE_DIR}/lib_lightgbm.dll"
              com/microsoft/ml/lightgbm/windows/x86_64
            COMMAND
              "${CMAKE_COMMAND}"
              -E
              copy_if_different
              "${PROJECT_SOURCE_DIR}/lib_lightgbm_swig.dll"
              com/microsoft/ml/lightgbm/windows/x86_64
            COMMAND "${Java_JAR_EXECUTABLE}" -cf lightgbmlib.jar com
        )
467
    else()
468
469
470
        add_custom_command(
            TARGET _lightgbm_swig
            POST_BUILD
471
472
            COMMAND "${Java_JAVAC_EXECUTABLE}" -d . java/*.java
            COMMAND cp "${PROJECT_SOURCE_DIR}/Release/*.dll" com/microsoft/ml/lightgbm/windows/x86_64
473
474
            COMMAND "${Java_JAR_EXECUTABLE}" -cf lightgbmlib.jar com
        )
475
    endif()
476
  elseif(APPLE)
477
478
479
480
481
482
483
484
485
486
487
    add_custom_command(
        TARGET _lightgbm_swig
        POST_BUILD
        COMMAND "${Java_JAVAC_EXECUTABLE}" -d . java/*.java
        COMMAND cp "${PROJECT_SOURCE_DIR}/*.dylib" com/microsoft/ml/lightgbm/osx/x86_64
        COMMAND
          cp
          "${PROJECT_SOURCE_DIR}/lib_lightgbm_swig.jnilib"
          com/microsoft/ml/lightgbm/osx/x86_64/lib_lightgbm_swig.dylib
        COMMAND "${Java_JAR_EXECUTABLE}" -cf lightgbmlib.jar com
    )
488
  else()
489
490
491
492
493
494
495
    add_custom_command(
        TARGET _lightgbm_swig
        POST_BUILD
        COMMAND "${Java_JAVAC_EXECUTABLE}" -d . java/*.java
        COMMAND cp "${PROJECT_SOURCE_DIR}/*.so" com/microsoft/ml/lightgbm/linux/x86_64
        COMMAND "${Java_JAR_EXECUTABLE}" -cf lightgbmlib.jar com
    )
496
  endif()
497
endif()
Guolin Ke's avatar
Guolin Ke committed
498
499

if(USE_MPI)
500
  target_link_libraries(lightgbm_objs PUBLIC ${MPI_CXX_LIBRARIES})
501
endif()
Guolin Ke's avatar
Guolin Ke committed
502

fanliwen's avatar
fanliwen committed
503
if(USE_OPENMP)
504
505
506
507
508
509
510
511
512
513
  if(CMAKE_CXX_COMPILER_ID STREQUAL "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.
    # 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()
514
endif()
fanliwen's avatar
fanliwen committed
515

516
if(USE_GPU)
517
  target_link_libraries(lightgbm_objs PUBLIC ${OpenCL_LIBRARY} ${Boost_LIBRARIES})
518
endif()
519

520
if(__INTEGRATE_OPENCL)
521
  # targets OpenCL and Boost are added in IntegratedOpenCL.cmake
522
  add_dependencies(lightgbm_objs OpenCL Boost)
523
  # variables INTEGRATED_OPENCL_* are set in IntegratedOpenCL.cmake
524
525
526
  target_include_directories(lightgbm_objs PRIVATE ${INTEGRATED_OPENCL_INCLUDES})
  target_compile_definitions(lightgbm_objs PRIVATE ${INTEGRATED_OPENCL_DEFINITIONS})
  target_link_libraries(lightgbm_objs PUBLIC ${INTEGRATED_OPENCL_LIBRARIES})
527
528
endif()

529
if(USE_CUDA OR USE_CUDA_EXP)
530
531
532
533
534
  # Disable cmake warning about policy CMP0104. Refer to issue #3754 and PR #4268.
  # Custom target properties does not propagate, thus we need to specify for
  # each target that contains or depends on cuda source.
  set_target_properties(lightgbm_objs PROPERTIES CUDA_ARCHITECTURES OFF)
  set_target_properties(_lightgbm PROPERTIES CUDA_ARCHITECTURES OFF)
535
  set_target_properties(lightgbm PROPERTIES CUDA_ARCHITECTURES OFF)
536

537
538
  set_target_properties(lightgbm_objs PROPERTIES CUDA_SEPARABLE_COMPILATION ON)

539
540
541
  # 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)
542
  set_target_properties(_lightgbm PROPERTIES CUDA_RESOLVE_DEVICE_SYMBOLS ON)
543
544
545
546
547
548

  # 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})
549
endif()
550

551
if(USE_HDFS)
552
  target_link_libraries(lightgbm_objs PUBLIC ${HDFS_CXX_LIBRARIES})
553
endif()
554

555
556
if(WIN32)
    if(MINGW OR CYGWIN)
557
      target_link_libraries(lightgbm_objs PUBLIC Ws2_32 IPHLPAPI)
558
559
    endif()
endif()
Guolin Ke's avatar
Guolin Ke committed
560

561
if(__BUILD_FOR_R)
562
563
  # utils/log.h and capi uses R headers, thus both object libraries need to link
  # with R lib.
564
  if(MSVC)
565
    set(R_LIB ${LIBR_MSVC_CORE_LIBRARY})
566
  else()
567
    set(R_LIB ${LIBR_CORE_LIBRARY})
568
  endif()
569
570
  target_link_libraries(lightgbm_objs PUBLIC ${R_LIB})
  target_link_libraries(lightgbm_capi_objs PUBLIC ${R_LIB})
571
endif()
572

573
574
575
576
577
578
579
580
581
#-- Google C++ tests
if(BUILD_CPP_TEST)
  find_package(GTest CONFIG)
  if(NOT GTEST_FOUND)
    message(STATUS "Did not find Google Test in the system root. Fetching Google Test now...")
    include(FetchContent)
    FetchContent_Declare(
      googletest
      GIT_REPOSITORY https://github.com/google/googletest.git
582
      GIT_TAG        release-1.11.0
583
584
585
586
    )
    FetchContent_MakeAvailable(googletest)
    add_library(GTest::GTest ALIAS gtest)
  endif()
587
588
589
590
591
592
593
594
595
596
597
598
599
600
  file(GLOB CPP_TEST_SOURCES tests/cpp_tests/*.cpp)
  if(MSVC)
    set(
      CompilerFlags
        CMAKE_CXX_FLAGS
        CMAKE_CXX_FLAGS_DEBUG
        CMAKE_CXX_FLAGS_RELEASE
        CMAKE_C_FLAGS
        CMAKE_C_FLAGS_DEBUG
        CMAKE_C_FLAGS_RELEASE
    )
    foreach(CompilerFlag ${CompilerFlags})
      string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}")
    endforeach()
601
  endif()
602
603
  add_executable(testlightgbm ${CPP_TEST_SOURCES})
  target_link_libraries(testlightgbm PRIVATE lightgbm_objs GTest::GTest)
604
605
endif()

606
607
608
609
610
611
install(
  TARGETS lightgbm _lightgbm
  RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin
  LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/lib
  ARCHIVE DESTINATION ${CMAKE_INSTALL_PREFIX}/lib
)
612

613
install(DIRECTORY ${LightGBM_HEADER_DIR}/LightGBM DESTINATION ${CMAKE_INSTALL_PREFIX}/include)