diff --git a/CMakeLists.txt b/CMakeLists.txt index 52391571..fe59b475 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -266,6 +266,32 @@ if(PLATFORM_NAME STREQUAL "Windows64") add_dependencies(Minecraft.Server GenerateItemNameMap) endif() +#neo: added - SDK generation +set(SDK_INPUT_DIRS + "${CMAKE_SOURCE_DIR}/Minecraft.World" + "${CMAKE_SOURCE_DIR}/Minecraft.Client" + "${CMAKE_SOURCE_DIR}/include" + "${CMAKE_SOURCE_DIR}/Minecraft.Client/${PLATFORM_NAME}/4JLibs" +) + +set(SDK_OUTPUT "${CMAKE_BINARY_DIR}/Minecraft.Client/$/sdk.h") +add_custom_command( + OUTPUT "${SDK_OUTPUT}" + COMMAND ${CMAKE_COMMAND} + "-DINPUT_DIRS=${SDK_INPUT_DIRS}" + "-DOUTPUT_FILE=${SDK_OUTPUT}" + -P "${CMAKE_SOURCE_DIR}/cmake/GenerateSdk.cmake" + DEPENDS + "${CMAKE_SOURCE_DIR}/cmake/GenerateSdk.cmake" + COMMENT "Generating sdk.h..." + VERBATIM +) + +add_custom_target(GenerateSdk ALL + DEPENDS "${SDK_OUTPUT}" +) + +set_property(TARGET GenerateSdk PROPERTY FOLDER "Build") target_include_directories(Minecraft.Client PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/generated" ) diff --git a/cmake/GenerateSdk.cmake b/cmake/GenerateSdk.cmake new file mode 100644 index 00000000..62b39a06 --- /dev/null +++ b/cmake/GenerateSdk.cmake @@ -0,0 +1,204 @@ +if(NOT INPUT_DIRS) + message(FATAL_ERROR "INPUT_DIRS must be set to a list of directories.") +endif() +if(NOT OUTPUT_FILE) + message(FATAL_ERROR "OUTPUT_FILE must be set.") +endif() + +set(_all_headers "") +foreach(_dir IN LISTS INPUT_DIRS) + if(EXISTS "${_dir}") + file(GLOB_RECURSE _hfiles "${_dir}/*.h") + list(APPEND _all_headers ${_hfiles}) + endif() +endforeach() + +if(NOT _all_headers) + message(FATAL_ERROR "No .h files found in INPUT_DIRS.") +endif() +list(REMOVE_DUPLICATES _all_headers) +list(SORT _all_headers) + +foreach(_h IN LISTS _all_headers) + get_filename_component(_bn "${_h}" NAME) + string(TOLOWER "${_bn}" _k) + set(_idx_${_k} "${_h}") +endforeach() + +foreach(_h IN LISTS _all_headers) + file(STRINGS "${_h}" _ll REGEX "^[ \t]*#[ \t]*include[ \t]+\"") + get_filename_component(_hd "${_h}" DIRECTORY) + + set(_dd "") + foreach(_l IN LISTS _ll) + if(_l MATCHES "^[ \t]*#[ \t]*include[ \t]+\"([^\"]+)\"") + set(_in "${CMAKE_MATCH_1}") + set(_rv "") + set(_try "${_hd}/${_in}") + get_filename_component(_try "${_try}" ABSOLUTE) + if(EXISTS "${_try}") + set(_rv "${_try}") + else() + string(TOLOWER "${_in}" _k2) + if(DEFINED _idx_${_k2}) + set(_rv "${_idx_${_k2}}") + endif() + endif() + if(_rv AND _rv IN_LIST _all_headers) + list(APPEND _dd "${_rv}") + endif() + endif() + endforeach() + if(_dd) + list(REMOVE_DUPLICATES _dd) + endif() + set(_de_${_h} "${_dd}") +endforeach() + +set(_sorted "") +set(_left ${_all_headers}) +while(_left) + set(_prog 0) + set(_next "") + foreach(_h IN LISTS _left) + set(_rdy 1) + foreach(_d IN LISTS _de_${_h}) + if(_d IN_LIST _left) + set(_rdy 0) + break() + endif() + endforeach() + if(_rdy) + list(APPEND _sorted "${_h}") + set(_prog 1) + else() + list(APPEND _next "${_h}") + endif() + endforeach() + if(NOT _prog) + foreach(_h IN LISTS _next) + list(APPEND _sorted "${_h}") + endforeach() + break() + endif() + set(_left ${_next}) +endwhile() + +set(_sys "") +set(_body "") + +foreach(_h IN LISTS _sorted) + file(STRINGS "${_h}" _ll) + + set(_inbc 0) + set(_out "") + foreach(_l IN LISTS _ll) + if(_l STREQUAL "") + continue() + endif() + + if(_inbc) + string(FIND "${_l}" "*/" _ce) + if(_ce GREATER -1) + math(EXPR _ca "${_ce} + 2") + string(SUBSTRING "${_l}" ${_ca} -1 _l) + set(_inbc 0) + else() + continue() + endif() + endif() + + string(FIND "${_l}" "//" _sl) + if(_sl GREATER -1) + string(SUBSTRING "${_l}" 0 ${_sl} _l) + endif() + + while(TRUE) + string(FIND "${_l}" "/*" _so) + if(_so EQUAL -1) + break() + endif() + string(SUBSTRING "${_l}" 0 ${_so} _bf) + string(SUBSTRING "${_l}" ${_so} -1 _ar) + string(FIND "${_ar}" "*/" _ce) + if(_ce EQUAL -1) + set(_l "${_bf}") + set(_inbc 1) + break() + else() + math(EXPR _ca "${_ce} + 2") + string(SUBSTRING "${_ar}" ${_ca} -1 _af) + set(_l "${_bf}${_af}") + endif() + endwhile() + + string(STRIP "${_l}" _ls) + + if(_ls MATCHES "^#[ \t]*pragma[ \t]+once") + continue() + endif() + if(_ls MATCHES "^#[ \t]*include[ \t]+\"([^\"]+)\"") + continue() + endif() + if(_ls MATCHES "^#[ \t]*include[ \t]+<([^>]+)>") + set(_sn "${CMAKE_MATCH_1}") + if(NOT _sn IN_LIST _sys) + list(APPEND _sys "${_sn}") + endif() + continue() + endif() + + if(_ls STREQUAL "") + continue() + endif() + + string(APPEND _out "${_l}\n") + endforeach() + + if(_out) + if(_body) + string(APPEND _body "\n") + endif() + string(APPEND _body "${_out}") + endif() +endforeach() + +set(_guard "MINECRAFT_LCE_SDK_H") +set(_tmp "${OUTPUT_FILE}.tmp") + +file(WRITE "${_tmp}" + "#ifndef ${_guard}\n" + "#define ${_guard}\n" + "\n" + "// Auto-generated. Do not edit.\n" + "// Minecraft Console Edition SDK Header\n" + "\n" +) + +if(_sys) + list(SORT _sys) + foreach(_s IN LISTS _sys) + file(APPEND "${_tmp}" "#include <${_s}>\n") + endforeach() + file(APPEND "${_tmp}" "\n") +endif() + +file(APPEND "${_tmp}" "${_body}") +file(APPEND "${_tmp}" "\n#endif // ${_guard}\n") + +if(EXISTS "${OUTPUT_FILE}") + execute_process( + COMMAND ${CMAKE_COMMAND} -E compare_files "${OUTPUT_FILE}" "${_tmp}" + RESULT_VARIABLE _ch + ) +else() + set(_ch 1) +endif() + +if(_ch) + file(RENAME "${_tmp}" "${OUTPUT_FILE}") + message(STATUS "GenerateSdk: wrote ${OUTPUT_FILE}") +else() + file(REMOVE "${_tmp}") + message(STATUS "GenerateSdk: ${OUTPUT_FILE} is up-to-date") +endif()