build(wasm): liblogging now builds for wasm
Further, due to limitations of file system access on wasm, liblogging now outputs all logs to the console syncronously
This commit is contained in:
@@ -1,15 +1,23 @@
|
|||||||
|
cmake = import('cmake')
|
||||||
|
|
||||||
quill_cmake_options = cmake.subproject_options()
|
quill_cmake_options = cmake.subproject_options()
|
||||||
quill_cmake_options.add_cmake_defines({
|
quill_cmake_options.add_cmake_defines({
|
||||||
'BUILD_SHARED_LIBS': 'ON',
|
'BUILD_STATIC_LIBS': 'ON',
|
||||||
'CMAKE_SKIP_INSTALL_RULES': 'ON'
|
'BUILD_SHARED_LIBS': 'OFF',
|
||||||
|
'CMAKE_SKIP_INSTALL_RULES': 'ON',
|
||||||
|
'CMAKE_POSITION_INDEPENDENT_CODE': 'ON'
|
||||||
})
|
})
|
||||||
|
|
||||||
quill_sp = cmake.subproject(
|
quill_sp = cmake.subproject(
|
||||||
'quill',
|
'quill',
|
||||||
options: quill_cmake_options,
|
options: quill_cmake_options,
|
||||||
)
|
)
|
||||||
|
|
||||||
quill_dep = quill_sp.dependency('quill')
|
quill_dep = quill_sp.dependency('quill')
|
||||||
|
|
||||||
message('Registering quill headers (' + meson.global_source_root() + '/subprojects/quill/include/quill) for installation...')
|
if get_option('default_library') != 'static'
|
||||||
quill_headers = meson.global_source_root() + '/subprojects/quill/include/quill'
|
message('Registering quill headers for installation...')
|
||||||
install_subdir(quill_headers, install_dir: get_option('includedir'))
|
# Note: verify this path matches your source structure
|
||||||
message('Done registering quill headers for installation!')
|
quill_headers = meson.global_source_root() + '/subprojects/quill/include/quill'
|
||||||
|
install_subdir(quill_headers, install_dir: get_option('includedir'))
|
||||||
|
endif
|
||||||
|
|||||||
19
cross/macos_arm64.ini
Normal file
19
cross/macos_arm64.ini
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
[binaries]
|
||||||
|
c = 'arm64-apple-darwin25-clang'
|
||||||
|
cpp = 'arm64-apple-darwin25-clang++'
|
||||||
|
ar = 'arm64-apple-darwin25-ar'
|
||||||
|
strip = 'arm64-apple-darwin25-strip'
|
||||||
|
pkg-config = 'pkg-config'
|
||||||
|
ranlib = '/usr/bin/true'
|
||||||
|
|
||||||
|
[host_machine]
|
||||||
|
system = 'darwin'
|
||||||
|
cpu_family = 'aarch64'
|
||||||
|
cpu = 'arm64'
|
||||||
|
endian = 'little'
|
||||||
|
|
||||||
|
[built-in options]
|
||||||
|
c_args = ['-mmacosx-version-min=15.0']
|
||||||
|
cpp_args = ['-mmacos-version-min=15.0']
|
||||||
|
c_link_args = ['-mmacosx-version-min=15.0']
|
||||||
|
cpp_link_args = ['-mmacos-version-min=15.0']
|
||||||
23
cross/wasm.ini
Normal file
23
cross/wasm.ini
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
[binaries]
|
||||||
|
c = 'emcc'
|
||||||
|
cpp = 'em++'
|
||||||
|
ar = 'emar'
|
||||||
|
strip = 'emstrip'
|
||||||
|
|
||||||
|
exec_wrapper = 'node'
|
||||||
|
|
||||||
|
[built-in options]
|
||||||
|
c_args = ['-Dpkg_config=false', '-Dbuild_tests=false', '-Dbuild_examples=true', '-s', 'MEMORY64=1', '-pthread', '-DQUILL_NO_THREAD_NAME_SUPPORT', '-DQUILL_IMMEDIATE_FLUSH']
|
||||||
|
cpp_args = ['-Dpkg_config=false', '-Dbuild_tests=false', '-Dbuild_examples=true', '-fwasm-exceptions', '-s', 'MEMORY64=1', '-pthread', '-DQUILL_NO_THREAD_NAME_SUPPORT', '-DQUILL_IMMEDIATE_FLUSH']
|
||||||
|
c_link_args = ['-s', 'WASM=1', '-s', 'ALLOW_MEMORY_GROWTH=1', '-s', 'MEMORY64=1', '-fwasm-exceptions', '-pthread', '-s', 'EXPORTED_RUNTIME_METHODS=["FS", "callMain"]']
|
||||||
|
cpp_link_args = ['-s', 'WASM=1', '-s', 'ALLOW_MEMORY_GROWTH=1', '-s', 'MEMORY64=1', '-fwasm-exceptions', '-pthread', '-s', 'EXPORTED_RUNTIME_METHODS=["FS", "callMain"]']
|
||||||
|
|
||||||
|
[host_machine]
|
||||||
|
system = 'emscripten'
|
||||||
|
cpu_family = 'wasm64'
|
||||||
|
cpu = 'wasm64'
|
||||||
|
endian = 'little'
|
||||||
|
|
||||||
|
[properties]
|
||||||
|
cmake_toolchain_file = '/home/tboudreaux/Programming/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake'
|
||||||
|
|
||||||
1
examples/meson.build
Normal file
1
examples/meson.build
Normal file
@@ -0,0 +1 @@
|
|||||||
|
executable('simple_logging_test', 'simple.cpp', dependencies: [logging_dep])
|
||||||
16
examples/simple.cpp
Normal file
16
examples/simple.cpp
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "quill/LogMacros.h"
|
||||||
|
|
||||||
|
#include "fourdst/logging/logging.h"
|
||||||
|
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
auto& logManager = fourdst::logging::LogManager::getInstance();
|
||||||
|
quill::Logger* logger = logManager.newFileLogger("test.log", "logger");
|
||||||
|
|
||||||
|
std::cout << "Logging...\n";
|
||||||
|
LOG_INFO(logger, "This is an info message: {}", 42);
|
||||||
|
std::cout << "Done Logging\n";
|
||||||
|
}
|
||||||
15
meson.build
15
meson.build
@@ -18,15 +18,24 @@
|
|||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
# *********************************************************************** #
|
# *********************************************************************** #
|
||||||
project('liblogging', 'cpp', version: 'v1.1.0', default_options: ['cpp_std=c++23'], meson_version: '>=1.5.0')
|
project('liblogging', 'cpp', version: 'v1.1.1', default_options: ['cpp_std=c++23'], meson_version: '>=1.5.0')
|
||||||
|
|
||||||
# Add default visibility for all C++ targets
|
# Add default visibility for all C++ targets
|
||||||
add_project_arguments('-fvisibility=default', language: 'cpp')
|
add_project_arguments('-fvisibility=default', language: 'cpp')
|
||||||
|
|
||||||
|
|
||||||
subdir('build-config')
|
subdir('build-config')
|
||||||
subdir('src')
|
subdir('src')
|
||||||
subdir('tests')
|
|
||||||
|
|
||||||
if get_option('pkg-config')
|
if get_option('build_tests')
|
||||||
|
subdir('tests')
|
||||||
|
endif
|
||||||
|
|
||||||
|
if get_option('build_examples')
|
||||||
|
subdir('examples')
|
||||||
|
endif
|
||||||
|
|
||||||
|
if get_option('pkg_config')
|
||||||
message('Generating pkg-config file for liblogging...')
|
message('Generating pkg-config file for liblogging...')
|
||||||
pkg = import('pkgconfig')
|
pkg = import('pkgconfig')
|
||||||
pkg.generate(
|
pkg.generate(
|
||||||
|
|||||||
@@ -1 +1,3 @@
|
|||||||
option('pkg-config', type: 'boolean', value: true, description: 'generate pkg-config file for liblogging (fourdst_liblogging.pc)')
|
option('pkg_config', type: 'boolean', value: true, description: 'generate pkg-config file for liblogging (fourdst_liblogging.pc)')
|
||||||
|
option('build_tests', type: 'boolean', value: true, description: 'generate unit tests (uses gtest)')
|
||||||
|
option('build_examples', type: 'boolean', value: true, description: 'generate example programs')
|
||||||
|
|||||||
@@ -24,7 +24,6 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
#include "quill/Logger.h"
|
#include "quill/Logger.h"
|
||||||
|
|
||||||
|
|||||||
@@ -22,17 +22,17 @@
|
|||||||
#include "quill/Frontend.h"
|
#include "quill/Frontend.h"
|
||||||
#include "quill/Logger.h"
|
#include "quill/Logger.h"
|
||||||
#include "quill/sinks/ConsoleSink.h"
|
#include "quill/sinks/ConsoleSink.h"
|
||||||
#include "quill/sinks/FileSink.h"
|
#include "quill/sinks/FileSink.h"
|
||||||
#include "quill/LogMacros.h"
|
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iostream>
|
|
||||||
#include <chrono>
|
|
||||||
#include <cmath>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <filesystem>
|
|
||||||
|
#if defined(__EMSCRIPTEN__)
|
||||||
|
#include <ranges>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "fourdst/logging/logging.h"
|
#include "fourdst/logging/logging.h"
|
||||||
|
|
||||||
@@ -41,28 +41,43 @@ namespace fourdst::logging {
|
|||||||
|
|
||||||
LogManager::LogManager() {
|
LogManager::LogManager() {
|
||||||
quill::Backend::start();
|
quill::Backend::start();
|
||||||
|
|
||||||
auto CLILogger = quill::Frontend::create_or_get_logger(
|
auto CLILogger = quill::Frontend::create_or_get_logger(
|
||||||
"root",
|
"root",
|
||||||
quill::Frontend::create_or_get_sink<quill::ConsoleSink>("sink_id_1"));
|
quill::Frontend::create_or_get_sink<quill::ConsoleSink>("sink_id_1"));
|
||||||
|
|
||||||
newFileLogger("fourdst.log", "log");
|
newFileLogger("fourdst.log", "log");
|
||||||
|
|
||||||
loggerMap.emplace("stdout", CLILogger);
|
loggerMap.emplace("stdout", CLILogger);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(__EMSCRIPTEN__)
|
||||||
|
|
||||||
|
LogManager::~LogManager() {
|
||||||
|
for (const auto& logger : loggerMap | std::views::values) {
|
||||||
|
logger->flush_log();
|
||||||
|
}
|
||||||
|
quill::Backend::stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
LogManager::~LogManager() = default;
|
LogManager::~LogManager() = default;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
quill::Logger* LogManager::getLogger(const std::string& loggerName) {
|
quill::Logger* LogManager::getLogger(const std::string& loggerName) {
|
||||||
auto it = loggerMap.find(loggerName); // Find *once*
|
auto it = loggerMap.find(loggerName);
|
||||||
if (it == loggerMap.end()) {
|
if (it == loggerMap.end()) {
|
||||||
throw std::runtime_error("Cannot find logger " + loggerName);
|
throw std::runtime_error("Cannot find logger " + loggerName);
|
||||||
}
|
}
|
||||||
return it->second; // Return the raw pointer from the shared_ptr
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> LogManager::getLoggerNames() {
|
std::vector<std::string> LogManager::getLoggerNames() {
|
||||||
std::vector<std::string> loggerNames;
|
std::vector<std::string> loggerNames;
|
||||||
loggerNames.reserve(loggerMap.size());
|
loggerNames.reserve(loggerMap.size());
|
||||||
for (const auto& pair : loggerMap) { // Use range-based for loop and const auto&
|
for (const auto& pair : loggerMap) {
|
||||||
loggerNames.push_back(pair.first);
|
loggerNames.push_back(pair.first);
|
||||||
}
|
}
|
||||||
return loggerNames;
|
return loggerNames;
|
||||||
@@ -72,13 +87,21 @@ std::vector<quill::Logger*> LogManager::getLoggers() {
|
|||||||
std::vector<quill::Logger*> loggers;
|
std::vector<quill::Logger*> loggers;
|
||||||
loggers.reserve(loggerMap.size());
|
loggers.reserve(loggerMap.size());
|
||||||
for (const auto& pair : loggerMap) {
|
for (const auto& pair : loggerMap) {
|
||||||
loggers.push_back(pair.second); // Get the raw pointer
|
loggers.push_back(pair.second);
|
||||||
}
|
}
|
||||||
return loggers;
|
return loggers;
|
||||||
}
|
}
|
||||||
|
|
||||||
quill::Logger* LogManager::newFileLogger(const std::string& filename,
|
quill::Logger* LogManager::newFileLogger(const std::string& filename,
|
||||||
const std::string& loggerName) {
|
const std::string& loggerName) {
|
||||||
|
|
||||||
|
#if defined(__EMSCRIPTEN__)
|
||||||
|
auto proxy_sink = quill::Frontend::create_or_get_sink<quill::ConsoleSink>("sink_id_1");
|
||||||
|
quill::Logger* rawLogger = quill::Frontend::create_or_get_logger(loggerName, std::move(proxy_sink));
|
||||||
|
|
||||||
|
loggerMap.emplace(loggerName, rawLogger);
|
||||||
|
return rawLogger;
|
||||||
|
#else
|
||||||
auto file_sink = quill::Frontend::create_or_get_sink<quill::FileSink>(
|
auto file_sink = quill::Frontend::create_or_get_sink<quill::FileSink>(
|
||||||
filename,
|
filename,
|
||||||
[]() {
|
[]() {
|
||||||
@@ -87,12 +110,13 @@ quill::Logger* LogManager::newFileLogger(const std::string& filename,
|
|||||||
return cfg;
|
return cfg;
|
||||||
}(),
|
}(),
|
||||||
quill::FileEventNotifier{});
|
quill::FileEventNotifier{});
|
||||||
// Get the raw pointer.
|
|
||||||
quill::Logger* rawLogger = quill::Frontend::create_or_get_logger(loggerName, std::move(file_sink));
|
quill::Logger* rawLogger = quill::Frontend::create_or_get_logger(loggerName, std::move(file_sink));
|
||||||
|
|
||||||
// Create a shared_ptr from the raw pointer.
|
|
||||||
loggerMap.emplace(loggerName, rawLogger);
|
loggerMap.emplace(loggerName, rawLogger);
|
||||||
return rawLogger;
|
return rawLogger;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Probe
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
--- quill/include/quill/core/Rdtsc.h.orig 2025-12-03 09:43:26.530875697 -0500
|
||||||
|
+++ quill/include/quill/core/Rdtsc.h 2025-12-03 09:42:49.852913743 -0500
|
||||||
|
@@ -16,7 +16,7 @@
|
||||||
|
#elif defined(__ARM_ARCH)
|
||||||
|
#include <chrono>
|
||||||
|
#include <cstdint>
|
||||||
|
-#elif (defined(_M_ARM) || defined(_M_ARM64))
|
||||||
|
+#elif (defined(_M_ARM) || defined(_M_ARM64) || defined(__wasm__))
|
||||||
|
#include <chrono>
|
||||||
|
#include <cstdint>
|
||||||
|
#elif (defined(__PPC64__))
|
||||||
|
@@ -72,7 +72,7 @@
|
||||||
|
// soft failover
|
||||||
|
return static_cast<uint64_t>(std::chrono::system_clock::now().time_since_epoch().count());
|
||||||
|
}
|
||||||
|
-#elif (defined(_M_ARM) || defined(_M_ARM64) || defined(__PPC64__))
|
||||||
|
+#elif (defined(_M_ARM) || defined(_M_ARM64) || defined(__PPC64__) || defined(__wasm__))
|
||||||
|
QUILL_NODISCARD QUILL_ATTRIBUTE_HOT inline uint64_t rdtsc() noexcept
|
||||||
|
{
|
||||||
|
// soft failover
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
--- quill/inlcude/quill/backend/BackendUtilities.h.orig 2025-12-03 10:02:26.861779737 -0500
|
||||||
|
+++ quill/include/quill/backend/BackendUtilities.h 2025-12-03 10:09:04.509482559 -0500
|
||||||
|
@@ -35,7 +35,7 @@
|
||||||
|
#elif defined(__CYGWIN__)
|
||||||
|
#include <sched.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
-#elif defined(__linux__)
|
||||||
|
+#elif (defined(__linux__) || defined(__EMSCRIPTEN__))
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <sched.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
@@ -84,6 +84,8 @@
|
||||||
|
thread_port_t mach_thread = pthread_mach_thread_np(pthread_self());
|
||||||
|
|
||||||
|
thread_policy_set(mach_thread, THREAD_AFFINITY_POLICY, (thread_policy_t)&policy, 1);
|
||||||
|
+#elif defined(__EMSCRIPTEN__)
|
||||||
|
+ (void)cpu_id;
|
||||||
|
#else
|
||||||
|
cpu_set_t cpuset;
|
||||||
|
CPU_ZERO(&cpuset);
|
||||||
|
@@ -102,7 +104,7 @@
|
||||||
|
/***/
|
||||||
|
QUILL_ATTRIBUTE_COLD inline void set_thread_name(char const* name)
|
||||||
|
{
|
||||||
|
-#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(QUILL_NO_THREAD_NAME_SUPPORT)
|
||||||
|
+#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(QUILL_NO_THREAD_NAME_SUPPORT) || defined(__EMSCRIPTEN__)
|
||||||
|
// Disabled on MINGW / Cygwin.
|
||||||
|
(void)name;
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
@@ -154,4 +156,4 @@
|
||||||
|
}
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
-QUILL_END_NAMESPACE
|
||||||
|
\ No newline at end of file
|
||||||
|
+QUILL_END_NAMESPACE
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
[wrap-git]
|
[wrap-git]
|
||||||
url = https://github.com/odygrd/quill
|
url = https://github.com/odygrd/quill
|
||||||
revision = v8.1.1
|
revision = v8.1.1
|
||||||
|
diff_files = quill/add_wasm_rdtsc_fallback_support.patch, quill/enable_pthread_header_emscripted.patch
|
||||||
|
|
||||||
[cmake]
|
[cmake]
|
||||||
|
|||||||
Reference in New Issue
Block a user