mirror of
https://github.com/yasm/yasm
synced 2026-08-26 22:26:05 -04:00
More makedep features (#80)
yasm.c: Added -MD, -MT and -MP options similar to gcc. Also added --makedep-dos2unix-slash for helping users of NUG make (and similar) on Windows. The -MD option does both assembling and Makefile dependency generation in one go, which convenient and a little quicker. nasm-preproc.c: Have to always gather dependencies to support -MD. Minimal cost. Co-authored-by: knut st. osmundsen <bird-skylake@anduin.net>
This commit is contained in:
parent
563a03be81
commit
241bf4c42c
2 changed files with 188 additions and 33 deletions
|
|
@ -70,6 +70,10 @@ static int special_options = 0;
|
|||
static int preproc_only = 0;
|
||||
static unsigned int force_strict = 0;
|
||||
static int generate_make_dependencies = 0;
|
||||
static int makedep_with_empty_recipts = 0;
|
||||
static int makedep_dos2unix_slash = 0;
|
||||
/*@null@*/ /*@only@*/ static const char *makedep_out_filename = NULL;
|
||||
/*@null@*/ /*@only@*/ static const char *makedep_target = NULL;
|
||||
static int warning_error = 0; /* warnings being treated as errors */
|
||||
static FILE *errfile;
|
||||
/*@null@*/ /*@only@*/ static char *error_filename = NULL;
|
||||
|
|
@ -105,7 +109,11 @@ static int preproc_only_handler(char *cmd, /*@null@*/ char *param, int extra);
|
|||
static int opt_include_option(char *cmd, /*@null@*/ char *param, int extra);
|
||||
static int opt_preproc_option(char *cmd, /*@null@*/ char *param, int extra);
|
||||
static int opt_ewmsg_handler(char *cmd, /*@null@*/ char *param, int extra);
|
||||
static int opt_makedep_and_assemble_handler(char *cmd, /*@null@*/ char *param, int extra);
|
||||
static int opt_makedep_empty_handler(char *cmd, /*@null@*/ char *param, int extra);
|
||||
static int opt_makedep_target_handler(char *cmd, /*@null@*/ char *param, int extra);
|
||||
static int opt_makedep_handler(char *cmd, /*@null@*/ char *param, int extra);
|
||||
static int opt_makedep_dos2unix_slash_handler(char *cmd, /*@null@*/ char *param, int extra);
|
||||
static int opt_prefix_handler(char *cmd, /*@null@*/ char *param, int extra);
|
||||
static int opt_suffix_handler(char *cmd, /*@null@*/ char *param, int extra);
|
||||
#if defined(CMAKE_BUILD) && defined(BUILD_SHARED_LIBS)
|
||||
|
|
@ -137,6 +145,10 @@ static void apply_preproc_standard_macros(const yasm_stdmac *stdmacs);
|
|||
static void apply_preproc_saved_options(void);
|
||||
static void print_list_keyword_desc(const char *name, const char *keyword);
|
||||
|
||||
#ifndef MAX
|
||||
# define MAX(a, b) ( ((a) > (b)) ? (a) : (b) )
|
||||
#endif
|
||||
|
||||
/* values for special_options */
|
||||
#define SPECIAL_SHOW_HELP 0x01
|
||||
#define SPECIAL_SHOW_VERSION 0x02
|
||||
|
|
@ -178,8 +190,18 @@ static opt_option options[] =
|
|||
N_("inhibits warning messages"), NULL },
|
||||
{ 'W', NULL, 0, opt_warning_handler, 0,
|
||||
N_("enables/disables warning"), NULL },
|
||||
{ 'M', NULL, 0, opt_makedep_handler, 0,
|
||||
{ 0, "MD", 1, opt_makedep_and_assemble_handler, 0,
|
||||
N_("generate Makefile dependencies and assemble normally"),
|
||||
N_("file")},
|
||||
{ 0, "MP", 0, opt_makedep_empty_handler, 0,
|
||||
N_("generate empty Makefile recipts for the include files"), NULL },
|
||||
{ 0, "MT", 1, opt_makedep_target_handler, 0,
|
||||
N_("the Makefile target to associate the dependencies with"),
|
||||
N_("target")},
|
||||
{ 'M', NULL, 0, opt_makedep_handler, 0, /* -M must come after -MD and -MP'! */
|
||||
N_("generate Makefile dependencies on stdout"), NULL },
|
||||
{ 0, "makedep-dos2unix-slash", 0, opt_makedep_dos2unix_slash_handler, 0,
|
||||
N_("convert DOS to UNIX slashes in Makefile dependencies file"), NULL },
|
||||
{ 'Z', NULL, 1, opt_error_file, 0,
|
||||
N_("redirect error messages to file"), N_("file") },
|
||||
{ 's', NULL, 0, opt_error_stdout, 0,
|
||||
|
|
@ -247,12 +269,129 @@ typedef struct constcharparam {
|
|||
|
||||
static constcharparam_head preproc_options;
|
||||
|
||||
static char *
|
||||
dos2unix_slash(char *path)
|
||||
{
|
||||
char *slash = strchr(path, '\\');
|
||||
while (slash) {
|
||||
*slash++ = '/';
|
||||
slash = strchr(slash, '\\');
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
static int
|
||||
do_generate_make_dependencies(void)
|
||||
{
|
||||
size_t empty_recipts_alloc = 0;
|
||||
size_t empty_recipts_len = 0;
|
||||
char *empty_recipts = NULL;
|
||||
char *preproc_buf;
|
||||
size_t linelen;
|
||||
size_t got;
|
||||
FILE *depout = stdout;
|
||||
const char *target;
|
||||
|
||||
/* Open the -MD <file>. */
|
||||
if ( makedep_out_filename != NULL
|
||||
&& strcmp(makedep_out_filename, "-") != 0) {
|
||||
depout = open_file(makedep_out_filename, "wt");
|
||||
if (!depout)
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* -MT (and later -MQ?) can be used to specify the target name.
|
||||
If not given, fall back on the object file. */
|
||||
target = makedep_target ? makedep_target : obj_filename;
|
||||
|
||||
/* Make sure preproc_buf is large enough for either of the main
|
||||
file names to avoid checking later (very ulikely that it isn't). */
|
||||
linelen = strlen(target);
|
||||
got = strlen(in_filename);
|
||||
preproc_buf = yasm_xmalloc(MAX(PREPROC_BUF_SIZE, MAX(got, linelen) + 1));
|
||||
|
||||
/* The target (the object file) to add the dependencies to. */
|
||||
if (!makedep_dos2unix_slash || makedep_target == NULL)
|
||||
fputs(target, depout);
|
||||
else
|
||||
fputs(dos2unix_slash(memcpy(preproc_buf, target, linelen + 1)),
|
||||
depout);
|
||||
|
||||
/* The source file (no empty rule for it, thus the code duplication). */
|
||||
linelen += 2 + got;
|
||||
if (linelen <= 72)
|
||||
fputs(": ", depout);
|
||||
else {
|
||||
fputs(": \\\n ", depout);
|
||||
linelen = 1 + got;
|
||||
}
|
||||
if (!makedep_dos2unix_slash)
|
||||
fwrite(in_filename, got, 1, depout);
|
||||
else
|
||||
fwrite(dos2unix_slash(memcpy(preproc_buf, in_filename, got + 1)),
|
||||
got, 1, depout);
|
||||
|
||||
/* Now the include files. */
|
||||
while ((got = yasm_preproc_get_included_file(cur_preproc, preproc_buf,
|
||||
PREPROC_BUF_SIZE)) != 0) {
|
||||
linelen += 1 + got;
|
||||
if (linelen <= 72)
|
||||
fputc(' ', depout);
|
||||
else {
|
||||
fputs(" \\\n ", depout);
|
||||
linelen = 1 + got;
|
||||
}
|
||||
if (makedep_dos2unix_slash)
|
||||
dos2unix_slash(preproc_buf);
|
||||
fwrite(preproc_buf, got, 1, depout);
|
||||
|
||||
if (makedep_with_empty_recipts) {
|
||||
/* We only get one shot at each include file, so we generate the
|
||||
dummy recipts in a buffer while we're writing the dependencies
|
||||
for the object file. (The empty recipts makes make shut up
|
||||
about deleted includes.) */
|
||||
static const char empty_tail[] = ":\n\n";
|
||||
size_t cur_len = empty_recipts_len;
|
||||
|
||||
empty_recipts_len = cur_len + got + sizeof(empty_tail) - 1;
|
||||
if (empty_recipts_len >= empty_recipts_alloc) {
|
||||
if (empty_recipts_alloc == 0)
|
||||
empty_recipts_alloc = 4096;
|
||||
while (empty_recipts_len >= empty_recipts_alloc)
|
||||
empty_recipts_alloc *= 2;
|
||||
empty_recipts = yasm_xrealloc(empty_recipts,
|
||||
empty_recipts_alloc);
|
||||
}
|
||||
|
||||
memcpy(&empty_recipts[cur_len], preproc_buf, got);
|
||||
cur_len += got;
|
||||
memcpy(&empty_recipts[cur_len], empty_tail, sizeof(empty_tail));
|
||||
}
|
||||
}
|
||||
|
||||
fputc('\n', depout);
|
||||
yasm_xfree(preproc_buf);
|
||||
|
||||
if (empty_recipts) {
|
||||
fputc('\n', depout);
|
||||
fwrite(empty_recipts, empty_recipts_len, 1, depout);
|
||||
yasm_xfree(empty_recipts);
|
||||
}
|
||||
|
||||
if ( depout != stdout
|
||||
&& fclose(depout) != 0) {
|
||||
print_error(_("error writing `%s'"), makedep_out_filename);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
do_preproc_only(void)
|
||||
{
|
||||
yasm_linemap *linemap;
|
||||
char *preproc_buf;
|
||||
size_t got;
|
||||
const char *base_filename;
|
||||
FILE *out = NULL;
|
||||
yasm_errwarns *errwarns = yasm_errwarns_create();
|
||||
|
|
@ -301,25 +440,7 @@ do_preproc_only(void)
|
|||
|
||||
/* Pre-process until done */
|
||||
if (generate_make_dependencies) {
|
||||
size_t totlen;
|
||||
|
||||
preproc_buf = yasm_xmalloc(PREPROC_BUF_SIZE);
|
||||
|
||||
fprintf(stdout, "%s: %s", obj_filename, in_filename);
|
||||
totlen = strlen(obj_filename)+2+strlen(in_filename);
|
||||
|
||||
while ((got = yasm_preproc_get_included_file(cur_preproc, preproc_buf,
|
||||
PREPROC_BUF_SIZE)) != 0) {
|
||||
totlen += got;
|
||||
if (totlen > 72) {
|
||||
fputs(" \\\n ", stdout);
|
||||
totlen = 2;
|
||||
}
|
||||
fputc(' ', stdout);
|
||||
fwrite(preproc_buf, got, 1, stdout);
|
||||
}
|
||||
fputc('\n', stdout);
|
||||
yasm_xfree(preproc_buf);
|
||||
do_generate_make_dependencies();
|
||||
} else {
|
||||
while ((preproc_buf = yasm_preproc_get_line(cur_preproc)) != NULL) {
|
||||
fputs(preproc_buf, out);
|
||||
|
|
@ -573,6 +694,10 @@ do_assemble(void)
|
|||
fclose(list);
|
||||
}
|
||||
|
||||
/* Generate make dependency. */
|
||||
if (generate_make_dependencies)
|
||||
do_generate_make_dependencies();
|
||||
|
||||
yasm_errwarns_output_all(errwarns, linemap, warning_error,
|
||||
print_yasm_error, print_yasm_warning);
|
||||
|
||||
|
|
@ -1170,6 +1295,32 @@ opt_ewmsg_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
opt_makedep_and_assemble_handler(/*@unused@*/ char *cmd, char *param,
|
||||
/*@unused@*/ int extra)
|
||||
{
|
||||
generate_make_dependencies = 1;
|
||||
makedep_out_filename = param;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
opt_makedep_empty_handler(/*@unused@*/ char *cmd, /*@unused@*/ char *param,
|
||||
/*@unused@*/ int extra)
|
||||
{
|
||||
makedep_with_empty_recipts = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
opt_makedep_target_handler(/*@unused@*/ char *cmd, char *param,
|
||||
/*@unused@*/ int extra)
|
||||
{
|
||||
makedep_target = param;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
opt_makedep_handler(/*@unused@*/ char *cmd, /*@unused@*/ char *param,
|
||||
/*@unused@*/ int extra)
|
||||
|
|
@ -1181,6 +1332,14 @@ opt_makedep_handler(/*@unused@*/ char *cmd, /*@unused@*/ char *param,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
opt_makedep_dos2unix_slash_handler(/*@unused@*/ char *cmd, /*@unused@*/ char *param,
|
||||
/*@unused@*/ int extra)
|
||||
{
|
||||
makedep_dos2unix_slash = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
opt_prefix_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -151,7 +151,8 @@ nasm_preproc_create(const char *in_filename, yasm_symtab *symtab,
|
|||
nasm_symtab = symtab;
|
||||
cur_lm = lm;
|
||||
cur_errwarns = errwarns;
|
||||
preproc_deps = NULL;
|
||||
preproc_deps = yasm_xmalloc(sizeof(struct preproc_dep_head));
|
||||
STAILQ_INIT(preproc_deps);
|
||||
done_dep_preproc = 0;
|
||||
preproc_nasm->line = NULL;
|
||||
preproc_nasm->file_name = NULL;
|
||||
|
|
@ -176,8 +177,12 @@ nasm_preproc_destroy(yasm_preproc *preproc)
|
|||
if (preproc_nasm->in)
|
||||
fclose(preproc_nasm->in);
|
||||
yasm_xfree(preproc);
|
||||
if (preproc_deps)
|
||||
yasm_xfree(preproc_deps);
|
||||
while (!STAILQ_EMPTY(preproc_deps)) {
|
||||
preproc_dep *dep = STAILQ_FIRST(preproc_deps);
|
||||
STAILQ_REMOVE_HEAD(preproc_deps, link);
|
||||
yasm_xfree(dep->name);
|
||||
yasm_xfree(dep);
|
||||
}
|
||||
yasm_xfree(nasm_src_set_fname(NULL));
|
||||
}
|
||||
|
||||
|
|
@ -222,10 +227,6 @@ nasm_preproc_add_dep(char *name)
|
|||
{
|
||||
preproc_dep *dep;
|
||||
|
||||
/* If not processing dependencies, simply return */
|
||||
if (!preproc_deps)
|
||||
return;
|
||||
|
||||
/* Save in preproc_deps */
|
||||
dep = yasm_xmalloc(sizeof(preproc_dep));
|
||||
dep->name = yasm__xstrdup(name);
|
||||
|
|
@ -236,11 +237,6 @@ static size_t
|
|||
nasm_preproc_get_included_file(yasm_preproc *preproc, /*@out@*/ char *buf,
|
||||
size_t max_size)
|
||||
{
|
||||
if (!preproc_deps) {
|
||||
preproc_deps = yasm_xmalloc(sizeof(struct preproc_dep_head));
|
||||
STAILQ_INIT(preproc_deps);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
char *line;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue