microsoft / microsoft/onnxruntime-inference-examples

Difficulty compiling/running the `c_cxx` examples. MNIST example works on Visual Studio 2022

Open
#212 3 comments 4 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C++
Stars
1.7k
Forks
414
Avg merge
1d 6h
Merged PRs (30d)
14

Description

Hello.

I had a few problems building the c_cxx examples provided in this repository. After some struggle, I got the MNIST example to work and can confirm that it runs well on Visual Studio 2022 with a CPU provider.

Here's a summary of the effort, following the instructions in the README.

My environment is:

  • Win11 with Visual Studio 2022
  • cmake v3.26.0-rc4
  • no libpng

I tried the Option 2 discussed in the README, building the onnxruntime from source. I could successfully build that using Visual Studio 17 2022 as the CMAKE generator. The .dll and .lib are generated and installed under C:\Program Files\onnxruntime, as well as the include/ headers. No problems to report.

When building the examples, however, things didn't go well. Specifically, trying the following within onnxruntime-inference-examples/c_cxx/build:

cmake .. -A x64 -T host=x64 -DONNXRUNTIME_ROOTDIR="C:\Program Files\onnxruntime"

msbuild onnxruntime_samples.sln /p:Configuration=Release

results in the following compilation error:

"D:\nnpolesl\onnx\onnxruntime-inference-examples\c_cxx\build\onnxruntime_samples.sln" (default target) (1) ->
"D:\nnpolesl\onnx\onnxruntime-inference-examples\c_cxx\build\imagenet\image_classifier.vcxproj.metaproj" (default targe
t) (7) ->
"D:\nnpolesl\onnx\onnxruntime-inference-examples\c_cxx\build\imagenet\image_classifier.vcxproj" (default target) (10) -
>
(ClCompile target) ->
  D:\nnpolesl\onnx\onnxruntime-inference-examples\c_cxx\include\providers.h(5,10): fatal  error C1083: Cannot open incl
ude file: 'cpu_provider_factory.h': No such file or directory [D:\nnpolesl\onnx\onnxruntime-inference-examples\c_cxx\bu
ild\imagenet\image_classifier.vcxproj]

It seems that the compiler is failing to find some headers. After closer inspection, I noticed that the include/ folder is organized differently in the installation from source than in the redistributable .zip files located here: https://github.com/microsoft/onnxruntime/releases/tag/v1.14.0

In the latest redistributable release, the include/ folder looks like this:

[onnxruntime-win-x86-1.14.0.zip]
include/
├── cpu_provider_factory.h
├── onnxruntime_c_api.h
├── onnxruntime_cxx_api.h
├── onnxruntime_cxx_inline.h
├── onnxruntime_run_options_config_keys.h
├── onnxruntime_session_options_config_keys.h
├── provider_options.h
└── tensorrt_provider_factory.h

whereas the include/ on a runtime build from source it looks like this:

include/
└── onnxruntime
    └── core
        ├── common
        │   ├── basic_types.h
        │   ├── code_location.h
        │   ├── common.h
        │   ├── const_pointer_container.h
        │   ├── denormal.h
        │   ├── eigen_common_wrapper.h
        │   ├── exceptions.h
        │   ├── gpu_profiler_common.h
        │   ├── gsl.h
        │   ├── hash_combine.h
        │   ├── inlined_containers.h
        │   ├── inlined_containers_fwd.h
        │   ├── logging
        │   │   ├── capture.h
        │   │   ├── isink.h
        │   │   ├── logging.h
        │   │   ├── macros.h
        │   │   └── severity.h
        │   ├── make_string.h
        │   ├── narrow.h
        │   ├── optional.h
        │   ├── parse_string.h
        │   ├── profiler_common.h
        │   ├── span_utils.h
        │   ├── spin_pause.h
        │   ├── status.h
        │   └── string_helper.h
        ├── framework
        │   ├── alloc_kind.h
        │   ├── allocator.h
        │   ├── buffer_deleter.h
        │   ├── customregistry.h
        │   ├── data_types.h
        │   ├── data_types_internal.h
        │   ├── endian.h
        │   ├── execution_provider.h
        │   ├── float16.h
        │   ├── framework_common.h
        │   ├── func_api.h
        │   ├── kernel_def_builder.h
        │   ├── kernel_registry.h
        │   ├── op_kernel.h
        │   ├── op_kernel_context.h
        │   ├── op_kernel_info.h
        │   ├── op_node_proto_helper.h
        │   ├── ort_value.h
        │   ├── ortdevice.h
        │   ├── ortmemoryinfo.h
        │   ├── provider_options.h
        │   ├── provider_options_utils.h
        │   ├── provider_shutdown.h
        │   ├── run_options.h
        │   ├── sparse_tensor.h
        │   ├── stream_handles.h
        │   ├── tensor.h
        │   ├── tensor_shape.h
        │   └── to_tensor_proto_element_type.h
        ├── graph
        │   ├── basic_types.h
        │   ├── constants.h
        │   ├── function.h
        │   ├── graph.h
        │   ├── graph_nodes.h
        │   ├── graph_viewer.h
        │   ├── indexed_sub_graph.h
        │   ├── node_arg.h
        │   └── schema_registry.h
        ├── optimizer
        │   ├── graph_transformer.h
        │   ├── graph_transformer_config.h
        │   ├── graph_transformer_level.h
        │   ├── graph_transformer_utils.h
        │   ├── rewrite_rule.h
        │   └── rule_based_graph_transformer.h
        ├── providers
        │   └── cpu
        │       └── cpu_provider_factory.h
        └── session
            ├── environment.h
            ├── experimental_onnxruntime_cxx_api.h
            ├── experimental_onnxruntime_cxx_inline.h
            ├── onnxruntime_c_api.h
            ├── onnxruntime_cxx_api.h
            ├── onnxruntime_cxx_inline.h
            ├── onnxruntime_run_options_config_keys.h
            ├── onnxruntime_session_options_config_keys.h
            └── snippets.dox

Beyond the fact that there are many more headers, these headers are organized in subfolders. Related to the error in the build process I found earlier, it seems we can't find cpu_provider_factory.h because the include path is not added in the CMakeLists.txt recipe:

https://github.com/microsoft/onnxruntime-inference-examples/blob/7f6a17283fc1a3f39cd315ba9f4597a0c25c58ef/c_cxx/CMakeLists.txt#L50

Thus, I modified the include_directories in the CMakeLists.txt to this:

include_directories(
  "${ONNXRUNTIME_ROOTDIR}/include" 
  "${ONNXRUNTIME_ROOTDIR}/include/onnxruntime/core/session"
  "${ONNXRUNTIME_ROOTDIR}/include/onnxruntime/core/providers/cpu"
)

This seems to fix the build error, which exits with the following status:

Build succeeded.

"D:\nnpolesl\onnx\onnxruntime-inference-examples\c_cxx\build\onnxruntime_samples.sln" (default target) (1) ->
"D:\nnpolesl\onnx\onnxruntime-inference-examples\c_cxx\build\imagenet\image_classifier.vcxproj.metaproj" (default targe
t) (7) ->
"D:\nnpolesl\onnx\onnxruntime-inference-examples\c_cxx\build\imagenet\image_classifier.vcxproj" (default target) (10) -
>
(ClCompile target) ->
  D:\nnpolesl\onnx\onnxruntime-inference-examples\c_cxx\imagenet\main.cc(131,12): warning C4189: 'dim_count': local var
iable is initialized but not referenced [D:\nnpolesl\onnx\onnxruntime-inference-examples\c_cxx\build\imagenet\image_cla
ssifier.vcxproj]

    1 Warning(s)
    0 Error(s)

Time Elapsed 00:00:14.07

However, when I attempt to run any of the generated .exes, I get a runtime crash. For example, running onnxruntime-inference-examples\c_cxx\build\MNIST\Release\mnist.exe results in the following MessageBox (although it is the same issue with all .exes):

image

This would seem a .dll issue. I tried copying the contents of C:\Program Files\onnxruntime\bin into the folder where the image_classifier.exe binary is located. This got rid of the previous error and the following MessageBox appeared:

image

This seems to be good news, as now the application is running, but it seems it can't find the .onnx model it is looking for. Looking at the source code of this example, it seems that the model needs to be called model.onnx. I copied the mnist.onnx located here: https://github.com/microsoft/onnxruntime/blob/main/onnxruntime/test/testdata/mnist.onnx and named it model.onnx within the same folder as mnist.exe. After that, I finally got this example to work.

image

Voila !

At first, I was posting this issue as being "unable to build the examples". However, in the process of writing the issue I figured out a few extra steps and got it to work in the end. Decided to keep writing as someone else might find this useful.

In any case, I think there are a few problems with the existing documentation that would be worth correcting:

  • The CMakeLists.txt won't work for a onnxruntime build from source, as it needs the include directory of /include/onnxruntime/core/providers/cpu (and maybe others). I think this CMakeLists.txt should be updated accordingly
  • The examples (e.g., MNIST) don't mention anything about the .onnx model they need and where to find it. Although one can figure it out by reading the source and repo structure, it'd be nice to have that documented somewhere (or to have an appropriate .bat script to download/run)
  • I haven't tried the other examples, it is possible that additional steps are needed to make those work

Kind regards,
Néstor

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with c_cxx/CMakeLists.txt and the c_cxx README, then reproduce the Windows Visual Studio build using an ONNX Runtime source installation. Check the include paths and document the runtime DLL and model.onnx requirements for the MNIST and other examples. Done means the documented steps build and run the examples from a source build.

Written by the indexing model from the issue text.

Assessment

Tech stack
cmake, cpp
Domain
build-system, documentation
Issue type
Documentation
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.