Cleanup the fbpackage artifacts from the load script
[hiphop-php.git] / CMake / HPHPFunctions.cmake
blobad6337a56c2ac1eabfeb9d14404a5004f4a11a70
1 include(GNUInstallDirs)
3 function(auto_sources RETURN_VALUE PATTERN SOURCE_SUBDIRS)
5   if ("${SOURCE_SUBDIRS}" STREQUAL "RECURSE")
6     SET(PATH ".")
7     if (${ARGC} EQUAL 4)
8       list(GET ARGV 3 PATH)
9     endif ()
10   endif()
12   if ("${SOURCE_SUBDIRS}" STREQUAL "RECURSE")
13     unset(${RETURN_VALUE})
14     file(GLOB SUBDIR_FILES "${PATH}/${PATTERN}")
15     list(APPEND ${RETURN_VALUE} ${SUBDIR_FILES})
17     file(GLOB subdirs RELATIVE ${PATH} ${PATH}/*)
19     foreach(DIR ${subdirs})
20       if (IS_DIRECTORY ${PATH}/${DIR})
21         if (NOT "${DIR}" STREQUAL "CMakeFiles")
22           file(GLOB_RECURSE SUBDIR_FILES "${PATH}/${DIR}/${PATTERN}")
23           list(APPEND ${RETURN_VALUE} ${SUBDIR_FILES})
24         endif()
25       endif()
26     endforeach()
27   else ()
28     file(GLOB ${RETURN_VALUE} "${PATTERN}")
30     foreach (PATH ${SOURCE_SUBDIRS})
31       file(GLOB SUBDIR_FILES "${PATH}/${PATTERN}")
32       list(APPEND ${RETURN_VALUE} ${SUBDIR_FILES})
33     endforeach(PATH ${SOURCE_SUBDIRS})
34   endif ()
36   if (${FILTER_OUT})
37     list(REMOVE_ITEM ${RETURN_VALUE} ${FILTER_OUT})
38   endif()
40   set(${RETURN_VALUE} ${${RETURN_VALUE}} PARENT_SCOPE)
41 endfunction(auto_sources)
43 macro(HHVM_SELECT_SOURCES DIR)
44   auto_sources(files "*.cpp" "RECURSE" "${DIR}")
45   foreach(f ${files})
46     if (NOT (${f} MATCHES "(ext_hhvm|/(old-)?tests?/)"))
47       list(APPEND CXX_SOURCES ${f})
48     endif()
49   endforeach()
50   auto_sources(files "*.c" "RECURSE" "${DIR}")
51   foreach(f ${files})
52     if (NOT (${f} MATCHES "(ext_hhvm|/(old-)?tests?/)"))
53       list(APPEND C_SOURCES ${f})
54     endif()
55   endforeach()
56   if (MSVC)
57     auto_sources(files "*.asm" "RECURSE" "${DIR}")
58     foreach(f ${files})
59       if (NOT (${f} MATCHES "(ext_hhvm|/(old-)?tests?/)"))
60         list(APPEND ASM_SOURCES ${f})
61       endif()
62     endforeach()
63   else()
64     auto_sources(files "*.S" "RECURSE" "${DIR}")
65     foreach(f ${files})
66       if (NOT (${f} MATCHES "(ext_hhvm|/(old-)?tests?/)"))
67         list(APPEND ASM_SOURCES ${f})
68       endif()
69     endforeach()
70   endif()
71   auto_sources(files "*.h" "RECURSE" "${DIR}")
72   foreach(f ${files})
73     if (NOT (${f} MATCHES "(/(old-)?tests?/)"))
74       list(APPEND HEADER_SOURCES ${f})
75     endif()
76   endforeach()
77 endmacro(HHVM_SELECT_SOURCES)
79 function(CONTAINS_STRING FILE SEARCH RETURN_VALUE)
80   file(STRINGS ${FILE} FILE_CONTENTS REGEX ".*${SEARCH}.*")
81   if (FILE_CONTENTS)
82     set(${RETURN_VALUE} True PARENT_SCOPE)
83   endif()
84 endfunction(CONTAINS_STRING)
86 macro(MYSQL_SOCKET_SEARCH)
87   execute_process(COMMAND mysql_config --socket OUTPUT_VARIABLE MYSQL_SOCK OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET)
88   if (NOT MYSQL_SOCK)
89     foreach (i
90       /var/run/mysqld/mysqld.sock
91       /var/tmp/mysql.sock
92       /var/run/mysql/mysql.sock
93       /var/lib/mysql/mysql.sock
94       /var/mysql/mysql.sock
95       /usr/local/mysql/var/mysql.sock
96       /Private/tmp/mysql.sock
97       /private/tmp/mysql.sock
98       /tmp/mysql.sock
99       )
100       if (EXISTS ${i})
101         set(MYSQL_SOCK ${i})
102         break()
103       endif()
104     endforeach()
105   endif()
106   if (MYSQL_SOCK)
107     set(MYSQL_UNIX_SOCK_ADDR ${MYSQL_SOCK} CACHE STRING "Path to MySQL Socket")
108   endif()
109 endmacro()
111 function(append_systemlib TARGET SOURCE SECTNAME)
112   if(CYGWIN OR MSVC OR MINGW)
113     list(APPEND ${TARGET}_SLIBS_NAMES "${SECTNAME}")
114     set(${TARGET}_SLIBS_NAMES ${${TARGET}_SLIBS_NAMES} PARENT_SCOPE)
115     list(APPEND ${TARGET}_SLIBS_SOURCES "${SOURCE}")
116     set(${TARGET}_SLIBS_SOURCES ${${TARGET}_SLIBS_SOURCES} PARENT_SCOPE)
117   else()
118     if (APPLE)
119       set(${TARGET}_SLIBS ${${TARGET}_SLIBS} -Wl,-sectcreate,__text,${SECTNAME},${SOURCE} PARENT_SCOPE)
120     else()
121       set(${TARGET}_SLIBS ${${TARGET}_SLIBS} "--add-section" "${SECTNAME}=${SOURCE}" PARENT_SCOPE)
122     endif()
123     # Add the systemlib file to the "LINK_DEPENDS" for the systemlib, this will cause it
124     # to be relinked and the systemlib re-embedded
125     set_property(TARGET ${TARGET} APPEND PROPERTY LINK_DEPENDS ${SOURCE})
126   endif()
127 endfunction(append_systemlib)
129 function(embed_sections TARGET DEST)
130   add_custom_command(TARGET ${TARGET} PRE_BUILD
131     # OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/generated-compiler-id.txt"
132     #        "${CMAKE_CURRENT_SOURCE_DIR}/generated-repo-schema-id.txt"
133     COMMAND "${HPHP_HOME}/hphp/util/generate-buildinfo.sh"
134     WORKING_DIRECTORY "${HPHP_HOME}/hphp/util"
135     COMMENT "Generating Repo Schema ID and Compiler ID"
136     VERBATIM)
138   if (APPLE)
139     set(COMPILER_ID -Wl,-sectcreate,__text,"compiler_id","${HPHP_HOME}/hphp/util/generated-compiler-id.txt")
140     set(REPO_SCHEMA -Wl,-sectcreate,__text,"repo_schema_id","${HPHP_HOME}/hphp/util/generated-repo-schema-id.txt")
141     target_link_libraries(${TARGET} ${${TARGET}_SLIBS} ${COMPILER_ID} ${REPO_SCHEMA})
142   elseif(CYGWIN OR MSVC OR MINGW)
143     set(RESOURCE_FILE "#pragma code_page(1252)\n")
144     set(RESOURCE_FILE "${RESOURCE_FILE}LANGUAGE 0, 0\n")
145     set(RESOURCE_FILE "${RESOURCE_FILE}\n")
146     set(RESOURCE_FILE "${RESOURCE_FILE}#include \"${HPHP_HOME}/hphp/runtime/version.h\"\n")
147     file(READ "${HPHP_HOME}/hphp/hhvm/hhvm.rc" VERSION_INFO)
148     set(RESOURCE_FILE "${RESOURCE_FILE}compiler_id RCDATA \"${HPHP_HOME}/hphp/util/generated-compiler-id.txt\"\n")
149     set(RESOURCE_FILE "${RESOURCE_FILE}repo_schema_id RCDATA \"${HPHP_HOME}/hphp/util/generated-repo-schema-id.txt\"\n")
150     set(RESOURCE_FILE "${RESOURCE_FILE}${VERSION_INFO}\n")
151     set(i 0)
152     foreach (nm ${${TARGET}_SLIBS_NAMES})
153       list(GET ${TARGET}_SLIBS_SOURCES ${i} source)
154       set(RESOURCE_FILE "${RESOURCE_FILE}${nm} RCDATA \"${source}\"\n")
155       math(EXPR i "${i} + 1")
156     endforeach()
157     file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/embed.rc "${RESOURCE_FILE}")
158   else()
159     add_custom_command(TARGET ${TARGET} POST_BUILD
160       COMMAND "objcopy"
161       ARGS "--add-section" "compiler_id=${HPHP_HOME}/hphp/util/generated-compiler-id.txt"
162            "--add-section" "repo_schema_id=${HPHP_HOME}/hphp/util/generated-repo-schema-id.txt"
163            ${${TARGET}_SLIBS}
164            ${DEST}
165       DEPENDS "${HPHP_HOME}/hphp/util/generated-compiler-id.txt"
166               "${HPHP_HOME}/hphp/util/generated-repo-schema-id.txt"
167       COMMENT "Embedding php in ${TARGET}")
168   endif()
169 endfunction(embed_sections)
171 macro(embed_systemlib_byname TARGET SLIB)
172   get_filename_component(SLIB_BN ${SLIB} "NAME_WE")
173   string(LENGTH ${SLIB_BN} SLIB_BN_LEN)
174   math(EXPR SLIB_BN_REL_LEN "${SLIB_BN_LEN} - 4")
175   string(SUBSTRING ${SLIB_BN} 4 ${SLIB_BN_REL_LEN} SLIB_EXTNAME)
176   string(MD5 SLIB_HASH_NAME ${SLIB_EXTNAME})
177   # Some platforms limit section names to 16 characters :(
178   string(SUBSTRING ${SLIB_HASH_NAME} 0 12 SLIB_HASH_NAME_SHORT)
179   if (CYGWIN OR MINGW OR MSVC)
180     # The dot would be causing the RC lexer to begin a number in the
181     # middle of our resource name, so use an underscore instead.
182     append_systemlib(${TARGET} ${SLIB} "ext_${SLIB_HASH_NAME_SHORT}")
183   else()
184     append_systemlib(${TARGET} ${SLIB} "ext.${SLIB_HASH_NAME_SHORT}")
185   endif()
186 endmacro()
188 function(embed_all_systemlibs TARGET ROOT DEST)
189   append_systemlib(${TARGET} ${ROOT}/system/systemlib.php systemlib)
190   foreach(SLIB ${EXTENSION_SYSTEMLIB_SOURCES} ${EZC_SYSTEMLIB_SOURCES})
191     embed_systemlib_byname(${TARGET} ${SLIB})
192   endforeach()
193   embed_sections(${TARGET} ${DEST})
194 endfunction(embed_all_systemlibs)
196 # Custom install function that doesn't relink, instead it uses chrpath to change it, if
197 # it's available, otherwise, it leaves the chrpath alone
198 function(HHVM_INSTALL TARGET DEST)
199   get_target_property(LOC ${TARGET} LOCATION)
200   get_target_property(TY ${TARGET} TYPE)
201   if (FOUND_CHRPATH)
202     get_target_property(RPATH ${TARGET} INSTALL_RPATH)
203     if (NOT RPATH STREQUAL "RPATH-NOTFOUND")
204       if (RPATH STREQUAL "")
205         install(CODE "execute_process(COMMAND \"${CHRPATH}\" \"-d\" \"${LOC}\" ERROR_QUIET)")
206       else()
207         install(CODE "execute_process(COMMAND \"${CHRPATH}\" \"-r\" \"${RPATH}\" \"${LOC}\" ERROR_QUIET)")
208       endif()
209     endif()
210   endif()
211   string(TOUPPER ${DEST} DEST_UPPER)
212   install(CODE "FILE(INSTALL DESTINATION \"\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_${DEST_UPPER}DIR}\" TYPE ${TY} FILES \"${LOC}\")")
213 endfunction(HHVM_INSTALL)
215 function(HHVM_PUBLIC_HEADERS TARGET)
216   install(
217     CODE "INCLUDE(\"${HPHP_HOME}/CMake/HPHPFunctions.cmake\")
218       HHVM_INSTALL_HEADERS(${TARGET} ${HPHP_HOME}
219       \"\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}\" ${ARGN})"
220     COMPONENT dev)
221 endfunction()
223 function(HHVM_INSTALL_HEADERS TARGET SRCROOT DEST)
224   message(STATUS "Installing header files for ${TARGET}")
225   foreach(src_rel ${ARGN})
226     # Determine the relative directory name so that we can mirror the
227     # directory structure in the output
228     file(RELATIVE_PATH dest_rel ${SRCROOT} ${src_rel})
229     if (IS_ABSOLUTE ${dest_rel})
230       message(WARNING "${TARGET}: Header file ${dest_rel} is not inside ${SRCROOT}")
231     else()
232       string(FIND ${dest_rel} / slash_pos REVERSE)
233       if(slash_pos EQUAL -1)
234         set(dest_rel)
235       else()
236         string(SUBSTRING ${dest_rel} 0 ${slash_pos} dest_rel)
237       endif()
238       file(COPY ${src_rel}
239         DESTINATION "$ENV{DESTDIR}${DEST}/${dest_rel}"
240         NO_SOURCE_PERMISSIONS)
241     endif()
242   endforeach()
243 endfunction()
245 macro(HHVM_EXT_OPTION EXTNAME PACKAGENAME)
246   if (NOT DEFINED EXT_${EXTNAME})
247     # Implicit check
248     find_package(${PACKAGENAME})
249   elseif (EXT_${EXTNAME} STREQUAL "ON")
250     # Explicit check
251     find_package(${PACKAGENAME} REQUIRED)
252   endif()
253 endmacro()
255 # Remove all files matching a set of patterns, and,
256 # optionally, not matching a second set of patterns,
257 # from a set of lists.
259 # Example:
260 # This will remove all files in the CPP_SOURCES list
261 # matching "/test/" or "Test.cpp$", but not matching
262 # "BobTest.cpp$".
263 # HHVM_REMOVE_MATCHES_FROM_LISTS(CPP_SOURCES MATCHES "/test/" "Test.cpp$" IGNORE_MATCHES "BobTest.cpp$")
265 # Parameters:
267 # [...]:
268 # The names of the lists to remove matches from.
270 # [MATCHES ...]:
271 # The matches to remove from the lists.
273 # [IGNORE_MATCHES ...]:
274 # The matches not to remove, even if they match
275 # the main set of matches to remove.
276 function(HHVM_REMOVE_MATCHES_FROM_LISTS)
277   set(LISTS_TO_SEARCH)
278   set(MATCHES_TO_REMOVE)
279   set(MATCHES_TO_IGNORE)
280   set(argumentState 0)
281   foreach (arg ${ARGN})
282     if ("x${arg}" STREQUAL "xMATCHES")
283       set(argumentState 1)
284     elseif ("x${arg}" STREQUAL "xIGNORE_MATCHES")
285       set(argumentState 2)
286     elseif (argumentState EQUAL 0)
287       list(APPEND LISTS_TO_SEARCH ${arg})
288     elseif (argumentState EQUAL 1)
289       list(APPEND MATCHES_TO_REMOVE ${arg})
290     elseif (argumentState EQUAL 2)
291       list(APPEND MATCHES_TO_IGNORE ${arg})
292     else()
293       message(FATAL_ERROR "Unknown argument state!")
294     endif()
295   endforeach()
297   foreach (theList ${LISTS_TO_SEARCH})
298     foreach (entry ${${theList}})
299       foreach (match ${MATCHES_TO_REMOVE})
300         if (${entry} MATCHES ${match})
301           set(SHOULD_IGNORE OFF)
302           foreach (ign ${MATCHES_TO_IGNORE})
303             if (${entry} MATCHES ${ign})
304               set(SHOULD_IGNORE ON)
305               break()
306             endif()
307           endforeach()
309           if (NOT SHOULD_IGNORE)
310             list(REMOVE_ITEM ${theList} ${entry})
311           endif()
312         endif()
313       endforeach()
314     endforeach()
315     set(${theList} ${${theList}} PARENT_SCOPE)
316   endforeach()
317 endfunction()
319 # Automatically create source_group directives for the sources passed in.
320 function(auto_source_group rootName rootDir)
321   file(TO_CMAKE_PATH "${rootDir}" rootDir)
322   string(LENGTH "${rootDir}" rootDirLength)
323   set(sourceGroups)
324   foreach (fil ${ARGN})
325     file(TO_CMAKE_PATH "${fil}" filePath)
326     string(FIND "${filePath}" "/" rIdx REVERSE)
327     if (rIdx EQUAL -1)
328       message(FATAL_ERROR "Unable to locate the final forward slash in '${filePath}'!")
329     endif()
330     string(SUBSTRING "${filePath}" 0 ${rIdx} filePath)
332     string(LENGTH "${filePath}" filePathLength)
333     string(FIND "${filePath}" "${rootDir}" rIdx)
334     if (rIdx EQUAL 0)
335       math(EXPR filePathLength "${filePathLength} - ${rootDirLength}")
336       string(SUBSTRING "${filePath}" ${rootDirLength} ${filePathLength} fileGroup)
338       string(REPLACE "/" "\\" fileGroup "${fileGroup}")
339       set(fileGroup "\\${rootName}${fileGroup}")
341       list(FIND sourceGroups "${fileGroup}" rIdx)
342       if (rIdx EQUAL -1)
343         list(APPEND sourceGroups "${fileGroup}")
344         source_group("${fileGroup}" REGULAR_EXPRESSION "${filePath}/[^/.]+(.(tab|yy))?.(c|cc|cpp|h|hpp|ll|php|tcc|y)$")
345       endif()
346     endif()
347   endforeach()
348 endfunction()
350 macro(add_precompiled_header PrecompiledHead PrecompiledSrc SourcesVar)
351   if (MSVC AND MSVC_ENABLE_PCH)
352     get_filename_component(PrecompiledHeader "${PrecompiledHead}" ABSOLUTE)
353     get_filename_component(PrecompiledSource "${PrecompiledSrc}" ABSOLUTE)
354     get_filename_component(PrecompiledBasename "${PrecompiledHeader}" NAME_WE)
355     get_filename_component(PrecompiledHeaderFilename "${PrecompiledHeader}" NAME)
356     set(PrecompiledBinary "${CMAKE_CURRENT_BINARY_DIR}/${PrecompiledBasename}.pch")
357     set(Sources ${${SourcesVar}})
359     set_source_files_properties(${PrecompiledSource} PROPERTIES
360       COMPILE_FLAGS "/Yc\"${PrecompiledHeaderFilename}\" /Fp\"${PrecompiledBinary}\""
361       OBJECT_OUTPUTS "${PrecompiledBinary}")
362     set_source_files_properties(${Sources} PROPERTIES
363       COMPILE_FLAGS "/Yu\"${PrecompiledHeader}\" /FI\"${PrecompiledHeader}\" /Fp\"${PrecompiledBinary}\""
364       OBJECT_DEPENDS "${PrecompiledBinary}")
366     list(APPEND ${SourcesVar} ${PrecompiledSource} ${PrecompiledHeader})
367   endif()
368 endmacro()
370 function(parse_version PREFIX VERSION)
371   if (NOT ${VERSION} MATCHES "^[0-9]+\\.[0-9]+(\\.[0-9]+)?(-.+)?$")
372     message(FATAL_ERROR "VERSION must conform to X.Y(.Z)?(-.+)?")
373   endif()
375   string(FIND ${VERSION} "-" SUFFIX_POS)
376   set(SUFFIX "")
377   if (SUFFIX_POS)
378     string(SUBSTRING ${VERSION} ${SUFFIX_POS} -1 SUFFIX)
379     string(SUBSTRING ${VERSION} 0 ${SUFFIX_POS} NUMERIC_VERSION)
380   else()
381     set(NUMERIC_VERSION ${VERSION})
382   endif()
384   string(REPLACE "." ";" VERSION_LIST "${NUMERIC_VERSION}")
385   list(GET VERSION_LIST 0 MAJOR)
386   list(GET VERSION_LIST 1 MINOR)
387   list(LENGTH VERSION_LIST VERSION_LIST_LENGTH)
388   if (VERSION_LIST_LENGTH GREATER 2)
389     list(GET VERSION_LIST 2 PATCH)
390   else()
391     set(PATCH 0)
392   endif()
394   set(${PREFIX}MAJOR ${MAJOR} PARENT_SCOPE)
395   set(${PREFIX}MINOR ${MINOR} PARENT_SCOPE)
396   set(${PREFIX}PATCH ${PATCH} PARENT_SCOPE)
397   set(${PREFIX}SUFFIX ${SUFFIX} PARENT_SCOPE)
398 endfunction()
400 # MSVC doesn't support a --whole-archive flag, but newer versions
401 # of CMake do support object libraries, which give the same result.
402 # As we can't easily upgrade the normal builds to CMake 3.0, we
403 # will just require CMake 3.0+ for MSVC builds only.
404 function(add_object_library libraryName)
405   if (MSVC)
406     add_library(${libraryName} OBJECT ${ARGN})
407   else()
408     add_library(${libraryName} STATIC ${ARGN})
409   endif()
410 endfunction()
412 # Get what might be the objects of the object libraries, if needed.
413 function(get_object_libraries_objects targetVariable)
414   set(OBJECTS)
415   if (MSVC)
416     foreach (fil ${ARGN})
417       list(APPEND OBJECTS $<TARGET_OBJECTS:${fil}>)
418     endforeach()
419   endif()
421   set(${targetVariable} ${OBJECTS} PARENT_SCOPE)
422 endfunction()
424 # Add the additional link targets for a set of object libraries,
425 # if needed.
426 function(link_object_libraries target)
427   if (MSVC)
428     return()
429   endif()
431   set(WHOLE_ARCHIVE_LIBS)
432   foreach (fil ${ARGN})
433     list(APPEND WHOLE_ARCHIVE_LIBS ${fil})
434   endforeach()
436   set(ANCHOR_SYMS)
437   if (APPLE)
438     set(ANCHOR_SYMS
439       -Wl,-pagezero_size,0x00001000
440       # Set the .text.keep section to be executable.
441       -Wl,-segprot,.text,rx,rx)
442     foreach(lib ${WHOLE_ARCHIVE_LIBS})
443       # It's important to use -Xlinker and not -Wl here: ${lib} needs to be its
444       # own option on the command line, since target_link_libraries will expand it
445       # from its logical name here into the full .a path. (Eww.)
446       list(APPEND ANCHOR_SYMS -Xlinker -force_load -Xlinker ${lib})
447     endforeach()
448   else()
449     set(ANCHOR_SYMS -Wl,--whole-archive ${WHOLE_ARCHIVE_LIBS} -Wl,--no-whole-archive)
450   endif()
452   target_link_libraries(${target} ${ANCHOR_SYMS})
453 endfunction()
455 # This should be called for object libraries, rather than calling
456 # hphp_link directly.
457 function(object_library_hphp_link target)
458   # Gold doesn't need this, and MSVC can't have it. (see below)
459   if (NOT ENABLE_LD_GOLD AND NOT MSVC)
460     hphp_link(${target})
461   endif()
462 endfunction()
464 # If a library needs to be linked in to make GNU ld happy,
465 # it should be done by calling this.
466 function(object_library_ld_link_libraries target)
467   if (${ARGC})
468     # CMake doesn't allow calls to target_link_libraries if the target
469     # is an OBJECT library, so MSVC can't have this.
470     if (NOT MSVC)
471       target_link_libraries(${target} ${ARGN})
472     endif()
473   endif()
474 endfunction()