CocosBuildHelpers.cmake 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. include(CMakeParseArguments)
  2. # copy resource `FILES` and `FOLDERS` to TARGET_FILE_DIR/Resources
  3. function(cocos_copy_target_res cocos_target)
  4. set(oneValueArgs COPY_TO)
  5. set(multiValueArgs FILES FOLDERS)
  6. cmake_parse_arguments(opt "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  7. # copy files
  8. foreach(cc_file ${opt_FILES})
  9. get_filename_component(file_name ${cc_file} NAME)
  10. add_custom_command(TARGET ${cocos_target} POST_BUILD
  11. COMMAND ${CMAKE_COMMAND} -E echo "copy file into Resources: ${file_name} ..."
  12. COMMAND ${CMAKE_COMMAND} -E copy_if_different ${cc_file} "${opt_COPY_TO}/${file_name}"
  13. )
  14. endforeach()
  15. # copy folders files
  16. foreach(cc_folder ${opt_FOLDERS})
  17. file(GLOB_RECURSE folder_files "${cc_folder}/*")
  18. get_filename_component(folder_abs_path ${cc_folder} ABSOLUTE)
  19. foreach(res_file ${folder_files})
  20. get_filename_component(res_file_abs_path ${res_file} ABSOLUTE)
  21. file(RELATIVE_PATH res_file_relat_path ${folder_abs_path} ${res_file_abs_path})
  22. add_custom_command(TARGET ${cocos_target} POST_BUILD
  23. COMMAND ${CMAKE_COMMAND} -E echo "copy file into Resources: ${res_file_relat_path} ..."
  24. COMMAND ${CMAKE_COMMAND} -E copy_if_different ${res_file} "${opt_COPY_TO}/${res_file_relat_path}"
  25. )
  26. endforeach()
  27. endforeach()
  28. endfunction()
  29. # mark `FILES` and files in `FOLDERS` as resource files, the destination is `RES_TO` folder
  30. # save all marked files in `res_out`
  31. function(cocos_mark_multi_resources res_out)
  32. set(oneValueArgs RES_TO)
  33. set(multiValueArgs FILES FOLDERS)
  34. cmake_parse_arguments(opt "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  35. set(tmp_file_list)
  36. foreach(cc_file ${opt_FILES})
  37. get_filename_component(cc_file_abs ${cc_file} ABSOLUTE)
  38. get_filename_component(file_dir ${cc_file_abs} DIRECTORY)
  39. cocos_mark_resources(FILES ${cc_file_abs} BASEDIR ${file_dir} RESOURCEBASE ${opt_RES_TO})
  40. endforeach()
  41. list(APPEND tmp_file_list ${opt_FILES})
  42. foreach(cc_folder ${opt_FOLDERS})
  43. file(GLOB_RECURSE folder_files "${cc_folder}/*")
  44. list(APPEND tmp_file_list ${folder_files})
  45. cocos_mark_resources(FILES ${folder_files} BASEDIR ${cc_folder} RESOURCEBASE ${opt_RES_TO})
  46. endforeach()
  47. set(${res_out} ${tmp_file_list} PARENT_SCOPE)
  48. endfunction()
  49. # get all linked libraries including transitive ones, recursive
  50. function(search_depend_libs_recursive cocos_target all_depends_out)
  51. set(all_depends_inner)
  52. set(targets_prepare_search ${cocos_target})
  53. while(true)
  54. foreach(tmp_target ${targets_prepare_search})
  55. get_target_property(tmp_depend_libs ${tmp_target} LINK_LIBRARIES)
  56. list(REMOVE_ITEM targets_prepare_search ${tmp_target})
  57. list(APPEND tmp_depend_libs ${tmp_target})
  58. foreach(depend_lib ${tmp_depend_libs})
  59. if(TARGET ${depend_lib})
  60. list(APPEND all_depends_inner ${depend_lib})
  61. if(NOT (depend_lib STREQUAL tmp_target))
  62. list(APPEND targets_prepare_search ${depend_lib})
  63. endif()
  64. endif()
  65. endforeach()
  66. endforeach()
  67. list(LENGTH targets_prepare_search targets_prepare_search_size)
  68. if(targets_prepare_search_size LESS 1)
  69. break()
  70. endif()
  71. endwhile(true)
  72. set(${all_depends_out} ${all_depends_inner} PARENT_SCOPE)
  73. endfunction()
  74. # get `cocos_target` depend all dlls, save the result in `all_depend_dlls_out`
  75. function(get_target_depends_ext_dlls cocos_target all_depend_dlls_out)
  76. set(depend_libs)
  77. set(all_depend_ext_dlls)
  78. search_depend_libs_recursive(${cocos_target} depend_libs)
  79. foreach(depend_lib ${depend_libs})
  80. if(TARGET ${depend_lib})
  81. get_target_property(found_shared_lib ${depend_lib} IMPORTED_IMPLIB)
  82. if(found_shared_lib)
  83. get_target_property(tmp_dlls ${depend_lib} IMPORTED_LOCATION)
  84. list(APPEND all_depend_ext_dlls ${tmp_dlls})
  85. endif()
  86. endif()
  87. endforeach()
  88. set(${all_depend_dlls_out} ${all_depend_ext_dlls} PARENT_SCOPE)
  89. endfunction()
  90. # copy the `cocos_target` needed dlls into TARGET_FILE_DIR
  91. function(cocos_copy_target_dll cocos_target)
  92. get_target_depends_ext_dlls(${cocos_target} all_depend_dlls)
  93. # remove repeat items
  94. if(all_depend_dlls)
  95. list(REMOVE_DUPLICATES all_depend_dlls)
  96. endif()
  97. foreach(cc_dll_file ${all_depend_dlls})
  98. get_filename_component(cc_dll_name ${cc_dll_file} NAME)
  99. add_custom_command(TARGET ${cocos_target} POST_BUILD
  100. COMMAND ${CMAKE_COMMAND} -E echo "copy dll into target file dir: ${cc_dll_name} ..."
  101. COMMAND ${CMAKE_COMMAND} -E copy_if_different ${cc_dll_file} "$<TARGET_FILE_DIR:${cocos_target}>/${cc_dll_name}"
  102. )
  103. endforeach()
  104. endfunction()
  105. # mark `FILES` as resources, files will be put into sub-dir tree depend on its absolute path
  106. function(cocos_mark_resources)
  107. set(oneValueArgs BASEDIR RESOURCEBASE)
  108. set(multiValueArgs FILES)
  109. cmake_parse_arguments(opt "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  110. if(NOT opt_RESOURCEBASE)
  111. set(opt_RESOURCEBASE Resources)
  112. endif()
  113. get_filename_component(BASEDIR_ABS ${opt_BASEDIR} ABSOLUTE)
  114. foreach(RES_FILE ${opt_FILES} ${opt_UNPARSED_ARGUMENTS})
  115. get_filename_component(RES_FILE_ABS ${RES_FILE} ABSOLUTE)
  116. file(RELATIVE_PATH RES ${BASEDIR_ABS} ${RES_FILE_ABS})
  117. get_filename_component(RES_LOC ${RES} PATH)
  118. set_source_files_properties(${RES_FILE} PROPERTIES
  119. MACOSX_PACKAGE_LOCATION "${opt_RESOURCEBASE}/${RES_LOC}"
  120. HEADER_FILE_ONLY 1
  121. )
  122. if(XCODE OR VS)
  123. string(REPLACE "/" "\\" ide_source_group "${opt_RESOURCEBASE}/${RES_LOC}")
  124. source_group("${ide_source_group}" FILES ${RES_FILE})
  125. endif()
  126. endforeach()
  127. endfunction()
  128. # mark the code sources of `cocos_target` into sub-dir tree
  129. function(cocos_mark_code_files cocos_target)
  130. set(oneValueArgs GROUPBASE)
  131. cmake_parse_arguments(opt "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  132. if(NOT opt_GROUPBASE)
  133. set(root_dir ${CMAKE_CURRENT_SOURCE_DIR})
  134. else()
  135. set(root_dir ${opt_GROUPBASE})
  136. message(STATUS "target ${cocos_target} code group base is: ${root_dir}")
  137. endif()
  138. message(STATUS "cocos_mark_code_files: ${cocos_target}")
  139. get_property(file_list TARGET ${cocos_target} PROPERTY SOURCES)
  140. foreach(single_file ${file_list})
  141. source_group_single_file(${single_file} GROUP_TO "Source Files" BASE_PATH "${root_dir}")
  142. endforeach()
  143. endfunction()
  144. # source group one file
  145. # cut the `single_file` absolute path from `BASE_PATH`, then mark file to `GROUP_TO`
  146. function(source_group_single_file single_file)
  147. set(oneValueArgs GROUP_TO BASE_PATH)
  148. cmake_parse_arguments(opt "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  149. # get relative_path
  150. get_filename_component(abs_path ${single_file} ABSOLUTE)
  151. file(RELATIVE_PATH relative_path_with_name ${opt_BASE_PATH} ${abs_path})
  152. get_filename_component(relative_path ${relative_path_with_name} PATH)
  153. # set source_group, consider sub source group
  154. string(REPLACE "/" "\\" ide_file_group "${opt_GROUP_TO}/${relative_path}")
  155. source_group("${ide_file_group}" FILES ${single_file})
  156. endfunction()
  157. # setup a cocos application
  158. function(setup_cocos_app_config app_name)
  159. # put all output app into bin/${app_name}
  160. set_target_properties(${app_name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/${app_name}")
  161. if(APPLE)
  162. # output macOS/iOS .app
  163. set_target_properties(${app_name} PROPERTIES MACOSX_BUNDLE 1)
  164. elseif(MSVC)
  165. # visual studio default is Console app, but we need Windows app
  166. set_property(TARGET ${app_name} APPEND PROPERTY LINK_FLAGS "/SUBSYSTEM:WINDOWS")
  167. endif()
  168. # auto mark code files for IDE when mark app
  169. if(XCODE OR VS)
  170. cocos_mark_code_files(${app_name})
  171. endif()
  172. endfunction()
  173. # if cc_variable not set, then set it cc_value
  174. macro(cocos_fake_set cc_variable cc_value)
  175. if(NOT DEFINED ${cc_variable})
  176. set(${cc_variable} ${cc_value})
  177. endif()
  178. endmacro()
  179. # generate macOS app package infomations, need improve for example, the using of info.plist
  180. macro(cocos_pak_xcode cocos_target)
  181. set(oneValueArgs
  182. INFO_PLIST
  183. BUNDLE_NAME
  184. BUNDLE_VERSION
  185. COPYRIGHT
  186. GUI_IDENTIFIER
  187. ICON_FILE
  188. INFO_STRING
  189. LONG_VERSION_STRING
  190. SHORT_VERSION_STRING
  191. )
  192. set(multiValueArgs)
  193. cmake_parse_arguments(COCOS_APP "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  194. # set default value
  195. cocos_fake_set(COCOS_APP_INFO_PLIST "MacOSXBundleInfo.plist.in")
  196. cocos_fake_set(COCOS_APP_BUNDLE_NAME "\${PRODUCT_NAME}")
  197. cocos_fake_set(COCOS_APP_BUNDLE_VERSION "1")
  198. cocos_fake_set(COCOS_APP_COPYRIGHT "Copyright © 2018. All rights reserved.")
  199. cocos_fake_set(COCOS_APP_GUI_IDENTIFIER "org.cocos2dx.${APP_NAME}")
  200. cocos_fake_set(COCOS_APP_ICON_FILE "Icon")
  201. cocos_fake_set(COCOS_APP_INFO_STRING "cocos2d-x app")
  202. cocos_fake_set(COCOS_APP_LONG_VERSION_STRING "1.0.0")
  203. cocos_fake_set(COCOS_APP_SHORT_VERSION_STRING "1.0")
  204. # set bundle info
  205. set_target_properties(${cocos_target}
  206. PROPERTIES
  207. MACOSX_BUNDLE_INFO_PLIST ${COCOS_APP_INFO_PLIST}
  208. )
  209. set(MACOSX_BUNDLE_BUNDLE_NAME ${COCOS_APP_BUNDLE_NAME})
  210. set(MACOSX_BUNDLE_BUNDLE_VERSION ${COCOS_APP_BUNDLE_VERSION})
  211. set(MACOSX_BUNDLE_COPYRIGHT ${COCOS_APP_COPYRIGHT})
  212. set(MACOSX_BUNDLE_GUI_IDENTIFIER ${COCOS_APP_GUI_IDENTIFIER})
  213. set(MACOSX_BUNDLE_ICON_FILE ${COCOS_APP_ICON_FILE})
  214. set(MACOSX_BUNDLE_INFO_STRING ${COCOS_APP_INFO_STRING})
  215. set(MACOSX_BUNDLE_LONG_VERSION_STRING ${COCOS_APP_LONG_VERSION_STRING})
  216. set(MACOSX_BUNDLE_SHORT_VERSION_STRING ${COCOS_APP_SHORT_VERSION_STRING})
  217. message(STATUS "cocos package: ${cocos_target}, plist file: ${COCOS_APP_INFO_PLIST}")
  218. cocos_config_app_xcode_property(${cocos_target})
  219. endmacro()
  220. # set Xcode property for application, include all depend target
  221. macro(cocos_config_app_xcode_property cocos_app)
  222. set(depend_libs)
  223. search_depend_libs_recursive(${cocos_app} depend_libs)
  224. foreach(depend_lib ${depend_libs})
  225. if(TARGET ${depend_lib})
  226. cocos_config_target_xcode_property(${depend_lib})
  227. endif()
  228. endforeach()
  229. endmacro()
  230. # custom Xcode property for iOS target
  231. macro(cocos_config_target_xcode_property cocos_target)
  232. if(IOS)
  233. set_xcode_property(${cocos_target} IPHONEOS_DEPLOYMENT_TARGET "8.0")
  234. set_xcode_property(${cocos_target} ENABLE_BITCODE "NO")
  235. set_xcode_property(${cocos_target} ONLY_ACTIVE_ARCH "YES")
  236. endif()
  237. endmacro()
  238. # This little macro lets you set any XCode specific property, from ios.toolchain.cmake
  239. function(set_xcode_property TARGET XCODE_PROPERTY XCODE_VALUE)
  240. set_property(TARGET ${TARGET} PROPERTY XCODE_ATTRIBUTE_${XCODE_PROPERTY} ${XCODE_VALUE})
  241. endfunction(set_xcode_property)
  242. # works same as find_package, but do additional care to properly find
  243. macro(cocos_find_package pkg_name pkg_prefix)
  244. if(NOT ${pkg_prefix}_FOUND)
  245. find_package(${pkg_name} ${ARGN})
  246. endif()
  247. if(NOT ${pkg_prefix}_INCLUDE_DIRS AND ${pkg_prefix}_INCLUDE_DIR)
  248. set(${pkg_prefix}_INCLUDE_DIRS ${${pkg_prefix}_INCLUDE_DIR})
  249. endif()
  250. if(NOT ${pkg_prefix}_LIBRARIES AND ${pkg_prefix}_LIBRARY)
  251. set(${pkg_prefix}_LIBRARIES ${${pkg_prefix}_LIBRARY})
  252. endif()
  253. message(STATUS "${pkg_name} include dirs: ${${pkg_prefix}_INCLUDE_DIRS}")
  254. endmacro()
  255. # cocos_use_pkg(pkg) function.
  256. # This function applies standard package variables (after find_package(pkg) call) to current scope
  257. # Recognized variables: <pkg>_INCLUDE_DIRS, <pkg>_LIBRARIES, <pkg>_LIBRARY_DIRS
  258. # Also if BUILD_SHARED_LIBS variable off, it is try to use <pkg>_STATIC_* vars before
  259. function(cocos_use_pkg target pkg)
  260. set(prefix ${pkg})
  261. set(_include_dirs)
  262. if(NOT _include_dirs)
  263. set(_include_dirs ${${prefix}_INCLUDE_DIRS})
  264. endif()
  265. if(NOT _include_dirs)
  266. # backward compat with old package-find scripts
  267. set(_include_dirs ${${prefix}_INCLUDE_DIR})
  268. endif()
  269. if(_include_dirs)
  270. include_directories(${_include_dirs})
  271. # message(STATUS "${pkg} add to include_dirs: ${_include_dirs}")
  272. endif()
  273. set(_library_dirs)
  274. if(NOT _library_dirs)
  275. set(_library_dirs ${${prefix}_LIBRARY_DIRS})
  276. endif()
  277. if(_library_dirs)
  278. link_directories(${_library_dirs})
  279. # message(STATUS "${pkg} add to link_dirs: ${_library_dirs}")
  280. endif()
  281. set(_libs)
  282. if(NOT _libs)
  283. set(_libs ${${prefix}_LIBRARIES})
  284. endif()
  285. if(NOT _libs)
  286. set(_libs ${${prefix}_LIBRARY})
  287. endif()
  288. if(_libs)
  289. target_link_libraries(${target} ${_libs})
  290. # message(STATUS "${pkg} libs added to '${target}': ${_libs}")
  291. endif()
  292. set(_defs)
  293. if(NOT _defs)
  294. set(_defs ${${prefix}_DEFINITIONS})
  295. endif()
  296. if(_defs)
  297. add_definitions(${_defs})
  298. # message(STATUS "${pkg} add definitions: ${_defs}")
  299. endif()
  300. set(_dlls)
  301. if(NOT _dlls)
  302. set(_dlls ${${prefix}_DLLS})
  303. endif()
  304. if(_dlls)
  305. if(MSVC)
  306. # message(STATUS "${target} add dll: ${_dlls}")
  307. get_property(pre_dlls
  308. TARGET ${target}
  309. PROPERTY CC_DEPEND_DLLS)
  310. if(pre_dlls)
  311. set(_dlls ${pre_dlls} ${_dlls})
  312. endif()
  313. set_property(TARGET ${target}
  314. PROPERTY
  315. CC_DEPEND_DLLS ${_dlls}
  316. )
  317. endif()
  318. endif()
  319. endfunction()