practically the whole thing up and running. I should make commits more often...
This commit is contained in:
@@ -0,0 +1,11 @@
|
|||||||
|
CC := gcc
|
||||||
|
FILES := src/main.c src/args.c src/new.c src/build.c src/run.c
|
||||||
|
|
||||||
|
build:
|
||||||
|
gcc -o main $(FILES)
|
||||||
|
sudo cp main /usr/bin/vendetta
|
||||||
|
rm -fr main
|
||||||
|
|
||||||
|
run:
|
||||||
|
vendetta new thing
|
||||||
|
ls
|
||||||
@@ -18,8 +18,8 @@ Vendetta uses **git** as the version control system and **make** as the build sy
|
|||||||
|
|
||||||
## Build a project
|
## Build a project
|
||||||
|
|
||||||
`vendetta build <project_name>`
|
`vendetta build`
|
||||||
|
|
||||||
## Build and run a project
|
## Build and run a project
|
||||||
|
|
||||||
`vendetta run <project_name>`
|
`vendetta run`
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
CC := gcc
|
||||||
|
CFLAGS := -Wall -Werror
|
||||||
|
LIBSPATH := -L/usr/lib/odweta/
|
||||||
|
INCLUDEDIR := -I/usr/include/odweta/
|
||||||
|
PATCH := -Wl,-rpath=/usr/lib/odweta/
|
||||||
|
|
||||||
|
.PHONY: build run
|
||||||
|
|
||||||
|
default: build
|
||||||
|
|
||||||
|
build: src/main.c # add files to compile here
|
||||||
|
@$(CC) $(CFLAGS) -o ./build/$@ $^ $(PATCH) $(INCLUDEDIR) $(LIBSPATH) $(LIBS)
|
||||||
|
|
||||||
|
run:
|
||||||
|
@./build/main
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# example_project
|
||||||
|
|
||||||
|
Your project description goes here
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
printf("Hello, world!\n");
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
#ifndef ARGS_H
|
||||||
|
#define ARGS_H
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
NEW, // create a project
|
||||||
|
BUILD, // build a project
|
||||||
|
RUN // build and run a project or run a project (is_built is denoted in .vendettaconfig => if true, just run, otherwise build and run)
|
||||||
|
} meg_e; // mutually_exclusive_group_e;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
meg_e main_arg;
|
||||||
|
char* project_name;
|
||||||
|
} args_t;
|
||||||
|
|
||||||
|
|
||||||
|
args_t parse_args(int argc, char** argv);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef BUILD_H
|
||||||
|
#define BUILD_H
|
||||||
|
|
||||||
|
void build_project();
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef NEW_H
|
||||||
|
#define NEW_H
|
||||||
|
|
||||||
|
void new_project(char* name);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef RUN_H
|
||||||
|
#define RUN_H
|
||||||
|
|
||||||
|
void run_project();
|
||||||
|
|
||||||
|
#endif
|
||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
#include "../include/args.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
args_t parse_args(int argc, char** argv) {
|
||||||
|
if (argc < 2 || argc > 3) {
|
||||||
|
fprintf(stderr, "invalid number of arguments\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
args_t args;
|
||||||
|
|
||||||
|
if (strcmp(argv[1], "new") == 0) {
|
||||||
|
args.main_arg = NEW;
|
||||||
|
if (argc != 3) {
|
||||||
|
fprintf(stderr, "not enough arguments supplied, supply a project name\n");
|
||||||
|
exit(1);
|
||||||
|
} // TODO: add licenses to newly created projects
|
||||||
|
args.project_name = (char*)malloc(sizeof(argv[2]));
|
||||||
|
strcpy(args.project_name, argv[2]);
|
||||||
|
} else if (strcmp(argv[1], "build") == 0) {
|
||||||
|
args.main_arg = BUILD;
|
||||||
|
} else if (strcmp(argv[1], "run") == 0) {
|
||||||
|
args.main_arg = RUN;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "invalid argument\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return args;
|
||||||
|
}
|
||||||
+135
@@ -0,0 +1,135 @@
|
|||||||
|
#include "../include/build.h"
|
||||||
|
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#define MAX(n) n
|
||||||
|
int src_files_num;
|
||||||
|
|
||||||
|
int count_src_files(char *src_dir) {
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
DIR *d;
|
||||||
|
struct dirent *dir;
|
||||||
|
d = opendir(src_dir); // all source (.c) files
|
||||||
|
if (d) {
|
||||||
|
while ((dir = readdir(d)) != NULL) {
|
||||||
|
if (dir->d_type == DT_REG) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_filenames(char src_files[][1000], char *src_dir) {
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
DIR *d;
|
||||||
|
struct dirent *dir;
|
||||||
|
d = opendir(src_dir); // all source (.c) files
|
||||||
|
if (d) {
|
||||||
|
while ((dir = readdir(d)) != NULL) {
|
||||||
|
if (dir->d_type == DT_REG) {
|
||||||
|
if (i < src_files_num) {
|
||||||
|
strcpy(src_files[i++], dir->d_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir(d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char *create_new_makefile(char src_files[][1000]) {
|
||||||
|
char makefile[999999]; // idk how many
|
||||||
|
strcpy(makefile, "\
|
||||||
|
CC := gcc\n\
|
||||||
|
CFLAGS := -Wall -Werror\n\
|
||||||
|
LIBSPATH := -L/usr/lib/odweta/\n\
|
||||||
|
INCLUDEDIR := -I/usr/include/odweta/\n\
|
||||||
|
PATCH := -Wl,-rpath=/usr/lib/odweta/\n\
|
||||||
|
\n\
|
||||||
|
.PHONY: build run\n\
|
||||||
|
\n\
|
||||||
|
default: build\n\
|
||||||
|
\n\
|
||||||
|
build: "); // src/main.c # add files to compile here\n
|
||||||
|
for (int i = 0; i < src_files_num; i++) {
|
||||||
|
strcat(makefile, "src/");
|
||||||
|
strcat(makefile, src_files[i]);
|
||||||
|
strcat(makefile, " ");
|
||||||
|
}
|
||||||
|
strcat(makefile, "\n\
|
||||||
|
\t@$(CC) $(CFLAGS) -o ./build/main $^ $(PATCH) $(INCLUDEDIR) $(LIBSPATH) $(LIBS)\n\
|
||||||
|
\n\
|
||||||
|
run:\n\
|
||||||
|
\t@./build/main\n");
|
||||||
|
|
||||||
|
char *ptr = makefile;
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_new_makefile(char *makefile) {
|
||||||
|
FILE *fd = fopen("Makefile", "w");
|
||||||
|
|
||||||
|
fprintf(fd, "%s", makefile);
|
||||||
|
|
||||||
|
fclose(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void save_build_status(int status_code) {
|
||||||
|
FILE *fd = fopen("./build/.build_status", "w");
|
||||||
|
if (!fd) {
|
||||||
|
fprintf(stderr, "Invalid permissions. Could not open ./build/.build_status "
|
||||||
|
"for writing.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(fd, "%d", status_code);
|
||||||
|
|
||||||
|
fclose(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void build_project() {
|
||||||
|
/* iterate through all files in the ./<project_name>/src/ directory
|
||||||
|
* create a new makefile with these files incuded for compilation
|
||||||
|
* run make
|
||||||
|
* if the build was successfull -> print something like 'the build was
|
||||||
|
* successfull'
|
||||||
|
*/
|
||||||
|
|
||||||
|
char cwd[2048];
|
||||||
|
getcwd(cwd, sizeof(cwd));
|
||||||
|
|
||||||
|
char src_dir[strlen(cwd) + 4 + 1];
|
||||||
|
strcpy(src_dir, cwd);
|
||||||
|
strcat(src_dir, "/src");
|
||||||
|
|
||||||
|
src_files_num = count_src_files(src_dir);
|
||||||
|
// printf("%d file(s) found in %s\n", src_files_num, src_dir);
|
||||||
|
|
||||||
|
char src_files[src_files_num][1000];
|
||||||
|
|
||||||
|
load_filenames(src_files, src_dir);
|
||||||
|
|
||||||
|
for (int i = 0; i < src_files_num; i++) {
|
||||||
|
// printf("%s\n", src_files[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *makefile = create_new_makefile(src_files);
|
||||||
|
|
||||||
|
write_new_makefile(makefile);
|
||||||
|
|
||||||
|
if (system("make") == 0) {
|
||||||
|
printf("The build was successful!\n");
|
||||||
|
save_build_status(0);
|
||||||
|
} else {
|
||||||
|
printf("An error occured while building.\n");
|
||||||
|
save_build_status(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
#include "../include/args.h"
|
||||||
|
#include "../include/build.h"
|
||||||
|
#include "../include/new.h"
|
||||||
|
#include "../include/run.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
args_t args = parse_args(argc, argv);
|
||||||
|
|
||||||
|
switch (args.main_arg) {
|
||||||
|
case NEW:
|
||||||
|
new_project(args.project_name);
|
||||||
|
break;
|
||||||
|
case BUILD:
|
||||||
|
build_project();
|
||||||
|
break;
|
||||||
|
case RUN:
|
||||||
|
run_project();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(args.project_name);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,203 @@
|
|||||||
|
#include "../include/new.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *main_c;
|
||||||
|
char *makefile;
|
||||||
|
char *readme;
|
||||||
|
} thing_t;
|
||||||
|
|
||||||
|
void main_c(char *name, char *path) {
|
||||||
|
FILE *fd = fopen(path, "w");
|
||||||
|
if (!fd) {
|
||||||
|
fprintf(stderr, "could not open main.c\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(fd, "#include <stdio.h>\n\nint main() {\n printf(\"Hello, "
|
||||||
|
"world!\\n\");\n}\n");
|
||||||
|
|
||||||
|
fclose(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void makefile(char *name, char *path) {
|
||||||
|
FILE *fd = fopen(path, "w");
|
||||||
|
if (!fd) {
|
||||||
|
fprintf(stderr, "could not open Makefile\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *payload = "\
|
||||||
|
CC := gcc\n\
|
||||||
|
CFLAGS := -Wall -Werror\n\
|
||||||
|
LIBSPATH := -L/usr/lib/odweta/\n\
|
||||||
|
INCLUDEDIR := -I/usr/include/odweta/\n\
|
||||||
|
PATCH := -Wl,-rpath=/usr/lib/odweta/\n\
|
||||||
|
\n\
|
||||||
|
.PHONY: build run\n\
|
||||||
|
\n\
|
||||||
|
default: build\n\
|
||||||
|
\n\
|
||||||
|
build: src/main.c # add files to compile here\n\
|
||||||
|
\t@$(CC) $(CFLAGS) -o ./build/$@ $^ $(PATCH) $(INCLUDEDIR) $(LIBSPATH) $(LIBS)\n\
|
||||||
|
\n\
|
||||||
|
run:\n\
|
||||||
|
\t@./build/main\n";
|
||||||
|
|
||||||
|
fprintf(fd, "%s", payload);
|
||||||
|
|
||||||
|
fclose(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void readme(char *name, char *path) {
|
||||||
|
FILE *fd = fopen(path, "w");
|
||||||
|
if (!fd) {
|
||||||
|
fprintf(stderr, "could not open README.md\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
char readme_text[strlen("# ") + strlen(name) +
|
||||||
|
strlen("\n\nYour project description goes here\n") + 1];
|
||||||
|
strcpy(readme_text, "# ");
|
||||||
|
strcat(readme_text, name);
|
||||||
|
strcat(readme_text, "\n\nYour project description goes here\n");
|
||||||
|
|
||||||
|
fprintf(fd, "%s", readme_text);
|
||||||
|
|
||||||
|
fclose(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fill_in_files(char *name, thing_t thing) {
|
||||||
|
main_c(name, thing.main_c);
|
||||||
|
makefile(name, thing.makefile);
|
||||||
|
readme(name, thing.readme);
|
||||||
|
// license(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dirs(char *name) {
|
||||||
|
char mkdir_str[strlen("mkdir -p ./") + strlen(name) + strlen("/src") + 1];
|
||||||
|
strcpy(mkdir_str, "mkdir -p ./");
|
||||||
|
strcat(mkdir_str, name);
|
||||||
|
strcat(mkdir_str, "/src");
|
||||||
|
|
||||||
|
system(mkdir_str);
|
||||||
|
|
||||||
|
char
|
||||||
|
mkdir_str2[strlen("mkdir -p ./") + strlen(name) + strlen("/include") + 1];
|
||||||
|
strcpy(mkdir_str2, "mkdir -p ./");
|
||||||
|
strcat(mkdir_str2, name);
|
||||||
|
strcat(mkdir_str2, "/include");
|
||||||
|
|
||||||
|
system(mkdir_str2);
|
||||||
|
|
||||||
|
char mkdir_str3[strlen("mkdir -p ./") + strlen(name) + strlen("/build") + 1];
|
||||||
|
strcpy(mkdir_str3, "mkdir -p ./");
|
||||||
|
strcat(mkdir_str3, name);
|
||||||
|
strcat(mkdir_str3, "/build");
|
||||||
|
|
||||||
|
system(mkdir_str3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void files(char *name) {
|
||||||
|
char smain_c[] = "/src/main.c";
|
||||||
|
char smakefile[] = "/Makefile";
|
||||||
|
char sreadme[] = "/README.md";
|
||||||
|
char slicense[] = "/LICENSE";
|
||||||
|
char sgitignore[] = "/.gitignore";
|
||||||
|
|
||||||
|
char touch1[strlen("touch ./") + strlen(name) + strlen(smain_c) + 1];
|
||||||
|
char touch2[strlen("touch ./") + strlen(name) + strlen(smakefile) + 1];
|
||||||
|
char touch3[strlen("touch ./") + strlen(name) + strlen(sreadme) + 1];
|
||||||
|
char touch4[strlen("touch ./") + strlen(name) + strlen(slicense) + 1];
|
||||||
|
char touch5[strlen("touch ./") + strlen(name) + strlen(sgitignore) + 1];
|
||||||
|
|
||||||
|
strcpy(touch1, "touch ./");
|
||||||
|
strcat(touch1, name);
|
||||||
|
strcat(touch1, smain_c);
|
||||||
|
|
||||||
|
strcpy(touch2, "touch ./");
|
||||||
|
strcat(touch2, name);
|
||||||
|
strcat(touch2, smakefile);
|
||||||
|
|
||||||
|
strcpy(touch3, "touch ./");
|
||||||
|
strcat(touch3, name);
|
||||||
|
strcat(touch3, sreadme);
|
||||||
|
|
||||||
|
strcpy(touch4, "touch ./");
|
||||||
|
strcat(touch4, name);
|
||||||
|
strcat(touch4, slicense);
|
||||||
|
|
||||||
|
strcpy(touch5, "touch ./");
|
||||||
|
strcat(touch5, name);
|
||||||
|
strcat(touch5, sgitignore);
|
||||||
|
|
||||||
|
system(touch1);
|
||||||
|
system(touch2);
|
||||||
|
system(touch3);
|
||||||
|
system(touch4);
|
||||||
|
system(touch5);
|
||||||
|
}
|
||||||
|
|
||||||
|
thing_t create_files(char *name) {
|
||||||
|
char main_c_path[2 + strlen(name) + 11 + 1];
|
||||||
|
char makefile_path[2 + strlen(name) + 9 + 1];
|
||||||
|
char readme_path[2 + strlen(name) + 10 + 1];
|
||||||
|
|
||||||
|
strcpy(main_c_path, "./");
|
||||||
|
strcpy(makefile_path, "./");
|
||||||
|
strcpy(readme_path, "./");
|
||||||
|
|
||||||
|
thing_t thing;
|
||||||
|
|
||||||
|
thing.main_c = (char *)malloc(sizeof(main_c_path));
|
||||||
|
thing.makefile = (char *)malloc(sizeof(makefile_path));
|
||||||
|
thing.readme = (char *)malloc(sizeof(readme_path));
|
||||||
|
|
||||||
|
strcat(main_c_path, name);
|
||||||
|
strcat(main_c_path, "/src/main.c");
|
||||||
|
|
||||||
|
strcat(makefile_path, name);
|
||||||
|
strcat(makefile_path, "/Makefile");
|
||||||
|
|
||||||
|
strcat(readme_path, name);
|
||||||
|
strcat(readme_path, "/README.md");
|
||||||
|
|
||||||
|
strcpy(thing.main_c, main_c_path);
|
||||||
|
strcpy(thing.makefile, makefile_path);
|
||||||
|
strcpy(thing.readme, readme_path);
|
||||||
|
|
||||||
|
dirs(name);
|
||||||
|
|
||||||
|
files(name);
|
||||||
|
|
||||||
|
return thing;
|
||||||
|
}
|
||||||
|
|
||||||
|
void new_project(char *name) {
|
||||||
|
thing_t thing = create_files(name);
|
||||||
|
|
||||||
|
char command[strlen("sudo chmod +w .//src/main.c -R") + strlen(name) + 1];
|
||||||
|
strcpy(command, "sudo chmod +w ./");
|
||||||
|
strcat(command, name);
|
||||||
|
strcat(command, "/src/main.c");
|
||||||
|
|
||||||
|
system(command);
|
||||||
|
|
||||||
|
char command2[strlen("sudo chmod +w .//**") + strlen(name) + 1];
|
||||||
|
strcpy(command2, "sudo chmod +w ./");
|
||||||
|
strcat(command2, name);
|
||||||
|
strcat(command2, "/**");
|
||||||
|
|
||||||
|
system(command2);
|
||||||
|
|
||||||
|
fill_in_files(
|
||||||
|
name,
|
||||||
|
thing); // fills in stuff like the Makefile with some boilerplate text
|
||||||
|
|
||||||
|
free(thing.main_c);
|
||||||
|
free(thing.makefile);
|
||||||
|
free(thing.readme);
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
#include "../include/run.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
int get_build_status() {
|
||||||
|
FILE *fd = fopen("./build/.build_status", "r");
|
||||||
|
if (!fd) {
|
||||||
|
fprintf(stderr, "Build the project before running it.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int i;
|
||||||
|
fscanf(fd, "%d", &i);
|
||||||
|
|
||||||
|
fclose(fd);
|
||||||
|
|
||||||
|
return i; // max 10 codes (so far only 2 => 0 -> success, 1 -> failure)
|
||||||
|
}
|
||||||
|
|
||||||
|
void run_project() {
|
||||||
|
if (get_build_status() == 0) { // success
|
||||||
|
// file exists => project has been built
|
||||||
|
system("make run");
|
||||||
|
} else {
|
||||||
|
// file does not exist => project has not been built
|
||||||
|
printf("Project not yet built. Build it first with 'vendetta build'.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user