first working version with fmt lib
This commit is contained in:
parent
1a07864a5f
commit
77055a1579
@ -7,26 +7,32 @@ set(FSFW_REVISION 0)
|
|||||||
# Add the cmake folder so the FindSphinx module is found
|
# Add the cmake folder so the FindSphinx module is found
|
||||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
|
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
|
||||||
|
|
||||||
|
set(FSFW_ETL_LIB_NAME etl)
|
||||||
|
set(FSFW_ETL_LINK_TARGET etl::etl)
|
||||||
set(FSFW_ETL_LIB_MAJOR_VERSION 20 CACHE STRING
|
set(FSFW_ETL_LIB_MAJOR_VERSION 20 CACHE STRING
|
||||||
"ETL library major version requirement"
|
"ETL library major version requirement"
|
||||||
)
|
)
|
||||||
set(FSFW_ETL_LIB_VERSION ${FSFW_ETL_LIB_MAJOR_VERSION}.27.3 CACHE STRING
|
set(FSFW_ETL_LIB_VERSION ${FSFW_ETL_LIB_MAJOR_VERSION}.27.3 CACHE STRING
|
||||||
"ETL library exact version requirement"
|
"ETL library exact version requirement"
|
||||||
)
|
)
|
||||||
set(FSFW_ETL_LINK_TARGET etl::etl)
|
|
||||||
|
|
||||||
set(FSFW_CATCH2_LIB_MAJOR_VERSION 3 CACHE STRING
|
set(FSFW_CATCH2_LIB_MAJOR_VERSION 3 CACHE STRING
|
||||||
"Catch2 library major version requirement"
|
"Catch2 library major version requirement"
|
||||||
)
|
)
|
||||||
set(FSFW_CATCH2_LIB_VERSION v${FSFW_CATCH2_LIB_MAJOR_VERSION}.0.0-preview5 CACHE STRING
|
set(FSFW_CATCH2_LIB_VERSION v${FSFW_CATCH2_LIB_MAJOR_VERSION}.0.0-preview5 CACHE STRING
|
||||||
"Catch2 library exact version requirement"
|
"Catch2 library exact version requirement"
|
||||||
)
|
)
|
||||||
|
|
||||||
set(FSFW_ETL_LIB_NAME etl)
|
set(FSFW_FMT_LIB_NAME fmt)
|
||||||
|
set(FSFW_FMT_LINK_TARGET fmt::fmt)
|
||||||
|
set(FSFW_FMT_LIB_MAJOR_VERSION 8 CACHE STRING "{fmt} library major version requirement")
|
||||||
|
set(FSFW_FMT_LIB_VERSION v${FSFW_FMT_LIB_MAJOR_VERSION}.1.1 CACHE STRING
|
||||||
|
"{fmt} library exact version requirement"
|
||||||
|
)
|
||||||
|
|
||||||
option(FSFW_GENERATE_SECTIONS
|
option(FSFW_GENERATE_SECTIONS
|
||||||
"Generate function and data sections. Required to remove unused code" ON
|
"Generate function and data sections. Required to remove unused code" ON
|
||||||
)
|
)
|
||||||
if(FSFW_GENERATE_SECTIONS)
|
if(FSFW_GENERATE_SECTIONS)
|
||||||
option(FSFW_REMOVE_UNUSED_CODE "Remove unused code" ON)
|
option(FSFW_REMOVE_UNUSED_CODE "Remove unused code" ON)
|
||||||
endif()
|
endif()
|
||||||
@ -60,7 +66,7 @@ set(FSFW_TEST_TGT fsfw-tests)
|
|||||||
set(FSFW_DUMMY_TGT fsfw-dummy)
|
set(FSFW_DUMMY_TGT fsfw-dummy)
|
||||||
|
|
||||||
project(${LIB_FSFW_NAME})
|
project(${LIB_FSFW_NAME})
|
||||||
add_library(${LIB_FSFW_NAME})
|
add_library(${LIB_FSFW_NAME} src/fsfw/serviceinterface/fmtWrapper.h src/fsfw/serviceinterface/fmtWrapper.cpp)
|
||||||
|
|
||||||
if(FSFW_BUILD_UNITTESTS)
|
if(FSFW_BUILD_UNITTESTS)
|
||||||
message(STATUS "Building the FSFW unittests in addition to the static library")
|
message(STATUS "Building the FSFW unittests in addition to the static library")
|
||||||
@ -104,7 +110,7 @@ if(FSFW_BUILD_UNITTESTS)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
message(STATUS "Finding and/or providing ETL library")
|
message(STATUS "Finding and/or providing etl (Embedded Template Library)")
|
||||||
|
|
||||||
# Check whether the user has already installed ETL first
|
# Check whether the user has already installed ETL first
|
||||||
find_package(${FSFW_ETL_LIB_NAME} ${FSFW_ETL_LIB_MAJOR_VERSION} QUIET)
|
find_package(${FSFW_ETL_LIB_NAME} ${FSFW_ETL_LIB_MAJOR_VERSION} QUIET)
|
||||||
@ -125,6 +131,27 @@ if(NOT ${FSFW_ETL_LIB_NAME}_FOUND)
|
|||||||
list(APPEND FSFW_FETCH_CONTENT_TARGETS ${FSFW_ETL_LIB_NAME})
|
list(APPEND FSFW_FETCH_CONTENT_TARGETS ${FSFW_ETL_LIB_NAME})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
message(STATUS "Finding and/or providing {fmt} formatting library")
|
||||||
|
|
||||||
|
# Check whether the user has already installed ETL first
|
||||||
|
find_package(fmt ${FSFW_FMT_LIB_MAJOR_VERSION} QUIET)
|
||||||
|
# Not installed, so use FetchContent to download and provide etl
|
||||||
|
if(NOT ${FSFW_FMT_LIB_NAME}_FOUND)
|
||||||
|
message(STATUS
|
||||||
|
"No {fmt} installation was found with find_package. Installing and providing "
|
||||||
|
"{fmt} with FindPackage"
|
||||||
|
)
|
||||||
|
include(FetchContent)
|
||||||
|
|
||||||
|
FetchContent_Declare(
|
||||||
|
${FSFW_FMT_LIB_NAME}
|
||||||
|
GIT_REPOSITORY https://github.com/fmtlib/fmt.git
|
||||||
|
GIT_TAG ${FSFW_FMT_LIB_VERSION}
|
||||||
|
)
|
||||||
|
|
||||||
|
list(APPEND FSFW_FETCH_CONTENT_TARGETS ${FSFW_FMT_LIB_NAME})
|
||||||
|
endif()
|
||||||
|
|
||||||
# The documentation for FetchContent recommends declaring all the dependencies
|
# The documentation for FetchContent recommends declaring all the dependencies
|
||||||
# before making them available. We make all declared dependency available here
|
# before making them available. We make all declared dependency available here
|
||||||
# after their declaration
|
# after their declaration
|
||||||
@ -147,10 +174,10 @@ set_property(CACHE FSFW_OSAL PROPERTY STRINGS host linux rtems freertos)
|
|||||||
# For configure files
|
# For configure files
|
||||||
target_include_directories(${LIB_FSFW_NAME} PRIVATE
|
target_include_directories(${LIB_FSFW_NAME} PRIVATE
|
||||||
${CMAKE_CURRENT_BINARY_DIR}
|
${CMAKE_CURRENT_BINARY_DIR}
|
||||||
)
|
)
|
||||||
target_include_directories(${LIB_FSFW_NAME} INTERFACE
|
target_include_directories(${LIB_FSFW_NAME} INTERFACE
|
||||||
${CMAKE_CURRENT_BINARY_DIR}
|
${CMAKE_CURRENT_BINARY_DIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
if(NOT CMAKE_CXX_STANDARD)
|
if(NOT CMAKE_CXX_STANDARD)
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
@ -383,7 +410,7 @@ target_include_directories(${LIB_FSFW_NAME} INTERFACE
|
|||||||
${FSFW_CONFIG_PATH_ABSOLUTE}
|
${FSFW_CONFIG_PATH_ABSOLUTE}
|
||||||
${FSFW_CORE_INC_PATH}
|
${FSFW_CORE_INC_PATH}
|
||||||
${FSFW_ADD_INC_PATHS_ABS}
|
${FSFW_ADD_INC_PATHS_ABS}
|
||||||
)
|
)
|
||||||
|
|
||||||
# Includes path required to compile FSFW itself as well
|
# Includes path required to compile FSFW itself as well
|
||||||
# We assume that the fsfwconfig folder uses include relative to the project
|
# We assume that the fsfwconfig folder uses include relative to the project
|
||||||
@ -393,24 +420,30 @@ target_include_directories(${LIB_FSFW_NAME} PRIVATE
|
|||||||
${FSFW_CONFIG_PATH_ABSOLUTE}
|
${FSFW_CONFIG_PATH_ABSOLUTE}
|
||||||
${FSFW_CORE_INC_PATH}
|
${FSFW_CORE_INC_PATH}
|
||||||
${FSFW_ADD_INC_PATHS_ABS}
|
${FSFW_ADD_INC_PATHS_ABS}
|
||||||
)
|
)
|
||||||
|
|
||||||
target_compile_options(${LIB_FSFW_NAME} PRIVATE
|
target_compile_options(${LIB_FSFW_NAME} PRIVATE
|
||||||
${FSFW_WARNING_FLAGS}
|
${FSFW_WARNING_FLAGS}
|
||||||
${COMPILER_FLAGS}
|
${COMPILER_FLAGS}
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
|
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
|
||||||
${FSFW_ETL_LINK_TARGET}
|
${FSFW_ETL_LINK_TARGET}
|
||||||
${FSFW_ADDITIONAL_LINK_LIBS}
|
${FSFW_ADDITIONAL_LINK_LIBS}
|
||||||
)
|
)
|
||||||
|
|
||||||
string(CONCAT POST_BUILD_COMMENT
|
string(CONCAT POST_BUILD_COMMENT
|
||||||
"######################################################################\n"
|
"######################################################################\n"
|
||||||
"Built FSFW v${FSFW_VERSION}.${FSFW_SUBVERSION}.${FSFW_REVISION}, "
|
"Built FSFW v${FSFW_VERSION}.${FSFW_SUBVERSION}.${FSFW_REVISION}, "
|
||||||
"Target OSAL: ${FSFW_OS_NAME}\n"
|
"Target OSAL: ${FSFW_OS_NAME}\n"
|
||||||
"######################################################################\n"
|
"######################################################################\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# The additional / is important to remove the last character from the path.
|
||||||
|
# Note that it does not matter if the OS uses / or \, because we are only
|
||||||
|
# saving the path size.
|
||||||
|
string(LENGTH "${CMAKE_SOURCE_DIR}/" SOURCE_PATH_SIZE)
|
||||||
|
target_compile_definitions(${LIB_FSFW_NAME} PRIVATE "-DFSFW_SOURCE_PATH_SIZE=${FSFW_SOURCE_PATH_SIZE}")
|
||||||
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
TARGET ${LIB_FSFW_NAME}
|
TARGET ${LIB_FSFW_NAME}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||||
|
fmtWrapper.cpp
|
||||||
ServiceInterfaceStream.cpp
|
ServiceInterfaceStream.cpp
|
||||||
ServiceInterfaceBuffer.cpp
|
ServiceInterfaceBuffer.cpp
|
||||||
ServiceInterfacePrinter.cpp
|
ServiceInterfacePrinter.cpp
|
||||||
|
24
src/fsfw/serviceinterface/fmtWrapper.cpp
Normal file
24
src/fsfw/serviceinterface/fmtWrapper.cpp
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#include "fmtWrapper.h"
|
||||||
|
|
||||||
|
#include "fsfw/ipc/MutexFactory.h"
|
||||||
|
|
||||||
|
std::array<char, 524> sif::PRINT_BUF = {};
|
||||||
|
MutexIF* sif::PRINT_MUTEX = nullptr;
|
||||||
|
|
||||||
|
const char* sif::PREFIX_ARR[4]= {DEBUG_PREFIX, INFO_PREFIX, WARNING_PREFIX, ERROR_PREFIX};
|
||||||
|
|
||||||
|
ReturnValue_t sif::initialize() {
|
||||||
|
sif::PRINT_MUTEX = MutexFactory::instance()->createMutex();
|
||||||
|
if(sif::PRINT_MUTEX == nullptr) {
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t sif::writeTypePrefix(LogLevel level) {
|
||||||
|
auto idx = static_cast<unsigned int>(level);
|
||||||
|
const auto result =
|
||||||
|
fmt::format_to_n(PRINT_BUF.begin(), PRINT_BUF.size() - 1,
|
||||||
|
fmt::runtime(fmt::format(fg(LOG_COLOR_ARR[idx]), PREFIX_ARR[idx])));
|
||||||
|
return result.size;
|
||||||
|
}
|
164
src/fsfw/serviceinterface/fmtWrapper.h
Normal file
164
src/fsfw/serviceinterface/fmtWrapper.h
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <fmt/chrono.h>
|
||||||
|
#include <fmt/color.h>
|
||||||
|
#include <fmt/compile.h>
|
||||||
|
#include <fmt/core.h>
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include "fsfw/ipc/MutexGuard.h"
|
||||||
|
#include "fsfw/ipc/MutexIF.h"
|
||||||
|
#include "fsfw/timemanager/Clock.h"
|
||||||
|
|
||||||
|
// Takes from stackoverflow to display relative paths:
|
||||||
|
// https://stackoverflow.com/questions/8487986/file-macro-shows-full-path
|
||||||
|
#ifdef FSFW_SOURCE_PATH_SIZE
|
||||||
|
#define __FILENAME_REL__ (((const char*)__FILE__ + SOURCE_PATH_SIZE))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
|
||||||
|
|
||||||
|
namespace sif {
|
||||||
|
|
||||||
|
extern std::array<char, 524> PRINT_BUF;
|
||||||
|
extern MutexIF* PRINT_MUTEX;
|
||||||
|
|
||||||
|
static const char INFO_PREFIX[] = "INFO";
|
||||||
|
static const char DEBUG_PREFIX[] = "DEBUG";
|
||||||
|
static const char WARNING_PREFIX[] = "WARNING";
|
||||||
|
static const char ERROR_PREFIX[] = "ERROR";
|
||||||
|
|
||||||
|
enum class LogLevel : unsigned int { DEBUG = 0, INFO = 1, WARNING = 2, ERROR = 3 };
|
||||||
|
|
||||||
|
extern const char* PREFIX_ARR[4];
|
||||||
|
|
||||||
|
static const std::array<fmt::color, 4> LOG_COLOR_ARR = {
|
||||||
|
fmt::color::deep_sky_blue, fmt::color::forest_green, fmt::color::orange_red, fmt::color::red};
|
||||||
|
|
||||||
|
ReturnValue_t initialize();
|
||||||
|
|
||||||
|
size_t writeTypePrefix(LogLevel level);
|
||||||
|
|
||||||
|
template <typename... T>
|
||||||
|
size_t logTraced(LogLevel level, const char* file, unsigned int line, bool timed,
|
||||||
|
fmt::format_string<T...> fmt, T&&... args) noexcept {
|
||||||
|
if(PRINT_MUTEX == nullptr) {
|
||||||
|
fmt::print("Please call sif::initialize at program startup\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
MutexGuard mg(PRINT_MUTEX);
|
||||||
|
size_t bufPos = writeTypePrefix(level);
|
||||||
|
auto currentIter = PRINT_BUF.begin() + bufPos;
|
||||||
|
if (timed) {
|
||||||
|
Clock::TimeOfDay_t logTime;
|
||||||
|
Clock::getDateAndTime(&logTime);
|
||||||
|
const auto result = fmt::format_to_n(currentIter, PRINT_BUF.size() - 1 - bufPos,
|
||||||
|
" | {}[l.{}] | {:02}:{:02}:{:02}.{:03} | {}", file, line,
|
||||||
|
logTime.hour, logTime.minute, logTime.second,
|
||||||
|
logTime.usecond / 1000, fmt::format(fmt, args...));
|
||||||
|
bufPos += result.size;
|
||||||
|
} else {
|
||||||
|
const auto result = fmt::format_to_n(currentIter, PRINT_BUF.size() - 1 - bufPos,
|
||||||
|
" | {}[l.{}] | {}", file, line, fmt::format(fmt, args...));
|
||||||
|
bufPos += result.size;
|
||||||
|
}
|
||||||
|
PRINT_BUF[bufPos] = '\0';
|
||||||
|
fmt::print(fmt::runtime(PRINT_BUF.data()));
|
||||||
|
return bufPos;
|
||||||
|
} catch (const fmt::v8::format_error& e) {
|
||||||
|
fmt::print("Printing failed with error: {}\n", e.what());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... T>
|
||||||
|
size_t log(LogLevel level, bool timed, fmt::format_string<T...> fmt, T&&... args) noexcept {
|
||||||
|
if(PRINT_MUTEX == nullptr) {
|
||||||
|
fmt::print("Please call sif::initialize at program startup\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
MutexGuard mg(PRINT_MUTEX);
|
||||||
|
size_t bufPos = writeTypePrefix(level);
|
||||||
|
auto currentIter = PRINT_BUF.begin() + bufPos;
|
||||||
|
if (timed) {
|
||||||
|
Clock::TimeOfDay_t logTime;
|
||||||
|
Clock::getDateAndTime(&logTime);
|
||||||
|
const auto result = fmt::format_to_n(
|
||||||
|
currentIter, PRINT_BUF.size() - bufPos, " | {:02}:{:02}:{:02}.{:03} | {}", logTime.hour,
|
||||||
|
logTime.minute, logTime.second, logTime.usecond / 1000, fmt::format(fmt, args...));
|
||||||
|
bufPos += result.size;
|
||||||
|
} else {
|
||||||
|
const auto result = fmt::format_to_n(
|
||||||
|
currentIter, PRINT_BUF.size() - bufPos, " | {}", fmt::format(fmt, args...));
|
||||||
|
bufPos += result.size;
|
||||||
|
}
|
||||||
|
PRINT_BUF[bufPos] = '\0';
|
||||||
|
fmt::print(fmt::runtime(PRINT_BUF.data()));
|
||||||
|
return bufPos;
|
||||||
|
} catch (const fmt::v8::format_error& e) {
|
||||||
|
fmt::print("Printing failed with error: {}\n", e.what());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... T>
|
||||||
|
void fdebug(const char* file, unsigned int line, fmt::format_string<T...> fmt, T&&... args) noexcept {
|
||||||
|
logTraced(LogLevel::DEBUG, file, line, false, fmt, args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... T>
|
||||||
|
void fdebug_t(const char* file, unsigned int line, fmt::format_string<T...> fmt, T&&... args) noexcept {
|
||||||
|
logTraced(LogLevel::DEBUG, file, line, true, fmt, args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... T>
|
||||||
|
void finfo_t(fmt::format_string<T...> fmt, T&&... args) {
|
||||||
|
log(LogLevel::INFO, true, fmt, args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... T>
|
||||||
|
void finfo(fmt::format_string<T...> fmt, T&&... args) {
|
||||||
|
log(LogLevel::INFO, false, fmt, args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... T>
|
||||||
|
void fwarning(const char* file, unsigned int line, fmt::format_string<T...> fmt, T&&... args) {
|
||||||
|
logTraced(LogLevel::WARNING, file, line, false, fmt, args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... T>
|
||||||
|
void fwarning_t(const char* file, unsigned int line, fmt::format_string<T...> fmt, T&&... args) {
|
||||||
|
logTraced(LogLevel::WARNING, file, line, true, fmt, args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... T>
|
||||||
|
void ferror(const char* file, unsigned int line, fmt::format_string<T...> fmt, T&&... args) {
|
||||||
|
logTraced(LogLevel::ERROR, file, line, false, fmt, args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... T>
|
||||||
|
void ferror_t(const char* file, unsigned int line, fmt::format_string<T...> fmt, T&&... args) {
|
||||||
|
logTraced(LogLevel::ERROR, file, line, true, fmt, args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace sif
|
||||||
|
|
||||||
|
#define FSFW_LOGI(format, ...) finfo(FMT_STRING(format), __VA_ARGS__)
|
||||||
|
|
||||||
|
#define FSFW_LOGIT(format, ...) finfo_t(FMT_STRING(format), __VA_ARGS__)
|
||||||
|
|
||||||
|
#define FSFW_LOGD(format, ...) sif::fdebug(__FILENAME__, __LINE__, FMT_STRING(format), __VA_ARGS__)
|
||||||
|
|
||||||
|
#define FSFW_LOGDT(format, ...) fdebug_t(__FILENAME__, __LINE__, FMT_STRING(format), __VA_ARGS__)
|
||||||
|
|
||||||
|
#define FSFW_LOGW(format, ...) fdebug(__FILENAME__, __LINE__, FMT_STRING(format), __VA_ARGS__)
|
||||||
|
|
||||||
|
#define FSFW_LOGWT(format, ...) fdebug_t(__FILENAME__, __LINE__, FMT_STRING(format), __VA_ARGS__)
|
||||||
|
|
||||||
|
#define FSFW_LOGE(format, ...) fdebug(__FILENAME__, __LINE__, FMT_STRING(format), __VA_ARGS__)
|
||||||
|
|
||||||
|
#define FSFW_LOGET(format, ...) fdebug_t(__FILENAME__, __LINE__, FMT_STRING(format), __VA_ARGS__)
|
Loading…
x
Reference in New Issue
Block a user