create new project

This commit is contained in:
falsycat 2023-11-24 00:07:31 +09:00
parent e55f035f80
commit 53612d9456
16 changed files with 465 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build*/

53
CMakeLists.txt Normal file
View File

@ -0,0 +1,53 @@
cmake_minimum_required(VERSION 3.27)
project(nf7 C)
set(CMAKE_C_STANDARD 23)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
include(tool/meta.cmake)
# ---- thirdparty import
add_subdirectory(thirdparty EXCLUDE_FROM_ALL)
# ---- generation
include(tool/meta.cmake)
# ---- common config
add_library(nf7config INTERFACE)
target_include_directories(nf7config
INTERFACE
${PROJECT_SOURCE_DIR}
${NF7_GENERATED_DIR}
)
target_compile_options(nf7config INTERFACE
$<$<CXX_COMPILER_ID:MSVC>:
/W4
$<$<CONFIG:Debug>:/WX>
>
$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:
-Wall -Wextra -Wpedantic
$<$<CONFIG:Debug>:-Werror>
>
)
# ---- util library
add_subdirectory(util)
# ---- interface library
add_library(nf7if INTERFACE)
target_sources(nf7if INTERFACE nf7.h)
target_link_libraries(nf7if INTERFACE nf7config nf7util uv)
# ---- core library
add_subdirectory(core)
# ---- main executable
add_executable(nf7)
target_sources(nf7 PRIVATE main.c)
target_link_libraries(nf7
PRIVATE
nf7if
nf7core
)

19
README.md Normal file
View File

@ -0,0 +1,19 @@
Nf7
====
Nf7 is an abstraction layer for Media-programming.
The goal is to allow creative activities on any platforms without any differences.
**UNDER REFACTORING:** Please checkout tag v0.4.1 to see a codebase which works.
## Build
```bash
$ cmake -B build
$ cmake --build build -j4
```
## License
WTFPLv2

19
core/CMakeLists.txt Normal file
View File

@ -0,0 +1,19 @@
# ---- basic modules
set(MODS
sdl2
)
# ---- core library
add_library(nf7core)
target_link_libraries(nf7core PRIVATE nf7if)
foreach(name IN LISTS MODS)
add_subdirectory(${name})
target_link_libraries(nf7core PRIVATE nf7core_${name})
endforeach()
# ---- generate all.h
target_meta_source(nf7core
PRIVATE all.c.sh
ARGS ${MODS}
)

25
core/all.c.sh Executable file
View File

@ -0,0 +1,25 @@
#!/bin/bash
echo "#include \"core/all.h\""
echo
echo "#include <assert.h>"
echo
echo "const uint32_t NF7_CORE_MAX_MODS = UINT32_C($#);"
echo
echo "uint32_t nf7_core_new(const struct nf7* nf7, struct nf7_mod** mods) {"
echo " assert(nullptr != nf7);"
echo " assert(nullptr != mods);"
echo
echo " uint32_t i = 0;"
echo
for name in $@; do
echo " extern struct nf7_mod* nf7_core_${name}_new(const struct nf7*);"
echo " mods[i] = nf7_core_${name}_new(nf7);"
echo " if (nullptr != mods[i]) {"
echo " assert(nullptr != mods[i]->meta);"
echo " ++i;"
echo " }"
echo
done
echo " return i;"
echo "}"

20
core/all.h Normal file
View File

@ -0,0 +1,20 @@
#pragma once
#include <stdint.h>
#include "nf7.h"
// A maximum number of modules which nf7core may provide.
extern const uint32_t NF7_CORE_MAX_MODS;
// Initializes all modules and returns their instances.
uint32_t nf7_core_new(const struct nf7* nf7, struct nf7_mod** mods);
// PRECONDS:
// - `nf7` is a valid pointer
// - `mods` is a valid pointer
// to memory large enough to keep `NF7_CORE_MAX_MODS` pointers
// POSTCONDS:
// - When x is lower than the return value,
// mods[x] is a valid pointer to an initialized module

12
core/sdl2/CMakeLists.txt Normal file
View File

@ -0,0 +1,12 @@
add_library(nf7core_sdl2)
target_sources(nf7core_sdl2
PRIVATE
mod.c
)
target_link_libraries(nf7core_sdl2
PRIVATE
nf7if
nf7util
OpenGL
SDL2
)

43
core/sdl2/mod.c Normal file
View File

@ -0,0 +1,43 @@
// No copyright
#include "core/sdl2/mod.h"
#include <assert.h>
#include <stdio.h>
#include "nf7.h"
#include "util/malloc.h"
struct nf7_mod* nf7_core_sdl2_new(const struct nf7* nf7) {
assert(nullptr != nf7);
struct nf7_core_sdl2* this = nf7_util_malloc_new(nf7->malloc, sizeof(*this));
if (nullptr == this) {
return nullptr;
}
*this = (struct nf7_core_sdl2) {
.meta = &nf7_core_sdl2,
.nf7 = nf7,
.malloc = nf7->malloc,
.uv = nf7->uv,
};
return (struct nf7_mod*) this;
}
static void del_(struct nf7_mod* this_) {
struct nf7_core_sdl2* this = (struct nf7_core_sdl2*) this_;
assert(nullptr != this);
nf7_util_malloc_del(this->malloc, this);
}
const struct nf7_mod_meta nf7_core_sdl2 = {
.name = (const uint8_t*) "nf7core_sdl2",
.desc = (const uint8_t*) "provides SDL2 features",
.ver = 0,
.delete = del_,
};

21
core/sdl2/mod.h Normal file
View File

@ -0,0 +1,21 @@
// No copyright
#pragma once
#include <SDL.h>
#include <uv.h>
#include "nf7.h"
#include "util/malloc.h"
extern const struct nf7_mod_meta nf7_core_sdl2;
struct nf7_core_sdl2 {
const struct nf7_mod_meta* meta;
const struct nf7* nf7;
struct nf7_util_malloc* malloc;
uv_loop_t* uv;
SDL_Window* win;
};

59
main.c Normal file
View File

@ -0,0 +1,59 @@
// No copyright
#include <stdatomic.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <uv.h>
#include "nf7.h"
#include "core/all.h"
static void cb_close_all_handles_(uv_handle_t*, void*);
int main(int argc, char** argv) {
// init loop
uv_loop_t uv;
if (0 != uv_loop_init(&uv)) {
return EXIT_FAILURE;
}
struct nf7 nf7 = {
.ver = 0,
.argc = argc,
.argv = (const char* const*) argv,
.uv = &uv,
};
// load modules
struct nf7_mod* nf7_mods[NF7_CORE_MAX_MODS];
nf7.mods.n = nf7_core_new(&nf7, nf7_mods);
nf7.mods.ptr = nf7_mods;
// main loop
if (0 != uv_run(&uv, UV_RUN_DEFAULT)) {
return EXIT_FAILURE;
}
// destroy modules
for (uint32_t i = 0; i < nf7.mods.n; ++i) {
struct nf7_mod* mod = nf7.mods.ptr[i];
if (nullptr != mod->meta->delete) {
mod->meta->delete(mod);
}
}
// teardown loop
uv_walk(&uv, cb_close_all_handles_, nullptr);
uv_run(&uv, UV_RUN_DEFAULT);
if (0 != uv_loop_close(&uv)) {
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
static void cb_close_all_handles_(uv_handle_t* handle, void*) {
uv_close(handle, nullptr);
}

42
nf7.h Normal file
View File

@ -0,0 +1,42 @@
// No copyright
#pragma once
#include <stdint.h>
#include <uv.h>
#include "util/malloc.h"
struct nf7;
struct nf7_mod;
struct nf7_mod_meta;
struct nf7 {
uint32_t ver;
uint32_t argc;
const char* const* argv;
uv_loop_t* uv;
struct nf7_util_malloc* malloc;
struct {
uint32_t n;
struct nf7_mod** ptr;
} mods;
};
struct nf7_mod {
const struct nf7_mod_meta* meta;
};
struct nf7_mod_meta {
const uint8_t* name;
const uint8_t* desc;
uint32_t ver;
void (*delete)(struct nf7_mod*);
void (*push_lua)(struct nf7_mod*);
};

18
thirdparty/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,18 @@
include(FetchContent)
# ---- libuv (MIT)
FetchContent_Declare(
libuv
GIT_REPOSITORY https://github.com/libuv/libuv.git
GIT_TAG v1.47.0
)
FetchContent_MakeAvailable(libuv)
# ---- OpenGL
find_package(OpenGL REQUIRED GLOBAL)
add_library(OpenGL ALIAS OpenGL::GL)
# ---- SDL2 (zlib)
find_package(SDL2 REQUIRED GLOBAL)
add_library(SDL2 ALIAS SDL2::SDL2)

44
tool/meta.cmake Normal file
View File

@ -0,0 +1,44 @@
# No copyright
# This function adds a custom command to execute ${args_src} and adds its output
# to sources of ${args_target} with a scope ${args_scope}
function(target_meta_source args_target args_scope args_src)
cmake_parse_arguments(args
""
""
"ARGS;DEPENDS"
${ARGN}
)
if (IS_ABSOLUTE "${args_src}")
set(src_abs "${args_src}")
else()
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${args_src}")
set(src_abs "${CMAKE_CURRENT_SOURCE_DIR}/${args_src}")
elseif(EXISTS "${CMAKE_CURRENT_BINARY_DIR}/${args_src}")
set(src_abs "${CMAKE_CURRENT_BINARY_DIR}/${args_src}")
else()
message(FATAL_ERROR "no source file found: ${args_src}")
endif()
endif()
get_filename_component(src_ext "${src_abs}" LAST_EXT)
get_filename_component(src_name "${src_abs}" NAME)
string(REGEX REPLACE "${src_ext}$" "" dst_name "${src_name}")
get_filename_component(src_dir_abs "${src_abs}" DIRECTORY)
string(REGEX REPLACE "^${CMAKE_SOURCE_DIR}/" "" src_dir "${src_dir_abs}")
set(dst_dir_abs "${CMAKE_BINARY_DIR}/generated/${src_dir}")
file(MAKE_DIRECTORY "${dst_dir_abs}")
set(dst_abs "${dst_dir_abs}/${dst_name}")
add_custom_command(
COMMAND "${src_abs}" ${args_ARGS} > "${dst_abs}"
OUTPUT "${dst_abs}"
DEPENDS ${args_DEPENDS}
WORKING_DIRECTORY "${src_dir_abs}"
VERBATIM
)
target_sources(${args_target} ${args_scope} "${dst_abs}")
endfunction()

8
util/CMakeLists.txt Normal file
View File

@ -0,0 +1,8 @@
add_library(nf7util)
target_sources(nf7util
PRIVATE
malloc.c
PUBLIC
malloc.h
)
target_link_libraries(nf7util PRIVATE nf7config)

43
util/malloc.c Normal file
View File

@ -0,0 +1,43 @@
// No copyright
#include "util/malloc.h"
#include <assert.h>
void* nf7_util_malloc_stack_new(struct nf7_util_malloc_stack* const this, const uint64_t n) {
assert(nullptr != this);
if (this->end < this->tail + n) {
const uint64_t tail = this->tail - this->begin;
const uint64_t size = tail + n;
uint8_t* const ptr = nf7_util_malloc_renew(this->malloc, this->begin, size);
if (nullptr == ptr) {
return nullptr;
}
this->begin = ptr;
// this->head = ptr + head; // unnecessary 'cause it'll be filled before return
this->tail = ptr + tail;
this->end = ptr + size;
}
this->head = this->tail;
this->tail += n;
return this->head;
}
void nf7_util_malloc_stack_del(struct nf7_util_malloc_stack* const this, void* const ptr) {
assert(nullptr != this);
assert(0 < this->refcnt);
if (--this->refcnt == 0) {
this->head = this->begin;
this->tail = this->begin;
return;
}
if (this->head == ptr) {
this->tail = this->head;
return;
}
}

38
util/malloc.h Normal file
View File

@ -0,0 +1,38 @@
// No copyright
#pragma once
#include <stdlib.h>
// ---- General Purpose Memory Allocator
// The current implementation is just a wrap of malloc/free.
struct nf7_util_malloc { uint8_t dummy_; };
static inline void* nf7_util_malloc_new(struct nf7_util_malloc*, uint64_t n) {
return n > 0? calloc(n, 1): nullptr;
}
static inline void nf7_util_malloc_del(struct nf7_util_malloc*, void* ptr) {
if (nullptr != ptr) { free(ptr); }
}
static inline void* nf7_util_malloc_renew(struct nf7_util_malloc* this, void* ptr, uint64_t n) {
if (n > 0) {
return nullptr != ptr? realloc(ptr, n): malloc(n);
} else {
nf7_util_malloc_del(this, ptr);
return nullptr;
}
}
// ---- Stack Allocator
struct nf7_util_malloc_stack {
struct nf7_util_malloc* malloc;
uint8_t* begin;
uint8_t* end;
uint8_t* head;
uint8_t* tail;
uint64_t refcnt;
};
void* nf7_util_malloc_stack_new(struct nf7_util_malloc_stack* this, uint64_t n);