Compare commits

...
Author SHA1 Message Date
John Colvin f1793754c5 scratch: spark clang build check pt 2023-12-15 13:20:17 -05:00
John Colvin 71a54ff4c5 build: Add spark-clang cmake preset
* This is a new preset, so won't break existing/default build
* Now we can use clangd on windows!
2023-12-15 10:38:28 -05:00
John Colvin 5e9abf3c52 fix (win cpp): Link fmt-header-only lib (not shared)
Linking the (shared) fmt lib results in runtime mem access errors
(something about allocations on different heaps?)

TODO: Understand exactly why this error was happening
2023-12-15 10:23:55 -05:00
John Colvin e1edfa5946 Add --verbose flag to spark cli 2023-12-15 10:18:09 -05:00
27 changed files with 256 additions and 46 deletions

No files matched your search

+5
View File
@@ -2,6 +2,10 @@ cmake_minimum_required(VERSION 3.12)
project(spark)
set(CMAKE_CXX_STANDARD 20)
if(MY_TEST_VCPKG)
add_subdirectory(src/lib_system)
add_subdirectory(src/app_tester)
else()
if(WIN32)
set(platform "windows")
else()
@@ -154,3 +158,4 @@ else()
DESTINATION "${SPARK_INSTALL_PREFIX}/bin")
endif()
endif()
endif()
+65
View File
@@ -34,6 +34,42 @@
}
},
{
"name": "spark-clang",
"binaryDir": "${sourceDir}/build/${presetName}",
"generator": "'Ninja Multi-Config'",
"cacheVariables": {
"CMAKE_C_COMPILER": "clang",
"CMAKE_CXX_COMPILER": "clang++",
"CMAKE_EXPORT_COMPILE_COMMANDS": {
"type": "BOOL",
"value": "ON"
},
"CMAKE_CXX_STANDARD": "20",
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/vcpkg/scripts/buildsystems/vcpkg.cmake",
"EXTERNALS_ROOT": "${sourceDir}/externals/windows",
"CONFIG_DEFAULTS_PATH": "config/profiles/default/*.conf",
"DOTNET_BINARY_DIR": "${sourceDir}/build/$<CONFIG>/bin/net7.0",
"DOTNET_WINDOWS_BINARY_DIR": "${sourceDir}/build/$<CONFIG>/bin/net7.0-windows"
}
},
{
"name": "tester",
"generator": "Visual Studio 17 2022",
"binaryDir": "${sourceDir}/build/tester",
"cacheVariables": {
"CMAKE_CXX_STANDARD": "20",
"CMAKE_SHARED_LINKER_FLAGS_DEBUG": "/DEBUG",
"CMAKE_SHARED_LINKER_FLAGS_RELEASE": "/OPT:REF /OPT:ICF /LTCG",
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/vcpkg/scripts/buildsystems/vcpkg.cmake",
"MY_TEST_VCPKG": {
"type": "BOOL",
"value": "ON"
}
}
},
{
"name": "sparkd",
"condition": {
@@ -258,6 +294,35 @@
"configuration": "Release"
},
{
"name": "spark-debug-clang",
"displayName": "Debug (clang)",
"inherits": "spark",
"configurePreset": "spark-clang",
"configuration": "Debug"
},
{
"name": "spark-release-clang",
"displayName": "Release (clang)",
"inherits": "spark",
"configurePreset": "spark-clang",
"configuration": "Release"
},
{
"name": "tester",
"hidden": true
},
{
"name": "tester-debug",
"displayName": "Debug",
"inherits": "tester",
"configurePreset": "tester",
"configuration": "Debug"
},
{
"name": "sparkd",
"condition": {
+8
View File
@@ -0,0 +1,8 @@
function(init_executable source_dir)
file(
GLOB_RECURSE ${PROJECT_NAME}_Sources
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
${source_dir}/*.cpp)
add_executable(${PROJECT_NAME} ${${PROJECT_NAME}_Sources})
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
endfunction(init_executable)
+29
View File
@@ -0,0 +1,29 @@
function(init_library source_dir)
file(
GLOB_RECURSE ${PROJECT_NAME}_Sources
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
${source_dir}/*.cpp)
# Note: cpp files inside 'tests' dir(s) are considered tests.
# Remove tests from main sources, and add them to test sources
set(${PROJECT_NAME}_Test_Sources)
foreach(item ${${PROJECT_NAME}_Sources})
if(${item} MATCHES "tests/*.cpp")
list(REMOVE_ITEM ${PROJECT_NAME}_Sources ${item})
list(APPEND ${PROJECT_NAME}_Test_Sources ${item})
endif()
endforeach()
# Add main library
add_library(${PROJECT_NAME} ${${PROJECT_NAME}_Sources})
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
# Add tests executable (if there are any)
if (${PROJECT_NAME}_Test_Sources)
add_executable(${PROJECT_NAME}-tests ${${PROJECT_NAME}_Test_Sources})
target_link_libraries(${PROJECT_NAME}-tests PRIVATE ${PROJECT_NAME})
# Catch2
find_package(Catch2 CONFIG REQUIRED COMPONENTS Catch2WithMain)
target_link_libraries(${PROJECT_NAME}-tests PRIVATE Catch2::Catch2WithMain)
endif()
endfunction(init_library)
@@ -8,6 +8,6 @@ namespace BCG
public class AddColumnsStream : MapStream
{
public AddColumnsStream(ViewStream vs, string columnDef) : base (vs, new ColumnAdder (columnDef)) {}
public AddColumnsStream(ViewStream vs, string columnDef) : base (vs, default) {}
}
}
}
@@ -104,13 +104,14 @@ namespace BCG {
if (!p.replayed)
return p;
}
else
{
double secondsElapsed = new BinaryReader(myFileReader).ReadDouble();
myNextPacketTime = myPlaybackStart + new TimeSpan(0, 0, 0, 0, (int)(1000 * secondsElapsed / myPlaybackSpeed));
if (onProgress != null)
onProgress(myFileReader.Position, myFileReader.Length);
}
return default;
// else
// {
// double secondsElapsed = new BinaryReader(myFileReader).ReadDouble();
// myNextPacketTime = myPlaybackStart + new TimeSpan(0, 0, 0, 0, (int)(1000 * secondsElapsed / myPlaybackSpeed));
// if (onProgress != null)
// onProgress(myFileReader.Position, myFileReader.Length);
// }
}
#region IWorker Members
@@ -130,7 +131,8 @@ namespace BCG {
_fire_packet(ops, row_array);
curr_packet.replay_timestamp = PersistorStream.epoch_now();
} else {
PlaybackPacket prev_packet = _get_previous_packet(curr_packet);
PlaybackPacket prev_packet = new(0, 0, Array.Empty<byte>());
// PlaybackPacket prev_packet = _get_previous_packet(curr_packet);
// this is the time we need to fire (replay) this packet
long time_to_fire = prev_packet.replay_timestamp + curr_packet.offset_from_previous;
long now_epoch = PersistorStream.epoch_now();
+6
View File
@@ -0,0 +1,6 @@
cmake_minimum_required(VERSION 3.23)
project(bts-tester)
include(${CMAKE_SOURCE_DIR}/cmake/InitExecutable.cmake)
init_executable(tester)
target_link_libraries(${PROJECT_NAME} PUBLIC
bts-system)
+9
View File
@@ -0,0 +1,9 @@
#include "system/foo.h"
#include <string>
int main(int argc, char ** argv) {
bts::system::Foo f{"jules"};
f.say_hello();
return 0;
}
+6 -1
View File
@@ -84,7 +84,12 @@ namespace mbts.ui.shell {
base.OnStartup(e);
_runtime = new ShellBootstrapper(
_opts?.user, _opts?.password, _opts?.sparkd, _opts?.restore_workspace);
_opts?.user,
_opts?.password,
_opts?.sparkd,
_opts?.restore_workspace,
_opts.verbose ? LogLevel.Diag : LogLevel.Warn,
_opts.verbose ? LogLevel.Diag : LogLevel.Info);
_runtime.Run();
// Select text on tab in
+7 -2
View File
@@ -1,4 +1,6 @@
namespace mbts.ui.shell {
using bts;
using mbts.config;
using mbts.ui.extensions;
@@ -23,10 +25,13 @@
string user = null,
string password = null,
string config_source = null,
bool? restore_workspace = null
bool? restore_workspace = null,
LogLevel config_console_log_level = LogLevel.Warn,
LogLevel config_file_log_level = LogLevel.Info
) : base(config_source) {
// Get the LoginModel instance on this thread to make sure it performs syncronous config initialization.
var login_model = LoginModel.init(config_source);
var login_model = LoginModel.init(
config_source, config_console_log_level, config_file_log_level);
// Show the dialog on a background thread so animations aren't blocked during the main application startup
var thread = new Thread(thread_start) {
IsBackground = true,
@@ -42,6 +42,11 @@ namespace Spark.Cli {
[Option(_SPARKD_OPT_NAME, MetaValue = "URL", HelpText = "The config server url")]
public string? sparkd { get; set; }
[Option(
"verbose",
HelpText ="Verbose logging while initializing config (once initialized, the log levels in config are used)")]
public bool verbose { get; set; }
/// <summary>
/// Conform opts to modern cli for backwards compatibility
/// </summary>
@@ -62,14 +62,19 @@ namespace mbts.ui.shell {
static Lazy<LoginModel> _instance;
readonly string _config_source;
readonly LogLevel _config_console_log_level;
readonly LogLevel _config_file_log_level;
private string _workspace;
private PreloginWorkspaceEnumerator _enum_workspace;
ServiceContext _ctx;
DispatcherFrame _frame = new DispatcherFrame();
LoginModel(string config_source) {
LoginModel(
string config_source, LogLevel config_console_log_level, LogLevel config_file_log_level) {
_config_source = config_source;
_config_console_log_level = config_console_log_level;
_config_file_log_level = config_file_log_level;
init().ignore();
}
@@ -84,10 +89,12 @@ namespace mbts.ui.shell {
public bool HasFatalError { get; set; }
public User[] Users { get; private set; }
public static LoginModel init(string config_source) {
public static LoginModel init(
string config_source, LogLevel config_console_log_level, LogLevel config_file_log_level) {
// '_instance' is lazy to guarentee it is only instantiated once
Interlocked.CompareExchange(
ref _instance, new(() => new(config_source)), null);
ref _instance,
new(() => new(config_source, config_console_log_level, config_file_log_level)), null);
return _instance.Value;
}
@@ -119,7 +126,7 @@ namespace mbts.ui.shell {
public async Task<bool> init() {
// Make sure config is initialized and working
try {
Configuration.initialize(_config_source);
Configuration.initialize(_config_source, _config_console_log_level, _config_file_log_level);
} catch (ApplicationException e) {
ErrorMessage = (e.Message ?? string.Empty) + " " + (App.stunnel_job_error ?? string.Empty);
HasFatalError = true;
+1 -1
View File
@@ -28,7 +28,7 @@ namespace bts.api.core {
public static ServiceContext create(string? config_server = null) {
var args = Environment.GetCommandLineArgs();
BTS.init(config_server, args);
BTS.init(config_server, LogLevel.Warn, LogLevel.Info, args);
var qbus = ApiNativeMethods.api_create_quickbus(null, 0);
return new ServiceContext(qbus);
}
@@ -50,14 +50,18 @@ namespace mbts.config {
}
}
public static void initialize(string? config_source = null) {
public static void initialize(
string? config_source = null,
LogLevel config_console_log_level = LogLevel.Warn,
LogLevel config_file_log_level = LogLevel.Info) {
if (_state == State.OK) {
return;
}
var cli_args = Environment.GetCommandLineArgs();
// Considered doing this async on a background thread but it wouldn't do any good. The next
// guy down the line to ask for config will just block until this completes.
try {
BTS.init(config_source);
BTS.init(config_source, config_file_log_level, config_console_log_level, cli_args);
} catch (ApplicationException) {
_state = State.Error;
throw;
+10 -7
View File
@@ -9,17 +9,20 @@ namespace bts
{
static int _needs_init_spark_lib = 0;
public static void init(string config_source = null) {
var args = Environment.GetCommandLineArgs();
init(config_source, args);
}
public static void init(string config_source = null, params string[] args) {
public static void init(
string config_source = null,
LogLevel console_log_level = LogLevel.Warn,
LogLevel file_log_level = LogLevel.Info,
params string[] args) {
utils.BTSNativeMethods.provide_command_line(args, args.Length);
var buffer = new StringBuilder(4096);
bool config_ok = utils.BTSNativeMethods.initialize_nothrow(
config_source ?? string.Empty, buffer, buffer.Capacity);
config_source ?? string.Empty,
buffer,
buffer.Capacity,
(short)console_log_level,
(short)file_log_level);
if (!config_ok) {
throw new ApplicationException(buffer.ToString());
}
@@ -27,6 +27,10 @@ namespace bts.utils
[DllImport("libspark")]
public static extern bool initialize_nothrow(
string config_source, StringBuilder buffer, int length);
string config_source,
StringBuilder buffer,
int length,
short console_log_level,
short file_log_level);
}
}
+1 -1
View File
@@ -37,7 +37,7 @@ CAPI Quickbus *api_create_quickbus(const char *qbconfig, long length) {
// If config hasn't been initialized yet do it now and suppress exceptions.
// When we're called from a nuget package we may not have defaults which can
// cause errors
config::initialize_nothrow("", nullptr, 0);
config::initialize_nothrow("", nullptr, 0, bts::Warn.ordinal, bts::Info.ordinal);
config::QuickbusNodeCfg cfg;
if (length > 0 && qbconfig != nullptr &&
@@ -2,7 +2,7 @@ function(get_link_libraries dest)
find_package(fmt CONFIG REQUIRED)
set(${dest}
crypt32
fmt::fmt
fmt::fmt-header-only
libcrypto
libcurl
libboost_system
+7 -5
View File
@@ -15,7 +15,9 @@ namespace internal {
// To allow config diagnostic logging
class ConfigLog {
public:
ConfigLog();
explicit ConfigLog(
bts::log::Level console_log_level = bts::Warn,
bts::log::Level file_log_level = bts::Info);
~ConfigLog();
void info(const std::string &msg);
@@ -50,7 +52,7 @@ class ConfigLog {
// Definition
//////////////////////////////////////////////////
inline ConfigLog::ConfigLog()
inline ConfigLog::ConfigLog(bts::log::Level console_log_level, bts::log::Level file_log_level)
: print_errors_(true), logger_hub_("config_logger"),
logger_(logger_hub_.make_logger()) {
log::LoggingConfig cfg;
@@ -66,9 +68,9 @@ inline ConfigLog::ConfigLog()
}
cfg.deployment_type = "Config";
f[log::Cfg.ordinal] = Warn;
f[log::Cfg.ordinal] = console_log_level;
cfg.sinks["console"] = std::make_pair(log::console_sink(cfg), f);
f[log::Cfg.ordinal] = Info;
f[log::Cfg.ordinal] = file_log_level;
cfg.sinks["syslog"] = std::make_pair(log::syslog_sink(cfg), f);
logger_hub_.config(cfg);
@@ -126,7 +128,7 @@ inline bool ConfigLog::enqueue(
return false;
}
return logger_.enqueue(
log::log_ts(), log::Cfg, level, file, line, msg_template, msg_args...);
log::log_ts(), log::Cfg, level, file, line, msg_template, std::move(msg_args)...);
}
} // namespace internal
+2 -1
View File
@@ -97,7 +97,8 @@ void run_config_query(
void ConfigQuerier::init_(bool verbose) {
char buffer[4096] = {0};
utils::TimeStamp start = utils::TimeStamp::now();
bool success = config::initialize_nothrow("", buffer, sizeof(buffer));
bool success = config::initialize_nothrow(
"", buffer, sizeof(buffer), bts::Warn.ordinal, bts::Info.ordinal);
double time = (utils::TimeStamp::now() - start).seconds();
if (success) {
+4 -3
View File
@@ -362,7 +362,7 @@ void check_rule(
}
void ConfigurationState::check_rules() {
initialize("");
initialize("", bts::Warn.ordinal, bts::Info.ordinal);
std::vector<std::shared_ptr<proto::Message>>::iterator iter;
for (iter = _config_chain.begin(); iter != _config_chain.end(); ++iter) {
proto::Message *message = (*iter).get();
@@ -371,12 +371,13 @@ void ConfigurationState::check_rules() {
check_rule(_defaults.get(), _rule_engine);
}
void ConfigurationState::initialize_settings(string config_source) {
void ConfigurationState::initialize_settings(
string config_source, bts::log::Level console_log_level, bts::log::Level file_log_level) {
std::lock_guard<std::recursive_mutex> lock(_initialization_mutex);
if (_is_initialized)
return;
ConfigLog log;
ConfigLog log{console_log_level, file_log_level};
CFG_LOG(log, Info, "Initializing settings from '{}'", config_source);
// For verbose config logs, uncomment line below
// log.set_print_errors(true);
+4 -1
View File
@@ -60,7 +60,10 @@ class ConfigurationState {
* @param config_source The source from which to load values. Can be a path
* (file or dir), or URL (config server).
*/
void initialize_settings(std::string config_source = "");
void initialize_settings(
std::string config_source = "",
bts::log::Level console_log_level = bts::Warn,
bts::log::Level file_log_level = bts::Info);
int load(const std::string &url, ConfigLog &);
int load_string(const std::string &values, bool print_errors = false);
+14 -4
View File
@@ -27,14 +27,24 @@ internal::ConfigurationState config_state;
// Public API
//////////////////////////////////////////
extern "C" BTS_EXPORT void initialize(const char *config_source) {
config_state.initialize_settings(string{config_source});
extern "C" BTS_EXPORT void initialize(
const char *config_source,
std::int16_t console_log_level,
std::int16_t file_log_level) {
config_state.initialize_settings(
string{config_source},
bts::log::Level{static_cast<std::uint8_t>(console_log_level)},
bts::log::Level{static_cast<std::uint8_t>(file_log_level)});
}
extern "C" BTS_EXPORT bool initialize_nothrow(
const char *config_source, char *error_message, size_t len) {
const char *config_source,
char *error_message,
size_t len,
std::int16_t console_log_level,
std::int16_t file_log_level) {
try {
initialize(config_source);
initialize(config_source, console_log_level, file_log_level);
} catch (std::exception &e) {
std::string msg = e.what();
if (msg.size() < len) {
+9 -2
View File
@@ -27,12 +27,19 @@ namespace config {
// config can result in network requests this function is available for
// applications that want to manage pauses in execution. Ex: initialize() on a
// background thread so that config::get<T>() is fast on a UI thread
extern "C" BTS_EXPORT void initialize(const char *config_path);
extern "C" BTS_EXPORT void initialize(
const char *config_path,
std::int16_t console_log_level,
std::int16_t file_log_level);
// Calls initialize() but catches any thrown exception and copies it to the
// provided buffer
extern "C" BTS_EXPORT bool initialize_nothrow(
const char *config_source, char *error_msg, size_t length);
const char *config_source,
char *error_msg,
size_t length,
std::int16_t console_log_level,
std::int16_t file_log_level);
std::vector<const google::protobuf::FieldDescriptor *> get_fields(
const std::vector<std::string> keys = {},
+8
View File
@@ -0,0 +1,8 @@
cmake_minimum_required(VERSION 3.23)
project(bts-system)
include(${CMAKE_SOURCE_DIR}/cmake/InitLibrary.cmake)
init_library(system)
# fmt
find_package(fmt CONFIG REQUIRED)
target_link_libraries(${PROJECT_NAME} PUBLIC fmt::fmt)
+8
View File
@@ -0,0 +1,8 @@
#include "foo.h"
#include <fmt/format.h>
namespace bts::system {
void Foo:: say_hello() {
std::cout << fmt::format("Hi, my name is {}", name) << std::endl;
}
}
+13
View File
@@ -0,0 +1,13 @@
#pragma once
#include <iostream>
#include <string>
namespace bts::system {
struct Foo {
std::string name;
void say_hello();
};
}