diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a01daf8..fb863792 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,8 @@ cmake_minimum_required(VERSION 3.5) set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") include(VersioningUtils) +include(CheckIncludeFile) + read_version_header("" "WPE_[A-Z]+_VERSION" "${CMAKE_CURRENT_SOURCE_DIR}/include/wpe/libwpe-version.h") set_project_version(${WPE_MAJOR_VERSION} ${WPE_MINOR_VERSION} ${WPE_MICRO_VERSION}) set(WPE_API_VERSION "1.0") @@ -129,6 +131,22 @@ if (WPE_ENABLE_XKB) set(WPE_PC_REQUIRES xkbcommon) endif () +check_include_file("android/log.h" HAVE_ANDROID_LOG_H) +if (HAVE_ANDROID_LOG_H) + include(CMakePushCheckState) + include(CheckFunctionExists) + + cmake_push_check_state(RESET) + list(APPEND CMAKE_REQUIRED_LIBRARIES -llog) + check_function_exists(__android_log_print HAVE_ANDROID_LOG_PRINT) + cmake_pop_check_state() + + if (HAVE_ANDROID_LOG_PRINT) + target_compile_definitions(wpe PRIVATE WPE_ENABLE_ANDROID=1) + target_link_libraries(wpe PRIVATE -llog) + endif () +endif () + install( TARGETS wpe RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} diff --git a/meson.build b/meson.build index 917e8564..38a71a8d 100644 --- a/meson.build +++ b/meson.build @@ -76,6 +76,12 @@ if not cc.has_function('dlopen') dependencies += dl_dep endif +android_log_lib = cc.find_library('log', has_headers: ['android/log.h'], required: false) +if android_log_lib.found() + add_project_arguments('-DWPE_ENABLE_ANDROID=1', language: ['c', 'cpp']) + dependencies += [android_log_lib] +endif + if pkg_cflags.length() > 0 add_project_arguments(pkg_cflags, language: ['c', 'cpp']) endif diff --git a/src/alloc.c b/src/alloc.c index 83b34173..f3bb63d0 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -28,10 +28,11 @@ #include +#include "logging-private.h" + void wpe_alloc_fail(const char* file, unsigned line, size_t amount) { - fprintf(stderr, "%s:%u: failed to allocate %zu bytes\n", file, line, amount); - fflush(stderr); + wpe_log_fatal("%s:%u: failed to allocate %zu bytes", file, line, amount); abort(); } diff --git a/src/loader-static.c b/src/loader-static.c index e195bcf7..7470852b 100644 --- a/src/loader-static.c +++ b/src/loader-static.c @@ -26,9 +26,10 @@ #include "loader-private.h" -#include #include +#include "logging-private.h" + extern struct wpe_loader_interface _wpe_loader_interface; bool @@ -51,9 +52,9 @@ void* wpe_load_object(const char* object_name) { if (!_wpe_loader_interface.load_object) { - fprintf(stderr, - "wpe_load_object: failed to load object with name '%s': backend doesn't implement load_object vfunc\n", - object_name); + wpe_log_fatal( + "wpe_load_object: failed to load object with name '%s': backend doesn't implement load_object vfunc", + object_name); abort(); } return _wpe_loader_interface.load_object(object_name); diff --git a/src/loader.c b/src/loader.c index 9e22061c..2772e7ca 100644 --- a/src/loader.c +++ b/src/loader.c @@ -31,6 +31,7 @@ #include #include "alloc-private.h" +#include "logging-private.h" static void* s_impl_library = 0; static struct wpe_loader_interface* s_impl_loader = 0; @@ -68,7 +69,7 @@ load_impl_library() #ifdef WPE_BACKEND s_impl_library = dlopen(WPE_BACKEND, RTLD_NOW); if (!s_impl_library) { - fprintf(stderr, "wpe: could not load compile-time defined WPE_BACKEND: %s\n", dlerror()); + wpe_log_fatal("could not load compile-time defined WPE_BACKEND: %s", dlerror()); abort(); } #else @@ -78,7 +79,7 @@ load_impl_library() if (env_library_name) { s_impl_library = dlopen(env_library_name, RTLD_NOW); if (!s_impl_library) { - fprintf(stderr, "wpe: could not load specified WPE_BACKEND_LIBRARY: %s\n", dlerror()); + wpe_log_fatal("could not load specified WPE_BACKEND_LIBRARY: %s", dlerror()); abort(); } wpe_loader_set_impl_library_name(env_library_name); @@ -88,7 +89,7 @@ load_impl_library() // Load libWPEBackend-default.so by ... default. s_impl_library = dlopen("libWPEBackend-default.so", RTLD_NOW); if (!s_impl_library) { - fprintf(stderr, "wpe: could not load the impl library. Is there any backend installed?: %s\n", dlerror()); + wpe_log_fatal("could not load the impl library. Is there any backend installed?: %s", dlerror()); abort(); } wpe_loader_set_impl_library_name("libWPEBackend-default.so"); @@ -103,13 +104,13 @@ wpe_loader_init(const char* impl_library_name) { #ifndef WPE_BACKEND if (!impl_library_name) { - fprintf(stderr, "wpe_loader_init: invalid implementation library name\n"); + wpe_log_fatal("wpe_loader_init: invalid implementation library name"); abort(); } if (s_impl_library) { if (!s_impl_library_name || strcmp(s_impl_library_name, impl_library_name) != 0) { - fprintf(stderr, "wpe_loader_init: already initialized\n"); + wpe_log_fatal("wpe_loader_init: already initialized"); return false; } return true; @@ -117,7 +118,7 @@ wpe_loader_init(const char* impl_library_name) s_impl_library = dlopen(impl_library_name, RTLD_NOW); if (!s_impl_library) { - fprintf(stderr, "wpe_loader_init could not load the library '%s': %s\n", impl_library_name, dlerror()); + wpe_log_error("wpe_loader_init could not load the library '%s': %s", impl_library_name, dlerror()); return false; } wpe_loader_set_impl_library_name(impl_library_name); @@ -147,7 +148,9 @@ wpe_load_object(const char* object_name) if (s_impl_loader) { if (!s_impl_loader->load_object) { - fprintf(stderr, "wpe_load_object: failed to load object with name '%s': backend doesn't implement load_object vfunc\n", object_name); + wpe_log_fatal( + "wpe_load_object: failed to load object with name '%s': backend doesn't implement load_object vfunc", + object_name); abort(); } return s_impl_loader->load_object(object_name); @@ -155,7 +158,7 @@ wpe_load_object(const char* object_name) void* object = dlsym(s_impl_library, object_name); if (!object) - fprintf(stderr, "wpe_load_object: failed to load object with name '%s'\n", object_name); + wpe_log_error("wpe_load_object: failed to load object with name '%s'", object_name); return object; } diff --git a/src/logging-private.h b/src/logging-private.h new file mode 100644 index 00000000..7deb1b5d --- /dev/null +++ b/src/logging-private.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2025 Igalia S.L. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if defined(WPE_ENABLE_ANDROID) && WPE_ENABLE_ANDROID +#include + +#define wpe_log(level, fmt, ...) __android_log_print(ANDROID_LOG_##level, "libwpe", (fmt), ##__VA_ARGS__) + +#else +#include + +#define wpe_log(level, fmt, ...) \ + do { \ + fprintf(stderr, "libwpe [" #level "]: " fmt "\n", ##__VA_ARGS__); \ + fflush(stderr); \ + } while (0) + +#endif + +#define wpe_log_debug(fmt, ...) wpe_log(DEBUG, fmt, ##__VA_ARGS__) +#define wpe_log_warning(fmt, ...) wpe_log(WARN, fmt, ##__VA_ARGS__) +#define wpe_log_error(fmt, ...) wpe_log(ERROR, fmt, ##__VA_ARGS__) +#define wpe_log_fatal(fmt, ...) wpe_log(FATAL, fmt, ##__VA_ARGS__)