diff --git a/cmake/modules/StandaloneCrt.cmake b/cmake/modules/StandaloneCrt.cmake index 8c25cf48df27..306e4af13c0c 100644 --- a/cmake/modules/StandaloneCrt.cmake +++ b/cmake/modules/StandaloneCrt.cmake @@ -23,6 +23,9 @@ if(MSVC) # When building for Windows, use standard CMake for compatibility with # Visual Studio build tools and not require Make to be on the system. + # TODO: test building with this MSVC conditional code removed + # when USE_MICRO is enabled + set(CRT_CONFIG, "src/runtime/micro/crt_config.h") add_library(host_standalone_crt @@ -40,129 +43,154 @@ if(MSVC) else() - message(STATUS "Build standalone CRT for microTVM") + function(create_crt_library CRT_LIBRARY) - function(tvm_crt_define_targets) - # Build an isolated build directory, separate from the TVM tree. - list(APPEND CRT_FILE_COPY_JOBS - "3rdparty/libcrc/include *.h -> include" - "3rdparty/libcrc/src crcccitt.c -> src/runtime/crt/microtvm_rpc_common" - "3rdparty/libcrc/tab gentab_ccitt.inc -> src/runtime/crt/tab" - "3rdparty/dlpack/include *.h -> include" - "3rdparty/dmlc-core/include *.h -> include" - "include/tvm/runtime c_*_api.h -> include/tvm/runtime" - "include/tvm/runtime metadata_types.h -> include/tvm/runtime" - "include/tvm/runtime/crt *.h -> include/tvm/runtime/crt" - "src/runtime/crt Makefile -> ." - "src/runtime/crt/include *.h -> include" - "src/runtime/crt/aot_executor *.c -> src/runtime/crt/aot_executor" - "src/runtime/crt/aot_executor_module *.c -> src/runtime/crt/aot_executor_module" - "src/runtime/crt/common *.c -> src/runtime/crt/common" - "src/runtime/crt/graph_executor *.c -> src/runtime/crt/graph_executor" - "src/runtime/crt/graph_executor_module *.c -> src/runtime/crt/graph_executor_module" - "src/runtime/crt/host *.cc -> template/host" - "src/runtime/crt/host *.py -> template/host" - "src/runtime/crt/host Makefile.template -> template/host" - "src/runtime/crt/memory *.c -> src/runtime/crt/memory" - "src/runtime/crt/microtvm_rpc_common *.cc -> src/runtime/crt/microtvm_rpc_common" - "src/runtime/crt/microtvm_rpc_server *.cc -> src/runtime/crt/microtvm_rpc_server" - "src/runtime/minrpc *.h -> src/runtime/minrpc" - "src/support generic_arena.h -> src/support" - "src/support ssize.h -> src/support" - "src/runtime/crt crt_config-template.h -> template" - ) - - set(standalone_crt_base "${CMAKE_CURRENT_BINARY_DIR}/standalone_crt") - - foreach(job_spec IN LISTS CRT_FILE_COPY_JOBS) - string(REPLACE " " ";" job_spec "${job_spec}") - list(LENGTH job_spec job_spec_length) - math(EXPR job_spec_length_mod "${job_spec_length} % 3") - if(NOT "${job_spec_length_mod}" EQUAL 1) - message(FATAL_ERROR "CRT copy job spec list length is ${job_spec_length}; parsed job spec is ${job_spec}") - endif() - math(EXPR job_spec_stop "${job_spec_length} - 3") - - list(GET job_spec 0 job_src_base) - set(job_src_base "${CMAKE_CURRENT_SOURCE_DIR}/${job_src_base}") - foreach(copy_pattern_index RANGE 1 "${job_spec_stop}" 3) - list(GET job_spec ${copy_pattern_index} copy_pattern) - math(EXPR copy_dest_index "${copy_pattern_index} + 2") - list(GET job_spec ${copy_dest_index} copy_dest) - - tvm_file_glob(GLOB_RECURSE copy_files - RELATIVE "${job_src_base}" - "${job_src_base}/${copy_pattern}") - list(LENGTH copy_files copy_files_length) - if("${copy_files_length}" EQUAL 0) - message(FATAL_ERROR "CRT copy job matched 0 files: ${job_src_base}/${copy_pattern} -> ${copy_dest}") - endif() - foreach(copy_src IN LISTS copy_files) - get_filename_component(dest_path "${standalone_crt_base}/${copy_dest}/${copy_src}" ABSOLUTE) - tvm_micro_add_copy_file(host_isolated_build_deps ${job_src_base}/${copy_src} ${dest_path}) - endforeach() - endforeach() - endforeach() + set(CRT_LIBRARY_NAME host_standalone_crt_${CRT_LIBRARY}) + set(CRT_LIBRARY_SOURCES "") - add_custom_target(standalone_crt DEPENDS ${host_isolated_build_deps}) + foreach(FILE_NAME IN LISTS ARGN) + list(APPEND CRT_LIBRARY_SOURCES ${FILE_NAME}) + endforeach() - get_filename_component(host_build_dir_abspath "${CMAKE_CURRENT_BINARY_DIR}/host_standalone_crt" ABSOLUTE) + add_library(${CRT_LIBRARY_NAME} + STATIC + ${CRT_LIBRARY_SOURCES}) - if(${VERBOSE}) - set(make_quiet QUIET=) - else(${VERBOSE}) - set(make_quiet ) - endif(${VERBOSE}) + # add this library to the list of CRT libraries + set(CRT_LIBRARIES ${CRT_LIBRARIES} ${CRT_LIBRARY_NAME} PARENT_SCOPE) - list(APPEND crt_libraries memory graph_executor microtvm_rpc_server microtvm_rpc_common common) # NOTE: listed in link order. - foreach(crt_lib_name IN LISTS crt_libraries) - list(APPEND crt_library_paths "host_standalone_crt/lib${crt_lib_name}.a") - endforeach() + target_include_directories(${CRT_LIBRARY_NAME} + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src/runtime/micro/ + ${STANDALONE_CRT_BASE}/include) - set(make_common_args - "CRT_CONFIG=${CMAKE_CURRENT_SOURCE_DIR}/src/runtime/micro/crt_config.h" - "BUILD_DIR=${host_build_dir_abspath}" - "EXTRA_CFLAGS=-fPIC" - "EXTRA_CXXFLAGS=-fPIC" - "EXTRA_LDFLAGS=-fPIC" - "${make_quiet}") - - add_custom_command( - OUTPUT ${crt_library_paths} - COMMAND make ARGS ${make_common_args} clean - COMMAND make ARGS ${make_common_args} all - WORKING_DIRECTORY "${standalone_crt_base}" - DEPENDS standalone_crt ${host_isolated_build_deps}) - - add_custom_target(host_standalone_crt DEPENDS ${crt_library_paths}) - - foreach(crt_lib IN LISTS crt_libraries) - set(cmake_crt_lib_name host_standalone_crt_${crt_lib}) - list(APPEND cmake_crt_libraries ${cmake_crt_lib_name}) - add_library(${cmake_crt_lib_name} STATIC IMPORTED GLOBAL) - set(cmake_crt_lib_path "${CMAKE_CURRENT_BINARY_DIR}/host_standalone_crt/lib${crt_lib}.a") - add_dependencies(${cmake_crt_lib_name} host_standalone_crt "${cmake_crt_lib_path}") - set_target_properties(${cmake_crt_lib_name} PROPERTIES - IMPORTED_LOCATION "${cmake_crt_lib_path}" - IMPORTED_OBJECTS "${cmake_crt_lib_path}" - PUBLIC_HEADER "${crt_headers}") - endforeach() + set_target_properties(${CRT_LIBRARY_NAME} + PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/host_standalone_crt + POSITION_INDEPENDENT_CODE ON) - # Create the `crttest` target if we can find GTest. If not, we create dummy - # targets that give the user an informative error message. - if(GTEST_FOUND) - tvm_file_glob(GLOB TEST_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/tests/crt/*.cc) - add_executable(crttest ${TEST_SRCS}) - target_include_directories(crttest SYSTEM PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/standalone_crt/include ${CMAKE_CURRENT_SOURCE_DIR}/src/runtime/micro) - target_link_libraries(crttest PRIVATE ${cmake_crt_libraries} GTest::GTest GTest::Main pthread dl) - set_target_properties(crttest PROPERTIES EXCLUDE_FROM_ALL 1) - set_target_properties(crttest PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD 1) - gtest_discover_tests(crttest) - endif() + # make these libraries dependent on standalone_crt which depends on host_isolated_build_deps to avoid + # race with the file copy jobs + add_dependencies(${CRT_LIBRARY_NAME} standalone_crt) endfunction() - tvm_crt_define_targets() + message(STATUS "Build standalone CRT for microTVM") + + # Build an isolated build directory, separate from the TVM tree. + list(APPEND CRT_FILE_COPY_JOBS + "3rdparty/libcrc/include *.h -> include" + "3rdparty/libcrc/src crcccitt.c -> src/runtime/crt/microtvm_rpc_common" + "3rdparty/libcrc/tab gentab_ccitt.inc -> src/runtime/crt/tab" + "3rdparty/dlpack/include *.h -> include" + "3rdparty/dmlc-core/include *.h -> include" + "include/tvm/runtime c_*_api.h -> include/tvm/runtime" + "include/tvm/runtime metadata_types.h -> include/tvm/runtime" + "include/tvm/runtime/crt *.h -> include/tvm/runtime/crt" + "src/runtime/crt Makefile -> ." + "src/runtime/crt/include *.h -> include" + "src/runtime/crt/aot_executor *.c -> src/runtime/crt/aot_executor" + "src/runtime/crt/aot_executor_module *.c -> src/runtime/crt/aot_executor_module" + "src/runtime/crt/common *.c -> src/runtime/crt/common" + "src/runtime/crt/graph_executor *.c -> src/runtime/crt/graph_executor" + "src/runtime/crt/graph_executor_module *.c -> src/runtime/crt/graph_executor_module" + "src/runtime/crt/host *.cc -> template/host" + "src/runtime/crt/host *.py -> template/host" + "src/runtime/crt/host Makefile.template -> template/host" + "src/runtime/crt/memory *.c -> src/runtime/crt/memory" + "src/runtime/crt/microtvm_rpc_common *.cc -> src/runtime/crt/microtvm_rpc_common" + "src/runtime/crt/microtvm_rpc_server *.cc -> src/runtime/crt/microtvm_rpc_server" + "src/runtime/minrpc *.h -> src/runtime/minrpc" + "src/support generic_arena.h -> src/support" + "src/support ssize.h -> src/support" + "src/runtime/crt crt_config-template.h -> template" + ) + + set(STANDALONE_CRT_BASE ${CMAKE_CURRENT_BINARY_DIR}/standalone_crt) + + foreach(job_spec IN LISTS CRT_FILE_COPY_JOBS) + string(REPLACE " " ";" job_spec "${job_spec}") + list(LENGTH job_spec job_spec_length) + math(EXPR job_spec_length_mod "${job_spec_length} % 3") + if(NOT "${job_spec_length_mod}" EQUAL 1) + message(FATAL_ERROR "CRT copy job spec list length is ${job_spec_length}; parsed job spec is ${job_spec}") + endif() + math(EXPR job_spec_stop "${job_spec_length} - 3") + + list(GET job_spec 0 job_src_base) + set(job_src_base "${CMAKE_CURRENT_SOURCE_DIR}/${job_src_base}") + foreach(copy_pattern_index RANGE 1 "${job_spec_stop}" 3) + list(GET job_spec ${copy_pattern_index} copy_pattern) + math(EXPR copy_dest_index "${copy_pattern_index} + 2") + list(GET job_spec ${copy_dest_index} copy_dest) + + tvm_file_glob(GLOB_RECURSE copy_files + RELATIVE "${job_src_base}" + "${job_src_base}/${copy_pattern}") + list(LENGTH copy_files copy_files_length) + if("${copy_files_length}" EQUAL 0) + message(FATAL_ERROR "CRT copy job matched 0 files: ${job_src_base}/${copy_pattern} -> ${copy_dest}") + endif() + foreach(copy_src IN LISTS copy_files) + get_filename_component(dest_path "${STANDALONE_CRT_BASE}/${copy_dest}/${copy_src}" ABSOLUTE) + tvm_micro_add_copy_file(host_isolated_build_deps ${job_src_base}/${copy_src} ${dest_path}) + endforeach() + endforeach() + endforeach() + + add_custom_target(standalone_crt DEPENDS ${host_isolated_build_deps}) + + set(CRT_LIBRARIES "") + set(RUNTIME_CRT_SOURCE_DIR ${STANDALONE_CRT_BASE}/src/runtime/crt) + + # these create_crt_library() targets are in link order and the common library needs to be last + create_crt_library(aot_executor + ${RUNTIME_CRT_SOURCE_DIR}/aot_executor/aot_executor.c) + + create_crt_library(aot_executor_module + ${RUNTIME_CRT_SOURCE_DIR}/aot_executor_module/aot_executor_module.c) + + create_crt_library(graph_executor + ${RUNTIME_CRT_SOURCE_DIR}/graph_executor/graph_executor.c + ${RUNTIME_CRT_SOURCE_DIR}/graph_executor/load_json.c) + + create_crt_library(graph_executor_module + ${RUNTIME_CRT_SOURCE_DIR}/graph_executor_module/graph_executor_module.c) + + create_crt_library(memory + ${RUNTIME_CRT_SOURCE_DIR}/memory/page_allocator.c + ${RUNTIME_CRT_SOURCE_DIR}/memory/stack_allocator.c) + + create_crt_library(microtvm_rpc_common + ${RUNTIME_CRT_SOURCE_DIR}/microtvm_rpc_common/crcccitt.c + ${RUNTIME_CRT_SOURCE_DIR}/microtvm_rpc_common/frame_buffer.cc + ${RUNTIME_CRT_SOURCE_DIR}/microtvm_rpc_common/framing.cc + ${RUNTIME_CRT_SOURCE_DIR}/microtvm_rpc_common/session.cc + ${RUNTIME_CRT_SOURCE_DIR}/microtvm_rpc_common/write_stream.cc) + + create_crt_library(microtvm_rpc_server + ${RUNTIME_CRT_SOURCE_DIR}/microtvm_rpc_server/rpc_server.cc) + + create_crt_library(common + ${RUNTIME_CRT_SOURCE_DIR}/common/crt_backend_api.c + ${RUNTIME_CRT_SOURCE_DIR}/common/crt_runtime_api.c + ${RUNTIME_CRT_SOURCE_DIR}/common/func_registry.c + ${RUNTIME_CRT_SOURCE_DIR}/common/ndarray.c + ${RUNTIME_CRT_SOURCE_DIR}/common/packed_func.c) + + add_custom_target(host_standalone_crt DEPENDS ${CRT_LIBRARIES} standalone_crt) + + # Create the `crttest` target if we can find GTest. If not, we create dummy + # targets that give the user an informative error message. + if(GTEST_FOUND) + tvm_file_glob(GLOB TEST_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/tests/crt/*.cc) + add_executable(crttest ${TEST_SRCS}) + target_include_directories(crttest SYSTEM PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/standalone_crt/include ${CMAKE_CURRENT_SOURCE_DIR}/src/runtime/micro) + target_link_libraries(crttest PRIVATE ${CRT_LIBRARIES} GTest::GTest GTest::Main pthread dl) + set_target_properties(crttest PROPERTIES EXCLUDE_FROM_ALL 1) + set_target_properties(crttest PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD 1) + gtest_discover_tests(crttest) + endif() set(TVM_CRT_LINKER_LIB host_standalone_crt_microtvm_rpc_common) if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") diff --git a/include/tvm/runtime/crt/crt.h b/include/tvm/runtime/crt/crt.h old mode 100755 new mode 100644