IVGCVSW-7031 Generate static execute network

 * Build ExecNet lib dependencies as object libs except libarmnn
 * Disable PIPE when building static ExecNet
 * Remove multiple definition from AsyncExecutionCallback
 * Disable DynamicBackend for ExecNet Static build
 * Disable inference  tests for TfLiteParser and ONNX during static ExecNet
 * Remove Tensorflow Parser if condition
 * Add Disable thread macro to InferenceModel
 * Don't compile dynamic backend symbols in Runtime.cpp for Baremetal and
   Exenet Static

Signed-off-by: Ryan OShea <ryan.oshea3@arm.com>
Change-Id: If41c063eab5f05b3df0a6e064924a36a177f116a
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 51c4cf2..476e080 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,5 @@
 #
-# Copyright © 2018-2022 Arm Ltd and Contributors. All rights reserved.
+# Copyright © 2018-2023 Arm Ltd and Contributors. All rights reserved.
 # Copyright 2020 NXP
 # SPDX-License-Identifier: MIT
 #
@@ -446,7 +446,7 @@
     add_definitions(-DARMNN_TFLITE_DELEGATE)
 endif()
 
-if(BUILD_BARE_METAL)
+if(BUILD_BARE_METAL OR EXECUTE_NETWORK_STATIC)
     add_library_ex(armnn STATIC ${armnn_sources})
 else()
     if (BUILD_SHARED_LIBS)
@@ -484,7 +484,7 @@
 target_link_libraries(armnn PUBLIC pipeCommon)
 target_link_libraries(armnn PUBLIC pipeClient)
 
-if(NOT BUILD_BARE_METAL)
+if(NOT BUILD_BARE_METAL AND NOT EXECUTE_NETWORK_STATIC)
     target_link_libraries(armnn PUBLIC ${CMAKE_DL_LIBS})
 endif()
 
diff --git a/cmake/GlobalConfig.cmake b/cmake/GlobalConfig.cmake
index dd20e15..6f3fee4 100644
--- a/cmake/GlobalConfig.cmake
+++ b/cmake/GlobalConfig.cmake
@@ -1,5 +1,5 @@
 #
-# Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
+# Copyright © 2022-2023 Arm Ltd and Contributors. All rights reserved.
 # Copyright 2020 NXP
 # SPDX-License-Identifier: MIT
 #
@@ -42,6 +42,19 @@
 option(BUILD_SHARED_LIBS "Determines if Armnn will be built statically or dynamically.
                           This is an experimental feature and not fully supported.
                           Only the ArmNN core and the Delegate can be built statically." ON)
+option(EXECUTE_NETWORK_STATIC " This is a limited experimental build that is entirely static.
+                                It currently only supports being set by changing the current CMake default options like so:
+                                BUILD_TF_LITE_PARSER=1/0
+                                BUILD_ARMNN_SERIALIZER=1/0
+                                ARMCOMPUTENEON=1/0
+                                ARMNNREF=1/0
+                                ARMCOMPUTECL=0
+                                BUILD_ONNX_PARSER=0
+                                BUILD_ARMNN_TFLITE_DELEGATE=0
+                                BUILD_TIMELINE_DECODER=0
+                                BUILD_BASE_PIPE_SERVER=0
+                                BUILD_UNIT_TESTS=0
+                                BUILD_GATORD_MOCK=0" OFF)
 
 include(SelectLibraryConfigurations)
 
@@ -137,6 +150,21 @@
 
 include(CMakeFindDependencyMacro)
 
+
+if(EXECUTE_NETWORK_STATIC)
+    add_definitions(-DARMNN_DISABLE_SOCKETS
+                    -DBUILD_SHARED_LIBS=0
+                    -DARMNN_EXECUTE_NETWORK_STATIC)
+endif()
+
+if(BUILD_BARE_METAL)
+    add_definitions(-DARMNN_BUILD_BARE_METAL
+            -DARMNN_DISABLE_FILESYSTEM
+            -DARMNN_DISABLE_PROCESSES
+            -DARMNN_DISABLE_THREADS
+            -DARMNN_DISABLE_SOCKETS)
+endif()
+
 if (NOT BUILD_PIPE_ONLY)
   # cxxopts (Alternative to boost::program_options)
   find_path(CXXOPTS_INCLUDE cxxopts/cxxopts.hpp PATHS third-party NO_CMAKE_FIND_ROOT_PATH)
@@ -149,11 +177,19 @@
   include_directories(SYSTEM "${GHC_INCLUDE}")
 endif()
 
+if(NOT BUILD_SHARED_LIBS)
+    set(CMAKE_FIND_LIBRARY_SUFFIXES .a .lib)
+endif()
+
 # pthread
 if (NOT BUILD_BARE_METAL)
 find_package(Threads)
 endif()
 
+if (EXECUTE_NETWORK_STATIC)
+    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libstdc++ -static-libgcc -static -pthread")
+endif()
+
 # Favour the protobuf passed on command line
 if(BUILD_ONNX_PARSER)
     find_library(PROTOBUF_LIBRARY_DEBUG NAMES "protobufd"
@@ -388,7 +424,7 @@
     add_definitions(-DARMNN_STREAMLINE_ENABLED)
 endif()
 
-if(NOT BUILD_BARE_METAL)
+if(NOT BUILD_BARE_METAL AND NOT EXECUTE_NETWORK_STATIC)
 if(HEAP_PROFILING OR LEAK_CHECKING)
     find_path(HEAP_PROFILER_INCLUDE gperftools/heap-profiler.h
             PATHS ${GPERFTOOLS_ROOT}/include
@@ -445,13 +481,5 @@
     endif()
 endif()
 
-if(BUILD_BARE_METAL)
-    add_definitions(-DARMNN_BUILD_BARE_METAL
-                    -DARMNN_DISABLE_FILESYSTEM
-                    -DARMNN_DISABLE_PROCESSES
-                    -DARMNN_DISABLE_THREADS
-                    -DARMNN_DISABLE_SOCKETS)
-endif()
-
 # ArmNN source files required for all build options
 include_directories(SYSTEM third-party)
diff --git a/delegate/CMakeLists.txt b/delegate/CMakeLists.txt
index fe5c962..d044ed9 100644
--- a/delegate/CMakeLists.txt
+++ b/delegate/CMakeLists.txt
@@ -1,5 +1,5 @@
 #
-# Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
+# Copyright © 2022-2023 Arm Ltd and Contributors. All rights reserved.
 # SPDX-License-Identifier: MIT
 #
 
diff --git a/profiling/client/src/ProfilingService.cpp b/profiling/client/src/ProfilingService.cpp
index b8e0348..37f0de9 100644
--- a/profiling/client/src/ProfilingService.cpp
+++ b/profiling/client/src/ProfilingService.cpp
@@ -1,5 +1,5 @@
 //
-// Copyright © 2019 Arm Ltd and Contributors. All rights reserved.
+// Copyright © 2019, 2022-2023 Arm Ltd and Contributors. All rights reserved.
 // SPDX-License-Identifier: MIT
 //
 
@@ -10,7 +10,7 @@
 #include <common/include/ProfilingGuid.hpp>
 #include <common/include/SocketConnectionException.hpp>
 
-#if defined(ARMNN_BUILD_BARE_METAL)
+#if defined(ARMNN_BUILD_BARE_METAL) || defined(ARMNN_EXECUTE_NETWORK_STATIC)
 #include <common/include/IgnoreUnused.hpp>
 #endif
 
@@ -26,7 +26,7 @@
 void ProfilingService::ResetExternalProfilingOptions(const arm::pipe::ProfilingOptions& options,
                                                      bool resetProfilingService)
 {
-#if !defined(ARMNN_BUILD_BARE_METAL)
+#if !defined(ARMNN_BUILD_BARE_METAL) && !defined(ARMNN_EXECUTE_NETWORK_STATIC)
     // Update the profiling options
     m_Options = options;
     m_TimelineReporting = options.m_TimelineEnabled;
@@ -41,23 +41,23 @@
 #else
     IgnoreUnused(options);
     IgnoreUnused(resetProfilingService);
-#endif // ARMNN_BUILD_BARE_METAL
+#endif // ARMNN_BUILD_BARE_METAL || ARMNN_EXECUTE_NETWORK_STATIC
 }
 
 bool ProfilingService::IsProfilingEnabled() const
 {
-#if !defined(ARMNN_BUILD_BARE_METAL)
+#if !defined(ARMNN_BUILD_BARE_METAL) && !defined(ARMNN_EXECUTE_NETWORK_STATIC)
     return m_Options.m_EnableProfiling;
 #else
     return false;
-#endif // ARMNN_BUILD_BARE_METAL
+#endif // ARMNN_BUILD_BARE_METAL && ARMNN_EXECUTE_NETWORK_STATIC
 }
 
 ProfilingState ProfilingService::ConfigureProfilingService(
         const ProfilingOptions& options,
         bool resetProfilingService)
 {
-#if !defined(ARMNN_BUILD_BARE_METAL)
+#if !defined(ARMNN_BUILD_BARE_METAL) && !defined(ARMNN_EXECUTE_NETWORK_STATIC)
     ResetExternalProfilingOptions(options, resetProfilingService);
     ProfilingState currentState = m_StateMachine.GetCurrentState();
     if (options.m_EnableProfiling)
@@ -106,12 +106,12 @@
     IgnoreUnused(options);
     IgnoreUnused(resetProfilingService);
     return ProfilingState::Uninitialised;
-#endif // ARMNN_BUILD_BARE_METAL
+#endif // ARMNN_BUILD_BARE_METAL && ARMNN_EXECUTE_NETWORK_STATIC
 }
 
 void ProfilingService::Update()
 {
-#if !defined(ARMNN_BUILD_BARE_METAL)
+#if !defined(ARMNN_BUILD_BARE_METAL) && !defined(ARMNN_EXECUTE_NETWORK_STATIC)
     if (!m_Options.m_EnableProfiling)
     {
         // Don't run if profiling is disabled
@@ -189,12 +189,12 @@
         throw arm::pipe::ProfilingException(fmt::format("Unknown profiling service state: {}",
                                             static_cast<int>(currentState)));
     }
-#endif // ARMNN_BUILD_BARE_METAL
+#endif // ARMNN_BUILD_BARE_METAL && ARMNN_EXECUTE_NETWORK_STATIC
 }
 
 void ProfilingService::Disconnect()
 {
-#if !defined(ARMNN_BUILD_BARE_METAL)
+#if !defined(ARMNN_BUILD_BARE_METAL) && !defined(ARMNN_EXECUTE_NETWORK_STATIC)
     ProfilingState currentState = m_StateMachine.GetCurrentState();
     switch (currentState)
     {
@@ -211,7 +211,7 @@
         throw arm::pipe::ProfilingException(fmt::format("Unknown profiling service state: {}",
                                                         static_cast<int>(currentState)));
     }
-#endif // ARMNN_BUILD_BARE_METAL
+#endif // ARMNN_BUILD_BARE_METAL && ARMNN_EXECUTE_NETWORK_STATIC
 }
 
 // Store a profiling context returned from a backend that support profiling, and register its counters
@@ -219,7 +219,7 @@
     const std::string& backendId,
     std::shared_ptr<IBackendProfilingContext> profilingContext)
 {
-#if !defined(ARMNN_BUILD_BARE_METAL)
+#if !defined(ARMNN_BUILD_BARE_METAL) && !defined(ARMNN_EXECUTE_NETWORK_STATIC)
     ARM_PIPE_ASSERT(profilingContext != nullptr);
     // Register the backend counters
     m_MaxGlobalCounterId = profilingContext->RegisterCounters(m_MaxGlobalCounterId);
@@ -227,7 +227,7 @@
 #else
     IgnoreUnused(backendId);
     IgnoreUnused(profilingContext);
-#endif // ARMNN_BUILD_BARE_METAL
+#endif // ARMNN_BUILD_BARE_METAL && ARMNN_EXECUTE_NETWORK_STATIC
 }
 const ICounterDirectory& ProfilingService::GetCounterDirectory() const
 {
@@ -343,14 +343,14 @@
 
 void ProfilingService::Initialize()
 {
-#if !defined(ARMNN_BUILD_BARE_METAL)
+#if !defined(ARMNN_BUILD_BARE_METAL) && !defined(ARMNN_EXECUTE_NETWORK_STATIC)
     m_Initialiser.InitialiseProfilingService(*this);
-#endif // ARMNN_BUILD_BARE_METAL
+#endif // ARMNN_BUILD_BARE_METAL && ARMNN_EXECUTE_NETWORK_STATIC
 }
 
 void ProfilingService::InitializeCounterValue(uint16_t counterUid)
 {
-#if !defined(ARMNN_BUILD_BARE_METAL)
+#if !defined(ARMNN_BUILD_BARE_METAL) && !defined(ARMNN_EXECUTE_NETWORK_STATIC)
     // Increase the size of the counter index if necessary
     if (counterUid >= m_CounterIndex.size())
     {
@@ -365,12 +365,12 @@
     m_CounterIndex.at(counterUid) = counterValuePtr;
 #else
     IgnoreUnused(counterUid);
-#endif // ARMNN_BUILD_BARE_METAL
+#endif // ARMNN_BUILD_BARE_METAL && ARMNN_EXECUTE_NETWORK_STATIC
 }
 
 void ProfilingService::Reset()
 {
-#if !defined(ARMNN_BUILD_BARE_METAL)
+#if !defined(ARMNN_BUILD_BARE_METAL) && !defined(ARMNN_EXECUTE_NETWORK_STATIC)
     // Stop the profiling service...
     Stop();
 
@@ -384,12 +384,12 @@
     // ...finally reset the profiling state machine
     m_StateMachine.Reset();
     m_BackendProfilingContexts.clear();
-#endif // ARMNN_BUILD_BARE_METAL
+#endif // ARMNN_BUILD_BARE_METAL && ARMNN_EXECUTE_NETWORK_STATIC
 }
 
 void ProfilingService::Stop()
 {
-#if !defined(ARMNN_BUILD_BARE_METAL)
+#if !defined(ARMNN_BUILD_BARE_METAL) && !defined(ARMNN_EXECUTE_NETWORK_STATIC)
     {   // only lock when we are updating the inference completed variable
         std::unique_lock<std::mutex> lck(m_ServiceActiveMutex);
         m_ServiceActive = false;
@@ -411,24 +411,24 @@
 
     // ...then move to the "NotConnected" state
     m_StateMachine.TransitionToState(ProfilingState::NotConnected);
-#endif // ARMNN_BUILD_BARE_METAL
+#endif // ARMNN_BUILD_BARE_METAL && ARMNN_EXECUTE_NETWORK_STATIC
 }
 
 inline void ProfilingService::CheckCounterUid(uint16_t counterUid) const
 {
-#if !defined(ARMNN_BUILD_BARE_METAL)
+#if !defined(ARMNN_BUILD_BARE_METAL) && !defined(ARMNN_EXECUTE_NETWORK_STATIC)
     if (!IsCounterRegistered(counterUid))
     {
         throw arm::pipe::InvalidArgumentException(fmt::format("Counter UID {} is not registered", counterUid));
     }
 #else
     IgnoreUnused(counterUid);
-#endif // ARMNN_BUILD_BARE_METAL
+#endif // ARMNN_BUILD_BARE_METAL && ARMNN_EXECUTE_NETWORK_STATIC
 }
 
 void ProfilingService::NotifyBackendsForTimelineReporting()
 {
-#if !defined(ARMNN_BUILD_BARE_METAL)
+#if !defined(ARMNN_BUILD_BARE_METAL) && !defined(ARMNN_EXECUTE_NETWORK_STATIC)
     BackendProfilingContext::iterator it = m_BackendProfilingContexts.begin();
     while (it != m_BackendProfilingContexts.end())
     {
@@ -437,23 +437,23 @@
         // Increment the Iterator to point to next entry
         it++;
     }
-#endif // ARMNN_BUILD_BARE_METAL
+#endif // ARMNN_BUILD_BARE_METAL && ARMNN_EXECUTE_NETWORK_STATIC
 }
 
 void ProfilingService::NotifyProfilingServiceActive()
 {
-#if !defined(ARMNN_BUILD_BARE_METAL)
+#if !defined(ARMNN_BUILD_BARE_METAL) && !defined(ARMNN_EXECUTE_NETWORK_STATIC)
     {   // only lock when we are updating the inference completed variable
         std::unique_lock<std::mutex> lck(m_ServiceActiveMutex);
         m_ServiceActive = true;
     }
     m_ServiceActiveConditionVariable.notify_one();
-#endif // ARMNN_BUILD_BARE_METAL
+#endif // ARMNN_BUILD_BARE_METAL && ARMNN_EXECUTE_NETWORK_STATIC
 }
 
 void ProfilingService::WaitForProfilingServiceActivation(unsigned int timeout)
 {
-#if !defined(ARMNN_BUILD_BARE_METAL)
+#if !defined(ARMNN_BUILD_BARE_METAL) && !defined(ARMNN_EXECUTE_NETWORK_STATIC)
     std::unique_lock<std::mutex> lck(m_ServiceActiveMutex);
 
     auto start = std::chrono::high_resolution_clock::now();
@@ -475,14 +475,14 @@
     }
 #else
     IgnoreUnused(timeout);
-#endif // ARMNN_BUILD_BARE_METAL
+#endif // ARMNN_BUILD_BARE_METAL && ARMNN_EXECUTE_NETWORK_STATIC
 }
 
 ProfilingService::~ProfilingService()
 {
-#if !defined(ARMNN_BUILD_BARE_METAL)
+#if !defined(ARMNN_BUILD_BARE_METAL) && !defined(ARMNN_EXECUTE_NETWORK_STATIC)
     Stop();
-#endif // ARMNN_BUILD_BARE_METAL
+#endif // ARMNN_BUILD_BARE_METAL && ARMNN_EXECUTE_NETWORK_STATIC
 }
 
 } // namespace pipe
diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt
index 31ff508..e5ee711 100644
--- a/samples/CMakeLists.txt
+++ b/samples/CMakeLists.txt
@@ -1,8 +1,8 @@
 #
-# Copyright © 2018-2022 Arm Ltd and Contributors. All rights reserved.
+# Copyright © 2018-2023 Arm Ltd and Contributors. All rights reserved.
 # SPDX-License-Identifier: MIT
 #
-if (NOT BUILD_BARE_METAL)
+if (NOT BUILD_BARE_METAL AND NOT EXECUTE_NETWORK_STATIC)
    if(BUILD_SAMPLE_APP AND ARMNNREF)
         add_executable(SimpleSample SimpleSample.cpp)
         target_link_libraries(SimpleSample armnn ${CMAKE_THREAD_LIBS_INIT})
diff --git a/src/armnn/AsyncExecutionCallback.cpp b/src/armnn/AsyncExecutionCallback.cpp
index 5b87927..73ce66b 100644
--- a/src/armnn/AsyncExecutionCallback.cpp
+++ b/src/armnn/AsyncExecutionCallback.cpp
@@ -1,5 +1,5 @@
 //
-// Copyright © 2021 Arm Ltd and Contributors. All rights reserved.
+// Copyright © 2021-2023 Arm Ltd and Contributors. All rights reserved.
 // SPDX-License-Identifier: MIT
 //
 
@@ -11,6 +11,8 @@
 namespace experimental
 {
 
+InferenceId AsyncExecutionCallback::nextID = 0u;
+
 void AsyncExecutionCallback::Notify(armnn::Status status, InferenceTimingPair timeTaken)
 {
     {
diff --git a/src/armnn/AsyncExecutionCallback.hpp b/src/armnn/AsyncExecutionCallback.hpp
index 9eab06b..d48f807 100644
--- a/src/armnn/AsyncExecutionCallback.hpp
+++ b/src/armnn/AsyncExecutionCallback.hpp
@@ -1,5 +1,5 @@
 //
-// Copyright © 2021 Arm Ltd and Contributors. All rights reserved.
+// Copyright © 2021-2023 Arm Ltd and Contributors. All rights reserved.
 // SPDX-License-Identifier: MIT
 //
 
@@ -68,7 +68,6 @@
     armnn::Status       m_Status = Status::Failure;
     InferenceId m_InferenceId;
 };
-InferenceId AsyncExecutionCallback::nextID = 0u;
 
 // Manager to create and monitor AsyncExecutionCallbacks
 // GetNewCallback will create a callback for use in Threadpool::Schedule
diff --git a/src/armnn/Runtime.cpp b/src/armnn/Runtime.cpp
index cec54f4..ff64e85 100644
--- a/src/armnn/Runtime.cpp
+++ b/src/armnn/Runtime.cpp
@@ -1,5 +1,5 @@
 //
-// Copyright © 2017, 2023 Arm Ltd and Contributors. All rights reserved.
+// Copyright © 2017, 2022-2023 Arm Ltd and Contributors. All rights reserved.
 // SPDX-License-Identifier: MIT
 //
 
@@ -20,7 +20,10 @@
 #include <armnn/utility/PolymorphicDowncast.hpp>
 #include <armnn/utility/Timer.hpp>
 
+#if !defined(ARMNN_BUILD_BARE_METAL) && !defined(ARMNN_EXECUTE_NETWORK_STATIC)
 #include <backendsCommon/DynamicBackendUtils.hpp>
+#endif
+
 #include <backendsCommon/memoryOptimizerStrategyLibrary/MemoryOptimizerStrategyLibrary.hpp>
 
 #include <client/include/backends/IBackendProfiling.hpp>
@@ -334,11 +337,11 @@
         throw RuntimeException(
                 "It is not possible to enable timeline reporting without profiling being enabled");
     }
-
+#if !defined(ARMNN_BUILD_BARE_METAL) && !defined(ARMNN_EXECUTE_NETWORK_STATIC)
     // Load any available/compatible dynamic backend before the runtime
     // goes through the backend registry
     LoadDynamicBackends(options.m_DynamicBackendsPath);
-
+#endif
     armnn::BackendIdSet supportedBackends;
     for (const auto& id : BackendRegistryInstance().GetBackendIds())
     {
@@ -354,9 +357,11 @@
             if (customAllocatorMapIterator != options.m_CustomAllocatorMap.end() &&
                 customAllocatorMapIterator->second == nullptr)
             {
+#if !defined(ARMNN_BUILD_BARE_METAL) && !defined(ARMNN_EXECUTE_NETWORK_STATIC)
                 // We need to manually clean up  the dynamic backends before throwing an exception.
                 DynamicBackendUtils::DeregisterDynamicBackends(m_DeviceSpec.GetDynamicBackends());
                 m_DeviceSpec.ClearDynamicBackends();
+#endif
                 throw armnn::Exception("Allocator associated with id " + id.Get() + " is null");
             }
 
@@ -579,10 +584,11 @@
                       << std::endl;
         }
     }
-
+#if !defined(ARMNN_BUILD_BARE_METAL) && !defined(ARMNN_EXECUTE_NETWORK_STATIC)
     // Clear all dynamic backends.
     DynamicBackendUtils::DeregisterDynamicBackends(m_DeviceSpec.GetDynamicBackends());
     m_DeviceSpec.ClearDynamicBackends();
+#endif
     m_BackendContexts.clear();
 
     BackendRegistryInstance().SetProfilingService(armnn::EmptyOptional());
@@ -763,6 +769,7 @@
     loadedNetwork->RegisterDebugCallback(func);
 }
 
+#if !defined(ARMNN_BUILD_BARE_METAL) && !defined(ARMNN_EXECUTE_NETWORK_STATIC)
 void RuntimeImpl::LoadDynamicBackends(const std::string& overrideBackendPath)
 {
     // Get the paths where to load the dynamic backends from
@@ -780,5 +787,5 @@
     // Add the registered dynamic backend ids to the list of supported backends
     m_DeviceSpec.AddSupportedBackends(registeredBackendIds, true);
 }
-
+#endif
 } // namespace armnn
diff --git a/src/armnnSerializer/CMakeLists.txt b/src/armnnSerializer/CMakeLists.txt
index 8acdafb..01c51e6 100755
--- a/src/armnnSerializer/CMakeLists.txt
+++ b/src/armnnSerializer/CMakeLists.txt
@@ -1,5 +1,5 @@
 #
-# Copyright © 2017, 2019-2020, 2022 Arm Ltd and Contributors. All rights reserved.
+# Copyright © 2017, 2019-2020, 2022-2023 Arm Ltd and Contributors. All rights reserved.
 # SPDX-License-Identifier: MIT
 #
 if(BUILD_ARMNN_SERIALIZER)
@@ -36,7 +36,7 @@
         ../armnnDeserializer/Deserializer.cpp
         )
 
-    if(BUILD_BARE_METAL)
+    if(BUILD_BARE_METAL OR EXECUTE_NETWORK_STATIC)
         add_library_ex(armnnSerializer STATIC ${armnn_serializer_sources})
     else()
         # We're going to export both a STATIC library and a SHARED library here.
@@ -52,9 +52,11 @@
     target_include_directories(armnnSerializer PRIVATE ../armnn)
     target_include_directories(armnnSerializer PRIVATE ../armnnUtils)
     target_include_directories(armnnSerializer PRIVATE ../../generated)
-    target_include_directories(armnnSerializer-static PRIVATE ../armnn)
-    target_include_directories(armnnSerializer-static PRIVATE ../armnnUtils)
-    target_include_directories(armnnSerializer-static PRIVATE ../../generated)
+    if (NOT BARE_METAL AND NOT EXECUTE_NETWORK_STATIC)
+        target_include_directories(armnnSerializer-static PRIVATE ../armnn)
+        target_include_directories(armnnSerializer-static PRIVATE ../armnnUtils)
+        target_include_directories(armnnSerializer-static PRIVATE ../../generated)
+    endif()
 
     list(APPEND armnn_serializer_sources
         ArmnnSchema_generated.h
@@ -64,12 +66,13 @@
     target_include_directories(armnnSerializer SYSTEM PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
 
     target_link_libraries(armnnSerializer armnn ${FLATBUFFERS_LIBRARY})
-
-    install(TARGETS armnnSerializer-static
-            EXPORT  armnn-targets
-            LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
-            ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
-    )
+    if (NOT BARE_METAL AND NOT EXECUTE_NETWORK_STATIC)
+        install(TARGETS armnnSerializer-static
+                EXPORT  armnn-targets
+                LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+                ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+        )
+    endif()
 
     install(TARGETS armnnSerializer
             EXPORT  armnn-targets
diff --git a/src/armnnTestUtils/CMakeLists.txt b/src/armnnTestUtils/CMakeLists.txt
index 3f6fb415..a4333cf 100755
--- a/src/armnnTestUtils/CMakeLists.txt
+++ b/src/armnnTestUtils/CMakeLists.txt
@@ -1,5 +1,5 @@
 #
-# Copyright © 2021 Arm Ltd and Contributors. All rights reserved.
+# Copyright © 2021, 2023 Arm Ltd and Contributors. All rights reserved.
 # SPDX-License-Identifier: MIT
 #
 
@@ -31,7 +31,7 @@
         TestUtils.hpp
         )
 
-if(NOT BUILD_BARE_METAL)
+if(NOT BUILD_BARE_METAL AND NOT EXECUTE_NETWORK_STATIC)
 list(APPEND armnnTestUtils_sources
         UnitTests.cpp
         UnitTests.hpp
@@ -41,6 +41,8 @@
 
 if(BUILD_BARE_METAL)
     add_library_ex(armnnTestUtils STATIC ${armnnTestUtils_sources})
+elseif(EXECUTE_NETWORK_STATIC)
+    add_library_ex(armnnTestUtils OBJECT ${armnnTestUtils_sources})
 else()
     add_library_ex(armnnTestUtils SHARED ${armnnTestUtils_sources})
 endif()
diff --git a/src/armnnTfLiteParser/CMakeLists.txt b/src/armnnTfLiteParser/CMakeLists.txt
index f9653b6..6096d1b 100755
--- a/src/armnnTfLiteParser/CMakeLists.txt
+++ b/src/armnnTfLiteParser/CMakeLists.txt
@@ -1,5 +1,5 @@
 #
-# Copyright © 2017 Arm Ltd. All rights reserved.
+# Copyright © 2017, 2023 Arm Ltd. All rights reserved.
 # SPDX-License-Identifier: MIT
 #
 if(BUILD_TF_LITE_PARSER)
@@ -11,7 +11,11 @@
         TfLiteParser.cpp
         )
 
-    add_library_ex(armnnTfLiteParser SHARED ${armnn_tf_lite_parser_sources})
+    if(EXECUTE_NETWORK_STATIC)
+        add_library_ex(armnnTfLiteParser OBJECT ${armnn_tf_lite_parser_sources})
+    else()
+        add_library_ex(armnnTfLiteParser SHARED ${armnn_tf_lite_parser_sources})
+    endif()
 
     include_directories(SYSTEM "${FLATBUFFERS_INCLUDE_PATH}")
     set_target_properties(armnnTfLiteParser PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
diff --git a/src/backends/backendsCommon/CMakeLists.txt b/src/backends/backendsCommon/CMakeLists.txt
index b2ab932..8d7e114 100644
--- a/src/backends/backendsCommon/CMakeLists.txt
+++ b/src/backends/backendsCommon/CMakeLists.txt
@@ -1,9 +1,9 @@
 #
-# Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
+# Copyright © 2017, 2023 Arm Ltd and Contributors. All rights reserved.
 # SPDX-License-Identifier: MIT
 #
 
-if(NOT BUILD_BARE_METAL)
+if(NOT BUILD_BARE_METAL AND NOT EXECUTE_NETWORK_STATIC)
 list(APPEND armnnBackendsCommon_sources
     DynamicBackend.cpp
     DynamicBackend.hpp
diff --git a/src/backends/dynamic/reference/CMakeLists.txt b/src/backends/dynamic/reference/CMakeLists.txt
index de46f7a..fe87528 100644
--- a/src/backends/dynamic/reference/CMakeLists.txt
+++ b/src/backends/dynamic/reference/CMakeLists.txt
@@ -1,9 +1,9 @@
 #
-# Copyright © 2017 Arm Ltd. All rights reserved.
+# Copyright © 2017, 2023 Arm Ltd. All rights reserved.
 # SPDX-License-Identifier: MIT
 #
 
-if(NOT BUILD_BARE_METAL)
+if((NOT BUILD_BARE_METAL) AND (NOT EXECUTE_NETWORK_STATIC))
 
 # File needed to wrap the existing backend into a dynamic one
 list(APPEND armnnRefDynamicBackend_sources
@@ -33,5 +33,5 @@
 set_target_properties(Arm_CpuRef_backend PROPERTIES PREFIX "")
 target_link_libraries(Arm_CpuRef_backend armnn)
 
-# BUILD_BARE_METAL
+# BUILD_BARE_METAL && EXECUTE_NETWORK_STATIC
 endif()
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index dd18a32..4c89267 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -1,5 +1,5 @@
 #
-# Copyright © 2018-2022 Arm Ltd and Contributors. All rights reserved.
+# Copyright © 2018-2023 Arm Ltd and Contributors. All rights reserved.
 # SPDX-License-Identifier: MIT
 #
 
@@ -21,7 +21,7 @@
 target_include_directories(inferenceTest PRIVATE ../src/backends)
 target_include_directories(inferenceTest PRIVATE ../third-party/stb)
 
-if (BUILD_TF_LITE_PARSER)
+if (BUILD_TF_LITE_PARSER AND NOT EXECUTE_NETWORK_STATIC)
     macro(TfLiteParserTest testName sources)
         add_executable_ex(${testName} ${sources})
         target_include_directories(${testName} PRIVATE ../src/armnnUtils)
@@ -112,7 +112,7 @@
 
 endif()
 
-if (BUILD_ONNX_PARSER)
+if (BUILD_ONNX_PARSER AND NOT EXECUTE_NETWORK_STATIC)
     macro(OnnxParserTest testName sources)
         add_executable_ex(${testName} ${sources})
         target_include_directories(${testName} PRIVATE ../src/armnnUtils)
@@ -139,7 +139,6 @@
 endif()
 
 if (BUILD_ARMNN_SERIALIZER
-        OR BUILD_TF_PARSER
         OR BUILD_TF_LITE_PARSER
         OR BUILD_ONNX_PARSER
         OR BUILD_ARMNN_TFLITE_DELEGATE)
@@ -168,22 +167,31 @@
     target_include_directories(ExecuteNetwork PRIVATE ../src/armnnUtils)
     target_include_directories(ExecuteNetwork PRIVATE ../src/backends)
     target_include_directories(ExecuteNetwork PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
-
-    if (BUILD_ARMNN_SERIALIZER)
-        target_link_libraries(ExecuteNetwork armnnSerializer)
+    if(EXECUTE_NETWORK_STATIC)
+        target_link_libraries(ExecuteNetwork
+                -Wl,--whole-archive
+                armnnSerializer
+                armnnTfLiteParser
+                armnn
+                pthread
+                -Wl,--no-whole-archive
+                )
+    else()
+        if (BUILD_ARMNN_SERIALIZER)
+            target_link_libraries(ExecuteNetwork armnnSerializer)
+        endif()
+        if (BUILD_TF_LITE_PARSER)
+            target_link_libraries(ExecuteNetwork armnnTfLiteParser)
+        endif()
+        if (BUILD_ONNX_PARSER)
+            target_link_libraries(ExecuteNetwork armnnOnnxParser)
+        endif()
+        if (BUILD_ARMNN_TFLITE_DELEGATE)
+            target_link_libraries(ExecuteNetwork ArmnnDelegate::ArmnnDelegate)
+        endif()
+        target_link_libraries(ExecuteNetwork armnn)
     endif()
 
-    if (BUILD_TF_LITE_PARSER)
-        target_link_libraries(ExecuteNetwork armnnTfLiteParser)
-    endif()
-    if (BUILD_ONNX_PARSER)
-        target_link_libraries(ExecuteNetwork armnnOnnxParser)
-    endif()
-    if (BUILD_ARMNN_TFLITE_DELEGATE)
-        target_link_libraries(ExecuteNetwork ArmnnDelegate::ArmnnDelegate)
-    endif()
-    target_link_libraries(ExecuteNetwork armnn)
-
    target_link_libraries(ExecuteNetwork ${CMAKE_THREAD_LIBS_INIT})
    addDllCopyCommands(ExecuteNetwork)
 endif()
diff --git a/tests/ExecuteNetwork/ArmNNExecutor.cpp b/tests/ExecuteNetwork/ArmNNExecutor.cpp
index 9657f05..139da5f 100644
--- a/tests/ExecuteNetwork/ArmNNExecutor.cpp
+++ b/tests/ExecuteNetwork/ArmNNExecutor.cpp
@@ -1,5 +1,5 @@
 //
-// Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
+// Copyright © 2022-2023 Arm Ltd and Contributors. All rights reserved.
 // SPDX-License-Identifier: MIT
 //
 
@@ -88,6 +88,7 @@
 
 void ArmNNExecutor::ExecuteAsync()
 {
+#if !defined(ARMNN_DISABLE_THREADS)
     std::vector<std::shared_ptr<armnn::IWorkingMemHandle>> memHandles;
     std::unique_ptr<armnn::Threadpool> threadpool;
     armnn::AsyncCallbackManager callbackManager;
@@ -157,6 +158,7 @@
     ARMNN_LOG(info) << "Overall Inference time: " << std::setprecision(2)
                     << std::fixed << totalInferenceDuration.count() << " ms\n";
 
+#endif
 }
 
 void ArmNNExecutor::ExecuteSync()
diff --git a/tests/InferenceModel.hpp b/tests/InferenceModel.hpp
index 2806924..fa1b1b0 100644
--- a/tests/InferenceModel.hpp
+++ b/tests/InferenceModel.hpp
@@ -1,5 +1,5 @@
 //
-// Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
+// Copyright © 2022-2023 Arm Ltd and Contributors. All rights reserved.
 // SPDX-License-Identifier: MIT
 //
 
@@ -7,7 +7,12 @@
 
 
 #include <armnn/ArmNN.hpp>
+
+#if !defined(ARMNN_DISABLE_THREADS)
 #include <armnn/Threadpool.hpp>
+#include <common/include/IgnoreUnused.hpp>
+#endif
+
 #include <armnn/Logging.hpp>
 #include <armnn/utility/Timer.hpp>
 #include <armnn/BackendRegistry.hpp>
@@ -511,7 +516,7 @@
 
             ARMNN_LOG(info) << "Network loading time: " << std::setprecision(2)
                             << std::fixed << armnn::GetTimeDuration(loading_start_time).count() << " ms.";
-
+#if !defined(ARMNN_DISABLE_THREADS)
             if (params.m_AsyncEnabled && params.m_ThreadPoolSize > 0)
             {
                 std::vector<std::shared_ptr<armnn::IWorkingMemHandle>> memHandles;
@@ -524,6 +529,7 @@
                                                                    m_Runtime.get(),
                                                                    memHandles);
             }
+#endif
         }
 
         if (ret == armnn::Status::Failure)
@@ -683,6 +689,7 @@
                   std::vector<armnnUtils::TContainer>& outputContainers,
                   std::shared_ptr<armnn::IAsyncExecutionCallback> cb)
     {
+#if !defined(ARMNN_DISABLE_THREADS)
         for (unsigned int i = 0; i < outputContainers.size(); ++i)
         {
             const unsigned int expectedOutputDataSize = GetOutputSize(i);
@@ -714,6 +721,7 @@
         {
             profiler->Print(std::cout);
         }
+#endif
     }
 
     const armnn::BindingPointInfo& GetInputBindingInfo(unsigned int inputIndex = 0u) const
@@ -770,7 +778,9 @@
 private:
     armnn::NetworkId m_NetworkIdentifier;
     std::shared_ptr<armnn::IRuntime> m_Runtime;
+#if !defined(ARMNN_DISABLE_THREADS)
     std::unique_ptr<armnn::Threadpool> m_Threadpool;
+#endif
 
     std::vector<armnn::BindingPointInfo> m_InputBindings;
     std::vector<armnn::BindingPointInfo> m_OutputBindings;