include(CMakeParseArguments) # copy resource `FILES` and `FOLDERS` to `COPY_TO` folder function(cocos_copy_res) set(oneValueArgs COPY_TO) set(multiValueArgs FILES FOLDERS) cmake_parse_arguments(opt "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) # copy files foreach(cc_file ${opt_FILES}) get_filename_component(file_name ${cc_file} NAME) configure_file(${cc_file} "${opt_COPY_TO}/${file_name}" COPYONLY) endforeach() # copy folders files foreach(cc_folder ${opt_FOLDERS}) file(GLOB_RECURSE folder_files "${cc_folder}/*") get_filename_component(folder_abs_path ${cc_folder} ABSOLUTE) foreach(res_file ${folder_files}) get_filename_component(res_file_abs_path ${res_file} ABSOLUTE) file(RELATIVE_PATH res_file_relat_path ${folder_abs_path} ${res_file_abs_path}) configure_file(${res_file} "${opt_COPY_TO}/${res_file_relat_path}" COPYONLY) endforeach() endforeach() endfunction() # mark `FILES` and files in `FOLDERS` as resource files, the destination is `RES_TO` folder # save all marked files in `res_out` function(cocos_mark_multi_resources res_out) set(oneValueArgs RES_TO) set(multiValueArgs FILES FOLDERS) cmake_parse_arguments(opt "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) set(tmp_file_list) foreach(cc_file ${opt_FILES}) get_filename_component(cc_file_abs ${cc_file} ABSOLUTE) get_filename_component(file_dir ${cc_file_abs} DIRECTORY) cocos_mark_resources(FILES ${cc_file_abs} BASEDIR ${file_dir} RESOURCEBASE ${opt_RES_TO}) endforeach() list(APPEND tmp_file_list ${opt_FILES}) foreach(cc_folder ${opt_FOLDERS}) file(GLOB_RECURSE folder_files "${cc_folder}/*") list(APPEND tmp_file_list ${folder_files}) cocos_mark_resources(FILES ${folder_files} BASEDIR ${cc_folder} RESOURCEBASE ${opt_RES_TO}) endforeach() set(${res_out} ${tmp_file_list} PARENT_SCOPE) endfunction() # get `cocos_target` depend all dlls, save the result in `all_depend_dlls_out` function(get_target_depends_ext_dlls cocos_target all_depend_dlls_out) set(all_depend_ext_dlls) set(targets_prepare_search ${cocos_target}) # targets_prepare_search, target need find ext libs set(have_searched_targets) set(need_search_targets) while(true) foreach(tmp_target ${targets_prepare_search}) get_target_property(tmp_depend_libs ${tmp_target} LINK_LIBRARIES) list(REMOVE_ITEM targets_prepare_search ${tmp_target}) # target itself use_cocos_pkg list(APPEND tmp_depend_libs ${tmp_target}) foreach(depend_lib ${tmp_depend_libs}) if(TARGET ${depend_lib}) get_target_property(tmp_dlls ${depend_lib} CC_DEPEND_DLLS) if(tmp_dlls) list(APPEND all_depend_ext_dlls ${tmp_dlls}) endif() if(NOT (depend_lib STREQUAL tmp_target)) list(APPEND targets_prepare_search ${depend_lib}) endif() endif() endforeach() endforeach() list(LENGTH targets_prepare_search targets_prepare_search_size) if(targets_prepare_search_size LESS 1) break() endif() endwhile(true) set(${all_depend_dlls_out} ${all_depend_ext_dlls} PARENT_SCOPE) endfunction() # copy the `cocos_target` needed dlls into `COPY_TO` folder function(cocos_copy_target_dll cocos_target) set(oneValueArgs COPY_TO) cmake_parse_arguments(opt "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) get_target_depends_ext_dlls(${cocos_target} all_depend_dlls) # remove repeat items if(all_depend_dlls) list(REMOVE_DUPLICATES all_depend_dlls) endif() # todo, add a option to enable/disable debug print message(STATUS "prepare to copy external dlls for ${cocos_target}:${all_depend_dlls}") foreach(cc_dll_file ${all_depend_dlls}) get_filename_component(cc_dll_name ${cc_dll_file} NAME) configure_file(${cc_dll_file} "${opt_COPY_TO}/${cc_dll_name}" COPYONLY) endforeach() endfunction() # mark `FILES` as resources, files will be put into sub-dir tree depend on its absolute path function(cocos_mark_resources) set(oneValueArgs BASEDIR RESOURCEBASE) set(multiValueArgs FILES) cmake_parse_arguments(opt "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) if(NOT opt_RESOURCEBASE) set(opt_RESOURCEBASE Resources) endif() get_filename_component(BASEDIR_ABS ${opt_BASEDIR} ABSOLUTE) foreach(RES_FILE ${opt_FILES} ${opt_UNPARSED_ARGUMENTS}) get_filename_component(RES_FILE_ABS ${RES_FILE} ABSOLUTE) file(RELATIVE_PATH RES ${BASEDIR_ABS} ${RES_FILE_ABS}) get_filename_component(RES_LOC ${RES} PATH) set_source_files_properties(${RES_FILE} PROPERTIES MACOSX_PACKAGE_LOCATION "${opt_RESOURCEBASE}/${RES_LOC}" HEADER_FILE_ONLY 1 ) if(XCODE OR VS) string(REPLACE "/" "\\" ide_source_group "${opt_RESOURCEBASE}/${RES_LOC}") source_group("${ide_source_group}" FILES ${RES_FILE}) endif() endforeach() endfunction() # mark the code sources of `cocos_target` into sub-dir tree function(cocos_mark_code_files cocos_target) set(oneValueArgs GROUPBASE) cmake_parse_arguments(opt "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) if(NOT opt_GROUPBASE) set(root_dir ${CMAKE_CURRENT_SOURCE_DIR}) else() set(root_dir ${opt_GROUPBASE}) message(STATUS "target ${cocos_target} code group base is: ${root_dir}") endif() message(STATUS "cocos_mark_code_files: ${cocos_target}") get_property(file_list TARGET ${cocos_target} PROPERTY SOURCES) foreach(single_file ${file_list}) source_group_single_file(${single_file} GROUP_TO "Source Files" BASE_PATH "${root_dir}") endforeach() endfunction() # source group one file # cut the `single_file` absolute path from `BASE_PATH`, then mark file to `GROUP_TO` function(source_group_single_file single_file) set(oneValueArgs GROUP_TO BASE_PATH) cmake_parse_arguments(opt "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) # get relative_path get_filename_component(abs_path ${single_file} ABSOLUTE) file(RELATIVE_PATH relative_path_with_name ${opt_BASE_PATH} ${abs_path}) get_filename_component(relative_path ${relative_path_with_name} PATH) # set source_group, consider sub source group string(REPLACE "/" "\\" ide_file_group "${opt_GROUP_TO}/${relative_path}") source_group("${ide_file_group}" FILES ${single_file}) endfunction() # setup a cocos application, include "APP_BIN_DIR", "APP_RES_DIR" config function(setup_cocos_app_config app_name) # set target PROPERTIES, depend different platforms if(APPLE) set(APP_BIN_DIR "${CMAKE_BINARY_DIR}/bin") set_target_properties(${app_name} PROPERTIES MACOSX_BUNDLE 1 ) elseif(MSVC) # only Debug and Release mode was supported when using MSVC. set(APP_BIN_DIR "${CMAKE_BINARY_DIR}/bin/${APP_NAME}/$") set(APP_RES_DIR "${CMAKE_BINARY_DIR}/bin/${APP_NAME}/${CMAKE_BUILD_TYPE}") #Visual Studio Defaults to wrong type set_target_properties(${app_name} PROPERTIES LINK_FLAGS "/SUBSYSTEM:WINDOWS") else(LINUX) set(APP_BIN_DIR "${CMAKE_BINARY_DIR}/bin/${CMAKE_BUILD_TYPE}/${APP_NAME}") set(APP_RES_DIR "${APP_BIN_DIR}/Resources") endif() set_target_properties(${app_name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${APP_BIN_DIR}") # auto mark code files for IDE when mark app if(XCODE OR VS) cocos_mark_code_files(${APP_NAME}) endif() set(APP_BIN_DIR ${APP_BIN_DIR} PARENT_SCOPE) set(APP_RES_DIR ${APP_RES_DIR} PARENT_SCOPE) endfunction() # if cc_variable not set, then set it cc_value macro(cocos_fake_set cc_variable cc_value) if(NOT DEFINED ${cc_variable}) set(${cc_variable} ${cc_value}) endif() endmacro() # generate macOS app package infomations, need improve for example, the using of info.plist macro(cocos_pak_xcode cocos_target) set(oneValueArgs INFO_PLIST BUNDLE_NAME BUNDLE_VERSION COPYRIGHT GUI_IDENTIFIER ICON_FILE INFO_STRING LONG_VERSION_STRING SHORT_VERSION_STRING ) set(multiValueArgs) cmake_parse_arguments(COCOS_APP "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) # set default value cocos_fake_set(COCOS_APP_INFO_PLIST "MacOSXBundleInfo.plist.in") cocos_fake_set(COCOS_APP_BUNDLE_NAME "\${PRODUCT_NAME}") cocos_fake_set(COCOS_APP_BUNDLE_VERSION "1") cocos_fake_set(COCOS_APP_COPYRIGHT "Copyright © 2018. All rights reserved.") cocos_fake_set(COCOS_APP_GUI_IDENTIFIER "org.cocos2dx.${APP_NAME}") cocos_fake_set(COCOS_APP_ICON_FILE "Icon") cocos_fake_set(COCOS_APP_INFO_STRING "cocos2d-x app") cocos_fake_set(COCOS_APP_LONG_VERSION_STRING "1.0.0") cocos_fake_set(COCOS_APP_SHORT_VERSION_STRING "1.0") # set bundle info set_target_properties(${cocos_target} PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${COCOS_APP_INFO_PLIST} ) set(MACOSX_BUNDLE_BUNDLE_NAME ${COCOS_APP_BUNDLE_NAME}) set(MACOSX_BUNDLE_BUNDLE_VERSION ${COCOS_APP_BUNDLE_VERSION}) set(MACOSX_BUNDLE_COPYRIGHT ${COCOS_APP_COPYRIGHT}) set(MACOSX_BUNDLE_GUI_IDENTIFIER ${COCOS_APP_GUI_IDENTIFIER}) set(MACOSX_BUNDLE_ICON_FILE ${COCOS_APP_ICON_FILE}) set(MACOSX_BUNDLE_INFO_STRING ${COCOS_APP_INFO_STRING}) set(MACOSX_BUNDLE_LONG_VERSION_STRING ${COCOS_APP_LONG_VERSION_STRING}) set(MACOSX_BUNDLE_SHORT_VERSION_STRING ${COCOS_APP_SHORT_VERSION_STRING}) message("cocos package: ${cocos_target}, plist file: ${COCOS_APP_INFO_PLIST}") cocos_config_app_xcode_property(${cocos_target}) endmacro() # set Xcode property for application, include all depend target macro(cocos_config_app_xcode_property cocos_app) cocos_config_target_xcode_property(${cocos_app}) # for example, cocos_target: cpp-tests link engine_lib: cocos2d get_target_property(engine_libs ${cocos_app} LINK_LIBRARIES) foreach(engine_lib ${engine_libs}) if(TARGET ${engine_lib}) cocos_config_target_xcode_property(${engine_lib}) # for example, engine_lib: cocos2d link external_lib: flatbuffers get_target_property(external_libs ${engine_lib} LINK_LIBRARIES) foreach(external_lib ${external_libs}) if(TARGET ${external_lib}) cocos_config_target_xcode_property(${external_lib}) endif() endforeach() endif() endforeach() endmacro() # custom Xcode property for iOS target macro(cocos_config_target_xcode_property cocos_target) if(IOS) set_xcode_property(${cocos_target} IPHONEOS_DEPLOYMENT_TARGET "8.0") set_xcode_property(${cocos_target} ENABLE_BITCODE "NO") set_xcode_property(${cocos_target} ONLY_ACTIVE_ARCH "YES") endif() endmacro() # This little macro lets you set any XCode specific property, from ios.toolchain.cmake function(set_xcode_property TARGET XCODE_PROPERTY XCODE_VALUE) set_property(TARGET ${TARGET} PROPERTY XCODE_ATTRIBUTE_${XCODE_PROPERTY} ${XCODE_VALUE}) endfunction(set_xcode_property) # works same as find_package, but do additional care to properly find macro(cocos_find_package pkg_name pkg_prefix) if(NOT ${pkg_prefix}_FOUND) find_package(${pkg_name} ${ARGN}) endif() if(NOT ${pkg_prefix}_INCLUDE_DIRS AND ${pkg_prefix}_INCLUDE_DIR) set(${pkg_prefix}_INCLUDE_DIRS ${${pkg_prefix}_INCLUDE_DIR}) endif() if(NOT ${pkg_prefix}_LIBRARIES AND ${pkg_prefix}_LIBRARY) set(${pkg_prefix}_LIBRARIES ${${pkg_prefix}_LIBRARY}) endif() message(STATUS "${pkg_name} include dirs: ${${pkg_prefix}_INCLUDE_DIRS}") endmacro() # cocos_use_pkg(pkg) function. # This function applies standard package variables (after find_package(pkg) call) to current scope # Recognized variables: _INCLUDE_DIRS, _LIBRARIES, _LIBRARY_DIRS # Also if BUILD_SHARED_LIBS variable off, it is try to use _STATIC_* vars before function(cocos_use_pkg target pkg) set(prefix ${pkg}) set(_include_dirs) if(NOT _include_dirs) set(_include_dirs ${${prefix}_INCLUDE_DIRS}) endif() if(NOT _include_dirs) # backward compat with old package-find scripts set(_include_dirs ${${prefix}_INCLUDE_DIR}) endif() if(_include_dirs) include_directories(${_include_dirs}) # message(STATUS "${pkg} add to include_dirs: ${_include_dirs}") endif() set(_library_dirs) if(NOT _library_dirs) set(_library_dirs ${${prefix}_LIBRARY_DIRS}) endif() if(_library_dirs) link_directories(${_library_dirs}) # message(STATUS "${pkg} add to link_dirs: ${_library_dirs}") endif() set(_libs) if(NOT _libs) set(_libs ${${prefix}_LIBRARIES}) endif() if(NOT _libs) set(_libs ${${prefix}_LIBRARY}) endif() if(_libs) target_link_libraries(${target} ${_libs}) # message(STATUS "${pkg} libs added to '${target}': ${_libs}") endif() set(_defs) if(NOT _defs) set(_defs ${${prefix}_DEFINITIONS}) endif() if(_defs) add_definitions(${_defs}) # message(STATUS "${pkg} add definitions: ${_defs}") endif() set(_dlls) if(NOT _dlls) set(_dlls ${${prefix}_DLLS}) endif() if(_dlls) if(MSVC) # message(STATUS "${target} add dll: ${_dlls}") get_property(pre_dlls TARGET ${target} PROPERTY CC_DEPEND_DLLS) if(pre_dlls) set(_dlls ${pre_dlls} ${_dlls}) endif() set_property(TARGET ${target} PROPERTY CC_DEPEND_DLLS ${_dlls} ) endif() endif() endfunction()