nss: upgrade to release 3.73
[LibreOffice.git] / solenv / gcc-wrappers / wrapper.cxx
blobfabfbfc9b34672bfb7adeb8d52bdf10779f04382
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include "wrapper.hxx"
12 #define WIN32_LEAN_AND_MEAN
14 #include <windows.h>
16 #define BUFLEN 2048
18 string getexe(string exename, bool maybeempty) {
19 char* cmdbuf;
20 size_t cmdlen;
21 _dupenv_s(&cmdbuf,&cmdlen,exename.c_str());
22 if(!cmdbuf) {
23 if (maybeempty) {
24 return string();
26 cout << "Error " << exename << " not defined. Did you forget to source the environment?" << endl;
27 exit(1);
29 string command(cmdbuf);
30 free(cmdbuf);
31 return command;
34 void setupccenv() {
35 // Set-up library path
36 string libpath="LIB=";
37 char* libbuf;
38 size_t liblen;
39 _dupenv_s(&libbuf,&liblen,"ILIB");
40 if (libbuf == nullptr) {
41 std::cerr << "No environment variable ILIB" << std::endl;
42 std::exit(EXIT_FAILURE);
44 libpath.append(libbuf);
45 free(libbuf);
46 if(_putenv(libpath.c_str())<0) {
47 cerr << "Error: could not export LIB" << endl;
48 exit(1);
51 // Set-up include path
52 string includepath="INCLUDE=.";
53 char* incbuf;
54 size_t inclen;
55 _dupenv_s(&incbuf,&inclen,"SOLARINC");
56 if (incbuf == nullptr) {
57 std::cerr << "No environment variable SOLARINC" << std::endl;
58 std::exit(EXIT_FAILURE);
60 string inctmp(incbuf);
61 free(incbuf);
63 // 3 = strlen(" -I")
64 for(size_t pos=0,len=0;pos<inctmp.length();) {
65 size_t endpos=inctmp.find(" -I",pos+1);
66 if(endpos==string::npos)
67 endpos=inctmp.length();
68 len=endpos-pos;
70 while(len>0&&inctmp[pos+len-1]==' ')
71 --len;
73 if(len>3) {
74 includepath.append(";");
75 includepath.append(inctmp,pos+3,len-3);
77 pos=endpos;
79 if(_putenv(includepath.c_str())<0) {
80 cerr << "Error: could not export INCLUDE" << endl;
81 exit(1);
85 string processccargs(vector<string> rawargs, string &env_prefix, bool &verbose)
87 // default env var prefix
88 env_prefix = "REAL_";
89 verbose = false;
90 bool env_prefix_next_arg = false;
92 // suppress the msvc banner
93 string args=" -nologo";
94 // TODO: should these options be enabled globally?
95 args.append(" -EHsc");
96 const char *const pDebugRuntime(getenv("MSVC_USE_DEBUG_RUNTIME"));
97 if (pDebugRuntime && !strcmp(pDebugRuntime, "TRUE"))
98 args.append(" -MDd");
99 else
100 args.append(" -MD");
101 args.append(" -Gy");
102 args.append(" -Ob1 -Oxs -Oy-");
104 // apparently these must be at the end
105 // otherwise configure tests may fail
106 // note: always use -debug so a PDB file is created
107 string linkargs(" -link -debug");
109 // instead of using synced PDB access (-FS), use inidividual PDB files based on output
110 const char *const pEnvIndividualPDBs(getenv("MSVC_USE_INDIVIDUAL_PDBS"));
111 const bool bIndividualPDBs = (pEnvIndividualPDBs && !strcmp(pEnvIndividualPDBs, "TRUE"));
113 for(vector<string>::iterator i = rawargs.begin(); i != rawargs.end(); ++i) {
114 if (env_prefix_next_arg)
116 env_prefix = *i;
117 env_prefix_next_arg = false;
118 continue;
121 args.append(" ");
122 if(*i == "-o") {
123 // TODO: handle more than just exe output
124 ++i;
125 size_t dot=(*i).find_last_of(".");
126 if(!(*i).compare(dot+1,3,"obj") || !(*i).compare(dot+1,1,"o"))
128 args.append("-Fo");
129 args.append(*i);
131 else if(!(*i).compare(dot+1,3,"exe"))
133 args.append("-Fe");
134 args.append(*i);
136 else if(!(*i).compare(dot+1,3,"dll"))
137 { // apparently cl.exe has no flag for dll?
138 linkargs.append(" -dll -out:");
139 linkargs.append(*i);
141 else if (dot == string::npos)
143 args.append("-Fe");
144 args.append(*i + ".exe");
146 else
148 cerr << "unknown -o argument - please adapt gcc-wrapper for \""
149 << (*i) << "\"" << endl;
150 exit(1);
153 if (bIndividualPDBs)
155 if (dot == string::npos)
156 args.append(" -Fd" + *i + ".pdb");
157 else
158 args.append(" -Fd" + (*i).substr(0, dot) + ".pdb");
161 else if(*i == "-g" || !(*i).compare(0,5,"-ggdb")) {
162 args.append("-Zi");
163 if (!bIndividualPDBs)
164 args.append(" -FS");
166 else if(!(*i).compare(0,2,"-D")) {
167 // need to re-escape strings for preprocessor
168 for(size_t pos=(*i).find("\""); pos!=string::npos; pos=(*i).find("\"",pos)) {
169 (*i).replace(pos,0,"\\");
170 pos+=2;
172 args.append(*i);
174 else if(!(*i).compare(0,2,"-L")) {
175 linkargs.append(" -LIBPATH:"+(*i).substr(2));
177 else if(!(*i).compare(0,2,"-l") && (*i).compare(0,5,"-link")) {
178 linkargs.append(" "+(*i).substr(2)+".lib");
180 else if(!(*i).compare(0,5,"-def:") || !(*i).compare(0,5,"/def:")) {
181 // why are we invoked with /def:? cl.exe should handle plain
182 // "foo.def" by itself
183 linkargs.append(" " + *i);
185 else if(!(*i).compare(0,12,"-fvisibility") || *i == "-fPIC") {
186 //TODO: drop other gcc-specific options
188 else if(!(*i).compare(0,4,"-Wl,")) {
189 //TODO: drop other gcc-specific options
191 else if(*i == "-Werror")
192 args.append("-WX");
193 else if (*i == "--wrapper-print-cmdline")
194 verbose = true;
195 else
197 size_t pos = i->find("=");
198 if (0 == i->compare(0, pos, "--wrapper-env-prefix"))
200 if (pos == string::npos)
201 env_prefix_next_arg = true;
202 else if (pos + 1 == i->length())
204 // bailout - missing arg
205 env_prefix_next_arg = true;
206 break;
208 else
209 env_prefix = i->substr(pos + 1);
211 else
212 args.append(*i);
216 if (env_prefix_next_arg)
218 cerr << "wrapper-env-prefix needs an argument!" << endl;
219 exit(1);
222 args.append(linkargs);
223 return args;
226 int startprocess(string command, string args, bool verbose)
228 STARTUPINFO si;
229 PROCESS_INFORMATION pi;
230 SECURITY_ATTRIBUTES sa;
232 HANDLE childout_read;
233 HANDLE childout_write;
235 memset(&sa,0,sizeof(sa));
236 memset(&si,0,sizeof(si));
237 memset(&pi,0,sizeof(pi));
239 sa.nLength=sizeof(sa);
240 sa.bInheritHandle=TRUE;
242 if(!CreatePipe(&childout_read,&childout_write,&sa,0)) {
243 cerr << "Error: could not create stdout pipe" << endl;
244 exit(1);
247 si.cb=sizeof(si);
248 si.dwFlags |= STARTF_USESTDHANDLES;
249 si.hStdOutput=childout_write;
250 si.hStdError=childout_write;
252 // support ccache
253 size_t pos=command.find("ccache ");
254 if(pos != string::npos) {
255 args.insert(0,"cl.exe");
256 command=command.substr(0,pos+strlen("ccache"))+".exe";
259 auto cmdline = "\"" + command + "\" " + args;
261 if (verbose)
262 cerr << "CMD= " << command << " " << args << endl;
264 // Commandline may be modified by CreateProcess
265 char* cmdlineBuf=_strdup(cmdline.c_str());
267 if(!CreateProcess(nullptr, // Process Name
268 cmdlineBuf, // Command Line
269 nullptr, // Process Handle not Inheritable
270 nullptr, // Thread Handle not Inheritable
271 TRUE, // Handles are Inherited
272 0, // No creation flags
273 nullptr, // Environment for process
274 nullptr, // Use same starting directory
275 &si, // Startup Info
276 &pi) // Process Information
278 auto const e = GetLastError();
279 cerr << "Error: could not create process \"" << cmdlineBuf << "\": " << e << endl;
280 exit(1);
283 // if you don't close this the process will hang
284 CloseHandle(childout_write);
286 // Get Process output
287 char buffer[BUFLEN];
288 DWORD readlen, writelen, ret;
289 HANDLE stdout_handle=GetStdHandle(STD_OUTPUT_HANDLE);
290 while(true) {
291 int success=ReadFile(childout_read,buffer,BUFLEN,&readlen,nullptr);
292 // check if the child process has exited
293 if(GetLastError()==ERROR_BROKEN_PIPE)
294 break;
295 if(!success) {
296 cerr << "Error: could not read from subprocess stdout" << endl;
297 exit(1);
299 if(readlen!=0) {
300 WriteFile(stdout_handle,buffer,readlen,&writelen,nullptr);
303 WaitForSingleObject(pi.hProcess, INFINITE);
304 GetExitCodeProcess(pi.hProcess, &ret);
305 CloseHandle(pi.hThread);
306 CloseHandle(pi.hProcess);
307 return int(ret);
310 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */