Skip to content

Commit

Permalink
refactor: remove atclient_atsign, atclient_atstr, refactor a bunc…
Browse files Browse the repository at this point in the history
…h of function signatures (#337)

* fix: atkey compound namespacing

* test: test_atclient_atkey_from_string

* feat: /scan in repl

* chore: atclient_get_atkeys debugging logging

* feat: repl /deleteall command

* refactor: atclient_atkey_metadata_to_protocol_str

* wip: aes_ctr expected strlen/size

* fix: metadata

* chore: optimize atclient_put

* fix: test_atkey_metadata

* docs: atclient_put

* feat: atclient_put args check function

* refactor: atclient_atkey_to_string

* fix: examples that use atclient_atkey_to_string

* fix: events errors

* fix: functional test error

* fix: repl errors

* chore: remove logging

* chore:

* fix:

* fix:

* feat: optimize and clean atclient_put

* refactor: atclient_get_sharedkey

* fix: atclient_put

* docs: atclient_put

* chore: delete atbytes.c and atstr.c

* chore: delete atbytes.h and atstr.h

* chore: remove atstr from get_sharedkey example

* chore: remove unused function in connection.c

* revert: "docs: atclient_put"

This reverts commit 126efad.

* revert: "revert: "docs: atclient_put""

This reverts commit 5287e4a.

* revert: "chore: delete atbytes.h and atstr.h"

This reverts commit 6e6c1fc.

* revert: "chore: delete atbytes.c and atstr.c"

This reverts commit 23fb412.

* chore: remove unused atkeysfile function

* refactor: metadata.h string to char *

* refactor: use char * and remove atstr in atclient_delete.c

* revert: "refactor: metadata.h string to char *"

This reverts commit 2582759.

* fix: atclient_delete

* chore: clean up atclient_delete.c

* feat: handle malloc == null

* fix: unit test failure

* feat: cleaned up atclient_get_publickey.c

* chore: cleaned up atclient_get_atkeys.c

* feat: optimize and clean up atclient_pkam_authenticate

* fix: failing test

* feat: remove strlen from atclient_atsign_without/with_at_symbol

* chore: remove `symbol` from function name

* wip:

* wip:

* fix: failing tests in test_atkey_create.c

* fix: test_atkey_from_string failing tests

* feat: update void returns to int in metadata.h/.c

* fix: failing tests in test_atkey_to_string.c

* fix: include stdint.h

* fix:

* chore: clean up atclient_get_publickey

* chore: clean up atclient_get_selfkey.c

* chore: clean up atchops/rsa.c

* chore: format base64.h

* docs: iv.h

* feat: made rsakey.c/.h more memory efficient

* fix: rsa public key unit test failure

* fix: atkey.c label error

* chore: clean up aesctr.h/.c

* chore: make iv.h/.c more minimal

* chore: clean up test_iv.c

* fix: functional tests helpers.c

* fix: at_talk compilation errors

* fix: crud examples compilation errors

* fix:

* fix: functional tests compilation errors

* chore: clean up test_stringutils.c

* fix: atclient_get_selfkey_valid_arguments

* feat: remove atclient_atstr from atclient_atkey_metadata

* feat: more atclient_atkey_metadata refactors

* chore: made atclient_atkey_metadata_from_jsonstr return `int` (originally `void`) because it is error prone

* fix: crud example

* chore: remove isHidden

* feat: atkeys.h/.c initializedfields

* feat: remove atclient_atstr from atkeysfile.h/.c

* fix:

* docs: log messages

* chore: delete unused atstr.h/.c and atbytes.h/.c

* fix: remove atbytes.c and atstr.c from CMakeLists.txt

* fix: atkey.c incorrect bool polarity

* fix: remove atstr.h includes

* fix:

* chore: format monitor.h

* feat: atkeys.c/.h public setters

* feat: more refactors and public facing bool checker functions

* chore: clean up test_atkey_from_string.c

* feat: remove atclient_atsign usages

* fix:

* fix:

* chore: clean up atclient_get_sharedkey

* wip: cleaning up encryption_key_helpers

* feat: cleaned up encryption_key_helpers

* fix:

* fix:

* fix:

* fix:

* fix: crud example

* fix: repl example

* feat: atclient_delete now returns commit_id

* fix: typo

* fix: typo

* refactor: metadata symbolic constants

* refactor: header symbolic constants

* refactor: extract atnotification to its own files and rename monitor message to "atclient_monitor_response"

* feat: atnotification.h/.c and notify_params.h/.c

* fix: examples

* fix:

* chore: snake case

* fix: syntax errors

* fix:

* fix:

* fix:

* fix:

* fix:

* feat: more error handling in aesctr

* fix:

* refactor: atclient_stringutils_long_strlen

* refactor: set shared_encryption_key

* chore: atchops refactors

* fix:

* chore: delete atsign.c/.h

* feat: request_options.c/.h

* chore: remove sys/time.h from notify.c

* feat: start on atclient_connection_read/write

* feat: update atclient_delete

* feat: make crud operations camel case and separate atclient_put into 3

* fix: failing tests

* fix: updated CMakeLists.txt

* fix:

* fix: examples

* fix: self key

* fix: warnings

* fix:

* fix:

* fix:

* fix:

* fix:

* fix:

* feat: free things

* feat: free more stuff

* refactor: public_key

* test: debug CI

* ci:

* ci:

* ci:

* chore:

* fix:

* fix:

* feat: function signature atclient_get_atkeys

* ci: remove debug temp

* fix: repl example

* refactor: atclient_get_shared_key

* refactor:

* feat: atclient_get_public_key new function signature

* fix:

* fix:

* fix:

* fix:

* feat: atclient_get_self_key new function signature

* fix: repl example

* fix: test

* fix: crud example

* fix:

* feat: connection_hooks.h/.c

* fix: atclient_connection_free

* fix:

* fix:

* feat: connection_hooks example

* fix: sample_cmake_project CI

* fix:

* fix:

* feat: remove readonly_src

* fix:

* feat: atchops/mbedtls.h, atclient/mbedtls.h, atclient/cjson.h

* fix:

* refactor: atclient_monitor_response_init/free, remove hooks from atclient_monitor_read, and made atclient_notify_params const in atclient_notify function signature

* fix: examples

* chore:

* docs: base64.h

* chore: remove generic atclient_put

* feat: more request options

* chore: delete atclient_put.c

* chore: add atclient_monitor_read hooks back

* fix: request_options stuff

* chore: move constants

* chore: remove regexlen from atclient_monitor_start

* fix: examples

* fix:
  • Loading branch information
JeremyTubongbanua authored Jul 30, 2024
1 parent a5f0ff9 commit c478d28
Show file tree
Hide file tree
Showing 124 changed files with 15,585 additions and 7,758 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build_source_tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,5 @@ jobs:
- name: Run sample_cmake_project executable
working-directory: examples/desktop/sample_cmake_project
run: |
./build/exec
./build/main
2 changes: 1 addition & 1 deletion .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ jobs:
- name: Run sample_cmake_project executable
working-directory: examples/desktop/sample_cmake_project
run: |
./build/exec
./build/main
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@afb54ba388a7dca6ecae48f608c4ff05ff4cc77a # v3.25.15
Expand Down
44 changes: 29 additions & 15 deletions examples/desktop/at_talk/src/main.c
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
#include <atchops/aes.h>
#include <atchops/aesctr.h>
#include <atchops/aes_ctr.h>
#include <atchops/base64.h>
#include <atchops/iv.h>
#include <atclient/atclient.h>
#include <atclient/atclient_utils.h>
#include <atclient/atkeysfile.h>
#include <atclient/atsign.h>
#include <atclient/constants.h>
#include <atclient/encryption_key_helpers.h>
#include <atclient/monitor.h>
Expand Down Expand Up @@ -152,14 +151,29 @@ int main(int argc, char *argv[]) {
atclient_atkey atkey;
atclient_atkey_init(&atkey);

if ((ret = atclient_atkey_create_sharedkey(&atkey, ATKEY_NAME, strlen(ATKEY_NAME), from_atsign, strlen(from_atsign),
to_atsign, strlen(to_atsign), ATKEY_NAMESPACE,
strlen(ATKEY_NAMESPACE))) != 0) {
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "atclient_atkey_create_sharedkey: %d\n", ret);
if ((ret = atclient_atkey_create_shared_key(&atkey, ATKEY_NAME, from_atsign, to_atsign, ATKEY_NAMESPACE)) != 0) {
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "atclient_atkey_create_shared_key: %d\n", ret);
}

atclient_notify_params_create(&params, ATCLIENT_NOTIFY_OPERATION_UPDATE, &atkey, line, true);
params.notification_expiry = 5000;
if((ret = atclient_notify_params_set_operation(&params, ATCLIENT_NOTIFY_OPERATION_UPDATE)) != 0) {
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "atclient_notify_params_set_operation: %d\n", ret);
}

if((ret = atclient_notify_params_set_atkey(&params, &atkey)) != 0) {
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "atclient_notify_params_set_atkey: %d\n", ret);
}

if((ret = atclient_notify_params_set_value(&params, line)) != 0) {
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "atclient_notify_params_set_value: %d\n", ret);
}

if((ret = atclient_notify_params_set_should_encrypt(&params, true)) != 0) {
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "atclient_notify_params_set_should_encrypt: %d\n", ret);
}

if((ret = atclient_notify_params_set_notification_expiry(&params, 5000)) != 0) {
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "atclient_notify_params_set_notification_expiry: %d\n", ret);
}

pthread_mutex_lock(&client_mutex);
if ((ret = atclient_notify(&atclient1, &params, NULL)) != 0) {
Expand Down Expand Up @@ -236,7 +250,7 @@ static void *monitor_handler(void *xargs) {
goto exit;
}
atclient_monitor_set_read_timeout(monitor, READ_TIMEOUT); // blocking read takes 1 second to timeout
if ((ret = atclient_monitor_start(monitor, MONITOR_REGEX, strlen(MONITOR_REGEX))) != 0) {
if ((ret = atclient_monitor_start(monitor, MONITOR_REGEX)) != 0) {
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to start monitor: %d\n", ret);
goto exit;
}
Expand All @@ -245,8 +259,8 @@ static void *monitor_handler(void *xargs) {
int tries = 1;

while (true) {
atclient_monitor_message message;
atclient_monitor_message_init(&message);
atclient_monitor_response message;
atclient_monitor_response_init(&message);

pthread_mutex_lock(&monitor_mutex);
pthread_mutex_lock(&client_mutex);
Expand All @@ -260,9 +274,9 @@ static void *monitor_handler(void *xargs) {
// We received a stats notification. Ignore it.
break;
}
if (atclient_atnotification_decryptedvalue_is_initialized(&(message.notification))) {
if (atclient_atnotification_is_decrypted_value_initialized(&(message.notification))) {
const atclient_atnotification *notification = &(message.notification);
printf("\n%s%s%s: %s\n", HGRN, notification->from, reset, notification->decryptedvalue);
printf("\n%s%s%s: %s\n", HGRN, notification->from, reset, notification->decrypted_value);
printf("%s%s%s: ", HBLU, from_atsign, reset);
fflush(stdout);
}
Expand Down Expand Up @@ -320,7 +334,7 @@ static void *monitor_handler(void *xargs) {
}
}

atclient_monitor_message_free(&message);
atclient_monitor_response_free(&message);
usleep(100);
}
goto exit;
Expand Down Expand Up @@ -358,7 +372,7 @@ static int reconnect_clients(atclient *monitor, atclient *ctx, const char *atser
* 3. Start monitor
*/
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_DEBUG, "Restarting monitor...\n");
if ((ret = atclient_monitor_start(monitor, MONITOR_REGEX, strlen(MONITOR_REGEX))) != 0) {
if ((ret = atclient_monitor_start(monitor, MONITOR_REGEX)) != 0) {
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to start monitor: %d\n", ret);
return ret;
}
Expand Down
2 changes: 2 additions & 0 deletions examples/desktop/connection_hooks/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/*build*/
/*bin*/
10 changes: 10 additions & 0 deletions examples/desktop/connection_hooks/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
cmake_minimum_required(VERSION 3.24)

project(temp)

find_package(atsdk REQUIRED)

add_executable(main ${CMAKE_CURRENT_LIST_DIR}/main.c)
target_link_libraries(main atsdk::atclient)

install(TARGETS main DESTINATION ${CMAKE_CURRENT_LIST_DIR}/bin)
186 changes: 186 additions & 0 deletions examples/desktop/connection_hooks/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
#include <atclient/connection.h>
#include <atclient/connection_hooks.h>
#include <atlogger/atlogger.h>
#include <string.h>
#include <stdlib.h>

#define TAG "main"

#define HOST "3b419d7a-2fee-5080-9289-f0e1853abb47.swarm0002.atsign.zone"
#define PORT 5770

void *pre_read_hook(atclient_connection_hook_params *params) {
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_INFO, "pre_read_hook was called\n");
// log params
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_DEBUG, "src (%p): \"%s\"\n", params->recv, (char *)params->src);
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_DEBUG, "src_len: %d\n", params->src_len);
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_DEBUG, "recv (%p): %s\n", params->recv, (char *)params->recv);
if (params->recv_len != NULL) {
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_DEBUG, "recv_len: %d\n", *params->recv_len);
} else {
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_DEBUG, "recv_len: NULL\n");
}
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_DEBUG, "recv_size: %d\n", params->recv_size);
return NULL;
}

void *post_read_hook(atclient_connection_hook_params *params) {
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_INFO, "post_read_hook was called\n");
// log params
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_DEBUG, "src (%p): \"%s\"\n", params->recv, (char *)params->src);
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_DEBUG, "src_len: %d\n", params->src_len);
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_DEBUG, "recv (%p): %s\n", params->recv, (char *)params->recv);
if (params->recv_len != NULL) {
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_DEBUG, "recv_len: %d\n", *params->recv_len);
} else {
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_DEBUG, "recv_len: NULL\n");
}
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_DEBUG, "recv_size: %d\n", params->recv_size);

return NULL;
}

void *pre_write_hook(atclient_connection_hook_params *params) {
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_INFO, "pre_write_hook was called\n");
// log params
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_DEBUG, "src (%p): \"%s\"\n", params->recv, (char *)params->src);
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_DEBUG, "src_len: %d\n", params->src_len);
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_DEBUG, "recv (%p): %s\n", params->recv, (char *)params->recv);
if (params->recv_len != NULL) {
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_DEBUG, "recv_len: %d\n", *params->recv_len);
} else {
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_DEBUG, "recv_len: NULL\n");
}
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_DEBUG, "recv_size: %d\n", params->recv_size);
return NULL;
}

void *post_write_hook(atclient_connection_hook_params *params) {
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_INFO, "post_write_hook was called\n");
// log params
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_DEBUG, "src (%p): \"%s\"\n", params->recv, (char *)params->src);
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_DEBUG, "src_len: %d\n", params->src_len);
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_DEBUG, "recv (%p): %s\n", params->recv, (char *)params->recv);
if (params->recv_len != NULL) {
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_DEBUG, "recv_len: %d\n", *params->recv_len);
} else {
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_DEBUG, "recv_len: NULL\n");
}
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_DEBUG, "recv_size: %d\n", params->recv_size);
return NULL;
}

int main(int argc, char *argv[]) {
int ret = 1;

atlogger_set_logging_level(ATLOGGER_LOGGING_LEVEL_DEBUG);

atclient_connection conn;
atclient_connection_init(&conn, ATCLIENT_CONNECTION_TYPE_ATSERVER);

const unsigned char *src = (const unsigned char *) "from:12alpaca\r\n";
const size_t src_len = strlen((char *) src);
unsigned char *recv = NULL;
size_t recv_len = 0;

if ((ret = atclient_connection_hooks_enable(&conn)) != 0) {
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to enable hooks\n");
goto exit;
}
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_INFO, "Enabled hooks\n");

if ((ret = atclient_connection_hooks_set(&conn, ATCLIENT_CONNECTION_HOOK_TYPE_PRE_READ, pre_read_hook)) != 0) {
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to set pre_read hook\n");
goto exit;
}
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_INFO, "Set pre_read_hook successfully\n");

if ((ret = atclient_connection_hooks_set(&conn, ATCLIENT_CONNECTION_HOOK_TYPE_POST_READ, post_read_hook)) != 0) {
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to set post_read hook\n");
goto exit;
}
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_INFO, "Set post_read_hook successfully\n");

if ((ret = atclient_connection_hooks_set(&conn, ATCLIENT_CONNECTION_HOOK_TYPE_PRE_WRITE, pre_write_hook)) != 0) {
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to set pre_write hook\n");
goto exit;
}
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_INFO, "Set pre_write_hook successfully\n");

if ((ret = atclient_connection_hooks_set(&conn, ATCLIENT_CONNECTION_HOOK_TYPE_POST_WRITE, post_write_hook)) != 0) {
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to set post_write hook\n");
goto exit;
}
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_INFO, "Set post_write_hook successfully\n");

if ((ret = atclient_connection_connect(&conn, HOST, PORT)) != 0) {
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to connect to %s:%d\n", HOST, PORT);
goto exit;
}
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_INFO, "Connected to %s:%d\n", HOST, PORT);

if ((ret = atclient_connection_write(&conn, (const unsigned char *)src, src_len)) != 0) {
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to write to %s:%d\n", HOST, PORT);
goto exit;
}

if ((ret = atclient_connection_write(&conn, (const unsigned char *)src, src_len)) != 0) {
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to write to %s:%d\n", HOST, PORT);
goto exit;
}

if ((ret = atclient_connection_read(&conn, &recv, &recv_len, 20)) != 0) {
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to read from %s:%d\n", HOST, PORT);
goto exit;
}
free(recv);
recv = NULL;

if ((ret = atclient_connection_read(&conn, &recv, &recv_len, 20)) != 0) {
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to read from %s:%d\n", HOST, PORT);
goto exit;
}
free(recv);
recv = NULL;

if ((ret = atclient_connection_read(&conn, &recv, &recv_len, 20)) != 0) {
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to read from %s:%d\n", HOST, PORT);
goto exit;
}
free(recv);
recv = NULL;

if ((ret = atclient_connection_read(&conn, &recv, &recv_len, 0)) != 0) {
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to read from %s:%d\n", HOST, PORT);
goto exit;
}
free(recv);
recv = NULL;

size_t recv_size = 4096;
recv = malloc(sizeof(unsigned char) * recv_size);
if(recv == NULL) {
ret = 1;
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to malloc\n");
goto exit;
}

if((ret = atclient_connection_send(&conn, src, src_len, recv, recv_size, &recv_len)) != 0) {
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "atclient_connection_send: %d\n", ret);
goto exit;
}

if ((ret = atclient_connection_disconnect(&conn)) != 0) {
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to disconnect from %s:%d\n", HOST, PORT);
goto exit;
}
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_INFO, "Disconnected from %s:%d\n", HOST, PORT);

ret = 0;
goto exit;
exit: {
free(recv);
atclient_connection_free(&conn);
return ret;
}
}
25 changes: 25 additions & 0 deletions examples/desktop/connection_hooks/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/bin/bash
set -eu

# Clean
rm -f build/CMakeCache.txt
rm -f bin/main

# Install dependencies
FULL_PATH_TO_SCRIPT="$(realpath "${BASH_SOURCE[0]}")"
SCRIPT_DIRECTORY="$(dirname "$FULL_PATH_TO_SCRIPT")"

# Install atsdk
"$SCRIPT_DIRECTORY/../../../tools/install.sh"

# Build
cd "$SCRIPT_DIRECTORY"

## CMake configure
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug

## CMake build
cmake --build build --target install

# Run
./bin/main $@
Loading

0 comments on commit c478d28

Please sign in to comment.