Hi,

I've been doing some QT work with MinGW and run up against that windres.exe uses popen, which on Windows calls cmd.exe, which only has a 8192 character limit.

Building something in QT (which sometimes has masses of defines) in Windows with MinGW, was failing with "command line is too long". I felt the correct thing was that windres.exe didn't have this limit on Windows, so I've implemented an alternative popen for Windows with a larger character limit of 32768.

Include the attached file in your build and in resrc.c change:


/*#if defined (_WIN32) && ! defined (__CYGWIN__)
#define popen    _popen* *
#define pclose    _pclose
#endif*/

to:

*/#if defined (_WIN32) && ! defined (__CYGWIN__)
extern FILE *win_popen_biglimit(const char *command,const char *mode );
extern int win_pclose_biglimit(FILE *stream);
#define popen    win_popen_biglimit
#define pclose    win_pclose_biglimit
#endif/
*

Of course solve this how ever you want, but this is the direction I think it should go. This can "just work" better than it is. It would be better if cmd.exe didn't have this low limit, but it does and I doubt MS are going to fix it anytime soon and even if they did, it wouldn't help the people running or targeting the existing version of Windows.

Hope this is useful,


Joe

/*
 * Copyright 2012      Joe Burmeister <joe.burmeis...@codethink.co.uk>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sub license,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the
 * next paragraph) shall be included in all copies or substantial portions
 * of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */
#if defined (_WIN32) && ! defined (__CYGWIN__)
#include <windows.h>
#include <stdio.h>
#include <fcntl.h>

struct pipe_process_pair
{
	int pipefd;
	HANDLE process;
};

typedef struct pipe_process_pair pipe_process_pair;

static struct pipe_process_pair pairs[128];

FILE *win_popen_biglimit( const char *command, const char *mode );
int win_pclose_biglimit(FILE *stream);


FILE *win_popen_biglimit( const char *command, const char *mode )
{
    PROCESS_INFORMATION piProcInfo;
    STARTUPINFO siStartInfo;
 
	if (mode[0] == '\0' || mode[1] != '\0')
		return NULL;
		
	int pipefds[2] = {0};
		
	if (_pipe(pipefds, 4096, O_TEXT))
		return NULL;
		
	ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
	ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION));
	
	siStartInfo.cb = sizeof(STARTUPINFO);
	siStartInfo.dwFlags = STARTF_USESTDHANDLES;
	
	int fd_index = 0;
	
	/*
	 * Return correct pipe handle and close handle not returned or used.
	 */
	if (mode[0] == 'r')
	{
		siStartInfo.hStdOutput = siStartInfo.hStdError = 
				(HANDLE)_get_osfhandle(pipefds[1]);
		if ( ! SetHandleInformation(siStartInfo.hStdOutput,
									HANDLE_FLAG_INHERIT, TRUE) )
			goto Error;
	}
	else if (mode[0] == 'w')
	{
		fd_index = 1;
		siStartInfo.hStdInput = (HANDLE)_get_osfhandle(pipefds[0]);
		if ( ! SetHandleInformation(siStartInfo.hStdInput,
									HANDLE_FLAG_INHERIT, 0) )
			goto Error;
	}
	else goto Error;

    if (CreateProcess(NULL,
                      (LPSTR)command,
                      NULL,
                      NULL,
                      TRUE,
                      0, /* no NEW_CONSOLE 
							by default for Ctrl+C handling */
                      NULL,
                      NULL,
                      &siStartInfo,
                      &piProcInfo) )
	{
        CloseHandle(piProcInfo.hThread);
        
        FILE* result = NULL;
        
		pipe_process_pair* pair = pairs;
		
		for(; pair < &pairs[sizeof(pairs)/sizeof(pipe_process_pair)];
			++pair)
		{
			if (!pair->process)
			{
				pair->pipefd = pipefds[fd_index];
				pair->process = piProcInfo.hProcess;
				
				result = _fdopen(pair->pipefd, mode);
				
				if (!result)
					pair->process = NULL;
				
				break;
			}
		}
		
        if (!result)
        {
			CloseHandle(piProcInfo.hProcess);
			goto Error;
		}
		
		/*
			Close reference not required in this process.
		*/
		_close(pipefds[!fd_index]);
		
        return result;
    }

Error:

	if (siStartInfo.hStdOutput != NULL)
		CloseHandle(siStartInfo.hStdOutput);
		
	if (siStartInfo.hStdInput != NULL)
		CloseHandle(siStartInfo.hStdInput);
		
	_close(pipefds[0]);
	_close(pipefds[1]);
		
    return NULL;
}


int win_pclose_biglimit(FILE *stream)
{
	int fd = fileno(stream);
	pipe_process_pair* pair = pairs;
			
	for(; pair < &pairs[sizeof(pairs)/sizeof(pipe_process_pair)];
		++pair)
	{
		if (pair->pipefd == fd)
		{
			WaitForSingleObject(pair->process, INFINITE);
			
			DWORD exitcode = -1;
			
			if (!GetExitCodeProcess(pair->process, &exitcode))
				exitcode = -1;
				
			CloseHandle(pair->process);
			pair->process = NULL;
			
			return exitcode;
		}
	}
	
	return -1;
}
#endif
_______________________________________________
bug-binutils mailing list
bug-binutils@gnu.org
https://lists.gnu.org/mailman/listinfo/bug-binutils

Reply via email to