Update release_notes.md
[platform/upstream/caffeonacl.git] / cmake / Utils.cmake
1 ################################################################################################
2 # Command alias for debugging messages
3 # Usage:
4 #   dmsg(<message>)
5 function(dmsg)
6   message(STATUS ${ARGN})
7 endfunction()
8
9 ################################################################################################
10 # Removes duplicates from list(s)
11 # Usage:
12 #   caffe_list_unique(<list_variable> [<list_variable>] [...])
13 macro(caffe_list_unique)
14   foreach(__lst ${ARGN})
15     if(${__lst})
16       list(REMOVE_DUPLICATES ${__lst})
17     endif()
18   endforeach()
19 endmacro()
20
21 ################################################################################################
22 # Clears variables from list
23 # Usage:
24 #   caffe_clear_vars(<variables_list>)
25 macro(caffe_clear_vars)
26   foreach(_var ${ARGN})
27     unset(${_var})
28   endforeach()
29 endmacro()
30
31 ################################################################################################
32 # Removes duplicates from string
33 # Usage:
34 #   caffe_string_unique(<string_variable>)
35 function(caffe_string_unique __string)
36   if(${__string})
37     set(__list ${${__string}})
38     separate_arguments(__list)
39     list(REMOVE_DUPLICATES __list)
40     foreach(__e ${__list})
41       set(__str "${__str} ${__e}")
42     endforeach()
43     set(${__string} ${__str} PARENT_SCOPE)
44   endif()
45 endfunction()
46
47 ################################################################################################
48 # Prints list element per line
49 # Usage:
50 #   caffe_print_list(<list>)
51 function(caffe_print_list)
52   foreach(e ${ARGN})
53     message(STATUS ${e})
54   endforeach()
55 endfunction()
56
57 ################################################################################################
58 # Function merging lists of compiler flags to single string.
59 # Usage:
60 #   caffe_merge_flag_lists(out_variable <list1> [<list2>] [<list3>] ...)
61 function(caffe_merge_flag_lists out_var)
62   set(__result "")
63   foreach(__list ${ARGN})
64     foreach(__flag ${${__list}})
65       string(STRIP ${__flag} __flag)
66       set(__result "${__result} ${__flag}")
67     endforeach()
68   endforeach()
69   string(STRIP ${__result} __result)
70   set(${out_var} ${__result} PARENT_SCOPE)
71 endfunction()
72
73 ################################################################################################
74 # Converts all paths in list to absolute
75 # Usage:
76 #   caffe_convert_absolute_paths(<list_variable>)
77 function(caffe_convert_absolute_paths variable)
78   set(__dlist "")
79   foreach(__s ${${variable}})
80     get_filename_component(__abspath ${__s} ABSOLUTE)
81     list(APPEND __list ${__abspath})
82   endforeach()
83   set(${variable} ${__list} PARENT_SCOPE)
84 endfunction()
85
86 ################################################################################################
87 # Reads set of version defines from the header file
88 # Usage:
89 #   caffe_parse_header(<file> <define1> <define2> <define3> ..)
90 macro(caffe_parse_header FILENAME FILE_VAR)
91   set(vars_regex "")
92   set(__parnet_scope OFF)
93   set(__add_cache OFF)
94   foreach(name ${ARGN})
95     if("${name}" STREQUAL "PARENT_SCOPE")
96       set(__parnet_scope ON)
97     elseif("${name}" STREQUAL "CACHE")
98       set(__add_cache ON)
99     elseif(vars_regex)
100       set(vars_regex "${vars_regex}|${name}")
101     else()
102       set(vars_regex "${name}")
103     endif()
104   endforeach()
105   if(EXISTS "${FILENAME}")
106     file(STRINGS "${FILENAME}" ${FILE_VAR} REGEX "#define[ \t]+(${vars_regex})[ \t]+[0-9]+" )
107   else()
108     unset(${FILE_VAR})
109   endif()
110   foreach(name ${ARGN})
111     if(NOT "${name}" STREQUAL "PARENT_SCOPE" AND NOT "${name}" STREQUAL "CACHE")
112       if(${FILE_VAR})
113         if(${FILE_VAR} MATCHES ".+[ \t]${name}[ \t]+([0-9]+).*")
114           string(REGEX REPLACE ".+[ \t]${name}[ \t]+([0-9]+).*" "\\1" ${name} "${${FILE_VAR}}")
115         else()
116           set(${name} "")
117         endif()
118         if(__add_cache)
119           set(${name} ${${name}} CACHE INTERNAL "${name} parsed from ${FILENAME}" FORCE)
120         elseif(__parnet_scope)
121           set(${name} "${${name}}" PARENT_SCOPE)
122         endif()
123       else()
124         unset(${name} CACHE)
125       endif()
126     endif()
127   endforeach()
128 endmacro()
129
130 ################################################################################################
131 # Reads single version define from the header file and parses it
132 # Usage:
133 #   caffe_parse_header_single_define(<library_name> <file> <define_name>)
134 function(caffe_parse_header_single_define LIBNAME HDR_PATH VARNAME)
135   set(${LIBNAME}_H "")
136   if(EXISTS "${HDR_PATH}")
137     file(STRINGS "${HDR_PATH}" ${LIBNAME}_H REGEX "^#define[ \t]+${VARNAME}[ \t]+\"[^\"]*\".*$" LIMIT_COUNT 1)
138   endif()
139
140   if(${LIBNAME}_H)
141     string(REGEX REPLACE "^.*[ \t]${VARNAME}[ \t]+\"([0-9]+).*$" "\\1" ${LIBNAME}_VERSION_MAJOR "${${LIBNAME}_H}")
142     string(REGEX REPLACE "^.*[ \t]${VARNAME}[ \t]+\"[0-9]+\\.([0-9]+).*$" "\\1" ${LIBNAME}_VERSION_MINOR  "${${LIBNAME}_H}")
143     string(REGEX REPLACE "^.*[ \t]${VARNAME}[ \t]+\"[0-9]+\\.[0-9]+\\.([0-9]+).*$" "\\1" ${LIBNAME}_VERSION_PATCH "${${LIBNAME}_H}")
144     set(${LIBNAME}_VERSION_MAJOR ${${LIBNAME}_VERSION_MAJOR} ${ARGN} PARENT_SCOPE)
145     set(${LIBNAME}_VERSION_MINOR ${${LIBNAME}_VERSION_MINOR} ${ARGN} PARENT_SCOPE)
146     set(${LIBNAME}_VERSION_PATCH ${${LIBNAME}_VERSION_PATCH} ${ARGN} PARENT_SCOPE)
147     set(${LIBNAME}_VERSION_STRING "${${LIBNAME}_VERSION_MAJOR}.${${LIBNAME}_VERSION_MINOR}.${${LIBNAME}_VERSION_PATCH}" PARENT_SCOPE)
148
149     # append a TWEAK version if it exists:
150     set(${LIBNAME}_VERSION_TWEAK "")
151     if("${${LIBNAME}_H}" MATCHES "^.*[ \t]${VARNAME}[ \t]+\"[0-9]+\\.[0-9]+\\.[0-9]+\\.([0-9]+).*$")
152       set(${LIBNAME}_VERSION_TWEAK "${CMAKE_MATCH_1}" ${ARGN} PARENT_SCOPE)
153     endif()
154     if(${LIBNAME}_VERSION_TWEAK)
155       set(${LIBNAME}_VERSION_STRING "${${LIBNAME}_VERSION_STRING}.${${LIBNAME}_VERSION_TWEAK}" ${ARGN} PARENT_SCOPE)
156     else()
157       set(${LIBNAME}_VERSION_STRING "${${LIBNAME}_VERSION_STRING}" ${ARGN} PARENT_SCOPE)
158     endif()
159   endif()
160 endfunction()
161
162 ########################################################################################################
163 # An option that the user can select. Can accept condition to control when option is available for user.
164 # Usage:
165 #   caffe_option(<option_variable> "doc string" <initial value or boolean expression> [IF <condition>])
166 function(caffe_option variable description value)
167   set(__value ${value})
168   set(__condition "")
169   set(__varname "__value")
170   foreach(arg ${ARGN})
171     if(arg STREQUAL "IF" OR arg STREQUAL "if")
172       set(__varname "__condition")
173     else()
174       list(APPEND ${__varname} ${arg})
175     endif()
176   endforeach()
177   unset(__varname)
178   if("${__condition}" STREQUAL "")
179     set(__condition 2 GREATER 1)
180   endif()
181
182   if(${__condition})
183     if("${__value}" MATCHES ";")
184       if(${__value})
185         option(${variable} "${description}" ON)
186       else()
187         option(${variable} "${description}" OFF)
188       endif()
189     elseif(DEFINED ${__value})
190       if(${__value})
191         option(${variable} "${description}" ON)
192       else()
193         option(${variable} "${description}" OFF)
194       endif()
195     else()
196       option(${variable} "${description}" ${__value})
197     endif()
198   else()
199     unset(${variable} CACHE)
200   endif()
201 endfunction()
202
203 ################################################################################################
204 # Utility macro for comparing two lists. Used for CMake debugging purposes
205 # Usage:
206 #   caffe_compare_lists(<list_variable> <list2_variable> [description])
207 function(caffe_compare_lists list1 list2 desc)
208   set(__list1 ${${list1}})
209   set(__list2 ${${list2}})
210   list(SORT __list1)
211   list(SORT __list2)
212   list(LENGTH __list1 __len1)
213   list(LENGTH __list2 __len2)
214
215   if(NOT ${__len1} EQUAL ${__len2})
216     message(FATAL_ERROR "Lists are not equal. ${__len1} != ${__len2}. ${desc}")
217   endif()
218
219   foreach(__i RANGE 1 ${__len1})
220     math(EXPR __index "${__i}- 1")
221     list(GET __list1 ${__index} __item1)
222     list(GET __list2 ${__index} __item2)
223     if(NOT ${__item1} STREQUAL ${__item2})
224       message(FATAL_ERROR "Lists are not equal. Differ at element ${__index}. ${desc}")
225     endif()
226   endforeach()
227 endfunction()
228
229 ################################################################################################
230 # Command for disabling warnings for different platforms (see below for gcc and VisualStudio)
231 # Usage:
232 #   caffe_warnings_disable(<CMAKE_[C|CXX]_FLAGS[_CONFIGURATION]> -Wshadow /wd4996 ..,)
233 macro(caffe_warnings_disable)
234   set(_flag_vars "")
235   set(_msvc_warnings "")
236   set(_gxx_warnings "")
237
238   foreach(arg ${ARGN})
239     if(arg MATCHES "^CMAKE_")
240       list(APPEND _flag_vars ${arg})
241     elseif(arg MATCHES "^/wd")
242       list(APPEND _msvc_warnings ${arg})
243     elseif(arg MATCHES "^-W")
244       list(APPEND _gxx_warnings ${arg})
245     endif()
246   endforeach()
247
248   if(NOT _flag_vars)
249     set(_flag_vars CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
250   endif()
251
252   if(MSVC AND _msvc_warnings)
253     foreach(var ${_flag_vars})
254       foreach(warning ${_msvc_warnings})
255         set(${var} "${${var}} ${warning}")
256       endforeach()
257     endforeach()
258   elseif((CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANGXX) AND _gxx_warnings)
259     foreach(var ${_flag_vars})
260       foreach(warning ${_gxx_warnings})
261         if(NOT warning MATCHES "^-Wno-")
262           string(REPLACE "${warning}" "" ${var} "${${var}}")
263           string(REPLACE "-W" "-Wno-" warning "${warning}")
264         endif()
265         set(${var} "${${var}} ${warning}")
266       endforeach()
267     endforeach()
268   endif()
269   caffe_clear_vars(_flag_vars _msvc_warnings _gxx_warnings)
270 endmacro()
271
272 ################################################################################################
273 # Helper function get current definitions
274 # Usage:
275 #   caffe_get_current_definitions(<definitions_variable>)
276 function(caffe_get_current_definitions definitions_var)
277   get_property(current_definitions DIRECTORY PROPERTY COMPILE_DEFINITIONS)
278   set(result "")
279
280   foreach(d ${current_definitions})
281     list(APPEND result -D${d})
282   endforeach()
283
284   caffe_list_unique(result)
285   set(${definitions_var} ${result} PARENT_SCOPE)
286 endfunction()
287
288 ################################################################################################
289 # Helper function get current includes/definitions
290 # Usage:
291 #   caffe_get_current_cflags(<cflagslist_variable>)
292 function(caffe_get_current_cflags cflags_var)
293   get_property(current_includes DIRECTORY PROPERTY INCLUDE_DIRECTORIES)
294   caffe_convert_absolute_paths(current_includes)
295   caffe_get_current_definitions(cflags)
296
297   foreach(i ${current_includes})
298     list(APPEND cflags "-I${i}")
299   endforeach()
300
301   caffe_list_unique(cflags)
302   set(${cflags_var} ${cflags} PARENT_SCOPE)
303 endfunction()
304
305 ################################################################################################
306 # Helper function to parse current linker libs into link directories, libflags and osx frameworks
307 # Usage:
308 #   caffe_parse_linker_libs(<Caffe_LINKER_LIBS_var> <directories_var> <libflags_var> <frameworks_var>)
309 function(caffe_parse_linker_libs Caffe_LINKER_LIBS_variable folders_var flags_var frameworks_var)
310
311   set(__unspec "")
312   set(__debug "")
313   set(__optimized "")
314   set(__framework "")
315   set(__varname "__unspec")
316
317   # split libs into debug, optimized, unspecified and frameworks
318   foreach(list_elem ${${Caffe_LINKER_LIBS_variable}})
319     if(list_elem STREQUAL "debug")
320       set(__varname "__debug")
321     elseif(list_elem STREQUAL "optimized")
322       set(__varname "__optimized")
323     elseif(list_elem MATCHES "^-framework[ \t]+([^ \t].*)")
324       list(APPEND __framework -framework ${CMAKE_MATCH_1})
325     else()
326       list(APPEND ${__varname} ${list_elem})
327       set(__varname "__unspec")
328     endif()
329   endforeach()
330
331   # attach debug or optimized libs to unspecified according to current configuration
332   if(CMAKE_BUILD_TYPE MATCHES "Debug")
333     set(__libs ${__unspec} ${__debug})
334   else()
335     set(__libs ${__unspec} ${__optimized})
336   endif()
337
338   set(libflags "")
339   set(folders "")
340
341   # convert linker libraries list to link flags
342   foreach(lib ${__libs})
343     if(TARGET ${lib})
344       list(APPEND folders $<TARGET_LINKER_FILE_DIR:${lib}>)
345       list(APPEND libflags -l${lib})
346     elseif(lib MATCHES "^-l.*")
347       list(APPEND libflags ${lib})
348     elseif(IS_ABSOLUTE ${lib})
349       get_filename_component(folder  ${lib} PATH)
350       get_filename_component(filename ${lib} NAME)
351       string(REGEX REPLACE "\\.[^.]*$" "" filename_without_shortest_ext ${filename})
352
353       string(REGEX MATCH "^lib(.*)" __match ${filename_without_shortest_ext})
354       list(APPEND libflags -l${CMAKE_MATCH_1})
355       list(APPEND folders    ${folder})
356     else()
357       message(FATAL_ERROR "Logic error. Need to update cmake script")
358     endif()
359   endforeach()
360
361   caffe_list_unique(libflags folders)
362
363   set(${folders_var} ${folders} PARENT_SCOPE)
364   set(${flags_var} ${libflags} PARENT_SCOPE)
365   set(${frameworks_var} ${__framework} PARENT_SCOPE)
366 endfunction()
367
368 ################################################################################################
369 # Helper function to detect Darwin version, i.e. 10.8, 10.9, 10.10, ....
370 # Usage:
371 #   caffe_detect_darwin_version(<version_variable>)
372 function(caffe_detect_darwin_version output_var)
373   if(APPLE)
374     execute_process(COMMAND /usr/bin/sw_vers -productVersion
375                     RESULT_VARIABLE __sw_vers OUTPUT_VARIABLE __sw_vers_out
376                     ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
377
378     set(${output_var} ${__sw_vers_out} PARENT_SCOPE)
379   else()
380     set(${output_var} "" PARENT_SCOPE)
381   endif()
382 endfunction()