kore

An easy to use, scalable and secure web application framework for writing web APIs in C.
Commits | Files | Refs | README | LICENSE | git clone https://git.kore.io/kore.git

commit ec7a7b33e7bde24e9af252602f29ed309656d74e
parent 8d92dd2af4c436b44cda972cca409157f24e2928
Author: Joris Vink <joris@coders.se>
Date:   Wed, 29 Jun 2016 16:23:00 +0200

Merge pull request #132 from nibroc/cpp

Compile and link C++ with g++ instead of gcc
Diffstat:
examples/cpp/conf/build.conf | 4++++
src/cli.c | 198+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
2 files changed, 153 insertions(+), 49 deletions(-)

diff --git a/examples/cpp/conf/build.conf b/examples/cpp/conf/build.conf @@ -6,10 +6,14 @@ cflags=-Wall -Wmissing-declarations -Wshadow cflags=-Wstrict-prototypes -Wmissing-prototypes cflags=-Wpointer-arith -Wcast-qual -Wsign-compare +cxxflags=-Wall -Wmissing-declarations -Wshadow +cxxflags=-Wpointer-arith -Wcast-qual -Wsign-compare + dev { # These cflags are added to the shared ones when # you build the "dev" flavor. cflags=-g + cxxflags=-g } #prod { diff --git a/src/cli.c b/src/cli.c @@ -60,10 +60,16 @@ #define LD_FLAGS_MAX 30 #define CFLAGS_MAX 30 +#define CXXFLAGS_MAX 30 + +#define BUILD_NOBUILD 0 +#define BUILD_C 1 +#define BUILD_CXX 2 struct buildopt { char *name; struct kore_buf *cflags; + struct kore_buf *cxxflags; struct kore_buf *ldflags; TAILQ_ENTRY(buildopt) list; }; @@ -96,12 +102,13 @@ static void cli_file_close(int); static void cli_run_kore(void *); static void cli_generate_certs(void); static void cli_link_library(void *); -static void cli_compile_cfile(void *); +static void cli_compile_source_file(void *); static void cli_mkdir(const char *, int); static int cli_dir_exists(const char *); static int cli_file_exists(const char *); static void cli_cleanup_files(const char *); static void cli_build_cflags(struct buildopt *); +static void cli_build_cxxflags(struct buildopt *); static void cli_build_ldflags(struct buildopt *); static void cli_file_writef(int, const char *, ...); static void cli_file_open(const char *, int, int *); @@ -111,12 +118,12 @@ static void cli_file_write(int, const void *, size_t); static int cli_vasprintf(char **, const char *, ...); static void cli_spawn_proc(void (*cb)(void *), void *); static void cli_write_asset(const char *, const char *); -static void cli_register_cfile(char *, struct dirent *); +static void cli_register_source_file(char *, struct dirent *); static void cli_file_create(const char *, const char *, size_t); static int cli_file_requires_build(struct stat *, const char *); static void cli_find_files(const char *, void (*cb)(char *, struct dirent *)); -static void cli_add_cfile(char *, char *, char *, +static void cli_add_source_file(char *, char *, char *, struct stat *, int); static struct buildopt *cli_buildopt_new(const char *); @@ -124,6 +131,7 @@ static struct buildopt *cli_buildopt_find(const char *); static void cli_buildopt_cleanup(void); static void cli_buildopt_parse(const char *); static void cli_buildopt_cflags(struct buildopt *, const char *); +static void cli_buildopt_cxxflags(struct buildopt *, const char *); static void cli_buildopt_ldflags(struct buildopt *, const char *); static void cli_flavor_load(void); @@ -201,19 +209,23 @@ static const char *build_data = "# %s build config\n" "# You can switch flavors using: kore flavor [newflavor]\n" "\n" - "# The cflags below are shared between flavors\n" + "# The flags below are shared between flavors\n" "cflags=-Wall -Wmissing-declarations -Wshadow\n" "cflags=-Wstrict-prototypes -Wmissing-prototypes\n" "cflags=-Wpointer-arith -Wcast-qual -Wsign-compare\n" "\n" + "cxxflags=-Wall -Wmissing-declarations -Wshadow\n" + "cxxflags=-Wpointer-arith -Wcast-qual -Wsign-compare\n" + "\n" "dev {\n" - " # These cflags are added to the shared ones when\n" + " # These flags are added to the shared ones when\n" " # you build the \"dev\" flavor.\n" " cflags=-g\n" + " cxxflags=-g\n" "}\n" "\n" "#prod {\n" - "# You can specify additional CFLAGS here which are only\n" + "# You can specify additional flags here which are only\n" "# included if you build with the \"prod\" flavor.\n" "#}\n"; @@ -234,15 +246,20 @@ static const char *gitignore = "*.o\n.flavor\n.objs\n%s.so\nassets.h\ncert\n"; static int s_fd = -1; static char *appl = NULL; static char *rootdir = NULL; -static char *compiler = "gcc"; +static char *compiler_c = "gcc"; +static char *compiler_cpp = "g++"; +static char *compiler_ld = "gcc"; static struct cfile_list source_files; static struct buildopt_list build_options; -static int cfiles_count; +static int source_files_count; +static int cxx_files_count; static struct cmd *command = NULL; static int cflags_count = 0; +static int cxxflags_count = 0; static int ldflags_count = 0; static char *flavor = NULL; static char *cflags[CFLAGS_MAX]; +static char *cxxflags[CXXFLAGS_MAX]; static char *ldflags[LD_FLAGS_MAX]; void @@ -392,9 +409,13 @@ cli_build(int argc, char **argv) appl = basename(pwd); if ((p = getenv("CC")) != NULL) - compiler = p; + compiler_c = p; + + if ((p = getenv("CXX")) != NULL) + compiler_cpp = p; - cfiles_count = 0; + source_files_count = 0; + cxx_files_count = 0; TAILQ_INIT(&source_files); TAILQ_INIT(&build_options); @@ -419,8 +440,13 @@ cli_build(int argc, char **argv) cli_buildopt_parse(build_path); free(build_path); + /* Build all source files. */ + cli_find_files(src_path, cli_register_source_file); + free(src_path); + printf("building %s (%s)\n", appl, flavor); cli_build_cflags(bopt); + cli_build_cxxflags(bopt); cli_build_ldflags(bopt); (void)cli_vasprintf(&obj_path, "%s/.objs", rootdir); @@ -444,17 +470,13 @@ cli_build(int argc, char **argv) free(assets_path); - /* Build all source files. */ - cli_find_files(src_path, cli_register_cfile); - free(src_path); - requires_relink = 0; TAILQ_FOREACH(cf, &source_files, list) { - if (cf->build == 0) + if (cf->build == BUILD_NOBUILD) continue; printf("compiling %s\n", cf->name); - cli_spawn_proc(cli_compile_cfile, cf); + cli_spawn_proc(cli_compile_source_file, cf); times[0].tv_usec = 0; times[0].tv_sec = cf->st.st_mtime; @@ -463,6 +485,10 @@ cli_build(int argc, char **argv) if (utimes(cf->opath, times) == -1) printf("utime(%s): %s\n", cf->opath, errno_s); + if (cf->build == BUILD_CXX) { + compiler_ld = compiler_cpp; + } + requires_relink++; } @@ -728,8 +754,8 @@ cli_build_asset(char *fpath, struct dirent *dp) *(ext)++ = '\0'; cli_write_asset(name, ext); *ext = '_'; - - cli_add_cfile(name, cpath, opath, &st, 0); + + cli_add_source_file(name, cpath, opath, &st, BUILD_NOBUILD); kore_mem_free(name); return; } @@ -788,17 +814,17 @@ cli_build_asset(char *fpath, struct dirent *dp) *--ext = '.'; /* Register the .c file now (cpath is free'd later). */ - cli_add_cfile(name, cpath, opath, &st, 1); + cli_add_source_file(name, cpath, opath, &st, BUILD_C); kore_mem_free(name); } static void -cli_add_cfile(char *name, char *fpath, char *opath, struct stat *st, +cli_add_source_file(char *name, char *fpath, char *opath, struct stat *st, int build) { struct cfile *cf; - cfiles_count++; + source_files_count++; cf = kore_malloc(sizeof(*cf)); cf->st = *st; @@ -811,10 +837,11 @@ cli_add_cfile(char *name, char *fpath, char *opath, struct stat *st, } static void -cli_register_cfile(char *fpath, struct dirent *dp) +cli_register_source_file(char *fpath, struct dirent *dp) { struct stat st; char *ext, *opath; + int build; if ((ext = strrchr(fpath, '.')) == NULL || (strcmp(ext, ".c") && strcmp(ext, ".cpp"))) @@ -825,11 +852,15 @@ cli_register_cfile(char *fpath, struct dirent *dp) (void)cli_vasprintf(&opath, "%s/.objs/%s.o", rootdir, dp->d_name); if (!cli_file_requires_build(&st, opath)) { - cli_add_cfile(dp->d_name, fpath, opath, &st, 0); - return; + build = BUILD_NOBUILD; + } else if (!strcmp(ext, ".cpp")) { + build = BUILD_CXX; + cxx_files_count++; + } else { + build = BUILD_C; } - cli_add_cfile(dp->d_name, fpath, opath, &st, 1); + cli_add_source_file(dp->d_name, fpath, opath, &st, build); } static void @@ -979,17 +1010,36 @@ cli_generate_certs(void) } static void -cli_compile_cfile(void *arg) +cli_compile_source_file(void *arg) { int idx, i; struct cfile *cf = arg; char *args[32 + CFLAGS_MAX]; + char *compiler; + char **flags; + int flags_count; + + switch (cf->build) { + case BUILD_C: + compiler = compiler_c; + flags = cflags; + flags_count = cflags_count; + break; + case BUILD_CXX: + compiler = compiler_cpp; + flags = cxxflags; + flags_count = cxxflags_count; + break; + default: + cli_fatal("cli_compile_file: unexpected file type: %d", cf->build); + break; + } idx = 0; args[idx++] = compiler; - for (i = 0; i < cflags_count; i++) - args[idx++] = cflags[i]; + for (i = 0; i < flags_count; i++) + args[idx++] = flags[i]; args[idx++] = "-c"; args[idx++] = cf->fpath; @@ -1006,12 +1056,12 @@ cli_link_library(void *arg) struct cfile *cf; int idx, i; char *libname; - char *args[cfiles_count + 11 + LD_FLAGS_MAX]; + char *args[source_files_count + 11 + LD_FLAGS_MAX]; (void)cli_vasprintf(&libname, "%s/%s.so", rootdir, appl); idx = 0; - args[idx++] = compiler; + args[idx++] = compiler_ld; TAILQ_FOREACH(cf, &source_files, list) args[idx++] = cf->opath; @@ -1023,7 +1073,7 @@ cli_link_library(void *arg) args[idx++] = libname; args[idx] = NULL; - execvp(compiler, args); + execvp(compiler_ld, args); } static void @@ -1087,6 +1137,8 @@ parse_option: if (!strcasecmp(p, "cflags")) { cli_buildopt_cflags(bopt, t); + } else if (!strcasecmp(p, "cxxflags")) { + cli_buildopt_cxxflags(bopt, t); } else if (!strcasecmp(p, "ldflags")) { cli_buildopt_ldflags(bopt, t); } else { @@ -1102,6 +1154,7 @@ cli_buildopt_new(const char *name) bopt = kore_malloc(sizeof(*bopt)); bopt->cflags = NULL; + bopt->cxxflags = NULL; bopt->ldflags = NULL; bopt->name = kore_strdup(name); @@ -1133,6 +1186,8 @@ cli_buildopt_cleanup(void) if (bopt->cflags != NULL) kore_buf_free(bopt->cflags); + if (bopt->cxxflags != NULL) + kore_buf_free(bopt->cxxflags); if (bopt->ldflags != NULL) kore_buf_free(bopt->ldflags); kore_mem_free(bopt); @@ -1154,6 +1209,20 @@ cli_buildopt_cflags(struct buildopt *bopt, const char *string) } static void +cli_buildopt_cxxflags(struct buildopt *bopt, const char *string) +{ + if (bopt == NULL) { + if ((bopt = cli_buildopt_find("_default")) == NULL) + cli_fatal("no _default build options"); + } + + if (bopt->cxxflags == NULL) + bopt->cxxflags = kore_buf_create(128); + + kore_buf_appendf(bopt->cxxflags, "%s ", string); +} + +static void cli_buildopt_ldflags(struct buildopt *bopt, const char *string) { if (bopt == NULL) { @@ -1168,38 +1237,44 @@ cli_buildopt_ldflags(struct buildopt *bopt, const char *string) } static void -cli_build_cflags(struct buildopt *bopt) +cli_build_flags_common(struct kore_buf* buf) { - struct buildopt *obopt; - char *string; - - if ((obopt = cli_buildopt_find(flavor)) == NULL) - cli_fatal("no such build flavor: %s", flavor); - - if (bopt->cflags == NULL) - bopt->cflags = kore_buf_create(128); - - kore_buf_appendf(bopt->cflags, + kore_buf_appendf(buf, "-fPIC -I%s/src -I%s/src/includes ", rootdir, rootdir); #if defined(PREFIX) - kore_buf_appendf(bopt->cflags, "-I%s/include ", PREFIX); + kore_buf_appendf(buf, "-I%s/include ", PREFIX); #else - kore_buf_appendf(bopt->cflags, "-I/usr/local/include "); + kore_buf_appendf(buf, "-I/usr/local/include "); #endif #if defined(__MACH__) /* Add default openssl include path from homebrew / ports under OSX. */ - kore_buf_appendf(bopt->cflags, "-I/opt/local/include "); - kore_buf_appendf(bopt->cflags, "-I/usr/local/opt/openssl/include "); + kore_buf_appendf(buf, "-I/opt/local/include "); + kore_buf_appendf(buf, "-I/usr/local/opt/openssl/include "); #endif #if defined(KORE_USE_PGSQL) - kore_buf_appendf(bopt->cflags, "-I%s ", PGSQL_INCLUDE_PATH); + kore_buf_appendf(buf, "-I%s ", PGSQL_INCLUDE_PATH); #endif #if defined(KORE_NO_HTTP) - kore_buf_appendf(bopt->cflags, "-DKORE_NO_HTTP "); + kore_buf_appendf(buf, "-DKORE_NO_HTTP "); #endif #if defined(KORE_NO_TLS) - kore_buf_appendf(bopt->cflags, "-DKORE_NO_TLS "); + kore_buf_appendf(buf, "-DKORE_NO_TLS "); #endif +} + +static void +cli_build_cflags(struct buildopt *bopt) +{ + struct buildopt *obopt; + char *string; + + if ((obopt = cli_buildopt_find(flavor)) == NULL) + cli_fatal("no such build flavor: %s", flavor); + + if (bopt->cflags == NULL) + bopt->cflags = kore_buf_create(128); + + cli_build_flags_common(bopt->cflags); if (obopt != NULL && obopt->cflags != NULL) { kore_buf_append(bopt->cflags, obopt->cflags->data, @@ -1212,6 +1287,31 @@ cli_build_cflags(struct buildopt *bopt) } static void +cli_build_cxxflags(struct buildopt *bopt) +{ + struct buildopt *obopt; + char *string; + + if ((obopt = cli_buildopt_find(flavor)) == NULL) + cli_fatal("no such build flavor: %s", flavor); + + if (bopt->cxxflags == NULL) + bopt->cxxflags = kore_buf_create(128); + + cli_build_flags_common(bopt->cxxflags); + + if (obopt != NULL && obopt->cxxflags != NULL) { + kore_buf_append(bopt->cxxflags, obopt->cxxflags->data, + obopt->cxxflags->offset); + } + + string = kore_buf_stringify(bopt->cxxflags, NULL); + if (cxx_files_count > 0) + printf("CXXFLAGS=%s\n", string); + cxxflags_count = kore_split_string(string, " ", cxxflags, CXXFLAGS_MAX); +} + +static void cli_build_ldflags(struct buildopt *bopt) { struct buildopt *obopt;