CMock - having a hard time excluding specific files from compilation
Hello,
I am trying to upgrade my project from an old snapshot to release v1.0.1
I am going through the STM32 libraries and the problem I am having is related to their stm32h5xx_hal_conf.h. This file provides headers and macros to enable/disable code in the headers, like types.
The problem I have is that they provide this file in their files but then you are supposed to create your own. In this new version I can't seem to be able to not include their file. Alternatively just for testing I could be using the cmock configuration to define some symbols.
I have tried using a combination of :paths: and :files but it always tells me it's using the default file.
I could delete or edit the default file but I feel like I should be able to remove specific files from the include list.
This has some parts cut out but I think it shows what I am trying to do. I am including with paths and then trying to remove the specific file with files.
:paths:
:test:
- test/**
:source:
- +:STM32Cube_FW_H5_V1.2.0/Drivers/**
:include:
- +:STM32Cube_FW_H5_V1.2.0/Drivers/**
:support:
- /test/support/ # this is where I have the config file I want to use
:libraries: []
:files:
:test: []
:source:
- -:STM32Cube_FW_H5_V1.2.0/Drivers/STM32H5xx_HAL_Driver/Inc/stm32h5xx_hal_conf.h
:include:
- -:STM32Cube_FW_H5_V1.2.0/Drivers/STM32H5xx_HAL_Driver/Inc/stm32h5xx_hal_conf.h
just to add, this might have not been an evident issue because of how the CMocks were built. I think now it's trying to mock functions that are disabled by macros:
#if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
/**
* @brief HAL FDCAN common Callback ID enumeration definition
*/
typedef enum
{
HAL_FDCAN_TX_FIFO_EMPTY_CB_ID = 0x00U, /*!< FDCAN Tx Fifo Empty callback ID */
HAL_FDCAN_HIGH_PRIO_MESSAGE_CB_ID = 0x01U, /*!< FDCAN High priority message callback ID */
HAL_FDCAN_TIMESTAMP_WRAPAROUND_CB_ID = 0x02U, /*!< FDCAN Timestamp wraparound callback ID */
HAL_FDCAN_TIMEOUT_OCCURRED_CB_ID = 0x03U, /*!< FDCAN Timeout occurred callback ID */
HAL_FDCAN_ERROR_CALLBACK_CB_ID = 0x04U, /*!< FDCAN Error callback ID */
HAL_FDCAN_MSPINIT_CB_ID = 0x05U, /*!< FDCAN MspInit callback ID */
HAL_FDCAN_MSPDEINIT_CB_ID = 0x06U, /*!< FDCAN MspDeInit callback ID */
} HAL_FDCAN_CallbackIDTypeDef;
/**
* @brief HAL FDCAN Callback pointer definition
*/
typedef void (*pFDCAN_CallbackTypeDef)(FDCAN_HandleTypeDef *hfdcan); /*!< pointer to a common FDCAN callback function */
typedef void (*pFDCAN_TxEventFifoCallbackTypeDef)(FDCAN_HandleTypeDef *hfdcan, uint32_t TxEventFifoITs); /*!< pointer to Tx event Fifo FDCAN callback function */
typedef void (*pFDCAN_RxFifo0CallbackTypeDef)(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs); /*!< pointer to Rx Fifo 0 FDCAN callback function */
typedef void (*pFDCAN_RxFifo1CallbackTypeDef)(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo1ITs); /*!< pointer to Rx Fifo 1 FDCAN callback function */
typedef void (*pFDCAN_TxBufferCompleteCallbackTypeDef)(FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndexes); /*!< pointer to Tx Buffer complete FDCAN callback function */
typedef void (*pFDCAN_TxBufferAbortCallbackTypeDef)(FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndexes); /*!< pointer to Tx Buffer abort FDCAN callback function */
typedef void (*pFDCAN_ErrorStatusCallbackTypeDef)(FDCAN_HandleTypeDef *hfdcan, uint32_t ErrorStatusITs); /*!< pointer to Error Status callback function */
#endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */
#if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
/* Callbacks Register/UnRegister functions ***********************************/
HAL_StatusTypeDef HAL_FDCAN_RegisterCallback(FDCAN_HandleTypeDef *hfdcan, HAL_FDCAN_CallbackIDTypeDef CallbackID,
pFDCAN_CallbackTypeDef pCallback);
HAL_StatusTypeDef HAL_FDCAN_UnRegisterCallback(FDCAN_HandleTypeDef *hfdcan, HAL_FDCAN_CallbackIDTypeDef CallbackID);
HAL_StatusTypeDef HAL_FDCAN_RegisterTxEventFifoCallback(FDCAN_HandleTypeDef *hfdcan,
pFDCAN_TxEventFifoCallbackTypeDef pCallback);
HAL_StatusTypeDef HAL_FDCAN_UnRegisterTxEventFifoCallback(FDCAN_HandleTypeDef *hfdcan);
HAL_StatusTypeDef HAL_FDCAN_RegisterRxFifo0Callback(FDCAN_HandleTypeDef *hfdcan,
pFDCAN_RxFifo0CallbackTypeDef pCallback);
HAL_StatusTypeDef HAL_FDCAN_UnRegisterRxFifo0Callback(FDCAN_HandleTypeDef *hfdcan);
HAL_StatusTypeDef HAL_FDCAN_RegisterRxFifo1Callback(FDCAN_HandleTypeDef *hfdcan,
pFDCAN_RxFifo1CallbackTypeDef pCallback);
HAL_StatusTypeDef HAL_FDCAN_UnRegisterRxFifo1Callback(FDCAN_HandleTypeDef *hfdcan);
HAL_StatusTypeDef HAL_FDCAN_RegisterTxBufferCompleteCallback(FDCAN_HandleTypeDef *hfdcan,
pFDCAN_TxBufferCompleteCallbackTypeDef pCallback);
HAL_StatusTypeDef HAL_FDCAN_UnRegisterTxBufferCompleteCallback(FDCAN_HandleTypeDef *hfdcan);
HAL_StatusTypeDef HAL_FDCAN_RegisterTxBufferAbortCallback(FDCAN_HandleTypeDef *hfdcan,
pFDCAN_TxBufferAbortCallbackTypeDef pCallback);
HAL_StatusTypeDef HAL_FDCAN_UnRegisterTxBufferAbortCallback(FDCAN_HandleTypeDef *hfdcan);
HAL_StatusTypeDef HAL_FDCAN_RegisterErrorStatusCallback(FDCAN_HandleTypeDef *hfdcan,
pFDCAN_ErrorStatusCallbackTypeDef pCallback);
HAL_StatusTypeDef HAL_FDCAN_UnRegisterErrorStatusCallback(FDCAN_HandleTypeDef *hfdcan);
#endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */
I think previously those functions were not being mocked and now they are hence why the issue comes up
I am convinced now my actual issue is that CMock does not ignore the functions that are gated by the defines.
But regardless of that, I still am not sure how to exclude specific includes
@lafonso-gnrc -- your example in the first block should indeed work. The paths are applied first, pulling in all the files that can be found in any of the provided paths. The files are processed after. In this case, it should find the specified files and remove them from the previous list.
There was a bug related to this (that I am forgetting the detail to at the moment) that was recently fixed. You might want to consider pulling the pre-release for 1.0.2 and giving that a try.
You may also want to issue ceedling files:header to get a list of the header files which have been identified as part of the collection by Ceedling.
One final note: If your file stm32h5xx_hal_conf.h is in the same folder as a C file which includes it, gcc (or many other compilers) won't bother to search other folders for the headers. It'll use the one in the immediate folder first. I don't believe this is your situation, but it's worth noting just in case.
Switching topics:
To get CMock to ignore functions gated by defines, etc. you'll need to have Ceedling run the preprocessor first. You can do this by setting :use_test_preprocessor to at least :mocks and possibly :all
Hello @mvandervoord and thank you for your time.
On first bit... well, I think this always has been an issue I've had, it just was not made evident due to the second problem. I might try out v1.0.2.
On the second topic, I have tried use_test_preprocessor to :mocks and :all.
I am now attempting to use mixin so I am not sure that could contribute (0.32 snapshot didn't have that feature I don't think).
What I had that was different and was important before was :use_preprocessor_directives: TRUE
Doing this in the project.yml works! I need to do :mocks instead of ```:all`` otherwise running .out crashes (possibly normal to crash there).
Is it not intended to have these options available per mixin?
:use_mocks: TRUE
:use_test_preprocessor: :all # options are :none, :mocks, :tests, or :all
:use_deep_preprocessor: :none # options are :none, :mocks, :tests, or :all
:use_backtrace: :none # options are :none, :simple, or :gdb
:use_decorators: :auto # decorate Ceedling's output text. options are :auto, :all, or :none
--edit: had pasted the old project.yml config where it still uses TRUE/FALSE, it was just a copy paste error into this comment
Hi @lafonso-gnrc -- yes, some of the features have had their name change between 0.32 and 1.0.n. This includes replacing the old use_preprocessor_directives with more complete preprocessing handling using use_test_preprocessor.
I'm not sure I'm following your question about mixins. You are definitely allowed to overwrite any of the settings you've listed in mixins. You can also set them in your main project file. Your mixins are applied one after another, over the top of the main project file... so whichever mixin / main project file that changes a setting LAST becomes the final value. If you don't want a mixin to touch a value, you can choose to not list it.
Feel free to ask further questions if I've misunderstood or my answers aren't clear. :)
Hello. I have commented about the mixin use_test_preprocessor in the more relevant #1070 . It was just my mistake setting up the mixin.
But about the original topic of this issue, I will have to explore that at some point, including trying out v1.0.2 snapshot. It's very common for the ST libraries to come with a example configuration file