commit c48809aea91c738f96bfd3eb68d012c409ad70c3
parent 3cdd1961a2230ac9baefeb7cfbf24bf5e6a63cab
Author: vx-clutch <[email protected]>
Date: Fri, 1 Aug 2025 21:32:27 -0400
save
Diffstat:
8 files changed, 209 insertions(+), 140 deletions(-)
diff --git a/TODO b/TODO
@@ -0,0 +1,6 @@
+1 Fix arg parseing
+2 Fix generated Makefile
+3 Add Licence
+
+Ideas
+1 Add --is-lib
diff --git a/c-out/bin/yait b/c-out/bin/yait
Binary files differ.
diff --git a/c-out/obj/main.o b/c-out/obj/main.o
Binary files differ.
diff --git a/config.mak b/config.mak
@@ -0,0 +1,4 @@
+PREFIX=/usr/bin/
+CFLAGS=-Wall -Wextra -ggdb
+LDFLAGS=
+CC=clang
diff --git a/yait/contents.h b/yait/contents.h
@@ -59,9 +59,7 @@ char *configure_template =
line ("done")
line ()
line ("printf \"checking for C compiler... \"")
- line ("trycc gcc")
- line ("trycc cc")
- line ("trycc clang")
+ line ("%s")
line ("printf \"%s\\n\" \"$CC\"")
line ()
line ("printf \"checking weather C compiler works... \"")
@@ -87,7 +85,7 @@ char *makefile_template =
line ("prefix = /usr/bin")
line ()
line ("%s_SRCS := $(shell find . -name '%s/*.c')")
- line ("%s_OBJS := $(patsubst ./%.c,c-out/obj/%%.o,$(%s_SRCS))")
+ line ("%s_OBJS := $(patsubst ./%%.c,c-out/obj/%%.o,$(%s_SRCS))")
line ()
line ("%s := c-out/bin/%s")
line ()
@@ -127,7 +125,7 @@ char *makefile_template =
line ("dist-clean: clean")
line ("\trm -f config.mak")
line ()
- line (".PHONY: all clean dist-clean install uninstall build format");
+ line (".PHONY: all clean dist-clean install uninstall");
/* .clang-format template */
char *clang_format_template =
diff --git a/yait/debug.h b/yait/debug.h
@@ -11,9 +11,9 @@
}
#else
#define on_error(msg, code) \
- if (err) \
+ if (code) \
{ \
- printfn (msg ": %s", strerror (err)); \
+ printfn (msg ": %s", strerror (code)); \
return code; \
}
#endif
diff --git a/yait/format.h b/yait/format.h
@@ -1,41 +1,39 @@
/* Copyright (C) vx_clutch
- *
+ *
* This file is part of yait
*
* This project and file is licenced under the BSD-3-Clause licence.
- * <https://opensource.org/license/bsd-3-clause>
+ * <https://opensource.org/licence/bsd-3-clause>
*/
#ifndef FORMAT_H
#define FORMAT_H
#include <stdbool.h>
+#include <string.h>
-/* License type enumeration */
typedef enum
{
- BSD3, /* BSD 3-Clause License */
- GPLv3, /* GNU General Public License v3 */
- MIT, /* MIT License */
- UNlICENSE, /* Unlicense */
-} license_t;
+ BSD3, /* BSD 3-Clause Licence */
+ GPLv3, /* GNU General Public Licence v3 */
+ MIT, /* MIT Licence */
+ UNLICENCE, /* Unlicence */
+ LICENCE_HELP, /* Help case */
+} licence_t;
-/* Library type enumeration - using bit flags for multiple selection */
+/* A bit field is used so that we can accomplish two things. (a) store lots of
+ libraries without taxing memory; and (b) a dynamic array is not neccescary.
+ */
typedef enum
{
- LIB_NONE = 0, /* No libraries selected */
- LIB_RAYLIB = 1 << 0, /* Raylib game library */
- LIB_WINAPI = 1 << 1, /* Windows API */
- LIB_CURL = 1 << 2, /* cURL library */
- /* Future libraries can be added here:
- * LIB_OPENGL = 1 << 3,
- * LIB_SDL2 = 1 << 4,
- * LIB_GTK = 1 << 5,
- * etc.
- */
+ LIB_NONE = 0, /* No libraries selected */
+ LIB_RAYLIB = 1 << 0, /* Raylib game library */
+ LIB_NCURSES = 1 << 1, /* Windows API */
+ LIB_CURL = 1 << 2, /* cURL library */
+ LIB_COUNT_, /* Number of Libraries */
+ LIB_HELP, /* Help case */
} lib_flags_t;
-/* Flag option type struct */
typedef struct
{
bool GNU;
@@ -44,26 +42,39 @@ typedef struct
bool use_cpp;
} flags_t;
-/* Project configuration structure */
typedef struct
{
- license_t license; /* License type for the project */
- char *project; /* Project name */
- char *name; /* Author/creator name */
+ licence_t licence; /* Licence type for the project */
+ char *project; /* Project name */
+ char *name; /* Author/creator name ( if not provided infered on sanitize ) */
lib_flags_t libraries; /* Selected libraries (bit field) */
flags_t flag; /* Flags */
-} format_t;
+} manifest_t;
-/* Default values */
-#define DEFAULT_LICENSE BSD3
-#define DEFAULT_GIT_INIT true
#define DEFAULT_CLANG_FORMAT true
+#define DEFAULT_GIT_INIT true
+#define DEFAULT_GNU false
#define DEFAULT_LIBRARIES LIB_NONE
+#define DEFAULT_LICENCE BSD3
-/* Helper macros for library operations */
#define HAS_LIBRARY(libs, lib) ((libs) & (lib))
#define ADD_LIBRARY(libs, lib) ((libs) |= (lib))
#define REMOVE_LIBRARY(libs, lib) ((libs) &= ~(lib))
-#define CLEAR_LIBRARIES(libs) ((libs) = LIB_NONE)
+
+static lib_flags_t
+TOlibrary (char *src)
+{
+ if (strcmp (src, "raylib"))
+ return LIB_RAYLIB;
+ if (strcmp (src, "ncurse"))
+ return LIB_NCURSES;
+ if (strcmp (src, "ncurses"))
+ return LIB_NCURSES;
+ if (strcmp (src, "curl"))
+ return LIB_CURL;
+ if (strcmp (src, "help"))
+ return LIB_HELP;
+ return LIB_COUNT_; /* bad case */
+}
#endif
diff --git a/yait/main.c b/yait/main.c
@@ -3,8 +3,8 @@
* This file is part of yait
*
* This project and file is licenced under the BSD-3-Clause licence.
- * <https://opensource.org/license/bsd-3-clause>
- */
+ * <https://opensource.org/licence/bsd-3-clause>
+ */
// Usage: yait [OPTION]... PROJECT [NAME]
@@ -22,22 +22,23 @@
#include "../core/print.h"
#include "../core/standard.h"
#include "contents.h"
-#include "format.h"
#include "debug.h"
+#include "format.h"
#define DEFAULT_USER_NAME "unknown"
#define DEFAULT_PROJECT_NAME "Project"
-#define DEFAULT_LICENSE BSD3
+#define DEFAULT_LICENCE BSD3
#define DEFAULT_GIT_INIT true
#define DEFAULT_CLANG_FORMAT true
/* This is to keep track of how deep we are within
- the project tree. This is used in reset_path */
+ the project tree. This is used in reset_path_ () */
int depth;
#define print_option(option, description) \
printf (" %-20s %-20s\n", option, description)
+// clang-format off
static void
usage (int status)
{
@@ -50,18 +51,20 @@ usage (int status)
printf ("Usage: yait [OPTION]... PROJECT [NAME]\n");
printf ("Creates a C project with opinionated defaults.\n");
printf ("When only given the first argument it will detect your name.\n\n");
- printf ("Mandatory arguments to long options are mandatory for short "
- "options too\n");
- print_option ("-l, --license=NAME",
- "Set license (gpl, mit, bsd) [default: bsd]");
+ printf ("Mandatory arguments to long options are mandatory for short options too\n");
+ print_option ("-l, --licence=NAME", "Set licence (gpl, mit, bsd) [default: bsd]");
+ print_option ("--lib=LIB", "Add a library to the project. You can list libraries with --lib=help.");
print_option ("--use-cpp", "Uses the CPP language instead of C");
print_option ("--git", "Initialize git repository");
print_option ("--GNU", "Adds standard GNU argument parsing to your project");
printf (" --help display this help text and exit\n");
printf (" --version output version information and exit\n");
}
+// clang-format on
-/* This macro exist purely because I like how it looks. */
+/* This macro exist purely because I like how it looks. This should be called
+ in every function that creates file to ensure they are being created in
+ right place. */
#define reset_path reset_path_ ()
static int
reset_path_ ()
@@ -77,43 +80,78 @@ reset_path_ ()
}
static int
-sanitize (format_t *fmt)
+sanitize (manifest_t *m)
{
- if (!fmt->project)
- fmt->project = DEFAULT_PROJECT_NAME;
- if (!fmt->name)
- fmt->name = DEFAULT_USER_NAME;
- if (fmt->license != BSD3 && fmt->license != GPLv3 && fmt->license != MIT)
- fmt->license = DEFAULT_LICENSE;
- fmt->flag.git = fmt->flag.git ? true : DEFAULT_GIT_INIT;
- fmt->flag.clang_format
- = fmt->flag.clang_format ? true : DEFAULT_CLANG_FORMAT;
- fmt->flag.GNU = fmt->flag.GNU ? true : false;
+ if (!m->project)
+ m->project = DEFAULT_PROJECT_NAME;
+ if (!m->name)
+ m->name = DEFAULT_USER_NAME;
+ if (!(m->licence == UNLICENCE))
+ m->licence = DEFAULT_LICENCE;
+ m->flag.git = m->flag.git ? true : DEFAULT_GIT_INIT;
+ m->flag.clang_format = m->flag.clang_format ? true : DEFAULT_CLANG_FORMAT;
+ m->flag.GNU = m->flag.GNU ? true : DEFAULT_GNU;
return 0;
}
+#define get(url) status = system ("git submodule add -q " url)
+static int
+create_libraries (manifest_t manifest)
+{
+ int status = 0;
+
+ if (!manifest.libraries)
+ {
+ return status;
+ }
+
+ reset_path;
+
+ for (int i = 0; i < LIB_COUNT_; ++i)
+ {
+ if HAS_LIBRARY (manifest.libraries, LIB_RAYLIB)
+ {
+ REMOVE_LIBRARY (manifest.libraries, LIB_RAYLIB);
+ get ("https://github.com/raysan5/raylib");
+ }
+ else if HAS_LIBRARY (manifest.libraries, LIB_NCURSES)
+ {
+ REMOVE_LIBRARY (manifest.libraries, LIB_NCURSES);
+ get ("https://github.com/mirror/ncurses");
+ }
+ else if HAS_LIBRARY (manifest.libraries, LIB_CURL)
+ {
+ REMOVE_LIBRARY (manifest.libraries, LIB_CURL);
+ get ("https://github.com/raysan5/raylib");
+ }
+ reset_path;
+ }
+
+ return status;
+}
+
static int
-create_license (format_t fmt, char **license_line_buffer)
+create_licence (manifest_t manifest, char **licence_line_buffer)
{
- if (fmt.license == UNlICENSE)
+ if (manifest.licence == UNLICENCE)
return 0;
reset_path;
- /* TODO: Run better checks on license_line_buffer to ensure we have enough
+ /* TODO: Run better checks on licence_line_buffer to ensure we have enough
space. This could be done through a multitude of ways; that is for you to
- figure out. */
- assert (license_line_buffer != NULL);
+ figure out. */
+ assert (licence_line_buffer != NULL);
// TODO: Remove this and actually implement the features.
#define TODO() \
printfn ("Not impl"); \
assert (1 == 2)
- switch (fmt.license)
+ switch (manifest.licence)
{
case BSD3:
- *license_line_buffer = "Bsd";
+ *licence_line_buffer = "Bsd";
TODO ();
break;
case GPLv3:
@@ -122,9 +160,9 @@ create_license (format_t fmt, char **license_line_buffer)
case MIT:
TODO ();
break;
- case UNlICENSE:
+ case UNLICENCE:
default:
- printfn ("bad logic in create_license_and_set_license_line()");
+ printfn ("bad logic in create_licence ()");
return 1;
}
@@ -132,36 +170,35 @@ create_license (format_t fmt, char **license_line_buffer)
}
static int
-maybe_apply_clang_format (format_t fmt)
+maybe_create_clang_format (manifest_t manifest)
{
- if (!fmt.flag.clang_format)
+ if (!manifest.flag.clang_format)
return 0;
reset_path;
- char *clang_fmt = "BasedOnStyle: LLVM\nIndentWidth: 2\nUseTab: Never\n";
- return create_file_with_content (".clang-format", clang_fmt, 0, NULL);
+ return create_file_with_content (".clang-format", clang_format_template);
}
static int
-setup_git (format_t fmt)
+setup_git (manifest_t manifest)
{
- if (!fmt.flag.git)
+ if (!manifest.flag.git)
return 0;
reset_path;
- int err = system ("git init --quiet");
- if (err)
- printfn ("failed on git initialize: %s", strerror (err));
+ int status = system ("git init --quiet");
+ if (status)
+ printfn ("failed on git initialize: %s", strerror (status));
- return err;
+ return status;
}
static int
-create_makefile (format_t fmt)
+create_makefile (manifest_t manifest)
{
- char *makefile_name = strdup (fmt.project);
+ char *makefile_name = strdup (manifest.project);
if (!makefile_name)
{
printfn ("fatal: out of memory");
@@ -176,7 +213,7 @@ create_makefile (format_t fmt)
create_file_with_content ("Makefile", makefile_template, makefile_name,
makefile_name, makefile_name, makefile_name,
- makefile_name, makefile_name, fmt.project,
+ makefile_name, makefile_name, manifest.project,
makefile_name, makefile_name);
free (makefile_name);
@@ -184,38 +221,51 @@ create_makefile (format_t fmt)
}
static int
-create_configure ()
+create_configure (manifest_t manifest)
{
+ int status = 0;
reset_path;
- create_file_with_content ("configure", configure_template);
- int err = system ("chmod +x configure");
- if (err)
- printfn ("error: %s", strerror (err));
- return err;
+ char *cc;
+ if (manifest.flag.use_cpp)
+ {
+ cc = "trycc g++\ntrycc CC\ntrycc clang++\n";
+ }
+ else
+ {
+ cc = "trycc gcc\ntrycc cc\ntrycc clang\n";
+ }
+
+ create_file_with_content ("configure", configure_template, cc);
+ status = system ("chmod +x configure");
+ if (status)
+ printfn ("error: %s", strerror (status));
+ return status;
}
static int
-generate_source_code (format_t fmt)
+generate_source_code (manifest_t manifest)
{
- int err;
+ int status;
- debug ("take %s/%s", fmt.project, fmt.project);
- err = create_and_enter_directory (fmt.project);
- on_error ("failed to create or enter directory", err);
+ debug ("take %s/%s", manifest.project, manifest.project);
+ status = create_and_enter_directory (manifest.project);
+ on_error ("failed to create or enter directory", status);
+ ++depth;
- if (fmt.flag.GNU)
+ if (manifest.flag.GNU)
{
debug ("GNU flag source branch");
- create_file_with_content ("main.c", main_c_gnu_template, fmt.project,
- fmt.name);
+ create_file_with_content ("main.c", main_c_gnu_template,
+ manifest.project, manifest.name);
goto atexit_clean;
}
debug ("default sourcebranch");
- create_file_with_content ("main.c", main_c_template, fmt.project, fmt.name);
+ create_file_with_content ("main.c", main_c_template, manifest.project,
+ manifest.name);
atexit_clean:
reset_path;
@@ -223,14 +273,13 @@ atexit_clean:
}
static int
-parse_arguments (format_t *conf, int argc, char **argv)
+parse_arguments (manifest_t *conf, int argc, char **argv)
{
- static struct option long_options[]
- = { { "GNU", no_argument, 0, 1 },
- { "use-cpp", no_argument, 0, 2 },
- { "git", no_argument, 0, 3 },
- { "license", required_argument, 0, 4 },
- { 0, 0, 0, 0 } };
+ static struct option long_options[] = {
+ { "GNU", no_argument, 0, 1 }, { "use-cpp", no_argument, 0, 2 },
+ { "git", no_argument, 0, 3 }, { "licence", required_argument, 0, 4 },
+ { "lib", required_argument, 0, 5 }, { 0, 0, 0, 0 }
+ };
int opt;
int long_index = 0;
@@ -248,12 +297,16 @@ parse_arguments (format_t *conf, int argc, char **argv)
case 3:
conf->flag.git = 1;
break;
- case 4: // TODO: Licence
+ case 4: // TODO: implement the licence options, and make it lowercase.
+ break;
+ case 5:
+ ADD_LIBRARY (conf->libraries, TOlibrary (optarg)); // TODO: Get this working
break;
case '?':
break;
}
}
+
int positional_count = 0;
for (int i = optind; i < argc; ++i)
{
@@ -264,56 +317,58 @@ parse_arguments (format_t *conf, int argc, char **argv)
}
if (positional_count == 0)
- {
- conf->project = argv[i];
- }
+ conf->name = argv[i];
else if (positional_count == 1)
- {
- conf->name = argv[i];
- }
+ conf->project = argv[i];
++positional_count;
}
+
return 0;
}
static int
-create_project (format_t fmt)
+create_project (manifest_t manifest)
{
- int err;
+ int status;
debugc ("sanitize");
- err = sanitize (&fmt);
- on_error ("failed to sanitize format", err);
+ status = sanitize (&manifest);
+ on_error ("failed to sanitize format", status);
done;
- debugc ("take %s", fmt.project);
- err = create_and_enter_directory (fmt.project);
+ debugc ("take %s", manifest.project);
+ status = create_and_enter_directory (manifest.project);
depth = 0;
- on_error ("failed to create or enter directory", err);
+ on_error ("failed to create or enter directory", status);
done;
- // debug ("create licenseing");
- // err = create_license_if_needed (fmt);
- // on_error ("failed to create license", err);
-
debugc ("create makefile");
- err = create_makefile (fmt);
- on_error ("failed to create Makefile", err);
+ status = create_makefile (manifest);
+ on_error ("failed to create Makefile", status);
done;
debug ("setup git");
- err = setup_git (fmt);
- if (err)
- printfn ("warning: git initialization failed: %s", strerror (err));
+ status = setup_git (manifest);
+ if (status)
+ {
+ printfn ("warning: git initialization failed: %s", strerror (status));
+ }
debug ("create .clang-format");
- err = maybe_apply_clang_format (fmt);
- if (err)
- printfn ("warning: clang-format setup failed: %s", strerror (err));
+ status = maybe_create_clang_format (manifest);
+ if (status)
+ {
+ printfn ("warning: clang-format setup failed: %s", strerror (status));
+ }
debugc ("generate source code");
- err = generate_source_code (fmt);
- on_error ("failed to generate source code", err);
+ status = generate_source_code (manifest);
+ on_error ("failed to generate source code", status);
+ done;
+
+ debugc ("get libraries");
+ status = create_libraries (manifest);
+ on_error ("failed to get libraries", status);
done;
return 0;
@@ -339,23 +394,18 @@ main (int argc, char **argv)
return status;
}
- format_t conf = { 0 };
+ manifest_t manifest = { 0 };
- // TODO: Argument Parsing
- conf.project = "sample_project";
- conf.name = "vx_clutch";
+ parse_arguments (&manifest, argc, argv);
- if (!conf.name)
+ if (!manifest.name) // TODO: Move to sanitize
{
struct passwd *pw = getpwuid (getuid ());
- conf.name = (pw && pw->pw_name) ? pw->pw_name : DEFAULT_USER_NAME;
+ manifest.name = (pw && pw->pw_name) ? pw->pw_name : DEFAULT_USER_NAME;
}
- conf.flag.git = DEFAULT_GIT_INIT;
- conf.flag.clang_format = DEFAULT_CLANG_FORMAT;
- conf.license = DEFAULT_LICENSE;
+ status = create_project (manifest);
- status = create_project (conf);
if (!status)
debug ("project made successfully");
else