jcomp.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749
  1. /*##############################################################################
  2. Copyright (C) 2011 HPCC Systems.
  3. All rights reserved. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Affero General Public License as
  5. published by the Free Software Foundation, either version 3 of the
  6. License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Affero General Public License for more details.
  11. You should have received a copy of the GNU Affero General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. ############################################################################## */
  14. #include "platform.h"
  15. #include "jlib.hpp"
  16. #include "jmisc.hpp"
  17. #include "jcomp.hpp"
  18. #include "jsem.hpp"
  19. #include "jexcept.hpp"
  20. #ifdef _WIN32
  21. #include <windows.h>
  22. #include <winbase.h>
  23. #include <io.h>
  24. #else
  25. #include <sys/wait.h>
  26. #endif
  27. #include <fcntl.h>
  28. #include <sys/types.h>
  29. #include <sys/stat.h>
  30. #include <stdio.h>
  31. #include "jfile.hpp"
  32. #include "jdebug.hpp"
  33. #include "jcomp.ipp"
  34. #define CC_EXTRA_OPTIONS ""
  35. #ifdef GENERATE_LISTING
  36. #undef CC_EXTRA_OPTIONS
  37. #define CC_EXTRA_OPTIONS " /FAs"
  38. #endif
  39. #ifdef _WIN32
  40. #define DEFAULT_COMPILER Vs6CppCompiler
  41. #else
  42. #define DEFAULT_COMPILER GccCppCompiler
  43. #endif
  44. //---------------------------------------------------------------------------
  45. #define BASE_ADDRESS "0x00480000"
  46. //#define BASE_ADDRESS "0x10000000"
  47. static const char * CC_NAME[] = { "\"#" PATHSEPSTR "bin" PATHSEPSTR "cl.bat\"", "\"#" PATHSEPSTR "bin" PATHSEPSTR "g++\"" };
  48. static const char * LINK_NAME[] = { "\"#" PATHSEPSTR "bin" PATHSEPSTR "link.bat\"", "\"#" PATHSEPSTR "bin" PATHSEPSTR "g++\"" };
  49. static const char * LIB_DIR[] = { "\"#\\lib\"", "\"#/lib\"" };
  50. static const char * LIB_OPTION_PREFIX[] = { "", "-Wl," };
  51. static const char * USE_LIBPATH_FLAG[] = { "/libpath:\"", "-L" };
  52. static const char * USE_LIBPATH_TAIL[] = { "\"", "" };
  53. static const char * USE_LIBRPATH_FLAG[] = { NULL, "-Wl,-rpath," };
  54. static const char * USE_LIB_FLAG[] = { "", "-l" };
  55. static const char * USE_LIB_TAIL[] = { ".lib", "" };
  56. static const char * USE_INCLUDE_FLAG[] = { "/I\"", "\"-I" };
  57. static const char * USE_DEFINE_FLAG[] = { "/D", "-D" };
  58. static const char * USE_INCLUDE_TAIL[] = { "\"", "\"" };
  59. static const char * INCLUDEPATH[] = { "\"#\\include\"", "\"#/include\"" };
  60. static const char * LINK_SEPARATOR[] = { " /link ", " " };
  61. static const char * OBJECT_FILE_EXT[] = { "obj", "o" };
  62. static const char * LIBFLAG_DEBUG[] = { "/MDd", "" };
  63. static const char * LIBFLAG_RELEASE[] = { "/MD", "" };
  64. static const char * COMPILE_ONLY[] = { "/c", "-c" };
  65. static const char * CC_OPTION_CORE[] = { "", "-fvisibility=hidden -DUSE_VISIBILITY=1" };
  66. static const char * LINK_OPTION_CORE[] = { "/DLL /libpath:." , "" };
  67. static const char * CC_OPTION_DEBUG[] = { "/Zm500 /EHsc /GR /Zi /nologo /bigobj", "-g -fPIC -pipe -O0" };
  68. static const char * DLL_LINK_OPTION_DEBUG[] = { "/BASE:" BASE_ADDRESS " /NOLOGO /LARGEADDRESSAWARE /INCREMENTAL:NO /DEBUG /DEBUGTYPE:CV", "-g -shared -L. -fPIC -pipe -O0" };
  69. static const char * EXE_LINK_OPTION_DEBUG[] = { "/BASE:" BASE_ADDRESS " /NOLOGO /LARGEADDRESSAWARE /INCREMENTAL:NO /DEBUG /DEBUGTYPE:CV", "-g -L. -Wl,-E -fPIC -pipe -O0" };
  70. static const char * CC_OPTION_RELEASE[] = { "/Zm500 /EHsc /GR /Oi /Ob1 /GF /nologo /bigobj", "-fPIC -pipe -O0" };
  71. static const char * DLL_LINK_OPTION_RELEASE[] = { "/BASE:" BASE_ADDRESS " /NOLOGO /LARGEADDRESSAWARE /INCREMENTAL:NO", "-shared -L. -fPIC -pipe -O0" };
  72. static const char * EXE_LINK_OPTION_RELEASE[] = { "/BASE:" BASE_ADDRESS " /NOLOGO /LARGEADDRESSAWARE /INCREMENTAL:NO", "-L. -Wl,-E -fPIC -pipe -O0" };
  73. static const char * LINK_TARGET[] = { " /out:", " -o " };
  74. static const char * DEFAULT_CC_LOCATION[] = { ".", "." };
  75. //===========================================================================
  76. static StringAttr compilerRoot;
  77. static StringAttr stdIncludes;
  78. static StringBuffer stdLibs;
  79. static StringBuffer &dequote(StringBuffer &in)
  80. {
  81. if (in.length() >= 2 && in.charAt(0)=='"' && in.charAt(in.length()-1)=='"')
  82. {
  83. in.remove(in.length()-1, 1);
  84. in.remove(0, 1);
  85. }
  86. return in;
  87. }
  88. static void doSetCompilerPath(const char * path, const char * includes, const char * libs, const char * tmpdir, unsigned targetCompiler, bool verbose)
  89. {
  90. if (!includes)
  91. includes = INCLUDEPATH[targetCompiler];
  92. if (!libs)
  93. libs = LIB_DIR[targetCompiler];
  94. if (verbose)
  95. {
  96. PrintLog("Include directory set to %s", includes);
  97. PrintLog("Library directory set to %s", libs);
  98. }
  99. compilerRoot.set(path ? path : targetCompiler==GccCppCompiler ? "/usr" : ".\\CL");
  100. stdIncludes.set(includes);
  101. stdLibs.clear();
  102. for (;;)
  103. {
  104. StringBuffer thislib;
  105. while (*libs && *libs != ';')
  106. thislib.append(*libs++);
  107. if (thislib.length())
  108. {
  109. stdLibs.append(" ").append(USE_LIBPATH_FLAG[targetCompiler]).append(thislib).append(USE_LIBPATH_TAIL[targetCompiler]);
  110. if (USE_LIBRPATH_FLAG[targetCompiler])
  111. stdLibs.append(" ").append(USE_LIBRPATH_FLAG[targetCompiler]).append(thislib);
  112. }
  113. if (!*libs)
  114. break;
  115. libs++;
  116. }
  117. StringBuffer fname;
  118. if (path)
  119. {
  120. const char *finger = CC_NAME[targetCompiler];
  121. while (*finger)
  122. {
  123. if (*finger == '#')
  124. fname.append(path);
  125. else
  126. fname.append(*finger);
  127. finger++;
  128. }
  129. #if defined(__linux__)
  130. StringBuffer clbin_dir;
  131. const char* dir_end = strrchr(fname, '/');
  132. if(dir_end == NULL)
  133. clbin_dir.append(".");
  134. else
  135. clbin_dir.append((dir_end - fname.str()) + 1, fname.str());
  136. StringBuffer pathenv(clbin_dir.str());
  137. const char* oldpath = getenv("PATH");
  138. if(oldpath != NULL && *oldpath != '\0')
  139. pathenv.append(":").append(oldpath);
  140. setenv("PATH", pathenv.str(), 1);
  141. #endif
  142. }
  143. else
  144. {
  145. fname.append(compilerRoot).append(CC_NAME[targetCompiler]);
  146. fname.replaceString("#",NULL);
  147. }
  148. if (verbose)
  149. PrintLog("Compiler path set to %s", fname.str());
  150. dequote(fname);
  151. #ifdef _WIN32
  152. if (_access(fname.str(), 4))
  153. {
  154. #else
  155. #if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__)
  156. struct stat filestatus;
  157. int r = stat(fname.str(), &filestatus);
  158. if ( (r != 0)
  159. || (!S_ISREG(filestatus.st_mode))
  160. || (filestatus.st_mode&(S_IXOTH|S_IXGRP|S_IXUSR)==0))
  161. {
  162. if (r == -1) errno = ENOENT;
  163. #endif
  164. #endif
  165. if (verbose)
  166. PrintLog("SetCompilerPath - no compiler found");
  167. throw MakeOsException(GetLastError(), "setCompilerPath could not locate compiler %s", fname.str());
  168. }
  169. if(tmpdir && *tmpdir)
  170. {
  171. //MORE: this should be done for the child process instead of the parent but invoke does not let me do it
  172. #if defined(__linux__)
  173. setenv("TMPDIR", tmpdir, 1);
  174. #endif
  175. #ifdef _WIN32
  176. StringBuffer tmpbuf;
  177. tmpbuf.append("TMP=").append(tmpdir);
  178. _putenv(tmpbuf.str());
  179. #endif
  180. }
  181. }
  182. //===========================================================================
  183. class CCompilerThreadParam : CInterface
  184. {
  185. public:
  186. IMPLEMENT_IINTERFACE;
  187. CCompilerThreadParam(const StringBuffer & _cmdline, Semaphore & _finishedCompiling, const StringBuffer & _logfile) : cmdline(_cmdline), finishedCompiling(_finishedCompiling), logfile(_logfile) {};
  188. StringBuffer cmdline;
  189. StringBuffer logfile;
  190. Semaphore & finishedCompiling;
  191. };
  192. //===========================================================================
  193. static void setDirectoryPrefix(StringAttr & target, const char * source)
  194. {
  195. if (source && *source)
  196. {
  197. StringBuffer temp;
  198. target.set(addDirectoryPrefix(temp, source));
  199. }
  200. }
  201. CppCompiler::CppCompiler(const char * _coreName, const char * _sourceDir, const char * _targetDir, unsigned _targetCompiler, bool _verbose)
  202. {
  203. #define CORE_NAME allSources.item(0)
  204. if (_coreName)
  205. addSourceFile(_coreName);
  206. targetCompiler = _targetCompiler;
  207. createDLL = true;
  208. #ifdef _DEBUG
  209. setDebug(true);
  210. setDebugLibrary(true);
  211. #else
  212. setDebug(false);
  213. setDebugLibrary(false);
  214. #endif
  215. setDirectoryPrefix(sourceDir, _sourceDir);
  216. setDirectoryPrefix(targetDir, _targetDir);
  217. maxCompileThreads = 1;
  218. onlyCompile = false;
  219. verbose = _verbose;
  220. saveTemps = false;
  221. abortChecker = NULL;
  222. }
  223. void CppCompiler::addCompileOption(const char * option)
  224. {
  225. compilerOptions.append(' ').append(option);
  226. }
  227. void CppCompiler::addDefine(const char * symbolName, const char * value)
  228. {
  229. compilerOptions.append(" ").append(USE_DEFINE_FLAG[targetCompiler]).append(symbolName);
  230. if (value)
  231. compilerOptions.append('=').append(value);
  232. }
  233. void CppCompiler::addLibrary(const char * libName)
  234. {
  235. if (verbose)
  236. PrintLog("addLibrary %s", libName);
  237. const char* lname = libName;
  238. const char * quote;
  239. StringBuffer path, tail; // NOTE - because of the (hacky) code below that sets lname to point within tail.str(), this must NOT be moved inside the if block
  240. if (targetCompiler == GccCppCompiler)
  241. {
  242. // It seems gcc compiler doesn't like things like -lmydir/libx.so
  243. splitFilename(libName, &path, &path, &tail, &tail);
  244. if(path.length())
  245. {
  246. addLibraryPath(path);
  247. lname = tail.str();
  248. // HACK - make it work with plugins. This should be handled at caller end!
  249. if (strncmp(lname, "lib", 3) == 0)
  250. lname += 3;
  251. }
  252. quote = NULL; //quoting lib names with gcc causes link error (lib not found)
  253. }
  254. else
  255. {
  256. quote = "\"";
  257. }
  258. linkerLibraries.append(" ").append(USE_LIB_FLAG[targetCompiler]).append(quote).append(lname).append(USE_LIB_TAIL[targetCompiler]).append(quote);
  259. }
  260. void CppCompiler::addLibraryPath(const char * libPath)
  261. {
  262. linkerOptions.append(" ").append(USE_LIBPATH_FLAG[targetCompiler]).append(libPath).append(USE_LIBPATH_TAIL[targetCompiler]);
  263. if (USE_LIBRPATH_FLAG[targetCompiler])
  264. linkerOptions.append(" ").append(USE_LIBRPATH_FLAG[targetCompiler]).append(libPath);
  265. }
  266. void CppCompiler::_addInclude(StringBuffer &s, const char * paths)
  267. {
  268. if (!paths)
  269. return;
  270. StringBuffer includePath;
  271. for (;;)
  272. {
  273. while (*paths && *paths != ENVSEPCHAR)
  274. includePath.append(*paths++);
  275. if (includePath.length())
  276. s.append(" ").append(USE_INCLUDE_FLAG[targetCompiler]).append(includePath).append(USE_INCLUDE_TAIL[targetCompiler]);
  277. if (!*paths)
  278. break;
  279. paths++;
  280. includePath.clear();
  281. }
  282. }
  283. void CppCompiler::addInclude(const char * paths)
  284. {
  285. _addInclude(compilerOptions, paths);
  286. }
  287. void CppCompiler::addLinkOption(const char * option)
  288. {
  289. if (option && *option)
  290. linkerOptions.append(' ').append(LIB_OPTION_PREFIX[targetCompiler]).append(option);
  291. }
  292. void CppCompiler::addSourceFile(const char * filename)
  293. {
  294. allSources.append(filename);
  295. }
  296. void CppCompiler::writeLogFile(const char* filepath, StringBuffer& log)
  297. {
  298. if(!filepath || !*filepath || !log.length())
  299. return;
  300. Owned <IFile> f = createIFile(filepath);
  301. if(f->exists())
  302. f->remove();
  303. Owned <IFileIO> fio = f->open(IFOcreaterw);
  304. if(fio.get())
  305. fio->write(0, log.length(), log.str());
  306. }
  307. bool CppCompiler::compile()
  308. {
  309. if (abortChecker && abortChecker->abortRequested())
  310. return false;
  311. TIME_SECTION(!verbose ? NULL : onlyCompile ? "compile" : "compile/link");
  312. Owned<IThreadPool> pool = createThreadPool("CCompilerWorker", this, NULL, maxCompileThreads?maxCompileThreads:1, INFINITE);
  313. addCompileOption(COMPILE_ONLY[targetCompiler]);
  314. bool ret = false;
  315. Semaphore finishedCompiling;
  316. int numSubmitted = 0;
  317. atomic_set(&numFailed, 0);
  318. ForEachItemIn(i0, allSources)
  319. {
  320. ret = compileFile(pool, allSources.item(i0), finishedCompiling);
  321. if (!ret)
  322. break;
  323. ++numSubmitted;
  324. }
  325. for (int idx = 0; idx < numSubmitted; idx++)
  326. {
  327. if (abortChecker)
  328. {
  329. while (!finishedCompiling.wait(5*1000))
  330. {
  331. if (abortChecker && abortChecker->abortRequested())
  332. {
  333. PrintLog("Aborting compilation");
  334. pool->stopAll(true);
  335. if (!pool->joinAll(true, 10*1000))
  336. WARNLOG("CCompilerWorker; timed out waiting for threads in pool");
  337. return false;
  338. }
  339. }
  340. }
  341. else
  342. finishedCompiling.wait();
  343. }
  344. if (atomic_read(&numFailed) > 0)
  345. ret = false;
  346. else if (!onlyCompile)
  347. ret = doLink();
  348. if (!saveTemps)
  349. {
  350. removeTemporaries();
  351. StringBuffer temp;
  352. ForEachItemIn(i2, allSources)
  353. remove(getObjectName(temp.clear(), allSources.item(i2)).str());
  354. }
  355. //Combine logfiles
  356. const char* cclog = ccLogPath.get();
  357. if(!cclog||!*cclog)
  358. cclog = queryCcLogName();
  359. Owned <IFile> dstfile = createIFile(cclog);
  360. dstfile->remove();
  361. Owned<IFileIO> dstIO = dstfile->open(IFOwrite);
  362. ForEachItemIn(i2, logFiles)
  363. {
  364. Owned <IFile> srcfile = createIFile(logFiles.item(i2));
  365. if (srcfile->exists())
  366. {
  367. dstIO->appendFile(srcfile);
  368. srcfile->remove();
  369. }
  370. }
  371. pool->joinAll(true, 1000);
  372. return ret;
  373. }
  374. bool CppCompiler::compileFile(IThreadPool * pool, const char * filename, Semaphore & finishedCompiling)
  375. {
  376. if (!filename || *filename == 0)
  377. return false;
  378. StringBuffer fullFileName;
  379. fullFileName.clear().append("\"").append(filename).append(".cpp").append("\"").append(" ");
  380. StringBuffer cmdline;
  381. cmdline.append(CC_NAME[targetCompiler]);
  382. cmdline.append(" ").append(sourceDir);
  383. cmdline.append(fullFileName);
  384. expandCompileOptions(cmdline);
  385. if (useDebugLibrary)
  386. cmdline.append(" ").append(LIBFLAG_DEBUG[targetCompiler]);
  387. else
  388. cmdline.append(" ").append(LIBFLAG_RELEASE[targetCompiler]);
  389. _addInclude(cmdline, stdIncludes);
  390. if (targetCompiler == Vs6CppCompiler)
  391. {
  392. if (targetDir.get())
  393. cmdline.append(" /Fo").append("\"").append(targetDir).append("\"");
  394. cmdline.append(" /Fd").append("\"").append(targetDir).append(createDLL ? SharedObjectPrefix : NULL).append(filename).append(".pdb").append("\"");//MORE: prefer create a single pdb file using coreName
  395. }
  396. else
  397. {
  398. cmdline.append(" -o ").append("\"").append(targetDir).append(filename).append('.').append(OBJECT_FILE_EXT[targetCompiler]).append("\"");
  399. }
  400. StringBuffer expanded;
  401. expandRootDirectory(expanded, cmdline);
  402. StringBuffer logFile;
  403. logFile.append(filename).append(".log.tmp");
  404. logFiles.append(logFile);
  405. Owned<CCompilerThreadParam> parm;
  406. if (verbose)
  407. PrintLog("%s", expanded.toCharArray());
  408. parm.setown(new CCompilerThreadParam(expanded, finishedCompiling, logFile));
  409. pool->start(parm.get());
  410. return true;
  411. }
  412. void CppCompiler::expandCompileOptions(StringBuffer & target)
  413. {
  414. target.append(" ").append(CC_OPTION_CORE[targetCompiler]).append(" ");
  415. if (targetDebug)
  416. target.append(CC_OPTION_DEBUG[targetCompiler]);
  417. else
  418. target.append(CC_OPTION_RELEASE[targetCompiler]);
  419. target.append(compilerOptions).append(CC_EXTRA_OPTIONS);
  420. }
  421. bool CppCompiler::doLink()
  422. {
  423. StringBuffer cmdline;
  424. cmdline.append(LINK_NAME[targetCompiler]).append(LINK_SEPARATOR[targetCompiler]);
  425. cmdline.append(" ");
  426. if (targetDebug)
  427. cmdline.append(createDLL ? DLL_LINK_OPTION_DEBUG[targetCompiler] : EXE_LINK_OPTION_DEBUG[targetCompiler]);
  428. else
  429. cmdline.append(createDLL ? DLL_LINK_OPTION_RELEASE[targetCompiler] : EXE_LINK_OPTION_RELEASE[targetCompiler]);
  430. cmdline.append(" ");
  431. if (createDLL)
  432. cmdline.append(" ").append(LINK_OPTION_CORE[targetCompiler]);
  433. cmdline.append(stdLibs);
  434. ForEachItemIn(i0, allSources)
  435. cmdline.append(" ").append("\"").append(targetDir).append(allSources.item(i0)).append(".").append(OBJECT_FILE_EXT[targetCompiler]).append("\"");
  436. cmdline.append(linkerOptions);
  437. cmdline.append(linkerLibraries);
  438. StringBuffer outName;
  439. outName.append(createDLL ? SharedObjectPrefix : NULL).append(CORE_NAME).append(createDLL ? SharedObjectExtension : ProcessExtension);
  440. cmdline.append(LINK_TARGET[targetCompiler]).append("\"").append(targetDir).append(outName).append("\"");
  441. StringBuffer temp;
  442. remove(temp.clear().append(targetDir).append(outName).str());
  443. StringBuffer expanded;
  444. expandRootDirectory(expanded, cmdline);
  445. DWORD runcode = 0;
  446. if (verbose)
  447. PrintLog("%s", expanded.toCharArray());
  448. StringBuffer logFile = StringBuffer(CORE_NAME).append("_link.log.tmp");
  449. logFiles.append(logFile);
  450. bool ret = invoke_program(expanded.toCharArray(), runcode, true, logFile) && (runcode == 0);
  451. return ret;
  452. }
  453. void CppCompiler::expandRootDirectory(StringBuffer & expanded, StringBuffer & in)
  454. {
  455. unsigned len = in.length();
  456. unsigned i;
  457. for (i = 0; i < len; i++)
  458. {
  459. char c = in.charAt(i);
  460. if (c == '#')
  461. {
  462. if (compilerRoot)
  463. expanded.append(compilerRoot);
  464. else
  465. expanded.append(DEFAULT_CC_LOCATION[targetCompiler]);
  466. }
  467. else
  468. expanded.append(c);
  469. }
  470. }
  471. StringBuffer & CppCompiler::getObjectName(StringBuffer & out, const char * filename)
  472. {
  473. out.append(targetDir);
  474. splitFilename(filename, NULL, NULL, &out, &out);
  475. return out.append(".").append(OBJECT_FILE_EXT[targetCompiler]);
  476. }
  477. void CppCompiler::removeTemporaries()
  478. {
  479. switch (targetCompiler)
  480. {
  481. case Vs6CppCompiler:
  482. case GccCppCompiler:
  483. {
  484. StringBuffer temp;
  485. remove(temp.clear().append(targetDir).append(CORE_NAME).append(".exp").str());
  486. remove(getObjectName(temp.clear(), CORE_NAME).str());
  487. remove(temp.clear().append(targetDir).append(CORE_NAME).append(".lib").str());
  488. #ifdef _WIN32
  489. remove(temp.clear().append(targetDir).append(CORE_NAME).append(".res.lib").str());
  490. #else
  491. remove(temp.clear().append(targetDir).append(CORE_NAME).append(".res.o.lib").str());
  492. remove(temp.clear().append(targetDir).append("lib").append(CORE_NAME).append(".res.o.so").str());
  493. #endif
  494. break;
  495. }
  496. }
  497. }
  498. void CppCompiler::setDebug(bool _debug)
  499. {
  500. targetDebug = _debug;
  501. }
  502. void CppCompiler::setDebugLibrary(bool debug)
  503. {
  504. useDebugLibrary = debug;
  505. }
  506. void CppCompiler::setCreateExe(bool _createExe)
  507. {
  508. createDLL = !_createExe;
  509. }
  510. void CppCompiler::setOptimizeLevel(unsigned level)
  511. {
  512. const char * option = NULL;
  513. switch (targetCompiler)
  514. {
  515. case Vs6CppCompiler:
  516. switch (level)
  517. {
  518. case 0: option = "/Od"; break;
  519. case 1: option = "/O1"; break;
  520. case 2: option = "/O2"; break;
  521. default: // i.e. 3 or higher
  522. option = "/Ob1gty /G6"; break;
  523. }
  524. break;
  525. case GccCppCompiler:
  526. switch (level)
  527. {
  528. case 0: option = "-O0"; break; // do not optimize
  529. case 1: option = "-O1"; break;
  530. case 2: option = "-O2"; break;
  531. default: // i.e. 3 or higher
  532. option = "-O3"; break;
  533. }
  534. break;
  535. }
  536. if (option)
  537. addCompileOption(option);
  538. }
  539. void CppCompiler::setTargetBitLength(unsigned bitlength)
  540. {
  541. const char * option = NULL;
  542. switch (targetCompiler)
  543. {
  544. case Vs6CppCompiler:
  545. switch (bitlength)
  546. {
  547. case 32: break; // 64-bit windows TBD at present....
  548. default:
  549. throwUnexpected();
  550. }
  551. break;
  552. case GccCppCompiler:
  553. switch (bitlength)
  554. {
  555. case 32: option = "-m32"; break;
  556. case 64: option = "-m64"; break;
  557. default:
  558. throwUnexpected();
  559. }
  560. break;
  561. }
  562. if (option)
  563. addCompileOption(option);
  564. }
  565. void CppCompiler::setCCLogPath(const char* path)
  566. {
  567. if(path && *path)
  568. ccLogPath.set(path);
  569. }
  570. //===========================================================================
  571. bool fileIsOlder(const char *dest, const char *src)
  572. {
  573. int h1 = _open(dest, _O_RDONLY);
  574. if (h1 == -1)
  575. return true;
  576. int h2 = _open(src, _O_RDONLY);
  577. assertex(h2 != -1);
  578. struct _stat stat1;
  579. struct _stat stat2;
  580. _fstat(h1, &stat1);
  581. _fstat(h2, &stat2);
  582. _close(h1);
  583. _close(h2);
  584. return stat1.st_mtime < stat2.st_mtime;
  585. }
  586. //===========================================================================
  587. void setCompilerPath(const char * path, const char * includes, const char * libs, const char * tmpdir, bool verbose)
  588. {
  589. doSetCompilerPath(path, includes, libs, tmpdir, DEFAULT_COMPILER, verbose);
  590. }
  591. void setCompilerPath(const char * path, const char * includes, const char * libs, const char * tmpdir, CompilerType targetCompiler, bool verbose)
  592. {
  593. doSetCompilerPath(path, includes, libs, tmpdir, targetCompiler, verbose);
  594. }
  595. ICppCompiler * createCompiler(const char * coreName, const char * sourceDir, const char * targetDir, bool verbose)
  596. {
  597. return new CppCompiler(coreName, sourceDir, targetDir, DEFAULT_COMPILER, verbose);
  598. }
  599. ICppCompiler * createCompiler(const char * coreName, const char * sourceDir, const char * targetDir, CompilerType targetCompiler, bool verbose)
  600. {
  601. return new CppCompiler(coreName, sourceDir, targetDir, targetCompiler, verbose);
  602. }
  603. //===========================================================================
  604. class CCompilerWorker : public CInterface, implements IPooledThread
  605. {
  606. public:
  607. IMPLEMENT_IINTERFACE;
  608. CCompilerWorker(CppCompiler * _compiler) : compiler(_compiler) {}
  609. bool canReuse() { return true; }
  610. bool stop() { return true; }
  611. void init(void *_params) { params.set((CCompilerThreadParam *)_params); }
  612. void main()
  613. {
  614. DWORD runcode = 0;
  615. bool success;
  616. try
  617. {
  618. success = invoke_program(params->cmdline, runcode, true, params->logfile) && (runcode == 0);
  619. }
  620. catch(IException* e)
  621. {
  622. StringBuffer sb;
  623. e->errorMessage(sb);
  624. e->Release();
  625. if (sb.length())
  626. PrintLog("%s", sb.str());
  627. success = false;
  628. }
  629. if (!success)
  630. atomic_inc(&compiler->numFailed);
  631. params->finishedCompiling.signal();
  632. return;
  633. }
  634. private:
  635. CppCompiler * compiler;
  636. Owned<CCompilerThreadParam> params;
  637. };
  638. IPooledThread *CppCompiler::createNew()
  639. {
  640. return new CCompilerWorker(this);
  641. }