Changes for Root6 (Mikolaj)
[u/mrichter/AliRoot.git] / cmake / CMakeALICE.cmake
1 # **************************************************************************
2 # * Copyright(c) 1998-2014, ALICE Experiment at CERN, All rights reserved. *
3 # *                                                                        *
4 # * Author: The ALICE Off-line Project.                                    *
5 # * Contributors are mentioned in the code where appropriate.              *
6 # *                                                                        *
7 # * Permission to use, copy, modify and distribute this software and its   *
8 # * documentation strictly for non-commercial purposes is hereby granted   *
9 # * without fee, provided that the above copyright notice appears in all   *
10 # * copies and that both the copyright notice and this permission notice   *
11 # * appear in the supporting documentation. The authors make no claims     *
12 # * about the suitability of this software for any purpose. It is          *
13 # * provided "as is" without express or implied warranty.                  *
14 # **************************************************************************
15
16 # General purpose functions
17
18 #########################
19 # ROOT utilities
20 #########################
21
22 # Generation of the dictionaries
23 # @DNAME  Dictionary name
24 # @LDNAME LinkDef file name, ex: LinkDef.h
25 # @DHDRS  Dictionary headers
26 # @DINCDIR Include folders that need to be passed to cint/cling
27 # @EXTRADEFINITIONS - optional, extra compile flags specific to library
28 #       - used as ${ARGV4}
29 macro(generate_dictionary DNAME LDNAME DHDRS DINCDIRS)
30
31     # Creating the INCLUDE path for cint/cling
32     foreach( dir ${DINCDIRS})
33         set(INCLUDE_PATH -I${dir} ${INCLUDE_PATH})
34     endforeach()
35     
36     # Get the list of definitions from the directory to be sent to CINT
37     get_directory_property(tmpdirdefs COMPILE_DEFINITIONS)
38     foreach(dirdef ${tmpdirdefs})
39         set(GLOBALDEFINITIONS -D${dirdef} ${GLOBALDEFINITIONS})
40     endforeach()
41     
42     # Custom definitions specific to library
43     # Received as the forth optional argument
44     separate_arguments(EXTRADEFINITIONS UNIX_COMMAND "${ARGV4}")
45
46     if (ROOT_VERSION_MAJOR LESS 6)
47     add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/G__${DNAME}.cxx ${CMAKE_CURRENT_BINARY_DIR}/G__${DNAME}.h
48                        COMMAND LD_LIBRARY_PATH=${ROOT_LIBDIR}:$ENV{LD_LIBRARY_PATH} ${ROOT_CINT}
49                        ARGS -f ${CMAKE_CURRENT_BINARY_DIR}/G__${DNAME}.cxx -c -p 
50                        ${GLOBALDEFINITIONS} ${EXTRADEFINITIONS} ${INCLUDE_PATH} 
51                        ${DHDRS} ${LDNAME}
52                        DEPENDS ${DHDRS} ${LDNAME} ${ROOT_CINT}
53                        WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
54                       )
55     else (ROOT_VERSION_MAJOR LESS 6)
56       add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/lib${DNAME}.rootmap ${CMAKE_CURRENT_BINARY_DIR}/G__${DNAME}.cxx ${CMAKE_CURRENT_BINARY_DIR}/G__${DNAME}_rdict.pcm
57                        COMMAND
58                          LD_LIBRARY_PATH=${ROOT_LIBDIR}:$ENV{LD_LIBRARY_PATH} ${ROOT_CINT}
59                        ARGS
60                          -f ${CMAKE_CURRENT_BINARY_DIR}/G__${DNAME}.cxx
61                          -rmf ${CMAKE_CURRENT_BINARY_DIR}/lib${DNAME}.rootmap -rml lib${DNAME}
62                          ${GLOBALDEFINITIONS} ${EXTRADEFINITIONS} ${INCLUDE_PATH} ${DHDRS} ${LDNAME}
63                        DEPENDS
64                          ${DHDRS} ${LDNAME} ${ROOT_CINT}
65                        WORKING_DIRECTORY
66                          ${CMAKE_CURRENT_BINARY_DIR}
67                       )
68
69     install(FILES "${CMAKE_CURRENT_BINARY_DIR}/lib${DNAME}.rootmap" DESTINATION lib)
70     install(FILES "${CMAKE_CURRENT_BINARY_DIR}/G__${DNAME}_rdict.pcm" DESTINATION lib)
71     
72     endif (ROOT_VERSION_MAJOR LESS 6)
73
74 endmacro(generate_dictionary)
75
76 # Generate the ROOTmap files
77 # @LIBNAME - library name: libAnalysis.so -> Analysis.rootmap
78 # @LIBDEPS - library dependencies
79 # @LINKDEF - LinkDef header
80 macro(generate_rootmap LIBNAME LIBDEPS LINKDEF)
81 #    message(STATUS "LIBNAME = ${LIBNAME}")
82 #    message(STATUS "LIBDEPS = ${LIBDEPS}")
83 #    message(STATUS "LINKDEF = ${LINKDEF}")
84 #    message(STATUS "ROOT_LIBMAP=${ROOT_LIBMAP}")
85
86 if (ROOT_VERSION_MAJOR LESS 6)
87
88     set(LOCAL_DEPS)
89     foreach(file ${LIBDEPS})
90         get_filename_component(ext ${file} EXT)
91         if(ext)
92             set(LOCAL_DEPS ${LOCAL_DEPS} ${file})
93         else()
94             set(LOCAL_DEPS ${LOCAL_DEPS} lib${file})
95         endif()
96     endforeach()
97
98 #    message(STATUS "Generating ROOT map for ${LIBNAME}")
99     add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/lib${LIBNAME}.rootmap
100                        COMMAND LD_LIBRARY_PATH=${ROOT_LIBDIR}:$ENV{LD_LIBRARY_PATH} ${ROOT_LIBMAP}
101                        ARGS -o ${CMAKE_CURRENT_BINARY_DIR}/lib${LIBNAME}.rootmap -l lib${LIBNAME} -d ${LOCAL_DEPS} -c ${LINKDEF}
102                        DEPENDS ${LIBNAME}
103                        WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} VERBATIM
104                       )
105     add_custom_target(lib${LIBNAME}.rootmap ALL DEPENDS  ${CMAKE_CURRENT_BINARY_DIR}/lib${LIBNAME}.rootmap)
106     install(FILES ${CMAKE_CURRENT_BINARY_DIR}/lib${LIBNAME}.rootmap DESTINATION lib)
107
108 endif (ROOT_VERSION_MAJOR LESS 6)
109
110 endmacro(generate_rootmap)
111
112 #########################
113 # Static utilities
114 #########################
115
116 # Generate the static dependecies from dynamic list
117 # @ shared_list - list of shared libraries
118 # @ static_list - the name of the variable that will contain the list of static libraries
119 macro(generate_static_dependencies shared_list static_list)
120     set(static_list_tmp "")
121     foreach(shared_lib ${shared_list})
122         set(static_list_tmp ${static_list_tmp} "${shared_lib}-static")
123     endforeach()
124     
125     # create the variable with the name received by the macro
126     set(${static_list} ${static_list_tmp})
127     # set the scope to parent in order to be visible in the parent
128     set(${static_list} PARENT_SCOPE)
129 endmacro(generate_static_dependencies)
130
131 #########################
132 # DA utilities
133 #########################
134
135 # Extract the first comment from a DA file
136 # Find the position for first /* and */ and extract the substring
137 macro(getDAdescription _detector _daname)
138     # Reading the file into a string
139     file(READ "${_detector}${_daname}da.cxx" tmpinfo)
140     
141     # Find the first occurance of /* */
142     string(FIND "${tmpinfo}" "/*" _first_position)
143     string(FIND "${tmpinfo}" "*/" _second_position)
144     
145     # Adding and removing 2 characters to remove /* */
146     math(EXPR _first_position ${_first_position}+2)
147     math(EXPR _second_position ${_second_position}-2)
148     
149     # Generating the length of the comment in order to take out the description
150     math(EXPR _desc_length ${_second_position}-${_first_position})
151     
152     if(${_desc_length} EQUAL 0 OR ${_desc_length} LESS 0)
153         message(FATAL_ERROR "{_detector}${_daname}da.cxx does not contain a description. Please add the description as the first /*comment*/ in the file")
154     else()
155         string(SUBSTRING "${tmpinfo}" ${_first_position}  ${_second_position} _da_description)
156         string(STRIP "${_da_description}" _da_description)
157         
158         # The variable can be accesed by the parent
159         set(RPM_DESCRIPTION ${_da_description})
160     endif()
161 endmacro()
162
163 # Set the compilation flags
164 macro(setDAflags)
165     # DIM
166     link_directories(${DIMDIR}/${ODIR})
167
168     #daqDA flags
169     include_directories(${daqDA})
170     link_directories(${daqDA})
171
172     # AMORE definitions
173     add_definitions(${AMORE_DEFINITIONS})
174     include_directories(${AMORE_INCLUDE_DIR})
175
176 endmacro()
177
178 # Generate a DA
179 macro(generateDA DETECTOR ALGORITHM STATIC_DEPENDENCIES)
180     setDAflags()
181
182     # Generating the DA executable
183     add_executable(${DETECTOR}${ALGORITHM}da.exe ${DETECTOR}${ALGORITHM}da.cxx) #
184
185     # DA flags and linking information
186     set(MODULE_COMPILE_FLAGS)
187     set(MODULE_LINK_FLAGS)
188
189     target_link_libraries(${DETECTOR}${ALGORITHM}da.exe ${STATIC_DEPENDENCIES} ${AMORE_AUXLIBS} daqDA ${DATE_MONLIBRARIES} ${DATE_RCPROXYLIBRARIES} Root RootExtra) # 1
190
191     # different flags
192     set(MODULE_COMPILE_FLAGS "  ${DATE_CFLAGS} ${AMORE_CFLAGS}")
193     set(MODULE_LINK_FLAGS "${DATE_LDFLAGS} ${AMORE_STATICLIBS}")
194
195     set_target_properties(${DETECTOR}${ALGORITHM}da.exe PROPERTIES COMPILE_FLAGS ${MODULE_COMPILE_FLAGS})
196     set_target_properties(${DETECTOR}${ALGORITHM}da.exe PROPERTIES LINK_FLAGS "${MODULE_LINK_FLAGS}")
197
198     # Installation
199     install(TARGETS ${DETECTOR}${ALGORITHM}da.exe RUNTIME DESTINATION bin)
200     
201     if(DARPM)
202         createDArpm("${DETECTOR}" "${ALGORITHM}")
203     endif(DARPM)
204 endmacro()
205
206 # DA rpm creation
207 macro(createDArpm DETECTOR ALGORITHM)
208     getDAdescription("${DETECTOR}" "${ALGORITHM}")
209
210     set(DA_EXECUTABLE "${DETECTOR}${ALGORITHM}da.exe")
211     set(DETECTOR "${DETECTOR}")
212     set(ALGORITHM "${ALGORITHM}")
213     set(RPM_DESCRIPTION ${RPM_DESCRIPTION})
214     
215     if(ALGORITHM STREQUAL "")
216         set(_ALGORITHM "none")
217         set(DA_PREFIX "opt/daqDA-${DETECTOR}")
218         set(DA_NAME "daqDA-${DETECTOR}")
219     else()
220         set(_ALGORITHM ${ALGORITHM})
221         set(DA_PREFIX "opt/daqDA-${DETECTOR}-${ALGORITHM}")
222         set(DA_NAME "daqDA-${DETECTOR}-${ALGORITHM}")
223     endif()
224
225     configure_file("${AliRoot_SOURCE_DIR}/cmake/da.spec.in" "${DETECTOR}${_ALGORITHM}-da.spec" @ONLY)
226
227     add_custom_command(TARGET ${DETECTOR}${ALGORITHM}da.exe POST_BUILD
228                        COMMAND mkdir ARGS -p da-${DETECTOR}${_ALGORITHM}-rpm/root/${DA_PREFIX}/
229                        COMMAND cp ARGS ${DETECTOR}${ALGORITHM}da.exe da-${DETECTOR}${_ALGORITHM}-rpm/root/${DA_PREFIX}/
230                        COMMAND rpmbuild ARGS --verbose --define "_topdir ${CMAKE_CURRENT_BINARY_DIR}/da-${DETECTOR}${_ALGORITHM}-rpm" --define "%buildroot ${CMAKE_CURRENT_BINARY_DIR}/da-${DETECTOR}${_ALGORITHM}-rpm/root" -bb ${DETECTOR}${_ALGORITHM}-da.spec
231                        WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} VERBATIM
232                        COMMENT "RPM creation for ${DETECTOR}-${_ALGORITHM}"
233     )
234     
235     # make clean will remove also the rpm folder
236     # Retrive the current list of file to be deleted - set_directory_property is overwriting, not adding to the list
237     get_directory_property(_clean_files ADDITIONAL_MAKE_CLEAN_FILES)
238     set(_clean_files da-${DETECTOR}${_ALGORITHM}-rpm  ${_clean_files})
239     set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${_clean_files}")
240     
241     # install RPM into $CMAKE_INSTALL_PREFIX/darpms
242     install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/da-${DETECTOR}${_ALGORITHM}-rpm/RPMS/ DESTINATION darpms PATTERN "\\.rpm")
243 endmacro()
244
245
246 # Prepend prefix to every element in the list. Note: this function modifies the input variable: this
247 # does not work for macros in CMake, only for functions. Also note that it does NOT automatically
248 # add a / between prefix and list item as it does not assume that we are dealing with directories
249 function(prepend_prefix INLIST PREFIX)
250     foreach(_ITEM ${${INLIST}})
251         list(APPEND _OUTLIST ${PREFIX}${_ITEM})
252     endforeach()
253     set(${INLIST} ${_OUTLIST} PARENT_SCOPE)
254 endfunction()
255
256
257 # This function is a drop-in replacement for the following CMake command:
258 #
259 #   install(FILES ... DESTINATION ... [OTHER_ARGS])
260 #
261 # The above command takes every single file and puts it in the destination directory, but relative
262 # paths are not taken into consideration, i.e. files a/b/c/file.h and boo.h will be both installed
263 # in dest.
264 #
265 # By replacing install() with install_relative(), boo.h will end in dest, and a/b/c/file.h will end
266 # in dest/a/b/c/file.h, i.e. relative paths are taken into account.
267 #
268 # If an absolute path was specified for an input file, a fatal error will be raised: only relative
269 # paths can be specified.
270 #
271 # Since it is a drop-in command, its syntax is identical to install():
272 #
273 #   install_relative(FILES ... DESTINATION ... [OTHER_ARGS])
274 #
275 # where OTHER_ARGS is passed as-is to the underlying install() command
276 function(install_relative)
277
278     set(_EXPECT_FILE TRUE)
279     set(_EXPECT_DEST FALSE)
280     set(_EXPECT_REST FALSE)
281
282     foreach(_ARG ${ARGN})
283
284         if(_EXPECT_FILE)
285
286             if(${_ARG} STREQUAL "FILES")
287                 set(_EXPECT_FILE FALSE)
288             else()
289                 message(FATAL_ERROR "You may only use install_relative() in place of install(FILES ...)")
290             endif()
291
292         elseif(_EXPECT_REST)
293             # Remaining arguments
294             list(APPEND _REST ${_ARG})
295         elseif(_EXPECT_DEST)
296             # Destination prefix
297             set(_DEST ${_ARG})
298             set(_EXPECT_DEST FALSE)
299             set(_EXPECT_REST TRUE)
300         elseif(_ARG STREQUAL "DESTINATION")
301             # From now on, copy the arguments ditto to the install() command
302             set(_EXPECT_DEST TRUE)
303         else()
304             # Append files to install
305             list(APPEND _FILES ${_ARG})
306         endif()
307
308     endforeach()
309
310     # Print out our results (debug)
311     #message(STATUS "[install_relative] FILES: ${_FILES}")
312     #message(STATUS "[install_relative] DEST: ${_DEST}")
313     #message(STATUS "[install_relative] REST: ${_REST}")
314
315     # Prepare a distinct install command for each file, depending on its path
316     foreach(_FILE ${_FILES})
317
318         if(CMAKE_VERSION VERSION_LESS "2.8.12")
319             get_filename_component(_FILEPREFIX ${_FILE} PATH)
320         else()
321             get_filename_component(_FILEPREFIX ${_FILE} DIRECTORY)
322         endif()
323         #message(STATUS "[install_relative] ${_FILE} --> ${_FILEPREFIX}")
324
325         string(SUBSTRING ${_FILE} 0 1 _FILE_FIRST)
326         if(${_FILE_FIRST} STREQUAL "/")
327             # An absolute path was found: not supported, error
328             message(FATAL_ERROR "Absolute paths are not supported by install_relative(): ${_FILE}")
329         endif()
330
331         install(FILES ${_FILE} DESTINATION ${_DEST}/${_FILEPREFIX} ${_REST})
332
333     endforeach()
334
335 endfunction()