1cmake_minimum_required(VERSION 3.1)
2
3# https://github.com/libigl/libigl/issues/751
4# http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20160425/351643.html
5if(APPLE)
6  if(NOT CMAKE_LIBTOOL)
7    find_program(CMAKE_LIBTOOL NAMES libtool)
8  endif()
9  if(CMAKE_LIBTOOL)
10    set(CMAKE_LIBTOOL ${CMAKE_LIBTOOL} CACHE PATH "libtool executable")
11    message(STATUS "Found libtool - ${CMAKE_LIBTOOL}")
12    get_property(languages GLOBAL PROPERTY ENABLED_LANGUAGES)
13    foreach(lang ${languages})
14      # Added -c
15      set(CMAKE_${lang}_CREATE_STATIC_LIBRARY
16        "${CMAKE_LIBTOOL} -c -static -o <TARGET> <LINK_FLAGS> <OBJECTS> ")
17    endforeach()
18  endif()
19endif()
20
21### Available options ###
22option(LIBIGL_USE_STATIC_LIBRARY     "Use libigl as static library" OFF)
23option(LIBIGL_WITH_CGAL              "Use CGAL"                     OFF)
24option(LIBIGL_WITH_COMISO            "Use CoMiso"                   OFF)
25option(LIBIGL_WITH_CORK              "Use Cork"                     OFF)
26option(LIBIGL_WITH_EMBREE            "Use Embree"                   OFF)
27option(LIBIGL_WITH_MATLAB            "Use Matlab"                   OFF)
28option(LIBIGL_WITH_MOSEK             "Use MOSEK"                    OFF)
29option(LIBIGL_WITH_OPENGL            "Use OpenGL"                   OFF)
30option(LIBIGL_WITH_OPENGL_GLFW       "Use GLFW"                     OFF)
31option(LIBIGL_WITH_OPENGL_GLFW_IMGUI "Use ImGui"                    OFF)
32option(LIBIGL_WITH_PNG               "Use PNG"                      OFF)
33option(LIBIGL_WITH_TETGEN            "Use Tetgen"                   OFF)
34option(LIBIGL_WITH_TRIANGLE          "Use Triangle"                 OFF)
35option(LIBIGL_WITH_PREDICATES        "Use exact predicates"         OFF)
36option(LIBIGL_WITH_XML               "Use XML"                      OFF)
37option(LIBIGL_WITH_PYTHON            "Use Python"                   OFF)
38option(LIBIGL_WITHOUT_COPYLEFT       "Disable Copyleft libraries"   OFF)
39option(LIBIGL_EXPORT_TARGETS         "Export libigl CMake targets"  OFF)
40
41################################################################################
42
43### Configuration
44set(LIBIGL_ROOT "${CMAKE_CURRENT_LIST_DIR}/..")
45set(LIBIGL_SOURCE_DIR "${LIBIGL_ROOT}/include")
46set(LIBIGL_EXTERNAL "${LIBIGL_ROOT}/external")
47
48# Dependencies are linked as INTERFACE targets unless libigl is compiled as a static library
49if(LIBIGL_USE_STATIC_LIBRARY)
50  set(IGL_SCOPE PUBLIC)
51else()
52  set(IGL_SCOPE INTERFACE)
53endif()
54
55# Download and update 3rdparty libraries
56list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
57include(LibiglDownloadExternal)
58
59################################################################################
60### IGL Common
61################################################################################
62
63add_library(igl_common INTERFACE)
64target_include_directories(igl_common SYSTEM INTERFACE
65  $<BUILD_INTERFACE:${LIBIGL_SOURCE_DIR}>
66  $<INSTALL_INTERFACE:include>
67)
68# Export igl_common as igl::common
69set_property(TARGET igl_common PROPERTY EXPORT_NAME igl::common)
70if(LIBIGL_USE_STATIC_LIBRARY)
71  target_compile_definitions(igl_common INTERFACE -DIGL_STATIC_LIBRARY)
72endif()
73
74# Transitive C++11 flags
75include(CXXFeatures)
76target_compile_features(igl_common INTERFACE ${CXX11_FEATURES})
77
78# Other compilation flags
79if(MSVC)
80  # Enable parallel compilation for Visual Studio
81  target_compile_options(igl_common INTERFACE /MP /bigobj)
82  target_compile_definitions(igl_common INTERFACE -DNOMINMAX)
83endif()
84
85### Set compiler flags for building the tests on Windows with Visual Studio
86include(LibiglWindows)
87
88if(BUILD_SHARED_LIBS)
89  # Generate position independent code
90  set_target_properties(igl_common PROPERTIES INTERFACE_POSITION_INDEPENDENT_CODE ON)
91endif()
92
93if(UNIX)
94  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
95  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
96endif()
97
98# Eigen
99if(TARGET Eigen3::Eigen)
100  # If an imported target already exists, use it
101  target_link_libraries(igl_common INTERFACE Eigen3::Eigen)
102else()
103  igl_download_eigen()
104  target_include_directories(igl_common SYSTEM INTERFACE
105    $<BUILD_INTERFACE:${LIBIGL_EXTERNAL}/eigen>
106    $<INSTALL_INTERFACE:include>
107  )
108endif()
109
110# C++11 Thread library
111find_package(Threads REQUIRED)
112target_link_libraries(igl_common INTERFACE ${CMAKE_THREAD_LIBS_INIT})
113
114################################################################################
115
116## CGAL dependencies on Windows: GMP & MPFR
117function(igl_download_cgal_deps)
118  if(WIN32)
119    igl_download_project(gmp
120        URL     https://cgal.geometryfactory.com/CGAL/precompiled_libs/auxiliary/x64/GMP/5.0.1/gmp-all-CGAL-3.9.zip
121        URL_MD5 508c1292319c832609329116a8234c9f
122    )
123    igl_download_project(mpfr
124        URL https://cgal.geometryfactory.com/CGAL/precompiled_libs/auxiliary/x64/MPFR/3.0.0/mpfr-all-CGAL-3.9.zip
125        URL_MD5 48840454eef0ff18730050c05028734b
126    )
127    set(ENV{GMP_DIR} "${LIBIGL_EXTERNAL}/gmp")
128    set(ENV{MPFR_DIR} "${LIBIGL_EXTERNAL}/mpfr")
129  endif()
130endfunction()
131
132################################################################################
133
134function(compile_igl_module module_dir)
135  string(REPLACE "/" "_" module_name "${module_dir}")
136  if(module_name STREQUAL "core")
137    set(module_libname "igl")
138  else()
139    set(module_libname "igl_${module_name}")
140  endif()
141  if(LIBIGL_USE_STATIC_LIBRARY)
142    file(GLOB SOURCES_IGL_${module_name}
143      "${LIBIGL_SOURCE_DIR}/igl/${module_dir}/*.cpp")
144    if(NOT LIBIGL_WITHOUT_COPYLEFT)
145      file(GLOB COPYLEFT_SOURCES_IGL_${module_name}
146        "${LIBIGL_SOURCE_DIR}/igl/copyleft/${module_dir}/*.cpp")
147      list(APPEND SOURCES_IGL_${module_name} ${COPYLEFT_SOURCES_IGL_${module_name}})
148    endif()
149    add_library(${module_libname} STATIC ${SOURCES_IGL_${module_name}} ${ARGN})
150    if(MSVC)
151      target_compile_options(${module_libname} PRIVATE /w) # disable all warnings (not ideal but...)
152    else()
153      #target_compile_options(${module_libname} PRIVATE -w) # disable all warnings (not ideal but...)
154    endif()
155  else()
156    add_library(${module_libname} INTERFACE)
157  endif()
158
159  target_link_libraries(${module_libname} ${IGL_SCOPE} igl_common)
160  if(NOT module_name STREQUAL "core")
161    target_link_libraries(${module_libname} ${IGL_SCOPE} igl)
162  endif()
163
164  # Alias target because it looks nicer
165  message(STATUS "Creating target: igl::${module_name} (${module_libname})")
166  add_library(igl::${module_name} ALIAS ${module_libname})
167  # Export as igl::${module_name}
168  set_property(TARGET ${module_libname} PROPERTY EXPORT_NAME igl::${module_name})
169endfunction()
170
171################################################################################
172### IGL Core
173################################################################################
174
175if(LIBIGL_USE_STATIC_LIBRARY)
176  file(GLOB SOURCES_IGL
177    "${LIBIGL_SOURCE_DIR}/igl/*.cpp"
178    "${LIBIGL_SOURCE_DIR}/igl/copyleft/*.cpp")
179endif()
180compile_igl_module("core" ${SOURCES_IGL})
181
182################################################################################
183### Download the python part ###
184if(LIBIGL_WITH_PYTHON)
185  igl_download_pybind11()
186endif()
187
188################################################################################
189### Compile the CGAL part ###
190if(LIBIGL_WITH_CGAL)
191  # Try to find the CGAL library
192  # CGAL Core is needed for
193  # `Exact_predicates_exact_constructions_kernel_with_sqrt`
194  if(NOT TARGET CGAL::CGAL)
195    set(CGAL_DIR "${LIBIGL_EXTERNAL}/cgal")
196    igl_download_cgal()
197    igl_download_cgal_deps()
198    if(EXISTS ${LIBIGL_EXTERNAL}/boost)
199      set(BOOST_ROOT "${LIBIGL_EXTERNAL}/boost")
200    endif()
201    if(LIBIGL_WITH_PYTHON)
202      option(CGAL_Boost_USE_STATIC_LIBS "Use static Boost libs with CGAL" OFF)
203    else()
204      option(CGAL_Boost_USE_STATIC_LIBS "Use static Boost libs with CGAL" ON)
205    endif()
206    find_package(CGAL CONFIG COMPONENTS Core PATHS ${CGAL_DIR} NO_DEFAULT_PATH)
207  endif()
208
209  # If CGAL has been found, then build the libigl module
210  if(TARGET CGAL::CGAL AND TARGET CGAL::CGAL_Core)
211    compile_igl_module("cgal")
212    target_link_libraries(igl_cgal ${IGL_SCOPE} CGAL::CGAL CGAL::CGAL_Core)
213  else()
214    set(LIBIGL_WITH_CGAL OFF CACHE BOOL "" FORCE)
215  endif()
216endif()
217
218# Helper function for `igl_copy_cgal_dll()`
219function(igl_copy_imported_dll src_target dst_target)
220  get_target_property(other_libs ${src_target} INTERFACE_LINK_LIBRARIES)
221  set(locations)
222  list(APPEND locations ${main_lib} ${other_libs})
223  foreach(location ${locations})
224    string(REGEX MATCH "^(.*)\\.[^.]*$" dummy ${location})
225    set(location "${CMAKE_MATCH_1}.dll")
226    if(EXISTS "${location}" AND location MATCHES "^.*\\.dll$")
227      add_custom_command(TARGET ${dst_target} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${location}" $<TARGET_FILE_DIR:${dst_target}>)
228    endif()
229  endforeach()
230endfunction()
231
232# Convenient functions to copy CGAL dlls into a target (executable) destination folder (for Windows)
233function(igl_copy_cgal_dll target)
234  if(WIN32 AND LIBIGL_WITH_CGAL)
235    igl_copy_imported_dll(CGAL::CGAL ${target})
236    igl_copy_imported_dll(CGAL::CGAL_Core ${target})
237  endif()
238endfunction()
239
240################################################################################
241### Compile the CoMISo part ###
242# NOTE: this cmakefile works only with the
243# comiso available here: https://github.com/libigl/CoMISo
244if(LIBIGL_WITH_COMISO)
245  compile_igl_module("comiso")
246  if(NOT TARGET CoMISo)
247    igl_download_comiso()
248    add_subdirectory("${LIBIGL_EXTERNAL}/CoMISo" CoMISo)
249  endif()
250  target_link_libraries(igl_comiso ${IGL_SCOPE} CoMISo)
251endif()
252
253################################################################################
254### Compile the cork part ###
255if(LIBIGL_WITH_CORK)
256  set(CORK_DIR "${LIBIGL_EXTERNAL}/cork")
257  if(NOT TARGET cork)
258    # call this "lib-cork" instead of "cork", otherwise cmake gets confused about
259    # "cork" executable
260    igl_download_cork()
261    add_subdirectory("${CORK_DIR}" "lib-cork")
262  endif()
263  compile_igl_module("cork")
264  target_include_directories(igl_cork ${IGL_SCOPE} cork)
265  target_include_directories(igl_cork ${IGL_SCOPE} "${CORK_DIR}/src")
266  target_link_libraries(igl_cork ${IGL_SCOPE} cork)
267endif()
268
269################################################################################
270### Compile the embree part ###
271if(LIBIGL_WITH_EMBREE)
272  set(EMBREE_DIR "${LIBIGL_EXTERNAL}/embree")
273
274  set(EMBREE_TESTING_INTENSITY 0 CACHE STRING "" FORCE)
275  set(EMBREE_ISPC_SUPPORT OFF CACHE BOOL " " FORCE)
276  set(EMBREE_TASKING_SYSTEM "INTERNAL" CACHE BOOL " " FORCE)
277  set(EMBREE_TUTORIALS OFF CACHE BOOL " " FORCE)
278  set(EMBREE_MAX_ISA "SSE2" CACHE STRING " " FORCE)
279  set(EMBREE_STATIC_LIB ON CACHE BOOL " " FORCE)
280  if(MSVC)
281    set(EMBREE_STATIC_RUNTIME ON CACHE BOOL " " FORCE)
282  endif()
283
284  if(NOT TARGET embree)
285    # TODO: Should probably save/restore the CMAKE_CXX_FLAGS_*, since embree seems to be
286    # overriding them on Windows. But well... it works for now.
287    igl_download_embree()
288    add_subdirectory("${EMBREE_DIR}" "embree")
289  endif()
290
291  compile_igl_module("embree")
292  target_link_libraries(igl_embree ${IGL_SCOPE} embree)
293  target_include_directories(igl_embree ${IGL_SCOPE} ${EMBREE_DIR}/include)
294  target_compile_definitions(igl_embree ${IGL_SCOPE} -DEMBREE_STATIC_LIB)
295endif()
296
297################################################################################
298### Compile the matlab part ###
299if(LIBIGL_WITH_MATLAB)
300  find_package(Matlab REQUIRED COMPONENTS MEX_COMPILER MX_LIBRARY ENG_LIBRARY MAT_LIBRARY)
301  compile_igl_module("matlab")
302  target_link_libraries(igl_matlab ${IGL_SCOPE} ${Matlab_LIBRARIES})
303  target_include_directories(igl_matlab ${IGL_SCOPE} ${Matlab_INCLUDE_DIRS})
304endif()
305
306################################################################################
307### Compile the mosek part ###
308if(LIBIGL_WITH_MOSEK)
309  find_package(MOSEK REQUIRED)
310  compile_igl_module("mosek")
311  target_link_libraries(igl_mosek ${IGL_SCOPE} ${MOSEK_LIBRARIES})
312  target_include_directories(igl_mosek ${IGL_SCOPE} ${MOSEK_INCLUDE_DIRS})
313  target_compile_definitions(igl_mosek ${IGL_SCOPE} -DLIBIGL_WITH_MOSEK)
314endif()
315
316################################################################################
317### Compile the opengl part ###
318if(LIBIGL_WITH_OPENGL)
319  # OpenGL module
320  compile_igl_module("opengl")
321
322  # OpenGL library
323  if (NOT CMAKE_VERSION VERSION_LESS "3.11")
324    cmake_policy(SET CMP0072 NEW)
325  endif()
326  find_package(OpenGL REQUIRED)
327  if(TARGET OpenGL::GL)
328    target_link_libraries(igl_opengl ${IGL_SCOPE} OpenGL::GL)
329  else()
330    target_link_libraries(igl_opengl ${IGL_SCOPE} ${OPENGL_gl_LIBRARY})
331    target_include_directories(igl_opengl SYSTEM ${IGL_SCOPE} ${OPENGL_INCLUDE_DIR})
332  endif()
333
334  # glad module
335  if(NOT TARGET glad)
336    igl_download_glad()
337    add_subdirectory(${LIBIGL_EXTERNAL}/glad glad)
338  endif()
339  target_link_libraries(igl_opengl ${IGL_SCOPE} glad)
340endif()
341
342################################################################################
343### Compile the GLFW part ###
344if(LIBIGL_WITH_OPENGL_GLFW)
345  if(TARGET igl::opengl)
346    # GLFW module
347    compile_igl_module("opengl/glfw")
348    if(NOT TARGET glfw)
349      set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL " " FORCE)
350      set(GLFW_BUILD_TESTS OFF CACHE BOOL " " FORCE)
351      set(GLFW_BUILD_DOCS OFF CACHE BOOL " " FORCE)
352      set(GLFW_INSTALL OFF CACHE BOOL " " FORCE)
353      igl_download_glfw()
354      add_subdirectory(${LIBIGL_EXTERNAL}/glfw glfw)
355    endif()
356    target_link_libraries(igl_opengl_glfw ${IGL_SCOPE} igl_opengl glfw)
357  endif()
358endif()
359
360################################################################################
361### Compile the ImGui part ###
362if(LIBIGL_WITH_OPENGL_GLFW_IMGUI)
363  if(TARGET igl::opengl_glfw)
364    # ImGui module
365    compile_igl_module("opengl/glfw/imgui")
366    if(NOT TARGET imgui)
367      igl_download_imgui()
368      add_subdirectory(${LIBIGL_EXTERNAL}/libigl-imgui imgui)
369    endif()
370    target_link_libraries(igl_opengl_glfw_imgui ${IGL_SCOPE} igl_opengl_glfw imgui)
371  endif()
372endif()
373
374################################################################################
375### Compile the png part ###
376if(LIBIGL_WITH_PNG)
377  # png/ module is anomalous because it also depends on opengl it really should
378  # be moved into the opengl/ directory and namespace ...
379  if(TARGET igl_opengl)
380    if(NOT TARGET stb_image)
381      igl_download_stb()
382      add_subdirectory(${LIBIGL_EXTERNAL}/stb stb_image)
383    endif()
384    compile_igl_module("png" "")
385    target_link_libraries(igl_png ${IGL_SCOPE} igl_stb_image igl_opengl)
386  endif()
387endif()
388
389################################################################################
390### Compile the tetgen part ###
391if(LIBIGL_WITH_TETGEN)
392  set(TETGEN_DIR "${LIBIGL_EXTERNAL}/tetgen")
393  if(NOT TARGET tetgen)
394    igl_download_tetgen()
395    add_subdirectory("${TETGEN_DIR}" "tetgen")
396  endif()
397  compile_igl_module("tetgen")
398  target_link_libraries(igl_tetgen ${IGL_SCOPE} tetgen)
399  target_include_directories(igl_tetgen ${IGL_SCOPE} ${TETGEN_DIR})
400endif()
401
402################################################################################
403### Compile the triangle part ###
404if(LIBIGL_WITH_TRIANGLE)
405  set(TRIANGLE_DIR "${LIBIGL_EXTERNAL}/triangle")
406  if(NOT TARGET triangle)
407    igl_download_triangle()
408    add_subdirectory("${TRIANGLE_DIR}" "triangle")
409  endif()
410  compile_igl_module("triangle")
411  target_link_libraries(igl_triangle ${IGL_SCOPE} triangle)
412  target_include_directories(igl_triangle ${IGL_SCOPE} ${TRIANGLE_DIR})
413endif()
414
415################################################################################
416### Compile the predicates part ###
417if(LIBIGL_WITH_PREDICATES)
418  set(PREDICATES_DIR "${LIBIGL_EXTERNAL}/predicates")
419  if(NOT TARGET predicates)
420    igl_download_predicates()
421    add_subdirectory("${PREDICATES_DIR}" "predicates")
422  endif()
423  compile_igl_module("predicates")
424  target_link_libraries(igl_predicates ${IGL_SCOPE} predicates)
425  target_include_directories(igl_predicates ${IGL_SCOPE} ${PREDICATES_DIR})
426  target_compile_definitions(igl_predicates ${IGL_SCOPE} -DLIBIGL_WITH_PREDICATES)
427endif()
428
429################################################################################
430### Compile the xml part ###
431if(LIBIGL_WITH_XML)
432  set(TINYXML2_DIR "${LIBIGL_EXTERNAL}/tinyxml2")
433  if(NOT TARGET tinyxml2)
434    igl_download_tinyxml2()
435    add_library(tinyxml2 STATIC ${TINYXML2_DIR}/tinyxml2.cpp ${TINYXML2_DIR}/tinyxml2.h)
436    target_include_directories(tinyxml2 PUBLIC ${TINYXML2_DIR})
437    set_target_properties(tinyxml2 PROPERTIES
438            COMPILE_DEFINITIONS "TINYXML2_EXPORT"
439            VERSION "3.0.0"
440            SOVERSION "3")
441  endif()
442  compile_igl_module("xml")
443  target_link_libraries(igl_xml ${IGL_SCOPE} tinyxml2)
444  target_include_directories(igl_xml ${IGL_SCOPE} ${TINYXML2_DIR})
445endif()
446
447################################################################################
448### Install and export all modules
449
450if(NOT LIBIGL_EXPORT_TARGETS)
451  return()
452endif()
453
454function(install_dir_files dir_name)
455  if (dir_name STREQUAL "core")
456    set(subpath "")
457  else()
458    set(subpath "/${dir_name}")
459  endif()
460
461  file(GLOB public_headers
462    ${CMAKE_CURRENT_SOURCE_DIR}/include/igl${subpath}/*.h
463  )
464
465  set(files_to_install ${public_headers})
466
467  if(NOT LIBIGL_USE_STATIC_LIBRARY)
468    file(GLOB public_sources
469      ${CMAKE_CURRENT_SOURCE_DIR}/include/igl${subpath}/*.cpp
470      ${CMAKE_CURRENT_SOURCE_DIR}/include/igl${subpath}/*.c
471    )
472  endif()
473  list(APPEND files_to_install ${public_sources})
474
475  install(
476    FILES ${files_to_install}
477    DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/igl${subpath}
478  )
479endfunction()
480
481################################################################################
482
483include(GNUInstallDirs)
484include(CMakePackageConfigHelpers)
485
486# Install and export core library
487install(
488   TARGETS
489     igl
490     igl_common
491   EXPORT igl-export
492   PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
493   LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
494   RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
495   ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
496)
497export(
498  TARGETS
499    igl
500    igl_common
501  FILE libigl-export.cmake
502)
503
504# Install headers for core library
505install_dir_files(core)
506install_dir_files(copyleft)
507
508# Write package configuration file
509configure_package_config_file(
510  ${CMAKE_CURRENT_LIST_DIR}/libigl-config.cmake.in
511  ${CMAKE_BINARY_DIR}/libigl-config.cmake
512  INSTALL_DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/libigl/cmake
513)
514install(
515  FILES
516    ${CMAKE_BINARY_DIR}/libigl-config.cmake
517  DESTINATION
518    ${CMAKE_INSTALL_DATADIR}/libigl/cmake
519)
520
521# Write export file
522export(EXPORT igl-export
523  FILE "${CMAKE_BINARY_DIR}/libigl-export.cmake"
524)
525install(EXPORT igl-export DESTINATION ${CMAKE_INSTALL_DATADIR}/libigl/cmake FILE libigl-export.cmake)
526
527
528export(PACKAGE libigl)
529
530