Last active
May 19, 2024 01:38
-
-
Save luncliff/2a892ce06cd319207720434966ded7fc to your computer and use it in GitHub Desktop.
C++, Swift build with CMake
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "logger.hpp" | |
#include "logger_binding.h" | |
#define FMT_HEADER_ONLY | |
#define SPDLOG_HEADER_ONLY | |
#include <fmt/format.h> | |
#include <fmt/xchar.h> | |
#include <spdlog/sinks/stdout_color_sinks.h> | |
#include <spdlog/sinks/stdout_sinks.h> | |
#include <spdlog/spdlog.h> | |
auto make_logger(const char* name, FILE* fout) noexcept(false) { | |
spdlog::sink_ptr sink0 = [fout]() -> spdlog::sink_ptr { | |
using mutex_t = spdlog::details::console_nullmutex; | |
if (fout == stdout || fout == stderr) | |
return std::make_shared<spdlog::sinks::stdout_color_sink_st>(); | |
using sink_t = spdlog::sinks::stdout_sink_base<mutex_t>; | |
return std::make_shared<sink_t>(fout); | |
}(); | |
return std::make_shared<spdlog::logger>(name, spdlog::sinks_init_list{sink0}); | |
} | |
void setup_logger(const char* name, FILE* fout) { | |
auto logger = make_logger(name, fout); | |
logger->set_pattern("%T.%e [%L] %8t %v"); | |
logger->set_level(spdlog::level::level_enum::debug); | |
spdlog::set_default_logger(logger); | |
} | |
void setup_logger(const char* name) { | |
return setup_logger(name, stdout); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <cstdio> | |
#if __has_include("logger_binding.h") | |
extern "C" { | |
#include "logger_binding.h" | |
} | |
#endif | |
void setup_logger(const char* name, FILE* fout); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
void setup_logger(const char* name); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Darwin | |
import Foundation | |
// public func setup_logger(_ name: UnsafePointer<CChar>!) -> Void | |
/// @see https://developer.apple.com/documentation/swift/using-imported-c-functions-in-swift | |
class CustomLogger { | |
init() { | |
changeName("test") | |
} | |
func changeName(_ name: String) { | |
let u8str = name.cString(using: .utf8) | |
setup_logger(u8str!) | |
// let sym: UnsafeMutableRawPointer? = dlsym(handle, "_setup_logger") | |
// if sym == nil { | |
// return | |
// } | |
// typealias FnSetup = @convention(c) (UnsafePointer<CChar>) -> Void | |
// let fn = unsafeBitCast(sym!, to: FnSetup.self) | |
// fn(u8str!) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Darwin | |
import Foundation | |
import XCTest | |
@testable import logger1 | |
class CustomLoggerTestCase: XCTestCase { | |
var handle: UnsafeMutableRawPointer? | |
override func setUp() { | |
handle = dlopen("liblogger1.dylib", RTLD_NOW) | |
if handle == nil { | |
handle = dlopen(nil, RTLD_NOW) | |
print("Using dlopen(nil)...") | |
} | |
XCTAssertNotNil(handle) | |
} | |
override func tearDown() { | |
dlclose(handle) | |
} | |
func testFunctions() { | |
let fn = dlsym(handle, "setup_logger") | |
XCTAssertNotNil(fn) | |
} | |
func testBindingClass() { | |
let logger = CustomLogger() | |
logger.changeName("XCTestCase") | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# CMakeLists.txt | |
cmake_minimum_required(VERSION 3.24) | |
project(cpp-swift-test VERSION 1.0 LANGUAGES CXX OBJCXX Swift) | |
message(STATUS "Using system: ${CMAKE_SYSTEM_VERSION}") | |
option(BUILD_TESTING "Build XCTest bundle" ON) | |
include(GNUInstallDirs) | |
enable_testing() | |
find_package(spdlog CONFIG REQUIRED) # spdlog::spdlog_header_only | |
# C++/Objective-C++ library | |
add_library(logger0 STATIC | |
logger.cpp | |
) | |
# some public interfaces | |
list(APPEND ifcs | |
logger.hpp | |
) | |
target_sources(logger0 PRIVATE ${ifcs}) | |
set_target_properties(logger0 PROPERTIES | |
CXX_STANDARD 17 | |
OBJCXX_STANDARD 17 | |
PUBLIC_HEADER "${ifcs}" | |
XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC ON # -fobjc-arc | |
) | |
target_compile_options(logger0 PRIVATE | |
-g | |
) | |
target_link_libraries(logger0 PRIVATE | |
spdlog::spdlog_header_only | |
) | |
# Swift framework with some C++ libraries | |
add_library(logger1 SHARED | |
${ifcs} | |
logger_binding.swift | |
) | |
# Swift-C bridge headers | |
list(APPEND bridges | |
logger_binding.h | |
) | |
target_sources(logger1 PRIVATE ${bridges}) | |
# It sould be `.framework` so we can `import` it in Swift sources | |
set_target_properties(logger1 PROPERTIES | |
LINKER_LANGUAGE Swift | |
Swift_LANGUAGE_VERSION 5.4 | |
FRAMEWORK TRUE | |
FRAMEWORK_VERSION A | |
PUBLIC_HEADER "${ifcs};${bridges}" | |
XCODE_ATTRIBUTE_SWIFT_OBJC_BRIDGING_HEADER "${bridges}" # | |
XCODE_ATTRIBUTE_ENABLE_TESTABILITY "YES" # for XCTest | |
) | |
target_include_directories(logger1 PRIVATE | |
${PROJECT_SOURCE_DIR} | |
) | |
target_link_libraries(logger1 PRIVATE | |
logger0 | |
"-framework Foundation" | |
) | |
if(NOT BUILD_TESTING) | |
return() | |
endif() | |
# https://cmake.org/cmake/help/latest/module/FindXCTest.html | |
find_package(XCTest REQUIRED) # XCTest_INCLUDE_DIRS, XCTest_LIBRARIES | |
xctest_add_bundle(test_suite logger1) | |
xctest_add_test(run_test_suite test_suite) | |
target_include_directories(test_suite PRIVATE ${XCTest_INCLUDE_DIRS}) | |
target_link_libraries(test_suite PRIVATE ${XCTest_LIBRARIES}) | |
# Swift sources may need customized compiler/linker option... | |
list(APPEND TEST_SRCS | |
logger_test.swift | |
) | |
set_source_files_properties(${TEST_SRCS} PROPERTIES | |
LANGUAGE Swift | |
COMPILE_OPTIONS "-Wall;-Wextra" | |
LINK_OPTIONS "-Wall" | |
) | |
target_sources(test_suite PRIVATE ${TEST_SRCS}) | |
# installation under CMAKE_INSTALL_PREFIX | |
install(TARGETS logger0 logger1 test_suite | |
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} | |
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} | |
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} | |
FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR} | |
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment