Version 4.2.0.1, tag libreoffice-4.2.0.1
[LibreOffice.git] / solenv / gcc-wrappers / wrapper.cxx
blob42ead2f9bed08744d62602acedb3b10a8fc124f4
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) {
19 char* cmdbuf;
20 size_t cmdlen;
21 _dupenv_s(&cmdbuf,&cmdlen,exename.c_str());
22 if(!cmdbuf) {
23 cout << "Error " << exename << " not defined. Did you forget to source the enviroment?" << endl;
24 exit(1);
26 string command(cmdbuf);
27 free(cmdbuf);
28 return command;
31 void setupccenv() {
32 // Set-up library path
33 string libpath="LIB=";
34 char* libbuf;
35 size_t liblen;
36 _dupenv_s(&libbuf,&liblen,"ILIB");
37 libpath.append(libbuf);
38 free(libbuf);
39 if(_putenv(libpath.c_str())<0) {
40 cerr << "Error: could not export LIB" << endl;
41 exit(1);
44 // Set-up include path
45 string includepath="INCLUDE=.;";
46 char* incbuf;
47 size_t inclen;
48 _dupenv_s(&incbuf,&inclen,"SOLARINC");
49 string inctmp(incbuf);
50 free(incbuf);
52 // 3 = strlen(" -I")
53 for(size_t pos=0; pos != string::npos;) {
54 size_t endpos=inctmp.find(" -I",pos+3);
55 size_t len=endpos-pos-3;
56 if(endpos==string::npos)
57 includepath.append(inctmp,pos+3,endpos);
58 else if(len>0) {
59 includepath.append(inctmp,pos+3,len);
60 includepath.append(";");
62 pos=inctmp.find(" -I",pos+len);
64 if(_putenv(includepath.c_str())<0) {
65 cerr << "Error: could not export INCLUDE" << endl;
66 exit(1);
70 string processccargs(vector<string> rawargs) {
71 // suppress the msvc banner
72 string args=" -nologo";
73 // TODO: should these options be enabled globally?
74 args.append(" -EHsc");
75 const char *const pDebugRuntime(getenv("MSVC_USE_DEBUG_RUNTIME"));
76 if (pDebugRuntime && !strcmp(pDebugRuntime, "TRUE"))
77 args.append(" -MDd");
78 else
79 args.append(" -MD");
80 args.append(" -Gy");
81 args.append(" -Zc:wchar_t-");
82 args.append(" -Ob1 -Oxs -Oy-");
84 // apparently these must be at the end
85 // otherwise configure tests may fail
86 string linkargs(" -link");
88 for(vector<string>::iterator i = rawargs.begin(); i != rawargs.end(); ++i) {
89 args.append(" ");
90 if(*i == "-o") {
91 // TODO: handle more than just exe output
92 ++i;
93 size_t dot=(*i).find_last_of(".");
94 if(!(*i).compare(dot+1,3,"obj") || !(*i).compare(dot+1,1,"o"))
96 args.append("-Fo");
97 args.append(*i);
99 else if(!(*i).compare(dot+1,3,"exe"))
101 args.append("-Fe");
102 args.append(*i);
104 else if(!(*i).compare(dot+1,3,"dll"))
105 { // apparently cl.exe has no flag for dll?
106 linkargs.append(" -dll -out:");
107 linkargs.append(*i);
109 else
111 cerr << "unknonwn -o argument - please adapt gcc-wrapper for \""
112 << (*i) << "\"";
113 exit(1);
116 else if(*i == "-g")
117 args.append("-Zi");
118 else if(!(*i).compare(0,2,"-D")) {
119 // need to re-escape strings for preprocessor
120 for(size_t pos=(*i).find("\"",0); pos!=string::npos; pos=(*i).find("\"",pos)) {
121 (*i).replace(pos,0,"\\");
122 pos+=2;
124 args.append(*i);
126 else if(!(*i).compare(0,2,"-L")) {
127 linkargs.append(" -LIBPATH:"+(*i).substr(2));
129 else if(!(*i).compare(0,2,"-l")) {
130 linkargs.append(" "+(*i).substr(2)+".lib");
132 else if(!(*i).compare(0,5,"-def:") || !(*i).compare(0,5,"/def:")) {
133 // why are we invoked with /def:? cl.exe should handle plain
134 // "foo.def" by itself
135 linkargs.append(" " + *i);
137 else if(!(*i).compare(0,12,"-fvisibility")) {
138 //TODO: drop other gcc-specific options
140 else if(!(*i).compare(0,4,"-Wl,")) {
141 //TODO: drop other gcc-specific options
143 else if(*i == "-Werror")
144 args.append("-WX");
145 else
146 args.append(*i);
148 args.append(linkargs);
149 return args;
152 int startprocess(string command, string args) {
153 STARTUPINFO si;
154 PROCESS_INFORMATION pi;
155 SECURITY_ATTRIBUTES sa;
157 HANDLE childout_read;
158 HANDLE childout_write;
160 memset(&sa,0,sizeof(sa));
161 memset(&si,0,sizeof(si));
162 memset(&pi,0,sizeof(pi));
164 sa.nLength=sizeof(sa);
165 sa.bInheritHandle=TRUE;
167 if(!CreatePipe(&childout_read,&childout_write,&sa,0)) {
168 cerr << "Error: could not create stdout pipe" << endl;
169 exit(1);
172 si.cb=sizeof(si);
173 si.dwFlags |= STARTF_USESTDHANDLES;
174 si.hStdOutput=childout_write;
175 si.hStdError=childout_write;
177 // support ccache
178 size_t pos=command.find("ccache ");
179 if(pos != string::npos) {
180 args.insert(0,"cl.exe");
181 command=command.substr(0,pos+strlen("ccache"))+".exe";
184 //cerr << "CMD= " << command << " " << args << endl;
186 // Commandline may be modified by CreateProcess
187 char* cmdline=_strdup(args.c_str());
189 if(!CreateProcess(command.c_str(), // Process Name
190 cmdline, // Command Line
191 NULL, // Process Handle not Inheritable
192 NULL, // Thread Handle not Inheritable
193 TRUE, // Handles are Inherited
194 0, // No creation flags
195 NULL, // Enviroment for process
196 NULL, // Use same starting directory
197 &si, // Startup Info
198 &pi) // Process Information
200 cerr << "Error: could not create process" << endl;
201 exit(1);
204 // if you don't close this the process will hang
205 CloseHandle(childout_write);
207 // Get Process output
208 char buffer[BUFLEN];
209 DWORD readlen, writelen, ret;
210 HANDLE stdout_handle=GetStdHandle(STD_OUTPUT_HANDLE);
211 while(true) {
212 int success=ReadFile(childout_read,buffer,BUFLEN,&readlen,NULL);
213 // check if the child process has exited
214 if(GetLastError()==ERROR_BROKEN_PIPE)
215 break;
216 if(!success) {
217 cerr << "Error: could not read from subprocess stdout" << endl;
218 exit(1);
220 if(readlen!=0) {
221 WriteFile(stdout_handle,buffer,readlen,&writelen,NULL);
224 WaitForSingleObject(pi.hProcess, INFINITE);
225 GetExitCodeProcess(pi.hProcess, &ret);
226 CloseHandle(pi.hThread);
227 CloseHandle(pi.hProcess);
228 return int(ret);
231 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */