1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
10 #include "wrapper.hxx"
12 #define WIN32_LEAN_AND_MEAN
18 string
getexe(string exename
, bool maybeempty
) {
21 _dupenv_s(&cmdbuf
,&cmdlen
,exename
.c_str());
26 cout
<< "Error " << exename
<< " not defined. Did you forget to source the environment?" << endl
;
29 string
command(cmdbuf
);
35 // Set-up library path
36 string libpath
="LIB=";
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
);
46 if(_putenv(libpath
.c_str())<0) {
47 cerr
<< "Error: could not export LIB" << endl
;
51 // Set-up include path
52 string includepath
="INCLUDE=.";
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
);
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();
70 while(len
>0&&inctmp
[pos
+len
-1]==' ')
74 includepath
.append(";");
75 includepath
.append(inctmp
,pos
+3,len
-3);
79 if(_putenv(includepath
.c_str())<0) {
80 cerr
<< "Error: could not export INCLUDE" << endl
;
85 string
processccargs(vector
<string
> rawargs
, string
&env_prefix
, bool &verbose
)
87 // default env var prefix
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"))
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
)
117 env_prefix_next_arg
= false;
123 // TODO: handle more than just exe output
125 size_t dot
=(*i
).find_last_of(".");
126 if(!(*i
).compare(dot
+1,3,"obj") || !(*i
).compare(dot
+1,1,"o"))
131 else if(!(*i
).compare(dot
+1,3,"exe"))
136 else if(!(*i
).compare(dot
+1,3,"dll"))
137 { // apparently cl.exe has no flag for dll?
138 linkargs
.append(" -dll -out:");
141 else if (dot
== string::npos
)
144 args
.append(*i
+ ".exe");
148 cerr
<< "unknown -o argument - please adapt gcc-wrapper for \""
149 << (*i
) << "\"" << endl
;
155 if (dot
== string::npos
)
156 args
.append(" -Fd" + *i
+ ".pdb");
158 args
.append(" -Fd" + (*i
).substr(0, dot
) + ".pdb");
161 else if(*i
== "-g" || !(*i
).compare(0,5,"-ggdb")) {
163 if (!bIndividualPDBs
)
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,"\\");
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")
193 else if (*i
== "--wrapper-print-cmdline")
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;
209 env_prefix
= i
->substr(pos
+ 1);
216 if (env_prefix_next_arg
)
218 cerr
<< "wrapper-env-prefix needs an argument!" << endl
;
222 args
.append(linkargs
);
226 int startprocess(string command
, string args
, bool verbose
)
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
;
248 si
.dwFlags
|= STARTF_USESTDHANDLES
;
249 si
.hStdOutput
=childout_write
;
250 si
.hStdError
=childout_write
;
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
;
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
276 &pi
) // Process Information
278 auto const e
= GetLastError();
279 cerr
<< "Error: could not create process \"" << cmdlineBuf
<< "\": " << e
<< endl
;
283 // if you don't close this the process will hang
284 CloseHandle(childout_write
);
286 // Get Process output
288 DWORD readlen
, writelen
, ret
;
289 HANDLE stdout_handle
=GetStdHandle(STD_OUTPUT_HANDLE
);
291 int success
=ReadFile(childout_read
,buffer
,BUFLEN
,&readlen
,nullptr);
292 // check if the child process has exited
293 if(GetLastError()==ERROR_BROKEN_PIPE
)
296 cerr
<< "Error: could not read from subprocess stdout" << endl
;
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
);
310 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */