/********************************************************************** * Premake - project.c * An interface around the project data. * * Copyright (c) 2002-2005 Jason Perkins and the Premake project * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License in the file LICENSE.txt for details. **********************************************************************/ #include #include #include "premake.h" #include "os.h" Project* project = NULL; static Package* my_pkg = NULL; static PkgConfig* my_cfg = NULL; static FileConfig* my_fcfg = NULL; static Option* my_opt = NULL; static char buffer[8192]; /************************************************************************ * Project lifecycle routines ***********************************************************************/ void prj_open() { if (project != NULL) prj_close(); project = ALLOCT(Project); } void prj_close() { int i, j; if (project != NULL) { for (i = 0; i < prj_get_numpackages(); ++i) { Package* package = project->packages[i]; for (j = 0; j < prj_get_numconfigs(); ++j) { PkgConfig* config = package->configs[j]; free((void*)config->buildopts); free((void*)config->defines); free((void*)config->files); free((void*)config->flags); free((void*)config->incpaths); free((void*)config->libpaths); free((void*)config->linkopts); free((void*)config->links); prj_freelist((void**)config->fileconfigs); } prj_freelist((void**)package->configs); if (package->data != NULL) free(package->data); } prj_freelist((void**)project->options); prj_freelist((void**)project->configs); prj_freelist((void**)project->packages); free(project); project = NULL; } } /************************************************************************ * Locate a package by name ***********************************************************************/ int prj_find_package(const char* name) { int i; for (i = 0; i < prj_get_numpackages(); ++i) { if (matches(name, project->packages[i]->name)) return i; } return -1; } /************************************************************************ * Retrieve the active configuration for the given package ***********************************************************************/ PkgConfig* prj_get_config_for(int i) { int j; for (j = 0; j < prj_get_numconfigs(); ++j) { if (my_pkg->configs[j] == my_cfg) return project->packages[i]->configs[j]; } return NULL; } /************************************************************************ * Get/set a file build action ***********************************************************************/ const char* prj_get_buildaction() { return my_fcfg->buildaction; } int prj_is_buildaction(const char* action) { return matches(my_fcfg->buildaction, action); } void prj_set_buildaction(const char* action) { my_fcfg->buildaction = action; } /************************************************************************ * Get/set generator-specific data ***********************************************************************/ void* prj_get_data() { return prj_get_data_for(my_pkg->index); } void* prj_get_data_for(int i) { return project->packages[i]->data; } void prj_set_data(void* data) { my_pkg->data = data; } /************************************************************************ * Return the list of defines for the current object ***********************************************************************/ int prj_get_numdefines() { return prj_getlistsize((void**)prj_get_defines()); } const char** prj_get_defines() { return my_cfg->defines; } /************************************************************************ * Query the object directories ***********************************************************************/ const char* prj_get_bindir() { if (my_cfg->bindir != NULL) { return my_cfg->bindir; } else { strcpy(buffer, path_build(my_pkg->path, my_cfg->prjConfig->bindir)); return buffer; } } /* * Get the relative directory FROM the current package TO the * binary output directory of the specified package. */ const char* prj_get_bindir_for(int i) { PkgConfig* cfg = prj_get_config_for(i); if (cfg->bindir != NULL) { const char* target; Package* pkg = prj_get_package_for(i); strcpy(buffer, path_build(my_pkg->path, pkg->path)); strcat(buffer, "/"); strcat(buffer, cfg->bindir); /* Now convert that to a relative path from here */ target = path_build("", buffer); if (target[0] == '/') ++target; return target; } else { // strcpy(buffer, path_build(my_pkg->path, prj_get_path())); // strcpy(buffer, "/"); // strcpy(buffer, cfg->prjConfig->bindir); strcpy(buffer, path_build(my_pkg->path, my_cfg->prjConfig->bindir)); return buffer; } } const char* prj_get_libdir() { if (my_cfg->libdir != NULL) { return my_cfg->libdir; } else { strcpy(buffer, path_build(my_pkg->path, my_cfg->prjConfig->libdir)); return buffer; } } const char* prj_get_libdir_for(int i) { PkgConfig* cfg = prj_get_config_for(i); if (cfg->libdir != NULL) { const char* target; Package* pkg = prj_get_package_for(i); strcpy(buffer, path_build(my_pkg->path, pkg->path)); strcat(buffer, "/"); strcat(buffer, cfg->libdir); /* Now convert that to a relative path from here */ target = path_build("", buffer); if (target[0] == '/') ++target; return target; } else { strcpy(buffer, path_build(my_pkg->path, my_cfg->prjConfig->libdir)); return buffer; } } const char* prj_get_objdir() { if (my_cfg->objdir != NULL) { return my_cfg->objdir; } else { return path_combine(my_pkg->objdir, my_cfg->prjConfig->name); } } const char* prj_get_pkgobjdir() { if (my_cfg->objdir == NULL) { return my_pkg->objdir; } else { return NULL; } } const char* prj_get_outdir() { return prj_get_outdir_for(my_pkg->index); } const char* prj_get_outdir_for(int i) { const char* targetdir; PkgConfig* cfg = prj_get_config_for(i); if (matches(cfg->kind, "lib")) strcpy(buffer, prj_get_libdir_for(i)); else strcpy(buffer, prj_get_bindir_for(i)); targetdir = path_getdir(cfg->target); if (strlen(targetdir) > 0) { strcat(buffer, "/"); strcat(buffer, targetdir); } return buffer; } /************************************************************************ * Custom target decorations ***********************************************************************/ const char* prj_get_prefix() { return my_cfg->prefix; } const char* prj_get_extension() { return my_cfg->extension; } /************************************************************************ * Return the files associated with the active object ***********************************************************************/ const char** prj_get_files() { return my_cfg->files; } int prj_has_file(const char* name) { const char** ptr = my_cfg->files; while (*ptr != NULL) { if (matches(*ptr, name)) return 1; ptr++; } return 0; } const char* prj_find_filetype(const char* extension) { const char** ptr = my_cfg->files; while (*ptr != NULL) { if (matches(path_getextension(*ptr), extension)) return *ptr; ptr++; } return NULL; } /************************************************************************ * Query the build flags ***********************************************************************/ int prj_has_flag(const char* flag) { return prj_has_flag_for(my_pkg->index, flag); } int prj_has_flag_for(int i, const char* flag) { PkgConfig* cfg = prj_get_config_for(i); const char** ptr = cfg->flags; while (*ptr != NULL) { if (matches(*ptr, flag)) return 1; ptr++; } return 0; } int prj_get_numbuildoptions() { return prj_getlistsize((void**)prj_get_buildoptions()); } const char** prj_get_buildoptions() { return my_cfg->buildopts; } int prj_get_numlinkoptions() { return prj_getlistsize((void**)prj_get_linkoptions()); } const char** prj_get_linkoptions() { return my_cfg->linkopts; } /************************************************************************ * Return the list of pre/post build commands for the current object ***********************************************************************/ int prj_get_numprebuildcommands() { return prj_getlistsize((void**)prj_get_prebuildcommands()); } const char** prj_get_prebuildcommands() { return my_cfg->prebuildcmds; } int prj_get_numprelinkcommands() { return prj_getlistsize((void**)prj_get_prelinkcommands()); } const char** prj_get_prelinkcommands() { return my_cfg->prelinkcmds; } int prj_get_numpostbuildcommands() { return prj_getlistsize((void**)prj_get_postbuildcommands()); } const char** prj_get_postbuildcommands() { return my_cfg->postbuildcmds; } /************************************************************************ * Query the target kind of the current object ***********************************************************************/ const char* prj_get_kind() { return my_cfg->kind; } int prj_is_kind(const char* kind) { return matches(my_cfg->kind, kind); } /************************************************************************ * Return the list of include paths for the current object ***********************************************************************/ int prj_get_numincpaths() { return prj_getlistsize((void**)prj_get_incpaths()); } const char** prj_get_incpaths() { return my_cfg->incpaths; } /************************************************************************ * Query the language of the current object ***********************************************************************/ const char* prj_get_language() { return my_pkg->lang; } const char* prj_get_language_for(int i) { return project->packages[i]->lang; } int prj_is_lang(const char* lang) { return matches(my_pkg->lang, lang); } /************************************************************************ * Return the list of linker paths for the current object ***********************************************************************/ const char** prj_get_libpaths() { return my_cfg->libpaths; } /************************************************************************ * Return the list of links for the current object ***********************************************************************/ int prj_get_numlinks() { return prj_getlistsize((void**)prj_get_links()); } const char** prj_get_links() { return my_cfg->links; } /************************************************************************ * Return the name of the active object ***********************************************************************/ const char* prj_get_name() { return project->name; } const char* prj_get_cfgname() { return my_cfg->prjConfig->name; } const char* prj_get_pkgname() { return my_pkg->name; } const char* prj_get_pkgname_for(int i) { return project->packages[i]->name; } /************************************************************************ * Return the total number of configurations in the project ***********************************************************************/ int prj_get_numconfigs() { return prj_getlistsize((void**)project->configs); } /************************************************************************ * Return the total number of options in the project ***********************************************************************/ int prj_get_numoptions() { return prj_getlistsize((void**)project->options); } /************************************************************************ * Return the total number of packages in the project ***********************************************************************/ int prj_get_numpackages() { return prj_getlistsize((void**)project->packages); } /************************************************************************ * Return the name and description of the currently selected option. ***********************************************************************/ const char* prj_get_optdesc() { return my_opt->desc; } const char* prj_get_optname() { return my_opt->flag; } /************************************************************************ * Return the active object ***********************************************************************/ Package* prj_get_package() { return my_pkg; } Package* prj_get_package_for(int i) { return project->packages[i]; } /************************************************************************ * Return the path to the generated object scripts. ***********************************************************************/ const char* prj_get_path() { return project->path; } const char* prj_get_pkgpath() { return my_pkg->path; } const char* prj_get_pkgpath_for(int i) { return project->packages[i]->path; } const char* prj_get_pkgfilename(const char* extension) { return prj_get_pkgfilename_for(my_pkg->index, extension); } const char* prj_get_pkgfilename_for(int i, const char* extension) { strcpy(buffer, path_build(project->path, prj_get_pkgpath_for(i))); if (strlen(buffer) > 0) strcat(buffer, "/"); strcat(buffer, project->packages[i]->name); if (extension != NULL) { strcat(buffer, "."); strcat(buffer, extension); } return buffer; } /************************************************************************ * Get the PCH information for the configuration. ***********************************************************************/ int prj_has_pch() { return (!prj_has_flag("no-pch") && my_cfg->pchHeader != NULL); } const char* prj_get_pch_header() { return my_cfg->pchHeader; } const char* prj_get_pch_source() { return my_cfg->pchSource; } /************************************************************************ * Query the list of resource defines for the current object ***********************************************************************/ int prj_get_numresdefines() { return prj_getlistsize((void**)prj_get_resdefines()); } const char** prj_get_resdefines() { return my_cfg->resdefines; } /************************************************************************ * Query the list of resource options for the current object ***********************************************************************/ int prj_get_numresoptions() { return prj_getlistsize((void**)prj_get_resoptions()); } const char** prj_get_resoptions() { return my_cfg->resopts; } /************************************************************************ * Query the list of resource paths for the current object ***********************************************************************/ int prj_get_numrespaths() { return prj_getlistsize((void**)prj_get_respaths()); } const char** prj_get_respaths() { return my_cfg->respaths; } /************************************************************************ * Return the script name for an object. ***********************************************************************/ const char* prj_get_script() { return project->script; } const char* prj_get_pkgscript() { return my_pkg->script; } /************************************************************************ * Return the target for the active object. There are a couple of * variants here; at some point I need to walk through all the usages * and see if I can merge these into one method. ***********************************************************************/ const char* prj_get_target() { return prj_get_target_for(my_pkg->index); } const char* prj_get_target_for(int i) { const char* extension = ""; /* Get the active configuration for this target */ Package* pkg = prj_get_package_for(i); PkgConfig* cfg = prj_get_config_for(i); const char* filename = path_getbasename(cfg->target); /* Prepopulate the buffer with the output directory */ prj_get_outdir_for(i); if (matches(buffer, ".")) strcpy(buffer, ""); if (strlen(buffer) > 0) strcat(buffer, "/"); if (cfg->prefix != NULL) strcat(buffer, cfg->prefix); if (matches(pkg->lang, "c#")) { strcat(buffer, filename); if (matches(cfg->kind, "dll")) extension = "dll"; else extension = "exe"; } else if (os_is("windows")) { /* CodeBlocks and GNU uses Unix naming for static libs */ if ((matches(g_target, "cb-gcc") || matches(g_target, "gnu")) && matches(cfg->kind, "lib")) { if (cfg->prefix == NULL) strcat(buffer, "lib"); strcat(buffer, filename); extension = "a"; } else { strcat(buffer, filename); if (matches(cfg->kind, "lib")) extension = "lib"; else if (matches(cfg->kind, "dll")) extension = "dll"; else extension = "exe"; } } else if (os_is("macosx") && matches(cfg->kind, "dll")) { if (cfg->prefix == NULL) strcat(buffer, "lib"); strcat(buffer, filename); if (prj_has_flag_for(i, "dylib")) extension = "dylib"; else extension = "so"; } else { if (matches(cfg->kind, "lib")) { if (cfg->prefix == NULL) strcat(buffer, "lib"); strcat(buffer, filename); extension = "a"; } else if (matches(cfg->kind, "dll")) { if (cfg->prefix == NULL) strcat(buffer, "lib"); strcat(buffer, filename); extension = "so"; } else { strcat(buffer, filename); } } /* Apply the file extension, which can be customized */ if (cfg->extension != NULL) extension = cfg->extension; if (strlen(extension) > 0) strcat(buffer, "."); strcat(buffer, extension); return buffer; } /* * Okay - I need to start documenting these functions better; I * can't remember what does what any more. This functions gets * the path FROM the current package directory TO the target of * the specified package. As you can see, I got off on the wrong * track here, and I'm trying to get it back. */ const char* prj_get_relativetarget_for(int i) { return prj_get_target_for(i); #if OBSOLETE char backpath[8192]; const char* target; /* Get the path back to the main project so I have a common * point of reference between myself and this dependency */ strcpy(backpath, path_build(prj_get_pkgpath(), prj_get_path())); /* Append the path to the dependent project library */ if (strlen(backpath) > 0) strcat(backpath, "/"); strcat(backpath, prj_get_pkgpath_for(i)); /* Append the path from the dependent project to its output dir */ if (strlen(backpath) > 0) strcat(backpath, "/"); strcat(backpath, prj_get_target_for(i)); /* Now convert that to a relative path from here */ target = path_build("", backpath); if (target[0] == '/') ++target; return target; #endif } const char* prj_get_target_raw() { return my_cfg->target; } const char* prj_get_targetname_for(int i) { PkgConfig* cfg = prj_get_config_for(i); strcpy(buffer, path_getname(cfg->target)); return buffer; } /************************************************************************ * Return package URL ***********************************************************************/ const char* prj_get_url() { return my_pkg->url; } /************************************************************************ * Activate a project object. ***********************************************************************/ void prj_select_config(int i) { if (my_pkg == NULL) prj_select_package(0); my_cfg = my_pkg->configs[i]; } void prj_select_file(const char* name) { int i; for (i = 0; i < prj_getlistsize((void**)my_cfg->files); ++i) { if (matches(my_cfg->files[i], name)) my_fcfg = my_cfg->fileconfigs[i]; } } void prj_select_option(int i) { my_opt = project->options[i]; } void prj_select_package(int i) { my_pkg = project->packages[i]; } /************************************************************************ * List management routines ***********************************************************************/ void** prj_newlist(int len) { void** list = (void**)malloc(sizeof(void*) * (len + 1)); list[len] = NULL; return list; } void prj_freelist(void** list) { int i = 0; while (list[i] != NULL) free(list[i++]); free(list); } int prj_getlistsize(void** list) { int count = 0; void** ptr = list; while (*ptr != NULL) { ptr++; count++; } return count; } int prj_has_guid() { return (my_pkg->guid != NULL); } const char* prj_get_guid() { return my_pkg->guid; } int prj_has_libpath(const char* path) { const char** libpath; if (path == NULL || strlen(path) == 0) return 1; libpath = prj_get_libpaths(); while (*libpath) { if (matches(*libpath, path)) return 1; libpath++; } if (matches(prj_get_libdir(), path)) return 1; if (matches(prj_get_bindir(), path)) return 1; return 0; } int prj_has_importlibname() { return (my_cfg->implibname != NULL); } const char* prj_get_importlibname() { return my_cfg->implibname; }