Merge pull request #132 from nibroc/cpp

Compile and link C++ with g++ instead of gcc
This commit is contained in:
Joris Vink 2016-06-29 16:23:00 +02:00 committed by GitHub
commit ec7a7b33e7
2 changed files with 156 additions and 52 deletions

View File

@ -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 {

204
src/cli.c
View File

@ -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;
cfiles_count = 0;
if ((p = getenv("CXX")) != NULL)
compiler_cpp = p;
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);
@ -1153,6 +1208,20 @@ cli_buildopt_cflags(struct buildopt *bopt, const char *string)
kore_buf_appendf(bopt->cflags, "%s ", 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)
{
@ -1167,6 +1236,32 @@ cli_buildopt_ldflags(struct buildopt *bopt, const char *string)
kore_buf_appendf(bopt->ldflags, "%s ", string);
}
static void
cli_build_flags_common(struct kore_buf* buf)
{
kore_buf_appendf(buf,
"-fPIC -I%s/src -I%s/src/includes ", rootdir, rootdir);
#if defined(PREFIX)
kore_buf_appendf(buf, "-I%s/include ", PREFIX);
#else
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(buf, "-I/opt/local/include ");
kore_buf_appendf(buf, "-I/usr/local/opt/openssl/include ");
#endif
#if defined(KORE_USE_PGSQL)
kore_buf_appendf(buf, "-I%s ", PGSQL_INCLUDE_PATH);
#endif
#if defined(KORE_NO_HTTP)
kore_buf_appendf(buf, "-DKORE_NO_HTTP ");
#endif
#if defined(KORE_NO_TLS)
kore_buf_appendf(buf, "-DKORE_NO_TLS ");
#endif
}
static void
cli_build_cflags(struct buildopt *bopt)
{
@ -1179,27 +1274,7 @@ cli_build_cflags(struct buildopt *bopt)
if (bopt->cflags == NULL)
bopt->cflags = kore_buf_create(128);
kore_buf_appendf(bopt->cflags,
"-fPIC -I%s/src -I%s/src/includes ", rootdir, rootdir);
#if defined(PREFIX)
kore_buf_appendf(bopt->cflags, "-I%s/include ", PREFIX);
#else
kore_buf_appendf(bopt->cflags, "-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 ");
#endif
#if defined(KORE_USE_PGSQL)
kore_buf_appendf(bopt->cflags, "-I%s ", PGSQL_INCLUDE_PATH);
#endif
#if defined(KORE_NO_HTTP)
kore_buf_appendf(bopt->cflags, "-DKORE_NO_HTTP ");
#endif
#if defined(KORE_NO_TLS)
kore_buf_appendf(bopt->cflags, "-DKORE_NO_TLS ");
#endif
cli_build_flags_common(bopt->cflags);
if (obopt != NULL && obopt->cflags != NULL) {
kore_buf_append(bopt->cflags, obopt->cflags->data,
@ -1211,6 +1286,31 @@ cli_build_cflags(struct buildopt *bopt)
cflags_count = kore_split_string(string, " ", cflags, CFLAGS_MAX);
}
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)
{