diff --git a/CMakeLists.txt b/CMakeLists.txt index 300c6acd1b..d28343d335 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,14 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules) list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/deps) +# For Windows we make sure the applications are built in a specific path to be able to run directly +# Finding the Dlls +if(WIN32) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) +endif() + # To configure which apps/operators to build include(HoloHubConfigHelpers) diff --git a/applications/endoscopy_tool_tracking/cpp/main.cpp b/applications/endoscopy_tool_tracking/cpp/main.cpp index da740a5168..21242dc04d 100644 --- a/applications/endoscopy_tool_tracking/cpp/main.cpp +++ b/applications/endoscopy_tool_tracking/cpp/main.cpp @@ -15,7 +15,11 @@ * limitations under the License. */ +#ifdef _WIN32 +#include +#else #include +#endif #include #include @@ -332,6 +336,20 @@ class App : public holoscan::Application { /** Helper function to parse the command line arguments */ bool parse_arguments(int argc, char** argv, std::string& data_path, std::string& config_path) { +#ifdef _WIN32 + // Windows-compatible argument parsing + for (int i = 1; i < argc; i++) { + std::string arg = argv[i]; + if ((arg == "-d" || arg == "--data") && i + 1 < argc) { + data_path = argv[++i]; + } else if ((arg == "-c" || arg == "--config") && i + 1 < argc) { + config_path = argv[++i]; + } else if (arg[0] == '-') { + holoscan::log_error("Unknown option '{}'", arg); + return false; + } + } +#else static struct option long_options[] = { {"data", required_argument, 0, 'd'}, {"config", required_argument, 0, 'c'}, {0, 0, 0, 0}}; @@ -351,6 +369,7 @@ bool parse_arguments(int argc, char** argv, std::string& data_path, std::string& return false; } } +#endif return true; } @@ -369,7 +388,7 @@ int main(int argc, char** argv) { if (input_path != nullptr && input_path[0] != '\0') { data_directory = std::string(input_path); } else if (std::filesystem::is_directory(std::filesystem::current_path() / "data/endoscopy")) { - data_directory = std::string((std::filesystem::current_path() / "data/endoscopy").c_str()); + data_directory = (std::filesystem::current_path() / "data/endoscopy").string(); } else { HOLOSCAN_LOG_ERROR( "Input data not provided. Use --data or set HOLOSCAN_INPUT_PATH environment variable."); @@ -377,18 +396,34 @@ int main(int argc, char** argv) { } } - std::string app_path(PATH_MAX, '\0'); +#ifdef _WIN32 + constexpr size_t MAX_PATH_LENGTH = 32767; // Windows max path length +#else + constexpr size_t MAX_PATH_LENGTH = PATH_MAX; +#endif + std::string app_path(MAX_PATH_LENGTH, '\0'); +#ifdef _WIN32 + // Windows: Get executable path + DWORD size = GetModuleFileNameA(NULL, app_path.data(), app_path.size()); + if (size == 0) { + HOLOSCAN_LOG_ERROR("Failed to get the application path"); + exit(-1); + } + app_path.resize(size); +#else + // Linux: Use /proc/self/exe if (readlink("/proc/self/exe", app_path.data(), app_path.size() - 1) == -1) { HOLOSCAN_LOG_ERROR("Failed to get the application path"); exit(-1); } - app_path = std::filesystem::canonical(app_path).parent_path(); +#endif + app_path = std::filesystem::canonical(app_path).parent_path().string(); if (config_path.empty()) { // Get the input data environment variable auto config_file_path = std::getenv("HOLOSCAN_CONFIG_PATH"); if (config_file_path == nullptr || config_file_path[0] == '\0') { - config_path = app_path / std::filesystem::path("endoscopy_tool_tracking.yaml"); + config_path = (std::filesystem::path(app_path) / "endoscopy_tool_tracking.yaml").string(); } else { config_path = config_file_path; } diff --git a/gxf_extensions/lstm_tensor_rt_inference/CMakeLists.txt b/gxf_extensions/lstm_tensor_rt_inference/CMakeLists.txt index 6175810cc3..9c532f6d8b 100644 --- a/gxf_extensions/lstm_tensor_rt_inference/CMakeLists.txt +++ b/gxf_extensions/lstm_tensor_rt_inference/CMakeLists.txt @@ -18,23 +18,52 @@ project(gxf_lstm_tensor_rt_inference) find_package(holoscan REQUIRED CONFIG PATHS "/opt/nvidia/holoscan" "/workspace/holoscan-sdk/install") +find_library(TENSORRT_LIBRARY_INFER nvinfer nvinfer_10 + HINTS + $ENV{TENSORRT_ROOT} + ${TENSORRT_ROOT} + ${holoscan_DIR}/../.. + PATH_SUFFIXES lib lib64 lib/x64 +) + +find_library(TENSORRT_LIBRARY_INFER_PLUGIN nvinfer_plugin nvinfer_plugin_10 + HINTS + $ENV{TENSORRT_ROOT} + ${TENSORRT_ROOT} + ${holoscan_DIR}/../.. + PATH_SUFFIXES lib lib64 lib/x64 +) + +find_library(TENSORRT_LIBRARY_ONNXPARSER nvonnxparser nvonnxparser_10 + HINTS + $ENV{TENSORRT_ROOT} + ${TENSORRT_ROOT} + ${holoscan_DIR}/../.. + PATH_SUFFIXES lib lib64 lib/x64 +) + # Create library add_library(gxf_lstm_tensor_rt_inference_lib SHARED tensor_rt_inference.cpp tensor_rt_inference.hpp ) -set_target_properties(gxf_lstm_tensor_rt_inference_lib PROPERTIES CXX_STANDARD 17) +set_target_properties(gxf_lstm_tensor_rt_inference_lib PROPERTIES + CXX_STANDARD 17 + WINDOWS_EXPORT_ALL_SYMBOLS ON +) + +target_link_directories(gxf_lstm_tensor_rt_inference_lib PUBLIC "${holoscan_DIR}/../..") +#message(FATAL_ERROR "${holoscan_DIR}/../..") target_link_libraries(gxf_lstm_tensor_rt_inference_lib PUBLIC CUDA::cudart GXF::cuda GXF::std - nvinfer - nvinfer_plugin - nvonnxparser - yaml-cpp + ${TENSORRT_LIBRARY_INFER} + ${TENSORRT_LIBRARY_INFER_PLUGIN} + ${TENSORRT_LIBRARY_ONNXPARSER} holoscan::core # included only as a way to find dlpack/dlpack.h for GXF::std ) @@ -42,6 +71,14 @@ target_link_libraries(gxf_lstm_tensor_rt_inference_lib add_library(gxf_lstm_tensor_rt_inference SHARED lstm_tensor_rt_extension.cpp ) + +# On Windows, use a .def file to export GxfExtensionFactory +if(WIN32) + target_sources(gxf_lstm_tensor_rt_inference PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/gxf_lstm_tensor_rt_inference.def + ) +endif() + target_link_libraries(gxf_lstm_tensor_rt_inference PUBLIC gxf_lstm_tensor_rt_inference_lib ) diff --git a/gxf_extensions/lstm_tensor_rt_inference/gxf_lstm_tensor_rt_inference.def b/gxf_extensions/lstm_tensor_rt_inference/gxf_lstm_tensor_rt_inference.def new file mode 100644 index 0000000000..9902563ea4 --- /dev/null +++ b/gxf_extensions/lstm_tensor_rt_inference/gxf_lstm_tensor_rt_inference.def @@ -0,0 +1,4 @@ +LIBRARY gxf_lstm_tensor_rt_inference +EXPORTS + GxfExtensionFactory + diff --git a/gxf_extensions/lstm_tensor_rt_inference/tensor_rt_inference.cpp b/gxf_extensions/lstm_tensor_rt_inference/tensor_rt_inference.cpp index 4ed3a925e8..999654f9c2 100644 --- a/gxf_extensions/lstm_tensor_rt_inference/tensor_rt_inference.cpp +++ b/gxf_extensions/lstm_tensor_rt_inference/tensor_rt_inference.cpp @@ -259,7 +259,7 @@ gxf_result_t TensorRtInference::registerInterface(gxf::Registrar* registrar) { "max_workspace_size", "Max Workspace Size", "Size of working space in bytes. Default to 64MB", - 67108864l); + int64_t(67108864)); result &= registrar->parameter(dla_core_, "dla_core", "DLA Core", @@ -428,19 +428,17 @@ gxf_result_t TensorRtInference::start() { const uint64_t output_number = output_tensor_names_.get().size(); const int64_t total_bindings_number = input_number + output_number; #if NV_TENSORRT_MAJOR < 8 || (NV_TENSORRT_MAJOR == 8 && NV_TENSORRT_MINOR <5) - if (cuda_engine_->getNbBindings() != static_cast(total_bindings_number)) { + const int nb_bindings = cuda_engine_->getNbBindings(); + if (nb_bindings != static_cast(total_bindings_number)) { #else - if (cuda_engine_->getNbIOTensors() != static_cast(total_bindings_number)) { + const int nb_bindings = cuda_engine_->getNbIOTensors(); + if (nb_bindings != static_cast(total_bindings_number)) { #endif GXF_LOG_ERROR( "Numbers of CUDA bindings mismatch: configured for %lu vs model requires %d. " "Please check TensorRTInference codelet configuration.\n", total_bindings_number, -#if NV_TENSORRT_MAJOR < 8 || (NV_TENSORRT_MAJOR == 8 && NV_TENSORRT_MINOR <5) - cuda_engine_->getNbBindings()); -#else - cuda_engine_->getNbIOTensors()); -#endif + nb_bindings); return GXF_ARGUMENT_INVALID; } @@ -988,12 +986,12 @@ gxf_result_t TensorRtInference::tick() { } // Copy output state tensor to input state tensor - cudaError_t cuda_status = CUDA_TRY(cudaMemcpyAsync(in_state_tensor_ptr, - out_tensor_ptr, - state_tensor_size, - cudaMemcpyDeviceToDevice, - cuda_stream_handler_.getCudaStream())); - if (cuda_status) { + cudaError_t cuda_status = cudaMemcpyAsync(in_state_tensor_ptr, + out_tensor_ptr, + state_tensor_size, + cudaMemcpyDeviceToDevice, + cuda_stream_handler_.getCudaStream()); + if (cuda_status != cudaSuccess) { GXF_LOG_ERROR("Failed to copy output tensor %s to input tensor %s: %s", output_state_tensor_names_.get()[0].c_str(), input_state_tensor_names_.get()[0].c_str(), diff --git a/operators/lstm_tensor_rt_inference/CMakeLists.txt b/operators/lstm_tensor_rt_inference/CMakeLists.txt index 3e6720c136..da2f3e0896 100644 --- a/operators/lstm_tensor_rt_inference/CMakeLists.txt +++ b/operators/lstm_tensor_rt_inference/CMakeLists.txt @@ -23,6 +23,11 @@ add_library(lstm_tensor_rt_inference SHARED lstm_tensor_rt_inference.hpp ) +set_target_properties(lstm_tensor_rt_inference PROPERTIES + WINDOWS_EXPORT_ALL_SYMBOLS ON +) + +target_link_directories(lstm_tensor_rt_inference PUBLIC "${holoscan_DIR}/../..") target_link_libraries(lstm_tensor_rt_inference holoscan::core) target_include_directories(lstm_tensor_rt_inference INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/operators/lstm_tensor_rt_inference/lstm_tensor_rt_inference.cpp b/operators/lstm_tensor_rt_inference/lstm_tensor_rt_inference.cpp index 8ce9bbf4e4..9c1ceb8532 100644 --- a/operators/lstm_tensor_rt_inference/lstm_tensor_rt_inference.cpp +++ b/operators/lstm_tensor_rt_inference/lstm_tensor_rt_inference.cpp @@ -89,7 +89,7 @@ void LSTMTensorRTInferenceOp::setup(OperatorSpec& spec) { "max_workspace_size", "Max Workspace Size", "Size of working space in bytes. Default to 64MB", - 67108864l); + int64_t(67108864)); spec.param(dla_core_, "dla_core", "DLA Core", @@ -119,6 +119,7 @@ void LSTMTensorRTInferenceOp::setup(OperatorSpec& spec) { "Ignore dimensions of 1 for input tensor dimension check.", true); + //spec.param(rx_, "rx", "RX", "List of receivers to take input tensors", {}); spec.param(rx_, "rx", "RX", "List of receivers to take input tensors", {&in_tensor}); spec.param(tx_, "tx", "TX", "Transmitter to publish output tensors", &out_tensor); diff --git a/operators/tool_tracking_postprocessor/CMakeLists.txt b/operators/tool_tracking_postprocessor/CMakeLists.txt index a288d51896..dfd42b2d8b 100644 --- a/operators/tool_tracking_postprocessor/CMakeLists.txt +++ b/operators/tool_tracking_postprocessor/CMakeLists.txt @@ -32,6 +32,8 @@ set_target_properties(tool_tracking_postprocessor CUDA_SEPARABLE_COMPILATION ON # compile for the architecture of the current GPU CUDA_ARCHITECTURES "native" + # On Windows, export all symbols automatically for shared libraries + WINDOWS_EXPORT_ALL_SYMBOLS ON ) target_link_libraries(tool_tracking_postprocessor