CMakeLists.txt 18.4 KB
Newer Older
1
OPTION(USE_MPI "Enable MPI-based distributed learning" OFF)
2
3
4
5
6
7
8
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)
OPTION(USE_DEBUG "Set to ON for Debug mode" OFF)
9
OPTION(USE_SANITIZER "Use santizer flags" OFF)
10
11
12
13
14
15
16
17
SET(
  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."
)
18
OPTION(BUILD_CPP_TEST "Build C++ tests with Google Test" OFF)
19
20
21
22
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)
  OPTION(APPLE_OUTPUT_DYLIB "Output dylib shared library" OFF)
25
endif()
26

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

37
PROJECT(lightgbm LANGUAGES C CXX)
Guolin Ke's avatar
Guolin Ke committed
38

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

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

50
51
52
53
54
55
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
56
57
58
59
60
61
62
63
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()
64
65
66
67
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
  if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "8.1.0")
    message(FATAL_ERROR "Insufficient AppleClang version")
  endif()
68
  cmake_minimum_required(VERSION 3.16)
69
70
elseif(MSVC)
  if(MSVC_VERSION LESS 1900)
71
72
73
74
    message(
      FATAL_ERROR
      "The compiler ${CMAKE_CXX_COMPILER} doesn't support required C++11 features. Please use a newer MSVC."
    )
75
76
  endif()
  cmake_minimum_required(VERSION 3.8)
77
endif()
Guolin Ke's avatar
Guolin Ke committed
78

79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
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)
94
95
96
  if(WIN32)
      FILE(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/com/microsoft/ml/lightgbm/windows/x86_64")
      include_directories($ENV{JAVA_HOME}/include/win32)
97
98
99
  elseif(APPLE)
      FILE(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/com/microsoft/ml/lightgbm/osx/x86_64")
      include_directories($ENV{JAVA_HOME}/include/darwin)
100
101
102
103
  else()
      FILE(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/com/microsoft/ml/lightgbm/linux/x86_64")
      include_directories($ENV{JAVA_HOME}/include/linux)
  endif()
104
endif()
105

106
SET(EIGEN_DIR "${PROJECT_SOURCE_DIR}/external_libs/eigen")
107
108
include_directories(${EIGEN_DIR})

109
110
111
# See https://gitlab.com/libeigen/eigen/-/blob/master/COPYING.README
ADD_DEFINITIONS(-DEIGEN_MPL2_ONLY)

112
if(__BUILD_FOR_R)
113
114
115
116
117
    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})
118
    ADD_DEFINITIONS(-DLGB_R_BUILD)
119
endif()
120

121
122
if(USE_TIMETAG)
    ADD_DEFINITIONS(-DTIMETAG)
123
endif()
124

Guolin Ke's avatar
Guolin Ke committed
125
126
if(USE_DEBUG)
    ADD_DEFINITIONS(-DDEBUG)
127
endif()
Guolin Ke's avatar
Guolin Ke committed
128

Guolin Ke's avatar
Guolin Ke committed
129
if(USE_MPI)
Guolin Ke's avatar
Guolin Ke committed
130
131
    find_package(MPI REQUIRED)
    ADD_DEFINITIONS(-DUSE_MPI)
Guolin Ke's avatar
Guolin Ke committed
132
else()
Guolin Ke's avatar
Guolin Ke committed
133
    ADD_DEFINITIONS(-DUSE_SOCKET)
134
endif()
Guolin Ke's avatar
Guolin Ke committed
135

136
if(USE_CUDA)
137
138
    SET(CMAKE_CUDA_HOST_COMPILER "${CMAKE_CXX_COMPILER}")
    enable_language(CUDA)
139
    SET(USE_OPENMP ON CACHE BOOL "CUDA requires OpenMP" FORCE)
140
endif()
141

142
143
144
if(USE_OPENMP)
    find_package(OpenMP REQUIRED)
    SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
145
endif()
Guolin Ke's avatar
Guolin Ke committed
146

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

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

174
if(USE_CUDA)
175
    find_package(CUDA 9.0 REQUIRED)
176
177
    include_directories(${CUDA_INCLUDE_DIRS})
    LIST(APPEND CMAKE_CUDA_FLAGS -Xcompiler=${OpenMP_CXX_FLAGS} -Xcompiler=-fPIC -Xcompiler=-Wall)
178
179
180
181
182

    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()
183
184
185
186
187
188
    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()
189
190
    list(POP_BACK CUDA_ARCHS CUDA_LAST_SUPPORTED_ARCH)
    list(APPEND CUDA_ARCHS "${CUDA_LAST_SUPPORTED_ARCH}+PTX")
191
    CUDA_SELECT_NVCC_ARCH_FLAGS(CUDA_ARCH_FLAGS ${CUDA_ARCHS})
192
193
194
195
196
197
198
199
200
201
202

    LIST(APPEND CMAKE_CUDA_FLAGS ${CUDA_ARCH_FLAGS})
    if(USE_DEBUG)
      SET(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -g")
    else()
      SET(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -O3 -lineinfo")
    endif()
    string(REPLACE ";" " " CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS}")
    message(STATUS "CMAKE_CUDA_FLAGS: ${CMAKE_CUDA_FLAGS}")

    ADD_DEFINITIONS(-DUSE_CUDA)
203
    if(NOT DEFINED CMAKE_CUDA_STANDARD)
204
205
206
207
      set(CMAKE_CUDA_STANDARD 11)
      set(CMAKE_CUDA_STANDARD_REQUIRED ON)
    endif()

208
209
210
211
    set(
      BASE_DEFINES
      -DPOWER_FEATURE_WORKGROUPS=12
      -DUSE_CONSTANT_BUF=0
212
    )
213
214
215
216
    set(
      ALLFEATS_DEFINES
      ${BASE_DEFINES}
      -DENABLE_ALL_FEATURES
217
    )
218
219
220
221
    set(
      FULLDATA_DEFINES
      ${ALLFEATS_DEFINES}
      -DIGNORE_INDICES
222
223
224
225
226
227
228
229
    )

    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)
230
      set_target_properties(histo${hsize}${hname} PROPERTIES CUDA_ARCHITECTURES OFF)
231
232
233
234
235
      if(hadd)
        list(APPEND histograms histo${hsize}${hname})
        set(histograms ${histograms} PARENT_SCOPE)
      endif()
      target_compile_definitions(
236
237
        histo${hsize}${hname}
        PRIVATE
238
239
240
241
242
        -DCONST_HESSIAN=${hconst}
        ${hdir}
      )
    endfunction()

243
    foreach(hsize _16_64_256)
244
245
246
247
248
249
250
      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()
251
endif()
252

253
254
255
256
257
258
259
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})
    ADD_DEFINITIONS(-DUSE_HDFS)
    SET(HDFS_CXX_LIBRARIES ${HDFS_LIB} ${JAVA_JVM_LIBRARY})
260
endif()
261

262
263
264
265
266
267
268
269
270
271
272
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})
273
  message(STATUS "Using _mm_prefetch")
274
275
276
  ADD_DEFINITIONS(-DMM_PREFETCH)
endif()

277
278
279
280
281
282
283
284
285
286
287
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})
288
  message(STATUS "Using _mm_malloc")
289
290
291
  ADD_DEFINITIONS(-DMM_MALLOC)
endif()

Guolin Ke's avatar
Guolin Ke committed
292
if(UNIX OR MINGW OR CYGWIN)
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
  SET(
    CMAKE_CXX_FLAGS
    "${CMAKE_CXX_FLAGS} -std=c++11 -pthread -Wextra -Wall -Wno-ignored-attributes -Wno-unknown-pragmas -Wno-return-type"
  )
  if(USE_DEBUG)
      SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0")
  else()
      SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
  endif()
  if(USE_SWIG)
      SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-strict-aliasing")
  endif()
  if(NOT USE_OPENMP)
      SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unknown-pragmas -Wno-unused-private-field")
  endif()
  if(__BUILD_FOR_R AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
      SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-cast-function-type")
  endif()
Guolin Ke's avatar
Guolin Ke committed
311
312
endif()

Nikita Titov's avatar
Nikita Titov committed
313
314
315
316
if(WIN32 AND MINGW)
    SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libstdc++")
endif()

Guolin Ke's avatar
Guolin Ke committed
317
if(MSVC)
318
319
    SET(
      variables
Guolin Ke's avatar
Guolin Ke committed
320
321
322
323
324
325
326
327
328
        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
    )
Guolin Ke's avatar
Guolin Ke committed
329
330
331
332
333
334
    SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4 /MP")
    if(USE_DEBUG)
        SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Od")
    else()
        SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /O2 /Ob2 /Oi /Ot /Oy")
    endif()
Guolin Ke's avatar
Guolin Ke committed
335
else()
336
337
338
    if(NOT BUILD_STATIC_LIB)
      set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
    endif()
Guolin Ke's avatar
Guolin Ke committed
339
    if(NOT USE_DEBUG)
340
      SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -funroll-loops")
Guolin Ke's avatar
Guolin Ke committed
341
    endif()
342
endif()
Guolin Ke's avatar
Guolin Ke committed
343
344

SET(LightGBM_HEADER_DIR ${PROJECT_SOURCE_DIR}/include)
Guolin Ke's avatar
Guolin Ke committed
345

Guolin Ke's avatar
Guolin Ke committed
346
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR})
Guolin Ke's avatar
Guolin Ke committed
347
SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR})
Guolin Ke's avatar
Guolin Ke committed
348

349
include_directories(${LightGBM_HEADER_DIR})
Guolin Ke's avatar
Guolin Ke committed
350
351

if(APPLE)
352
  if(APPLE_OUTPUT_DYLIB)
353
354
355
356
    SET(CMAKE_SHARED_LIBRARY_SUFFIX ".dylib")
  else()
    SET(CMAKE_SHARED_LIBRARY_SUFFIX ".so")
  endif()
357
endif()
Guolin Ke's avatar
Guolin Ke committed
358
359
360

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

363
364
365
366
367
368
369
370
371
file(
    GLOB
    SOURCES
      src/boosting/*.cpp
      src/io/*.cpp
      src/metric/*.cpp
      src/objective/*.cpp
      src/network/*.cpp
      src/treelearner/*.cpp
372
if(USE_CUDA)
373
      src/treelearner/*.cu
374
endif()
Guolin Ke's avatar
Guolin Ke committed
375
376
)

377
378
379
380
add_library(lightgbm_objs OBJECT ${SOURCES})

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

382
set(API_SOURCES "src/c_api.cpp")
383
384
# Only build the R part of the library if building for
# use with the R package
385
if(__BUILD_FOR_R)
386
  list(APPEND API_SOURCES "src/lightgbm_R.cpp")
387
endif()
388

389
390
add_library(lightgbm_capi_objs OBJECT ${API_SOURCES})

391
if(BUILD_STATIC_LIB)
392
  add_library(_lightgbm STATIC)
393
else()
394
  add_library(_lightgbm SHARED)
395
endif()
396
# LightGBM headers include openmp, cuda, R etc. headers,
397
398
# thus PUBLIC is required for building _lightgbm_swig target.
target_link_libraries(_lightgbm PUBLIC lightgbm_capi_objs lightgbm_objs)
399

400
if(MSVC)
401
  set_target_properties(_lightgbm PROPERTIES OUTPUT_NAME "lib_lightgbm")
402
endif()
403

404
405
406
407
408
409
if(USE_SWIG)
  set_property(SOURCE swig/lightgbmlib.i PROPERTY CPLUSPLUS ON)
  LIST(APPEND swig_options -package com.microsoft.ml.lightgbm)
  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)
410
  # needed to ensure Linux build does not have lib prefix specified twice, e.g. liblib_lightgbm_swig
411
  set_target_properties(_lightgbm_swig PROPERTIES PREFIX "")
412
  # needed in some versions of CMake for VS and MinGW builds to ensure output dll has lib prefix
413
414
415
  set_target_properties(_lightgbm_swig PROPERTIES OUTPUT_NAME "lib_lightgbm_swig")
  if(WIN32)
    if(MINGW OR CYGWIN)
416
417
418
        add_custom_command(
            TARGET _lightgbm_swig
            POST_BUILD
419
            COMMAND "${Java_JAVAC_EXECUTABLE}" -d . java/*.java
420
421
422
423
424
425
426
427
428
429
430
431
432
433
            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
        )
434
    else()
435
436
437
        add_custom_command(
            TARGET _lightgbm_swig
            POST_BUILD
438
439
            COMMAND "${Java_JAVAC_EXECUTABLE}" -d . java/*.java
            COMMAND cp "${PROJECT_SOURCE_DIR}/Release/*.dll" com/microsoft/ml/lightgbm/windows/x86_64
440
441
            COMMAND "${Java_JAR_EXECUTABLE}" -cf lightgbmlib.jar com
        )
442
    endif()
443
  elseif(APPLE)
444
445
446
447
448
449
450
451
452
453
454
    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
    )
455
  else()
456
457
458
459
460
461
462
    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
    )
463
  endif()
464
endif()
Guolin Ke's avatar
Guolin Ke committed
465
466

if(USE_MPI)
467
  target_link_libraries(lightgbm_objs PUBLIC ${MPI_CXX_LIBRARIES})
468
endif()
Guolin Ke's avatar
Guolin Ke committed
469

fanliwen's avatar
fanliwen committed
470
if(USE_OPENMP)
471
472
473
474
475
476
477
478
479
480
  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()
481
endif()
fanliwen's avatar
fanliwen committed
482

483
if(USE_GPU)
484
  target_link_libraries(lightgbm_objs PUBLIC ${OpenCL_LIBRARY} ${Boost_LIBRARIES})
485
endif()
486

487
if(__INTEGRATE_OPENCL)
488
  # targets OpenCL and Boost are added in IntegratedOpenCL.cmake
489
  add_dependencies(lightgbm_objs OpenCL Boost)
490
  # variables INTEGRATED_OPENCL_* are set in IntegratedOpenCL.cmake
491
492
493
  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})
494
495
endif()

496
if(USE_CUDA)
497
498
499
500
501
  # 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)
502
  set_target_properties(lightgbm PROPERTIES CUDA_ARCHITECTURES OFF)
503
504
505
506

  # 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)
507
  set_target_properties(_lightgbm PROPERTIES CUDA_RESOLVE_DEVICE_SYMBOLS ON)
508
509
510
511
512
513

  # 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})
514
endif()
515

516
if(USE_HDFS)
517
  target_link_libraries(lightgbm_objs PUBLIC ${HDFS_CXX_LIBRARIES})
518
endif()
519

520
521
if(WIN32)
    if(MINGW OR CYGWIN)
522
      target_link_libraries(lightgbm_objs PUBLIC Ws2_32 IPHLPAPI)
523
524
    endif()
endif()
Guolin Ke's avatar
Guolin Ke committed
525

526
if(__BUILD_FOR_R)
527
528
  # utils/log.h and capi uses R headers, thus both object libraries need to link
  # with R lib.
529
  if(MSVC)
530
    set(R_LIB ${LIBR_MSVC_CORE_LIBRARY})
531
  else()
532
    set(R_LIB ${LIBR_CORE_LIBRARY})
533
  endif()
534
535
  target_link_libraries(lightgbm_objs PUBLIC ${R_LIB})
  target_link_libraries(lightgbm_capi_objs PUBLIC ${R_LIB})
536
endif()
537

538
539
540
541
542
543
544
545
546
#-- 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
547
      GIT_TAG        release-1.11.0
548
549
550
551
    )
    FetchContent_MakeAvailable(googletest)
    add_library(GTest::GTest ALIAS gtest)
  endif()
552
553
554
555
556
557
558
559
560
561
562
563
564
565
  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()
566
  endif()
567
568
  add_executable(testlightgbm ${CPP_TEST_SOURCES})
  target_link_libraries(testlightgbm PRIVATE lightgbm_objs GTest::GTest)
569
570
endif()

571
572
573
574
575
576
install(
  TARGETS lightgbm _lightgbm
  RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin
  LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/lib
  ARCHIVE DESTINATION ${CMAKE_INSTALL_PREFIX}/lib
)
577

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