From 0723a83fd6cebe059629c88a6e9e2c9ffb696534 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Tue, 6 Aug 2024 22:03:19 +0100 Subject: [PATCH] Avoid linker errors on Windows with long command lines --- NEWS.md | 2 ++ src/cgen.c | 33 +++++++++++++++++++++++++++++++-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index 59898d699..488fdfdcf 100644 --- a/NEWS.md +++ b/NEWS.md @@ -17,6 +17,8 @@ coverage database file instead of a top-level unit name. - The `--force-init` command which was deprecated in the 1.7 release has been removed. +- Elaboration of large designs on Windows no longer fail with linker + errors due to excessive command line length. ## Version 1.13.1 - 2024-07-25 - Windows installer was missing some standard library files. diff --git a/src/cgen.c b/src/cgen.c index 5058c2d99..701b4017c 100644 --- a/src/cgen.c +++ b/src/cgen.c @@ -62,6 +62,7 @@ static A(char *) link_args; static A(char *) cleanup_files = AINIT; #define UNITS_PER_JOB 25 +#define LARGE_OBJECT_COUNT 10 static void cgen_find_children(vcode_unit_t root, unit_list_t *units) { @@ -215,8 +216,29 @@ static void cgen_link(const char *module_name, char **objs, int nobjs) cgen_link_arg("-o"); cgen_link_arg("%s", so_path); - for (int i = 0; i < nobjs; i++) - cgen_link_arg("%s", objs[i]); + char *tmplist = NULL; + if (nobjs >= LARGE_OBJECT_COUNT) { + // If there are a large number of objects to link then pass them + // in a file rather than individually to avoid command line length + // limits on Windows + + tmplist = nvc_temp_file(); + + FILE *f = fopen(tmplist, "w"); + if (f == NULL) + fatal_errno("%s", tmplist); + + for (int i = 0; i < nobjs; i++) + fprintf(f, "%s\n", objs[i]); + + fclose(f); + + cgen_link_arg("@%s", tmplist); + } + else { + for (int i = 0; i < nobjs; i++) + cgen_link_arg("%s", objs[i]); + } #if defined LINKER_PATH && defined __OpenBSD__ // Extra linker arguments to make constructors work on OpenBSD @@ -250,6 +272,13 @@ static void cgen_link(const char *module_name, char **objs, int nobjs) fatal_errno("unlink: %s", objs[i]); } + if (tmplist != NULL) { + if (unlink(tmplist) != 0) + fatal_errno("unlink: %s", tmplist); + + free(tmplist); + } + progress("linking shared library"); for (size_t i = 0; i < link_args.count; i++)