Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't compile with CMake - umock_c_prod.h: no such file or directory #2654

Open
bertulli opened this issue Oct 24, 2024 · 1 comment
Open

Comments

@bertulli
Copy link

bertulli commented Oct 24, 2024

Hi all, thank you for your work. I know this has been noticed before (#2436 #1364 #1086) but apparently the proposed solutions did not fix the problem for me.

Platform: Ubuntu 22.04
SDK submodule: 7afef615156a74aa2a0393506bff04ec215e4c11 azure-iot-sdk-c (2018-03-07-temp-pod-1460-g7afef6151)

I am trying to integrate the IoTHub provisioning (with x509) into our application. I want to adapt the code I found in provisioning_client/samples/prov_dev_client_ll_x509_sample/prov_dev_client_ll_x509_sample.c, but since I'd like to not have everything into a single file, I tried creating a separate {cpp/hpp} couple of files, called azure-helpers that will contain the Azure connection logic (both provisioning and MQTT telemetry). However, it fails by telling me during compilation:

$ make
# [...]
[ 69%] Building CXX object CMakeFiles/azure-helpers.dir/azure-helpers.cpp.o
In file included from /home/abertulli/MWE/include/azure-helpers.hpp:15,
                 from /home/abertulli/MWE/azure-helpers.cpp:5:
/home/abertulli/MWE/azure-iot-sdk-c/iothub_client/inc/iothub.h:12:10: fatal error: umock_c/umock_c_prod.h: No such file or directory
   12 | #include "umock_c/umock_c_prod.h"
      |          ^~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
make[2]: *** [CMakeFiles/azure-helpers.dir/build.make:76: CMakeFiles/azure-helpers.dir/azure-helpers.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:469: CMakeFiles/azure-helpers.dir/all] Error 2
make: *** [Makefile:136: all] Error 2

What can I do to make it find the right header? Thanks!


MWE

  • CMakeLists.txt:
cmake_minimum_required (VERSION 3.7)
PROJECT(MWE)

# Change as wished
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_BUILD_TYPE "Debug")

# Default to C++14
if(NOT CMAKE_CXX_STANDARD)
  set(CMAKE_CXX_STANDARD 14)
endif()

set(CMAKE_THREAD_LIBS_INIT "-lpthread")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
set(CMAKE_HAVE_THREADS_LIBRARY 1)
set(CMAKE_USE_WIN32_THREADS_INIT 0)
set(CMAKE_USE_PTHREADS_INIT 1)
set(THREADS_PREFER_PTHREAD_FLAG ON)

if(CMAKE_TOOLCHAIN_FILE)
  message("Cross compilation detected")
  message("CMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}")
endif()

########
# main #
########

include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/include) # for all files

set(main_files
  main.cpp
)

add_executable(${PROJECT_NAME} ${main_files})

#################
# Azure helpers #
#################

add_library(azure-helpers azure-helpers.cpp)
target_link_libraries(${PROJECT_NAME} azure-helpers)

###################
# Azure IoT C SDK #
###################

# Set Azure IoT SDK C settings
set(use_mqtt ON CACHE  BOOL "Set mqtt on" FORCE )
set(skip_samples ON CACHE  BOOL "Set slip_samples on" FORCE )
set(BUILD_TESTING OFF CACHE  BOOL "Set BUILD_TESTING off" FORCE )

# additional provisioning settings
set(use_prov_client ON)
set(hsm_type_x509 ON)
target_include_directories(azure-helpers PUBLIC azure-iot-sdk-c/provisioning_client/inc)

# Add Azure IoT SDK C
add_subdirectory(./azure-iot-sdk-c out)

compileAsC99()

#Conditionally use the SDK trusted certs in the samples
if(${use_sample_trusted_cert})
    add_definitions(-DSET_TRUSTED_CERT_IN_SAMPLES)
    include_directories(${PROJECT_SOURCE_DIR}/certs)
    set(iothub_c_files ${iothub_c_files} ${PROJECT_SOURCE_DIR}/certs/certs.c)
endif()

target_include_directories(azure-helpers PUBLIC .)
target_include_directories(azure-helpers PUBLIC ${IOTHUB_CLIENT_INC_FOLDER})
target_include_directories(azure-helpers PUBLIC ${DEV_AUTH_MODULES_CLIENT_INC_FOLDER})
target_include_directories(azure-helpers PUBLIC ${SHARED_UTIL_INC_FOLDER})
target_include_directories(azure-helpers PUBLIC ${CMAKE_CURRENT_LIST_DIR}/adapters)
target_include_directories(azure-helpers PUBLIC ${AZURE_SDK_PATH}/deps/umock-c/inc)
target_include_directories(azure-helpers PUBLIC ${AZURE_SDK_PATH}/c-utility/deps/azure-macro-utils-c/inc)

if(${use_openssl})
    add_definitions(-DUSE_OPENSSL)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUSE_OPENSSL")
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUSE_OPENSSL")
    if (WIN32)
        target_link_libraries(prov_dev_client_ll_x509_sample $ENV{OpenSSLDir}/lib/ssleay32.lib $ENV{OpenSSLDir}/lib/libeay32.lib)
        file(COPY $ENV{OpenSSLDir}/bin/libeay32.dll DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Debug)
        file(COPY $ENV{OpenSSLDir}/bin/ssleay32.dll DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Debug)
    endif()
endif()

target_link_libraries(${PROJECT_NAME} iothub_client)

if (${use_http})
    target_link_libraries(${PROJECT_NAME} prov_http_transport)
endif()
if (${use_mqtt})
    target_link_libraries(${PROJECT_NAME} prov_mqtt_transport prov_mqtt_ws_transport iothub_client_mqtt_transport)
endif()
if (${use_amqp})
    target_link_libraries(${PROJECT_NAME} prov_amqp_ws_transport prov_amqp_transport iothub_client_amqp_transport)
    linkUAMQP(${PROJECT_NAME})
endif()

target_link_libraries(${PROJECT_NAME}
    iothub_client
    prov_device_ll_client
    prov_auth_client
    aziotsharedutil
    hsm_security_client
)
  • main.cpp:
#include <azure-helpers.hpp>

int main(int argc, char *argv[])
{
  return 0;
}
  • azure-helpers.cpp:
// Adapted from a sample from Microsoft. For those parts,
// copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#include <azure-helpers.hpp>

MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(PROV_DEVICE_RESULT, PROV_DEVICE_RESULT_VALUE);
MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(PROV_DEVICE_REG_STATUS, PROV_DEVICE_REG_STATUS_VALUES);

IOTHUBMESSAGE_DISPOSITION_RESULT receive_msg_callback(IOTHUB_MESSAGE_HANDLE message, void* user_context)
{
    (void)message;
    IOTHUB_CLIENT_SAMPLE_INFO* iothub_info = (IOTHUB_CLIENT_SAMPLE_INFO*)user_context;
    (void)printf("Stop message received from IoTHub\r\n");
    iothub_info->stop_running = true;
    return IOTHUBMESSAGE_ACCEPTED;
}

void registration_status_callback(PROV_DEVICE_REG_STATUS reg_status, void* user_context)
{
    (void)user_context;
    (void)printf("Provisioning Status: %s\r\n", MU_ENUM_TO_STRING(PROV_DEVICE_REG_STATUS, reg_status));
}

void iothub_connection_status(IOTHUB_CLIENT_CONNECTION_STATUS result, IOTHUB_CLIENT_CONNECTION_STATUS_REASON reason, void* user_context)
{
    (void)reason;
    if (user_context == NULL)
    {
        printf("iothub_connection_status user_context is NULL\r\n");
    }
    else
    {
        IOTHUB_CLIENT_SAMPLE_INFO* iothub_info = (IOTHUB_CLIENT_SAMPLE_INFO*)user_context;
        if (result == IOTHUB_CLIENT_CONNECTION_AUTHENTICATED)
        {
            iothub_info->connected = true;
        }
        else
        {
            iothub_info->connected = false;
            iothub_info->stop_running = true;
        }
    }
}

void register_device_callback(PROV_DEVICE_RESULT register_result, const char* iothub_uri, const char* device_id, void* user_context)
{
    if (user_context == NULL)
    {
        printf("user_context is NULL\r\n");
    }
    else
    {
        CLIENT_SAMPLE_INFO* user_ctx = (CLIENT_SAMPLE_INFO*)user_context;
        user_ctx->registration_complete = true;
        if (register_result == PROV_DEVICE_RESULT_OK)
        {
            (void)printf("Registration Information received from service: %s\r\n", iothub_uri);
            (void)mallocAndStrcpy_s(&user_ctx->iothub_uri, iothub_uri);
            (void)mallocAndStrcpy_s(&user_ctx->device_id, device_id);
        }
        else
        {
            (void)printf("Failure encountered on registration %s\r\n", MU_ENUM_TO_STRING(PROV_DEVICE_RESULT, register_result) );
        }
    }
}
  • include/azure-helpers.hpp:
#ifndef AZURE_HELPERS_H
#define AZURE_HELPERS_H

// Adapted from a sample from Microsoft. For those parts,
// copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#include <stdio.h>
#include <stdlib.h>

#include <fstream>
#include <string>
#include <sstream>

#include "iothub.h"
#include "iothub_message.h"
#include "iothub_client_version.h"
#include "azure_c_shared_utility/threadapi.h"
#include "azure_c_shared_utility/tickcounter.h"
#include "azure_c_shared_utility/shared_util_options.h"
#include "azure_c_shared_utility/http_proxy_io.h"

#include "iothub_device_client_ll.h"
#include "iothub_client_options.h"
#include "azure_prov_client/prov_device_ll_client.h"
#include "azure_prov_client/prov_security_factory.h"

// Provisioning information:
static const char *global_prov_uri = "global.azure-devices-provisioning.net";
static const char* id_scope = "<insert-here>";
static const char* registration_id = "<insert-here>";   // Case sensitive.

//
// The protocol you wish to use should be uncommented
//
#define SAMPLE_MQTT
//#define SAMPLE_MQTT_OVER_WEBSOCKETS
//#define SAMPLE_AMQP
//#define SAMPLE_AMQP_OVER_WEBSOCKETS
//#define SAMPLE_HTTP

// If using an OpenSSL ENGINE uncomment and modify the line below. 
//#define SAMPLE_OPENSSL_ENGINE "pkcs11"

#ifdef SET_TRUSTED_CERT_IN_SAMPLES
#include "certs.h"
#endif // SET_TRUSTED_CERT_IN_SAMPLES
#ifdef SAMPLE_MQTT
#include "iothubtransportmqtt.h"
#include "azure_prov_client/prov_transport_mqtt_client.h"
#endif // SAMPLE_MQTT
#ifdef SAMPLE_MQTT_OVER_WEBSOCKETS
#include "iothubtransportmqtt_websockets.h"
#include "azure_prov_client/prov_transport_mqtt_ws_client.h"
#endif // SAMPLE_MQTT_OVER_WEBSOCKETS
#ifdef SAMPLE_AMQP
#include "iothubtransportamqp.h"
#include "azure_prov_client/prov_transport_amqp_client.h"
#endif // SAMPLE_AMQP
#ifdef SAMPLE_AMQP_OVER_WEBSOCKETS
#include "iothubtransportamqp_websockets.h"
#include "azure_prov_client/prov_transport_amqp_ws_client.h"
#endif // SAMPLE_AMQP_OVER_WEBSOCKETS
#ifdef SAMPLE_HTTP
#include "iothubtransporthttp.h"
#include "azure_prov_client/prov_transport_http_client.h"
#endif // SAMPLE_HTTP

#ifdef SET_TRUSTED_CERT_IN_SAMPLES
#include "certs.h"
#endif // SET_TRUSTED_CERT_IN_SAMPLES


#ifdef SAMPLE_OPENSSL_ENGINE
static const char* opensslEngine = SAMPLE_OPENSSL_ENGINE;
static const OPTION_OPENSSL_KEY_TYPE x509_key_from_engine = KEY_TYPE_ENGINE;
#endif

#define MESSAGES_TO_SEND                10
#define TIME_BETWEEN_MESSAGES_SECONDS   1

typedef struct CLIENT_SAMPLE_INFO_TAG
{
    PROV_DEVICE_LL_HANDLE handle;
    unsigned int sleep_time_msec;
    char* iothub_uri;
    char* device_id;
    bool registration_complete;
} CLIENT_SAMPLE_INFO;

typedef struct IOTHUB_CLIENT_SAMPLE_INFO_TAG
{
    bool connected;
    bool stop_running;
} IOTHUB_CLIENT_SAMPLE_INFO;

//static
IOTHUBMESSAGE_DISPOSITION_RESULT
receive_msg_callback(IOTHUB_MESSAGE_HANDLE message, void *user_context);

//static
void registration_status_callback(PROV_DEVICE_REG_STATUS reg_status,
                                         void *user_context);

//static
void
iothub_connection_status(IOTHUB_CLIENT_CONNECTION_STATUS result,
                         IOTHUB_CLIENT_CONNECTION_STATUS_REASON reason,
                         void *user_context);

//static
void register_device_callback(PROV_DEVICE_RESULT register_result,
                              const char *iothub_uri, const char *device_id,
                              void *user_context);

#endif /* AZURE_HELPERS_H */
  • Configuration with CMake:
$ cmake ..
-- The C compiler identification is GNU 11.4.0
-- The CXX compiler identification is GNU 11.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- IoT Client SDK Version = 1.14.0
CMake Warning (dev) at azure-iot-sdk-c/CMakeLists.txt:63 (option):
  Policy CMP0077 is not set: option() honors normal variables.  Run "cmake
  --help-policy CMP0077" for policy details.  Use the cmake_policy command to
  set the policy and suppress this warning.

  For compatibility with older versions of CMake, option is clearing the
  normal variable 'use_prov_client'.
This warning is for project developers.  Use -Wno-dev to suppress it.

CMake Warning (dev) at azure-iot-sdk-c/CMakeLists.txt:70 (option):
  Policy CMP0077 is not set: option() honors normal variables.  Run "cmake
  --help-policy CMP0077" for policy details.  Use the cmake_policy command to
  set the policy and suppress this warning.

  For compatibility with older versions of CMake, option is clearing the
  normal variable 'hsm_type_x509'.
This warning is for project developers.  Use -Wno-dev to suppress it.

-- Provisioning SDK Version = 1.14.0
CMake Deprecation Warning at azure-iot-sdk-c/deps/azure-macro-utils-c/CMakeLists.txt:4 (cmake_minimum_required):
  Compatibility with CMake < 2.8.12 will be removed from a future version of
  CMake.

  Update the VERSION argument <min> value or use a ...<max> suffix to tell
  CMake that the project does not need compatibility with older versions.


CMake Deprecation Warning at azure-iot-sdk-c/deps/umock-c/CMakeLists.txt:4 (cmake_minimum_required):
  Compatibility with CMake < 2.8.12 will be removed from a future version of
  CMake.

  Update the VERSION argument <min> value or use a ...<max> suffix to tell
  CMake that the project does not need compatibility with older versions.


-- Looking for include file stdint.h
-- Looking for include file stdint.h - found
-- Looking for include file stdbool.h
-- Looking for include file stdbool.h - found
-- target architecture: x86_64
-- Performing Test CXX_FLAG_CXX11
-- Performing Test CXX_FLAG_CXX11 - Success
-- Found OpenSSL: /usr/lib/x86_64-linux-gnu/libcrypto.so (found version "3.0.2")
-- Found CURL: /usr/lib/x86_64-linux-gnu/libcurl.so (found version "7.81.0")
-- Found CURL: /usr/lib/x86_64-linux-gnu/libcurl.so
-- target architecture: x86_64
-- IoT Hub Architecture: x86_64
-- Configuring done
-- Generating done
-- Build files have been written to: /home/abertulli/MWE/build
@bertulli
Copy link
Author

bertulli commented Nov 5, 2024

Important update: I noticed that the problem arises when trying to compile my azure-helpers.cpp as a separate object file. If I instead do

# snippet
set(main_files
  main.cpp
  azure-helpers.cpp # <---- HERE
)

add_executable(${PROJECT_NAME} ${main_files})

target_include_directories(${PROJECT_NAME} PUBLIC azure-iot-sdk-c/provisioning_client/inc) # <---- ADDED

and remove everything in my CMakeLists.txt related to the target azure-helpers then it works. Should I then guess it is something related to the transitive propagation of include directories?


Note that, upon successful compilation, i can use my IDE to see that the previously not found header is azure-iot-sdk-c/deps/umock-c/inc/umock_c/umock_c_prod.h. Going up in the tree, the closest CMakeLists.txt I can find is in azure-iot-sdk-c/deps/umock-c/, where I also see

#these are the include folders
#the following "set" statetement exports across the project a global variable called UMOCK_C_INC_FOLDER that expands to whatever needs to included when using umock_c library
set(UMOCK_C_INC_FOLDER ${CMAKE_CURRENT_LIST_DIR}/inc CACHE INTERNAL "this is what needs to be included if using umock_c lib" FORCE)

so setting instead in my project

# AFTER including the Azure IoT C SDK!
target_include_directories(azure-helpers PUBLIC ${UMOCK_C_INC_FOLDER})

changed the error message to

In file included from /home/abertulli/MWE/azure-iot-sdk-c/iothub_client/inc/iothub.h:12,
                 from /home/abertulli/MWE/include/azure-helpers.hpp:15,
                 from /home/abertulli/MWE/azure-helpers.cpp:5:
/home/abertulli/MWE/azure-iot-sdk-c/deps/umock-c/inc/umock_c/umock_c_prod.h:4:10: fatal error: azure_macro_utils/macro_utils.h: No such file or directory
    4 | #include "azure_macro_utils/macro_utils.h"
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Following the same research, in the relevant CMake file I found

#these are the include folders
#the following "set" statement exports across the project a global variable called MACRO_UTILS_INC_FOLDER that expands to whatever needs to included when using macro_utils
set(MACRO_UTILS_INC_FOLDER ${CMAKE_CURRENT_LIST_DIR}/inc CACHE INTERNAL "this is what needs to be included if using macro utils" FORCE)

and finally, adding

# again after adding the Azure SDK
target_include_directories(azure-helpers PUBLIC ${MACRO_UTILS_INC_FOLDER})

I can compile the project.

A quick search with grep -inr --include \*.txt 'set(.*INC_FOLDER' azure-iot-sdk-c/ revealed there are many that folders can included like that, and looking at grep -inr --include \*.md 'INC_FOLDER' azure-iot-sdk-c/ it seems that the only documentation about that is in the dependencies of the project, not in the "main" documentation, if I understood correctly. Is there something in the docs that I missed? Or should we open a PR?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant