1# Copyright 2021 The Draco Authors
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#      http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15if(DRACO_CMAKE_DRACO_OPTIONS_CMAKE_)
16  return()
17endif() # DRACO_CMAKE_DRACO_OPTIONS_CMAKE_
18set(DRACO_CMAKE_DRACO_OPTIONS_CMAKE_)
19
20set(draco_features_file_name "${draco_build}/draco/draco_features.h")
21set(draco_features_list)
22
23# Simple wrapper for CMake's builtin option command that tracks draco's build
24# options in the list variable $draco_options.
25macro(draco_option)
26  unset(option_NAME)
27  unset(option_HELPSTRING)
28  unset(option_VALUE)
29  unset(optional_args)
30  unset(multi_value_args)
31  set(single_value_args NAME HELPSTRING VALUE)
32  cmake_parse_arguments(option "${optional_args}" "${single_value_args}"
33                        "${multi_value_args}" ${ARGN})
34
35  if(NOT (option_NAME AND option_HELPSTRING AND DEFINED option_VALUE))
36    message(FATAL_ERROR "draco_option: NAME HELPSTRING and VALUE required.")
37  endif()
38
39  option(${option_NAME} ${option_HELPSTRING} ${option_VALUE})
40
41  if(DRACO_VERBOSE GREATER 2)
42    message("--------- draco_option ---------\n" "option_NAME=${option_NAME}\n"
43            "option_HELPSTRING=${option_HELPSTRING}\n"
44            "option_VALUE=${option_VALUE}\n"
45            "------------------------------------------\n")
46  endif()
47
48  list(APPEND draco_options ${option_NAME})
49  list(REMOVE_DUPLICATES draco_options)
50endmacro()
51
52# Dumps the $draco_options list via CMake message command.
53macro(draco_dump_options)
54  foreach(option_name ${draco_options})
55    message("${option_name}: ${${option_name}}")
56  endforeach()
57endmacro()
58
59# Set default options.
60macro(draco_set_default_options)
61  draco_option(NAME DRACO_FAST HELPSTRING "Try to build faster libs." VALUE OFF)
62  draco_option(NAME DRACO_JS_GLUE HELPSTRING
63               "Enable JS Glue and JS targets when using Emscripten." VALUE ON)
64  draco_option(NAME DRACO_IE_COMPATIBLE HELPSTRING
65               "Enable support for older IE builds when using Emscripten." VALUE
66               OFF)
67  draco_option(NAME DRACO_MESH_COMPRESSION HELPSTRING "Enable mesh compression."
68               VALUE ON)
69  draco_option(NAME DRACO_POINT_CLOUD_COMPRESSION HELPSTRING
70               "Enable point cloud compression." VALUE ON)
71  draco_option(NAME DRACO_PREDICTIVE_EDGEBREAKER HELPSTRING
72               "Enable predictive edgebreaker." VALUE ON)
73  draco_option(NAME DRACO_STANDARD_EDGEBREAKER HELPSTRING
74               "Enable stand edgebreaker." VALUE ON)
75  draco_option(NAME DRACO_BACKWARDS_COMPATIBILITY HELPSTRING
76               "Enable backwards compatibility." VALUE ON)
77  draco_option(NAME DRACO_DECODER_ATTRIBUTE_DEDUPLICATION HELPSTRING
78               "Enable attribute deduping." VALUE OFF)
79  draco_option(NAME DRACO_TESTS HELPSTRING "Enables tests." VALUE OFF)
80  draco_option(NAME DRACO_WASM HELPSTRING "Enables WASM support." VALUE OFF)
81  draco_option(NAME DRACO_UNITY_PLUGIN HELPSTRING
82               "Build plugin library for Unity." VALUE OFF)
83  draco_option(NAME DRACO_ANIMATION_ENCODING HELPSTRING "Enable animation."
84               VALUE OFF)
85  draco_option(NAME DRACO_GLTF HELPSTRING "Support GLTF." VALUE OFF)
86  draco_option(NAME DRACO_MAYA_PLUGIN HELPSTRING
87               "Build plugin library for Maya." VALUE OFF)
88  draco_check_deprecated_options()
89endmacro()
90
91# Warns when a deprecated option is used and sets the option that replaced it.
92macro(draco_handle_deprecated_option)
93  unset(option_OLDNAME)
94  unset(option_NEWNAME)
95  unset(optional_args)
96  unset(multi_value_args)
97  set(single_value_args OLDNAME NEWNAME)
98  cmake_parse_arguments(option "${optional_args}" "${single_value_args}"
99                        "${multi_value_args}" ${ARGN})
100
101  if("${${option_OLDNAME}}")
102    message(WARNING "${option_OLDNAME} is deprecated. Use ${option_NEWNAME}.")
103    set(${option_NEWNAME} ${${option_OLDNAME}})
104  endif()
105endmacro()
106
107# Checks for use of deprecated options.
108macro(draco_check_deprecated_options)
109  draco_handle_deprecated_option(OLDNAME ENABLE_EXTRA_SPEED NEWNAME DRACO_FAST)
110  draco_handle_deprecated_option(OLDNAME ENABLE_JS_GLUE NEWNAME DRACO_JS_GLUE)
111  draco_handle_deprecated_option(OLDNAME ENABLE_MESH_COMPRESSION NEWNAME
112                                 DRACO_MESH_COMPRESSION)
113  draco_handle_deprecated_option(OLDNAME ENABLE_POINT_CLOUD_COMPRESSION NEWNAME
114                                 DRACO_POINT_CLOUD_COMPRESSION)
115  draco_handle_deprecated_option(OLDNAME ENABLE_PREDICTIVE_EDGEBREAKER NEWNAME
116                                 DRACO_PREDICTIVE_EDGEBREAKER)
117  draco_handle_deprecated_option(OLDNAME ENABLE_STANDARD_EDGEBREAKER NEWNAME
118                                 DRACO_STANDARD_EDGEBREAKER)
119  draco_handle_deprecated_option(OLDNAME ENABLE_BACKWARDS_COMPATIBILITY NEWNAME
120                                 DRACO_BACKWARDS_COMPATIBILITY)
121  draco_handle_deprecated_option(OLDNAME ENABLE_DECODER_ATTRIBUTE_DEDUPLICATION
122                                 NEWNAME DRACO_DECODER_ATTRIBUTE_DEDUPLICATION)
123  draco_handle_deprecated_option(OLDNAME ENABLE_TESTS NEWNAME DRACO_TESTS)
124  draco_handle_deprecated_option(OLDNAME ENABLE_WASM NEWNAME DRACO_WASM)
125  draco_handle_deprecated_option(OLDNAME BUILD_UNITY_PLUGIN NEWNAME
126                                 DRACO_UNITY_PLUGIN)
127  draco_handle_deprecated_option(OLDNAME BUILD_ANIMATION_ENCODING NEWNAME
128                                 DRACO_ANIMATION_ENCODING)
129  draco_handle_deprecated_option(OLDNAME BUILD_FOR_GLTF NEWNAME DRACO_GLTF)
130  draco_handle_deprecated_option(OLDNAME BUILD_MAYA_PLUGIN NEWNAME
131                                 DRACO_MAYA_PLUGIN)
132  draco_handle_deprecated_option(OLDNAME BUILD_USD_PLUGIN NEWNAME
133                                 BUILD_SHARED_LIBS)
134
135endmacro()
136
137# Macro for setting Draco features based on user configuration. Features enabled
138# by this macro are Draco global.
139macro(draco_set_optional_features)
140  if(DRACO_GLTF)
141    # Override settings when building for GLTF.
142    draco_enable_feature(FEATURE "DRACO_MESH_COMPRESSION_SUPPORTED")
143    draco_enable_feature(FEATURE "DRACO_NORMAL_ENCODING_SUPPORTED")
144    draco_enable_feature(FEATURE "DRACO_STANDARD_EDGEBREAKER_SUPPORTED")
145  else()
146    if(DRACO_POINT_CLOUD_COMPRESSION)
147      draco_enable_feature(FEATURE "DRACO_POINT_CLOUD_COMPRESSION_SUPPORTED")
148    endif()
149    if(DRACO_MESH_COMPRESSION)
150      draco_enable_feature(FEATURE "DRACO_MESH_COMPRESSION_SUPPORTED")
151      draco_enable_feature(FEATURE "DRACO_NORMAL_ENCODING_SUPPORTED")
152
153      if(DRACO_STANDARD_EDGEBREAKER)
154        draco_enable_feature(FEATURE "DRACO_STANDARD_EDGEBREAKER_SUPPORTED")
155      endif()
156      if(DRACO_PREDICTIVE_EDGEBREAKER)
157        draco_enable_feature(FEATURE "DRACO_PREDICTIVE_EDGEBREAKER_SUPPORTED")
158      endif()
159    endif()
160
161    if(DRACO_BACKWARDS_COMPATIBILITY)
162      draco_enable_feature(FEATURE "DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED")
163    endif()
164
165
166    if(NOT EMSCRIPTEN)
167      # For now, enable deduplication for both encoder and decoder.
168      # TODO(ostava): Support for disabling attribute deduplication for the C++
169      # decoder is planned in future releases.
170      draco_enable_feature(FEATURE
171                           DRACO_ATTRIBUTE_INDICES_DEDUPLICATION_SUPPORTED)
172      draco_enable_feature(FEATURE
173                           DRACO_ATTRIBUTE_VALUES_DEDUPLICATION_SUPPORTED)
174    endif()
175  endif()
176
177  if(DRACO_UNITY_PLUGIN)
178    draco_enable_feature(FEATURE "DRACO_UNITY_PLUGIN")
179    set(CMAKE_POSITION_INDEPENDENT_CODE ON)
180  endif()
181
182  if(DRACO_MAYA_PLUGIN)
183    draco_enable_feature(FEATURE "DRACO_MAYA_PLUGIN")
184    set(CMAKE_POSITION_INDEPENDENT_CODE ON)
185  endif()
186
187endmacro()
188
189# Macro that handles tracking of Draco preprocessor symbols for the purpose of
190# producing draco_features.h.
191#
192# ~~~
193# draco_enable_feature(FEATURE <feature_name> [TARGETS <target_name>])
194# ~~~
195#
196# FEATURE  is required. It should be a Draco preprocessor symbol. TARGETS is
197# optional. It can be one or more draco targets.
198#
199# When the TARGETS argument is not present the preproc symbol is added to
200# draco_features.h. When it is draco_features.h is unchanged, and
201# target_compile_options() is called for each target specified.
202macro(draco_enable_feature)
203  set(def_flags)
204  set(def_single_arg_opts FEATURE)
205  set(def_multi_arg_opts TARGETS)
206  cmake_parse_arguments(DEF "${def_flags}" "${def_single_arg_opts}"
207                        "${def_multi_arg_opts}" ${ARGN})
208  if("${DEF_FEATURE}" STREQUAL "")
209    message(FATAL_ERROR "Empty FEATURE passed to draco_enable_feature().")
210  endif()
211
212  # Do nothing/return early if $DEF_FEATURE is already in the list.
213  list(FIND draco_features_list ${DEF_FEATURE} df_index)
214  if(NOT df_index EQUAL -1)
215    return()
216  endif()
217
218  list(LENGTH DEF_TARGETS df_targets_list_length)
219  if(${df_targets_list_length} EQUAL 0)
220    list(APPEND draco_features_list ${DEF_FEATURE})
221  else()
222    foreach(target ${DEF_TARGETS})
223      target_compile_definitions(${target} PRIVATE ${DEF_FEATURE})
224    endforeach()
225  endif()
226endmacro()
227
228# Function for generating draco_features.h.
229function(draco_generate_features_h)
230  file(WRITE "${draco_features_file_name}.new"
231       "// GENERATED FILE -- DO NOT EDIT\n\n" "#ifndef DRACO_FEATURES_H_\n"
232       "#define DRACO_FEATURES_H_\n\n")
233
234  foreach(feature ${draco_features_list})
235    file(APPEND "${draco_features_file_name}.new" "#define ${feature}\n")
236  endforeach()
237
238  file(APPEND "${draco_features_file_name}.new"
239       "\n#endif  // DRACO_FEATURES_H_")
240
241  # Will replace ${draco_features_file_name} only if the file content has
242  # changed. This prevents forced Draco rebuilds after CMake runs.
243  configure_file("${draco_features_file_name}.new"
244                 "${draco_features_file_name}")
245  file(REMOVE "${draco_features_file_name}.new")
246endfunction()
247
248# Sets default options for the build and processes user controlled options to
249# compute enabled features.
250macro(draco_setup_options)
251  draco_set_default_options()
252  draco_set_optional_features()
253endmacro()
254