CocosBuildHelpers.cmake 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. include(CMakeParseArguments)
  2. # find a prebuilt lib by `lib_name` and save the result in `lib_out`
  3. function(cocos_find_prebuilt_lib_by_name lib_name lib_out)
  4. set(search_path ${COCOS_PREBUILT_PATH})
  5. if(XCODE OR VS)
  6. set(search_path ${COCOS_PREBUILT_PATH}/${CMAKE_BUILD_TYPE})
  7. endif()
  8. message(STATUS "search_path cocos prebuilt library: ${search_path}")
  9. find_library(found_lib ${lib_name} PATHS ${search_path} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
  10. if(found_lib)
  11. message(STATUS "find cocos prebuilt library: ${found_lib}")
  12. else()
  13. message(STATUS "can't find cocos prebuilt library: ${lib_name}")
  14. endif()
  15. set(${lib_out} ${found_lib} PARENT_SCOPE)
  16. unset(found_lib CACHE)
  17. endfunction()
  18. # copy resource `FILES` and `FOLDERS` to `COPY_TO` folder before `cocos_target` build
  19. function(cocos_copy_target_res cocos_target)
  20. set(oneValueArgs COPY_TO)
  21. set(multiValueArgs FILES FOLDERS)
  22. cmake_parse_arguments(opt "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  23. # copy files
  24. foreach(cc_file ${opt_FILES})
  25. get_filename_component(file_name ${cc_file} NAME)
  26. add_custom_command(TARGET ${cocos_target} PRE_BUILD
  27. COMMAND ${CMAKE_COMMAND} -E copy_if_different
  28. ${cc_file}
  29. "${opt_COPY_TO}/${file_name}"
  30. )
  31. endforeach()
  32. # copy folders
  33. foreach(cc_folder ${opt_FOLDERS})
  34. add_custom_command(TARGET ${cocos_target} PRE_BUILD
  35. COMMAND ${CMAKE_COMMAND} -E copy_directory
  36. ${cc_folder}
  37. ${opt_COPY_TO}
  38. )
  39. endforeach()
  40. endfunction()
  41. # mark `FILES` and files in `FOLDERS` as resource files, the destination is `RES_TO` folder
  42. # save all marked files in `res_out`
  43. function(cocos_mark_multi_resources res_out)
  44. set(oneValueArgs RES_TO)
  45. set(multiValueArgs FILES FOLDERS)
  46. cmake_parse_arguments(opt "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  47. set(tmp_file_list)
  48. foreach(cc_file ${opt_FILES})
  49. get_filename_component(cc_file_abs ${cc_file} ABSOLUTE)
  50. get_filename_component(file_dir ${cc_file_abs} DIRECTORY)
  51. cocos_mark_resources(FILES ${cc_file_abs} BASEDIR ${file_dir} RESOURCEBASE ${opt_RES_TO})
  52. endforeach()
  53. list(APPEND tmp_file_list ${opt_FILES})
  54. foreach(cc_folder ${opt_FOLDERS})
  55. file(GLOB_RECURSE folder_files "${cc_folder}/*")
  56. list(APPEND tmp_file_list ${folder_files})
  57. cocos_mark_resources(FILES ${folder_files} BASEDIR ${cc_folder} RESOURCEBASE ${opt_RES_TO})
  58. endforeach()
  59. set(${res_out} ${tmp_file_list} PARENT_SCOPE)
  60. endfunction()
  61. # get `cocos_target` depend all dlls, save the result in `all_depend_dlls_out`
  62. function(get_target_depends_ext_dlls cocos_target all_depend_dlls_out)
  63. set(all_depend_ext_dlls)
  64. set(targets_prepare_search ${cocos_target})
  65. # targets_prepare_search, target need find ext libs
  66. set(have_searched_targets)
  67. set(need_search_targets)
  68. while(true)
  69. foreach(tmp_target ${targets_prepare_search})
  70. get_target_property(tmp_depend_libs ${tmp_target} LINK_LIBRARIES)
  71. list(REMOVE_ITEM targets_prepare_search ${tmp_target})
  72. # target itself use_cocos_pkg
  73. list(APPEND tmp_depend_libs ${tmp_target})
  74. foreach(depend_lib ${tmp_depend_libs})
  75. if(TARGET ${depend_lib})
  76. get_target_property(tmp_dlls ${depend_lib} DEPEND_DLLS)
  77. if(tmp_dlls)
  78. list(APPEND all_depend_ext_dlls ${tmp_dlls})
  79. endif()
  80. if(NOT (depend_lib STREQUAL tmp_target))
  81. list(APPEND targets_prepare_search ${depend_lib})
  82. endif()
  83. endif()
  84. endforeach()
  85. endforeach()
  86. list(LENGTH targets_prepare_search targets_prepare_search_size)
  87. if(targets_prepare_search_size LESS 1)
  88. break()
  89. endif()
  90. endwhile(true)
  91. set(${all_depend_dlls_out} ${all_depend_ext_dlls} PARENT_SCOPE)
  92. endfunction()
  93. # copy the `cocos_target` needed dlls into `COPY_TO` folder
  94. function(cocos_copy_target_dll cocos_target)
  95. set(oneValueArgs COPY_TO)
  96. cmake_parse_arguments(opt "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  97. get_target_depends_ext_dlls(${cocos_target} all_depend_dlls)
  98. # remove repeat items
  99. list(REMOVE_DUPLICATES all_depend_dlls)
  100. message(STATUS "prepare to copy external dlls for ${cocos_target}:${all_depend_dlls}")
  101. foreach(single_target_dll ${all_depend_dlls})
  102. add_custom_command(TARGET ${cocos_target} PRE_BUILD
  103. COMMAND ${CMAKE_COMMAND} -E copy_if_different
  104. ${single_target_dll}
  105. ${opt_COPY_TO}
  106. )
  107. endforeach(single_target_dll)
  108. endfunction()
  109. # find dlls in a dir which `LIB_ABS_PATH` located, and save the result in `dlls_out`
  110. function(cocos_find_dlls_for_lib dlls_out)
  111. set(oneValueArgs LIB_ABS_PATH)
  112. cmake_parse_arguments(opt "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  113. get_filename_component(lib_dir ${opt_LIB_ABS_PATH} DIRECTORY)
  114. file(GLOB lib_dir_files "${lib_dir}/*")
  115. set(cc_dlls)
  116. foreach(dir_file ${lib_dir_files})
  117. if(${dir_file} MATCHES "dll$")
  118. list(APPEND cc_dlls ${dir_file})
  119. endif()
  120. endforeach()
  121. set(${dlls_out} ${cc_dlls} PARENT_SCOPE)
  122. endfunction()
  123. # mark `FILES` as resources, files will be put into sub-dir tree depend on its absolute path
  124. function(cocos_mark_resources)
  125. set(oneValueArgs BASEDIR RESOURCEBASE)
  126. set(multiValueArgs FILES)
  127. cmake_parse_arguments(opt "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  128. if(NOT opt_RESOURCEBASE)
  129. set(opt_RESOURCEBASE Resources)
  130. endif()
  131. get_filename_component(BASEDIR_ABS ${opt_BASEDIR} ABSOLUTE)
  132. foreach(RES_FILE ${opt_FILES} ${opt_UNPARSED_ARGUMENTS})
  133. get_filename_component(RES_FILE_ABS ${RES_FILE} ABSOLUTE)
  134. file(RELATIVE_PATH RES ${BASEDIR_ABS} ${RES_FILE_ABS})
  135. get_filename_component(RES_LOC ${RES} PATH)
  136. set_source_files_properties(${RES_FILE} PROPERTIES
  137. MACOSX_PACKAGE_LOCATION "${opt_RESOURCEBASE}/${RES_LOC}"
  138. HEADER_FILE_ONLY 1
  139. )
  140. if(XCODE OR VS)
  141. string(REPLACE "/" "\\" ide_source_group "${opt_RESOURCEBASE}/${RES_LOC}")
  142. source_group("${ide_source_group}" FILES ${RES_FILE})
  143. endif()
  144. endforeach()
  145. endfunction()
  146. # mark the code sources of `cocos_target` into sub-dir tree
  147. function(cocos_mark_code_files cocos_target)
  148. set(oneValueArgs GROUPBASE)
  149. cmake_parse_arguments(opt "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  150. if(NOT opt_GROUPBASE)
  151. set(root_dir ${CMAKE_CURRENT_SOURCE_DIR})
  152. else()
  153. set(root_dir ${opt_GROUPBASE})
  154. message(STATUS "target ${cocos_target} code group base is: ${root_dir}")
  155. endif()
  156. message(STATUS "cocos_mark_code_files: ${cocos_target}")
  157. get_property(file_list TARGET ${cocos_target} PROPERTY SOURCES)
  158. foreach(single_file ${file_list})
  159. source_group_single_file(${single_file} GROUP_TO "Source Files" BASE_PATH "${root_dir}")
  160. endforeach()
  161. endfunction()
  162. # source group one file
  163. # cut the `single_file` absolute path from `BASE_PATH`, then mark file to `GROUP_TO`
  164. function(source_group_single_file single_file)
  165. set(oneValueArgs GROUP_TO BASE_PATH)
  166. cmake_parse_arguments(opt "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  167. # get relative_path
  168. get_filename_component(abs_path ${single_file} ABSOLUTE)
  169. file(RELATIVE_PATH relative_path_with_name ${opt_BASE_PATH} ${abs_path})
  170. get_filename_component(relative_path ${relative_path_with_name} PATH)
  171. # set source_group, consider sub source group
  172. string(REPLACE "/" "\\" ide_file_group "${opt_GROUP_TO}/${relative_path}")
  173. source_group("${ide_file_group}" FILES ${single_file})
  174. endfunction()
  175. # build a cocos application
  176. # hrough compile the files `APP_SRC`, link the libs in `*LIBS`, use the packages in `*.PKGS`
  177. # this method hide the link lib details, those is prebuilt libs or not
  178. function(cocos_build_app app_name)
  179. set(multiValueArgs
  180. APP_SRC
  181. DEPEND_COMMON_LIBS
  182. DEPEND_ANDROID_LIBS
  183. COMMON_USE_PKGS
  184. LINUX_USE_PKGS
  185. DEPEND_MACOSX_LIBS
  186. DEPEND_WINDOWS_LIBS
  187. )
  188. cmake_parse_arguments(opt "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  189. if(ANDROID)
  190. add_library(${app_name} SHARED ${opt_APP_SRC})
  191. foreach(android_lib ${opt_DEPEND_ANDROID_LIBS})
  192. if(USE_COCOS_PREBUILT)
  193. target_link_libraries(${app_name} -Wl,-whole-archive "${${_${android_lib}_prefix}_LIBRARIES}" -Wl,-no-whole-archive)
  194. else()
  195. target_link_libraries(${app_name} -Wl,-whole-archive ${android_lib} -Wl,-no-whole-archive)
  196. add_dependencies(${app_name} ${android_lib})
  197. endif()
  198. endforeach()
  199. else()
  200. add_executable(${app_name} ${opt_APP_SRC})
  201. endif()
  202. # set target PROPERTIES, depend different platforms
  203. if(APPLE)
  204. set(APP_BIN_DIR "${CMAKE_BINARY_DIR}/bin")
  205. set_target_properties(${app_name} PROPERTIES MACOSX_BUNDLE 1
  206. )
  207. elseif(MSVC)
  208. set(APP_BIN_DIR "${CMAKE_BINARY_DIR}/bin/${APP_NAME}/$<CONFIG>")
  209. set(APP_RES_DIR "${APP_BIN_DIR}")
  210. #Visual Studio Defaults to wrong type
  211. set_target_properties(${app_name} PROPERTIES LINK_FLAGS "/SUBSYSTEM:WINDOWS")
  212. else(LINUX)
  213. set(APP_BIN_DIR "${CMAKE_BINARY_DIR}/bin/${CMAKE_BUILD_TYPE}/${APP_NAME}")
  214. set(APP_RES_DIR "${APP_BIN_DIR}/Resources")
  215. endif()
  216. set_target_properties(${app_name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${APP_BIN_DIR}")
  217. if(MACOSX)
  218. list(APPEND opt_DEPEND_COMMON_LIBS ${opt_DEPEND_MACOSX_LIBS})
  219. elseif(WINDOWS)
  220. list(APPEND opt_DEPEND_COMMON_LIBS ${opt_DEPEND_WINDOWS_LIBS})
  221. endif()
  222. # link commom libs, and common libs need external or system libs
  223. if(USE_COCOS_PREBUILT)
  224. include(CocosUseLibs)
  225. foreach(common_lib ${opt_DEPEND_COMMON_LIBS})
  226. message(STATUS "${app_name} prepare to link engine lib: ${common_lib}")
  227. cocos_use_pkg(${app_name} ${_${common_lib}_prefix})
  228. if(common_lib STREQUAL "cocos2d")
  229. target_use_cocos2d_depend_libs(${app_name})
  230. elseif(common_lib STREQUAL "jscocos2d")
  231. target_use_jscocos2d_depend_libs(${app_name})
  232. elseif(common_lib STREQUAL "luacocos2d")
  233. target_use_luacocos2d_depend_libs(${app_name})
  234. elseif(common_lib STREQUAL "simulator")
  235. target_use_simulator_depend_libs(${app_name})
  236. endif()
  237. endforeach()
  238. else()
  239. foreach(common_lib ${opt_DEPEND_COMMON_LIBS})
  240. target_link_libraries(${app_name} ${common_lib})
  241. add_dependencies(${app_name} ${common_lib})
  242. endforeach()
  243. endif()
  244. if(LINUX)
  245. foreach(_pkg ${opt_LINUX_USE_PKGS})
  246. cocos_use_pkg(${app_name} ${_pkg})
  247. endforeach()
  248. endif()
  249. foreach(_pkg ${opt_COMMON_USE_PKGS})
  250. cocos_use_pkg(${app_name} ${_pkg})
  251. endforeach()
  252. # auto mark code files for IDE when mark app
  253. if(XCODE OR VS)
  254. cocos_mark_code_files(${APP_NAME})
  255. endif()
  256. # generate prebuilt auto when build app if GEN_COCOS_PREBUILT=ON
  257. if(GEN_COCOS_PREBUILT)
  258. add_dependencies(${APP_NAME} prebuilt)
  259. endif()
  260. set(APP_BIN_DIR ${APP_BIN_DIR} PARENT_SCOPE)
  261. set(APP_RES_DIR ${APP_RES_DIR} PARENT_SCOPE)
  262. endfunction()
  263. # if cc_variable not set, then set it cc_value
  264. macro(cocos_fake_set cc_variable cc_value)
  265. if(NOT DEFINED ${cc_variable})
  266. set(${cc_variable} ${cc_value})
  267. endif()
  268. endmacro()
  269. # generate macOS app package infomations, need improve for example, the using of info.plist
  270. macro(cocos_pak_xcode cocos_target)
  271. set(oneValueArgs
  272. INFO_PLIST
  273. BUNDLE_NAME
  274. BUNDLE_VERSION
  275. COPYRIGHT
  276. GUI_IDENTIFIER
  277. ICON_FILE
  278. INFO_STRING
  279. LONG_VERSION_STRING
  280. SHORT_VERSION_STRING
  281. )
  282. set(multiValueArgs)
  283. cmake_parse_arguments(COCOS_APP "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  284. # set default value
  285. cocos_fake_set(COCOS_APP_INFO_PLIST "MacOSXBundleInfo.plist.in")
  286. cocos_fake_set(COCOS_APP_BUNDLE_NAME "\${PRODUCT_NAME}")
  287. cocos_fake_set(COCOS_APP_BUNDLE_VERSION "1")
  288. cocos_fake_set(COCOS_APP_COPYRIGHT "Copyright © 2018. All rights reserved.")
  289. cocos_fake_set(COCOS_APP_GUI_IDENTIFIER "org.cocos2dx.${APP_NAME}")
  290. cocos_fake_set(COCOS_APP_ICON_FILE "Icon")
  291. cocos_fake_set(COCOS_APP_INFO_STRING "cocos2d-x app")
  292. cocos_fake_set(COCOS_APP_LONG_VERSION_STRING "1.0.0")
  293. cocos_fake_set(COCOS_APP_SHORT_VERSION_STRING "1.0")
  294. # set bundle info
  295. set_target_properties(${cocos_target}
  296. PROPERTIES
  297. MACOSX_BUNDLE_INFO_PLIST ${COCOS_APP_INFO_PLIST}
  298. )
  299. set(MACOSX_BUNDLE_BUNDLE_NAME ${COCOS_APP_BUNDLE_NAME})
  300. set(MACOSX_BUNDLE_BUNDLE_VERSION ${COCOS_APP_BUNDLE_VERSION})
  301. set(MACOSX_BUNDLE_COPYRIGHT ${COCOS_APP_COPYRIGHT})
  302. set(MACOSX_BUNDLE_GUI_IDENTIFIER ${COCOS_APP_GUI_IDENTIFIER})
  303. set(MACOSX_BUNDLE_ICON_FILE ${COCOS_APP_ICON_FILE})
  304. set(MACOSX_BUNDLE_INFO_STRING ${COCOS_APP_INFO_STRING})
  305. set(MACOSX_BUNDLE_LONG_VERSION_STRING ${COCOS_APP_LONG_VERSION_STRING})
  306. set(MACOSX_BUNDLE_SHORT_VERSION_STRING ${COCOS_APP_SHORT_VERSION_STRING})
  307. message("cocos package: ${cocos_target}, plist file: ${COCOS_APP_INFO_PLIST}")
  308. cocos_config_app_xcode_property(${cocos_target})
  309. endmacro()
  310. # set Xcode property for application, include all depend target
  311. macro(cocos_config_app_xcode_property cocos_app)
  312. cocos_config_target_xcode_property(${cocos_app})
  313. # for example, cocos_target: cpp-tests link engine_lib: cocos2d
  314. get_target_property(engine_libs ${cocos_app} LINK_LIBRARIES)
  315. foreach(engine_lib ${engine_libs})
  316. if(TARGET ${engine_lib})
  317. cocos_config_target_xcode_property(${engine_lib})
  318. # for example, engine_lib: cocos2d link external_lib: flatbuffers
  319. get_target_property(external_libs ${engine_lib} LINK_LIBRARIES)
  320. foreach(external_lib ${external_libs})
  321. if(TARGET ${external_lib})
  322. cocos_config_target_xcode_property(${external_lib})
  323. endif()
  324. endforeach()
  325. endif()
  326. endforeach()
  327. endmacro()
  328. # custom Xcode property for iOS target
  329. macro(cocos_config_target_xcode_property cocos_target)
  330. if(IOS)
  331. set_xcode_property(${cocos_target} IPHONEOS_DEPLOYMENT_TARGET "8.0")
  332. set_xcode_property(${cocos_target} ENABLE_BITCODE "NO")
  333. set_xcode_property(${cocos_target} ONLY_ACTIVE_ARCH "YES")
  334. endif()
  335. endmacro()
  336. # This little macro lets you set any XCode specific property, from ios.toolchain.cmake
  337. function(set_xcode_property TARGET XCODE_PROPERTY XCODE_VALUE)
  338. set_property(TARGET ${TARGET} PROPERTY XCODE_ATTRIBUTE_${XCODE_PROPERTY} ${XCODE_VALUE})
  339. endfunction(set_xcode_property)
  340. # works same as find_package, but do additional care to properly find
  341. macro(cocos_find_package pkg_name pkg_prefix)
  342. if(NOT USE_EXTERNAL_PREBUILT OR NOT ${pkg_prefix}_FOUND)
  343. find_package(${pkg_name} ${ARGN})
  344. endif()
  345. if(NOT ${pkg_prefix}_INCLUDE_DIRS AND ${pkg_prefix}_INCLUDE_DIR)
  346. set(${pkg_prefix}_INCLUDE_DIRS ${${pkg_prefix}_INCLUDE_DIR})
  347. endif()
  348. if(NOT ${pkg_prefix}_LIBRARIES AND ${pkg_prefix}_LIBRARY)
  349. set(${pkg_prefix}_LIBRARIES ${${pkg_prefix}_LIBRARY})
  350. endif()
  351. message(STATUS "${pkg_name} include dirs: ${${pkg_prefix}_INCLUDE_DIRS}")
  352. endmacro()
  353. # cocos_use_pkg(pkg) function.
  354. # This function applies standard package variables (after find_package(pkg) call) to current scope
  355. # Recognized variables: <pkg>_INCLUDE_DIRS, <pkg>_LIBRARIES, <pkg>_LIBRARY_DIRS
  356. # Also if BUILD_SHARED_LIBS variable off, it is try to use <pkg>_STATIC_* vars before
  357. function(cocos_use_pkg target pkg)
  358. set(prefix ${pkg})
  359. set(_include_dirs)
  360. if(NOT _include_dirs)
  361. set(_include_dirs ${${prefix}_INCLUDE_DIRS})
  362. endif()
  363. if(NOT _include_dirs)
  364. # backward compat with old package-find scripts
  365. set(_include_dirs ${${prefix}_INCLUDE_DIR})
  366. endif()
  367. if(_include_dirs)
  368. include_directories(${_include_dirs})
  369. # message(STATUS "${pkg} add to include_dirs: ${_include_dirs}")
  370. endif()
  371. set(_library_dirs)
  372. if(NOT _library_dirs)
  373. set(_library_dirs ${${prefix}_LIBRARY_DIRS})
  374. endif()
  375. if(_library_dirs)
  376. link_directories(${_library_dirs})
  377. # message(STATUS "${pkg} add to link_dirs: ${_library_dirs}")
  378. endif()
  379. set(_libs)
  380. if(NOT _libs)
  381. set(_libs ${${prefix}_LIBRARIES})
  382. endif()
  383. if(NOT _libs)
  384. set(_libs ${${prefix}_LIBRARY})
  385. endif()
  386. if(_libs)
  387. target_link_libraries(${target} ${_libs})
  388. # message(STATUS "${pkg} libs added to '${target}': ${_libs}")
  389. endif()
  390. set(_defs)
  391. if(NOT _defs)
  392. set(_defs ${${prefix}_DEFINITIONS})
  393. endif()
  394. if(_defs)
  395. add_definitions(${_defs})
  396. # message(STATUS "${pkg} add definitions: ${_defs}")
  397. endif()
  398. set(_dlls)
  399. if(NOT _dlls)
  400. set(_dlls ${${prefix}_DLLS})
  401. endif()
  402. if(_dlls)
  403. if(MSVC)
  404. # message(STATUS "${target} add dll: ${_dlls}")
  405. get_property(pre_dlls
  406. TARGET ${target}
  407. PROPERTY DEPEND_DLLS)
  408. if(pre_dlls)
  409. set(_dlls ${pre_dlls} ${_dlls})
  410. endif()
  411. set_property(TARGET ${target}
  412. PROPERTY
  413. DEPEND_DLLS ${_dlls}
  414. )
  415. endif()
  416. endif()
  417. endfunction()