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.add_cmake_defines({
|
||||
'BUILD_SHARED_LIBS': 'ON',
|
||||
'CMAKE_SKIP_INSTALL_RULES': 'ON'
|
||||
'BUILD_STATIC_LIBS': 'ON',
|
||||
'BUILD_SHARED_LIBS': 'OFF',
|
||||
'CMAKE_SKIP_INSTALL_RULES': 'ON',
|
||||
'CMAKE_POSITION_INDEPENDENT_CODE': 'ON'
|
||||
})
|
||||
|
||||
quill_sp = cmake.subproject(
|
||||
'quill',
|
||||
options: quill_cmake_options,
|
||||
)
|
||||
|
||||
quill_dep = quill_sp.dependency('quill')
|
||||
|
||||
message('Registering quill headers (' + meson.global_source_root() + '/subprojects/quill/include/quill) for installation...')
|
||||
quill_headers = meson.global_source_root() + '/subprojects/quill/include/quill'
|
||||
install_subdir(quill_headers, install_dir: get_option('includedir'))
|
||||
message('Done registering quill headers for installation!')
|
||||
if get_option('default_library') != 'static'
|
||||
message('Registering quill headers for installation...')
|
||||
# Note: verify this path matches your source structure
|
||||
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
|
||||
#
|
||||
# *********************************************************************** #
|
||||
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_project_arguments('-fvisibility=default', language: 'cpp')
|
||||
|
||||
|
||||
subdir('build-config')
|
||||
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...')
|
||||
pkg = import('pkgconfig')
|
||||
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 <map>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
#include "quill/Logger.h"
|
||||
|
||||
|
||||
@@ -23,16 +23,16 @@
|
||||
#include "quill/Logger.h"
|
||||
#include "quill/sinks/ConsoleSink.h"
|
||||
#include "quill/sinks/FileSink.h"
|
||||
#include "quill/LogMacros.h"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <filesystem>
|
||||
|
||||
#if defined(__EMSCRIPTEN__)
|
||||
#include <ranges>
|
||||
#endif
|
||||
|
||||
|
||||
#include "fourdst/logging/logging.h"
|
||||
|
||||
@@ -41,28 +41,43 @@ namespace fourdst::logging {
|
||||
|
||||
LogManager::LogManager() {
|
||||
quill::Backend::start();
|
||||
|
||||
auto CLILogger = quill::Frontend::create_or_get_logger(
|
||||
"root",
|
||||
quill::Frontend::create_or_get_sink<quill::ConsoleSink>("sink_id_1"));
|
||||
|
||||
newFileLogger("fourdst.log", "log");
|
||||
|
||||
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;
|
||||
|
||||
#endif
|
||||
|
||||
quill::Logger* LogManager::getLogger(const std::string& loggerName) {
|
||||
auto it = loggerMap.find(loggerName); // Find *once*
|
||||
auto it = loggerMap.find(loggerName);
|
||||
if (it == loggerMap.end()) {
|
||||
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> loggerNames;
|
||||
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);
|
||||
}
|
||||
return loggerNames;
|
||||
@@ -72,13 +87,21 @@ std::vector<quill::Logger*> LogManager::getLoggers() {
|
||||
std::vector<quill::Logger*> loggers;
|
||||
loggers.reserve(loggerMap.size());
|
||||
for (const auto& pair : loggerMap) {
|
||||
loggers.push_back(pair.second); // Get the raw pointer
|
||||
loggers.push_back(pair.second);
|
||||
}
|
||||
return loggers;
|
||||
}
|
||||
|
||||
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>(
|
||||
filename,
|
||||
[]() {
|
||||
@@ -87,12 +110,13 @@ quill::Logger* LogManager::newFileLogger(const std::string& filename,
|
||||
return cfg;
|
||||
}(),
|
||||
quill::FileEventNotifier{});
|
||||
// Get the raw pointer.
|
||||
|
||||
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);
|
||||
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]
|
||||
url = https://github.com/odygrd/quill
|
||||
revision = v8.1.1
|
||||
diff_files = quill/add_wasm_rdtsc_fallback_support.patch, quill/enable_pthread_header_emscripted.patch
|
||||
|
||||
[cmake]
|
||||
Reference in New Issue
Block a user