[build] Abstract build logic to provider lookup

Allow future extensibility for different build types.
Display detected type in project window title.
This commit is contained in:
Andy Williams 2016-05-16 08:58:32 +01:00
parent 4a759dfaf6
commit 357acdca7b
7 changed files with 279 additions and 57 deletions

View File

@ -938,10 +938,20 @@ static char *
_edi_win_title_get(const char *path)
{
char *winname, *dirname;
const char *type;
Edi_Build_Provider *provider;
int len;
provider = edi_build_provider_for_project_get();
if (provider)
type = provider->id;
else
type = "unknown";
dirname = basename((char*)path);
winname = malloc((8 + strlen(dirname)) * sizeof(char));
snprintf(winname, 8 + strlen(dirname), "Edi :: %s", dirname);
len = 8 + 3 + strlen(dirname) + strlen(type);
winname = malloc(len * sizeof(char));
snprintf(winname, len, "Edi :: %s (%s)", dirname, type);
return winname;
}

View File

@ -34,6 +34,7 @@ extern "C" {
#endif
#include <edi_create.h>
#include <edi_build_provider.h>
#include <edi_builder.h>
#include <edi_path.h>

View File

@ -11,6 +11,7 @@ AM_CPPFLAGS = \
lib_LTLIBRARIES = libedi.la
includes_HEADERS = \
edi_build_provider.h \
edi_builder.h \
edi_create.h \
edi_path.h \
@ -19,6 +20,8 @@ includesdir = $(includedir)/edi-@VMAJ@
libedi_la_SOURCES = \
edi_private.h \
edi_build_provider_make.c \
edi_build_provider.c \
edi_builder.c \
edi_create.c \
edi_path.c \

View File

@ -0,0 +1,34 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "Edi.h"
#include "edi_build_provider.h"
#include "edi_private.h"
extern Edi_Build_Provider _edi_build_provider_make;
EAPI Edi_Build_Provider *edi_build_provider_for_project_get()
{
return edi_build_provider_for_project_path_get(edi_project_get());
}
EAPI Edi_Build_Provider *edi_build_provider_for_project_path_get(const char *path)
{
if (!path)
return NULL;
if (_edi_build_provider_make.path_supported_is(path))
return &_edi_build_provider_make;
return NULL;
}
EAPI Edi_Build_Provider *edi_build_provider_for_id_get(const char *id)
{
if (!strcmp("make", id))
return &_edi_build_provider_make;
return NULL;
}

View File

@ -0,0 +1,77 @@
#ifndef EDI_BUILD_PROVIDER_H_
# define EDI_BUILD_PROVIDER_H_
#ifdef __cplusplus
extern "C" {
#endif
/**
* @file
* @brief These routines are used for managing information about supported build environments.
*/
typedef struct _Edi_Build_Provider
{
const char *id;
Eina_Bool (*path_supported_is)(const char *path);
Eina_Bool (*file_hidden_is)(const char *path);
void (*build)(void);
void (*test)(void);
void (*clean)(void);
} Edi_Build_Provider;
/**
* @brief Lookup information in build provider registry.
* @defgroup Lookup
*
* @{
*
* Looking up build providers based on project tree or id etc.
*
*/
/**
* Look up a build provider based on a project tree.
*
* @param path the root of a project tree to find the build provider for.
*
* @return an Edi_Build_Provider if one is registered for the type of project or NULL otherwise
*
* @ingroup Lookup
*/
EAPI Edi_Build_Provider *edi_build_provider_for_project_path_get(const char *path);
/**
* Look up a build provider based on the current project tree.
*
* @return an Edi_Build_Provider if one is registered for the current type of project or NULL otherwise
*
* @ingroup Lookup
*/
EAPI Edi_Build_Provider *edi_build_provider_for_project_get();
/**
* Look up a build provider based on a provider id.
* This is useful for overriding project tree based lookup.
*
* @param id the id of a provider you wish to get a handle for.
*
* @return an Edi_Build_Provider if one is registered or NULL otherwise
*
* @ingroup Lookup
*/
EAPI Edi_Build_Provider *edi_build_provider_for_id_get(const char *id);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* EDI_BUILD_PROVIDER_H_ */

View File

@ -0,0 +1,128 @@
#ifdef HAVE_CONFIG
# include "config.h"
#endif
#include <unistd.h>
#include <Ecore.h>
#include <Ecore_File.h>
#include "Edi.h"
#include "edi_private.h"
static Eina_Bool
_relative_path_exists(const char *base, const char *relative)
{
const char *path;
Eina_Bool ret;
path = edi_path_append(base, relative);
ret = ecore_file_exists(path);
free((void *)path);
return ret;
}
static Eina_Bool
_make_project_supported(const char *path)
{
return _relative_path_exists(path, "Makefile") ||
_relative_path_exists(path, "configure") ||
_relative_path_exists(path, "CMakeLists.txt") || // TODO move this one to a cmake file
_relative_path_exists(path, "autogen.sh");
}
static Eina_Bool
_make_file_hidden_is(const char *relative)
{
int len;
if (!relative || strlen(relative) == 0)
return EINA_FALSE;
len = strlen(relative);
if (relative[len-1] == 'o' && len >= 2)
{
if (relative[len-2] == '.')
return EINA_TRUE;
else
{
if ((relative[len-2] == 's' || relative[len-2] == 'l') &&
len >= 3 && relative[len-3] == '.')
return EINA_TRUE;
}
}
return EINA_FALSE;
}
static void
_make_build_make(void)
{
chdir(edi_project_get());
ecore_exe_pipe_run("make", ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ |
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR |
ECORE_EXE_USE_SH, NULL);
}
static void
_make_build_configure(void)
{
chdir(edi_project_get());
ecore_exe_pipe_run("./configure && make",
ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ |
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR |
ECORE_EXE_USE_SH, NULL);
}
static void
_make_build_cmake(void)
{
chdir(edi_project_get());
ecore_exe_pipe_run("mkdir -p build && cd build && cmake .. && make && cd ..",
ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ |
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR |
ECORE_EXE_USE_SH, NULL);
}
static void
_make_build_autogen(void)
{
chdir(edi_project_get());
ecore_exe_pipe_run("./autogen.sh && make",
ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ |
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR |
ECORE_EXE_USE_SH, NULL);
}
static void
_make_build(void)
{
if (edi_project_file_exists("Makefile"))
_make_build_make();
else if (edi_project_file_exists("configure"))
_make_build_configure();
else if (edi_project_file_exists("CMakeLists.txt"))
_make_build_cmake();
else if (edi_project_file_exists("autogen.sh"))
_make_build_autogen();
}
static void
_make_test(void)
{
chdir(edi_project_get());
ecore_exe_pipe_run("env CK_VERBOSITY=verbose make check", ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ |
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR, NULL);
}
static void
_make_clean(void)
{
chdir(edi_project_get());
ecore_exe_pipe_run("make clean", ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ |
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR, NULL);
}
Edi_Build_Provider _edi_build_provider_make =
{"make", _make_project_supported, _make_file_hidden_is,
_make_build, _make_test, _make_clean};

View File

@ -12,78 +12,47 @@
EAPI Eina_Bool
edi_builder_can_build(void)
{
return edi_project_file_exists("Makefile") ||
edi_project_file_exists("configure") ||
edi_project_file_exists("CMakeLists.txt") ||
edi_project_file_exists("autogen.sh");
}
Edi_Build_Provider *provider;
EAPI void
_edi_builder_build_make(void)
{
chdir(edi_project_get());
ecore_exe_pipe_run("make", ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ |
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR |
ECORE_EXE_USE_SH, NULL);
}
provider = edi_build_provider_for_project_get();
EAPI void
_edi_builder_build_configure(void)
{
chdir(edi_project_get());
ecore_exe_pipe_run("./configure && make",
ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ |
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR |
ECORE_EXE_USE_SH, NULL);
}
EAPI void
_edi_builder_build_cmake(void)
{
chdir(edi_project_get());
ecore_exe_pipe_run("mkdir -p build && cd build && cmake .. && make && cd ..",
ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ |
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR |
ECORE_EXE_USE_SH, NULL);
}
EAPI void
_edi_builder_build_autogen(void)
{
chdir(edi_project_get());
ecore_exe_pipe_run("./autogen.sh && make",
ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ |
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR |
ECORE_EXE_USE_SH, NULL);
return !!provider;
}
EAPI void
edi_builder_build(void)
{
if (edi_project_file_exists("Makefile"))
_edi_builder_build_make();
else if (edi_project_file_exists("configure"))
_edi_builder_build_configure();
else if (edi_project_file_exists("CMakeLists.txt"))
_edi_builder_build_cmake();
else if (edi_project_file_exists("autogen.sh"))
_edi_builder_build_autogen();
Edi_Build_Provider *provider;
provider = edi_build_provider_for_project_get();
if (!provider)
return;
provider->build();
}
EAPI void
edi_builder_test(void)
{
chdir(edi_project_get());
ecore_exe_pipe_run("env CK_VERBOSITY=verbose make check", ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ |
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR, NULL);
Edi_Build_Provider *provider;
provider = edi_build_provider_for_project_get();
if (!provider)
return;
provider->test();
}
EAPI void
edi_builder_clean(void)
{
chdir(edi_project_get());
ecore_exe_pipe_run("make clean", ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ |
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR, NULL);
Edi_Build_Provider *provider;
provider = edi_build_provider_for_project_get();
if (!provider)
return;
provider->clean();
}