// Gestionnaire de compilation-linker C++ - R. Ansari 10/2000 // LAL (Orsay) / IN2P3-CNRS DAPNIA/SPP (Saclay) / CEA #include "sopnamsp.h" #include "cxxcmplnk.h" #include "sspvflags.h" #include /*! \class SOPHYA::CxxCompilerLinker \ingroup SysTools This classes handles the compilation of a C++ source code and building of a shared library. The present version has been adapted for different compilers and systems: - Linux + GNU compiler (g++) - Linux + Intel compiler (icc) - Darwin + GNU compiler (MaxOS X 10.3 and 10.4) - OSF1 + cxx (HP/Compaq/Digital OSF-Tru64 and cxx c++ compiler) - IRIX64 + CC : Silicon Graphics system and C++ compiler - AIX + xlC : IBM system and C++ compiler \sa SOPHYA::PDynLinkMgr \code #include "cxxcmplnk.h" CxxCompilerLinker cxx; string name = "toto.cc"; string oname = "toto.o"; string soname = "toto.so"; int rc; // compiling file rc = cxx.Compile(name, oname); // linking and building the shared object rc = cxx.BuildSO(oname, soname); \endcode */ static char * gcxx_opt = "-O -fdollars-in-identifiers"; static char * KCC_opt = "-O --exceptions --rtti --auto_instantiation --one_instantiation_per_object -D__KCC__"; static char * icc_opt = "-O -fpic -frtti"; static char * cxx_opt = "-O -no_implicit_include -pthread"; static char * SGICC_opt = "-O -prelink -D__SGICC__ -LANG:std"; static char * xlC_opt = "-O -qrtti=all -qeh=v6"; /* --Methode-- */ /*! Constructor \param fglibsophya : if \c true libsophya.so is used when linking \param fglibextsophya : if \c true libextsophya.so is used when linking \param fglibpi : if \c true libPI.so is used when linking */ CxxCompilerLinker::CxxCompilerLinker(bool fglibsophya, bool fglibextsophya, bool fglibpi) : verbose(false) { string syscomp = ""; #if defined(OSF1) cppFlags += "-DOSF1" ; syscomp = "OSF1-"; #elif defined(Linux) cppFlags += "-DLinux" ; syscomp = "Linux-"; #elif defined(SunOS) cppFlags += "-DSunOS" ; syscomp = "SunOS-"; #elif defined(IRIX64) cppFlags += "-DIRIX64" ; syscomp = "IRIX64-"; #elif defined(AIX) cppFlags += "-DAIX" ; syscomp = "AIX-"; #elif defined(HPUX) cppFlags += "-DHPUX" ; syscomp = "HPUX-"; #elif defined(Darwin) cppFlags += "-DDarwin"; syscomp = "Darwin-"; #endif #if defined( __GNUG__ ) compCmd = "g++ "; compOptions = gcxx_opt; linkOptions = "-O -shared"; syscomp += "g++/"; #endif #if defined( __DECCXX ) compCmd = "cxx "; compOptions = cxx_opt; linkOptions = compOptions + " -shared"; syscomp += "cxx/"; #endif #if defined( __KCC__ ) compCmd = "KCC "; compOptions = KCC_opt; linkOptions = KCC_opt; syscomp += "KCC/"; #endif #if defined( __SGICC__ ) compCmd = "CC "; compOptions = SGICC_opt; linkOptions = "-shared -O -LANG:std"; syscomp += "CC/"; #ifdef SGI_ARCH64 compOptions += " -64 -DSGI_ARCH64 "; linkOptions += " -64 "; #endif #endif #if defined( __INTEL_COMPILER ) compCmd = "icpc "; compOptions = icc_opt; linkOptions = icc_opt + string(" -shared"); syscomp += "icc/"; #endif #if defined( __IBMCPP__ ) compCmd = "xlC "; compOptions = xlC_opt; linkOptions = xlC_opt + string(" -brtl -qmkshrobj "); syscomp += "xlC/"; #endif #ifndef Darwin linkCmd = compCmd; #else linkCmd = "c++ -bundle "; linkOptions = "-lSystem -lm"; #endif cppFlags += " -I. "; compOptions += " -c "; bool fgenv1 = false; bool fgenv2 = false; char* varenv=NULL; varenv=getenv("SOPHYABASE"); string sbaserep = "./"; if (varenv) { fgenv1 = true; sbaserep = varenv; if (sbaserep[sbaserep.length()-1] != '/') sbaserep += '/'; cppFlags += ( " -I" + sbaserep + "include/ "); linkOptions += " -L" + sbaserep + "slb/"; } varenv=getenv("SOPHYABASEREP"); if (varenv) { fgenv2 = true; string dpcbase = varenv; if (dpcbase[dpcbase.length()-1] != '/') dpcbase += '/'; cppFlags += ( " -I" + dpcbase + "Include/ "); linkOptions += " -L" + dpcbase + syscomp + "ShLibs/"; char * varenvextl=getenv("EXTLIBDIR"); if (varenvextl) { string extlib = varenvextl; if (extlib[extlib.length()-1] != '/') extlib += '/'; cppFlags += ( " -I" + extlib +"Include/ "); } } if (!fgenv1 && !fgenv2) cout << " CxxCompilerLinker()/Warning : SOPHYABASE not defined" << endl; if (fgenv1 && fgenv2) cout << " CxxCompilerLinker()/Warning : both SOPHYABASE and SOPHYABASEREP defined" << endl; #if defined( SINGLESLB_SOPHYA_PI_EXT ) if (fglibsophya || fglibpi) linkOptions += " -lAsophyaextPI "; /* cout << " +++ DBG/CxxCompilerLinker() - in AIX fglibpi= " << ((fglibpi) ? " true " : " false ") << endl; // Reza:Dec 2005 : pb avec les programmes PI sur AIX si linke avec shared lib PI // (Portage sur regatta.calcul.u-psud.fr AIX 5.3 , libXm Xt X11 en .a uniquement) if (fglibpi) { linkOptions += " -L" + sbaserep + "lib/"; linkOptions += " -lPIext -lPIGcont -lPI -lXm -lXt -lX11 -lpthread "; } */ cout << "CxxCompilerLinker()/Warning: SINGLESLB_SOPHYA_PI_EXT -> linkOptions= " << linkOptions << endl; #else if (fglibsophya) linkOptions += " -lsophya "; if (fglibextsophya) linkOptions += " -lextsophya "; if (fglibpi) linkOptions += " -lPI "; #endif linkOptions += " -lm "; if ( (varenv=getenv("TMPDIR")) != NULL ) { tmpDir = varenv; if (tmpDir[tmpDir.length()-1] != '/') tmpDir += '/'; } } /* --Methode-- */ CxxCompilerLinker::~CxxCompilerLinker() { } /* --Methode-- */ /*! Compiles the file \c name using the C++ compiler driver and produces the output object file \c oname. If no output name is specified, a default output file name is made from the input name, with the suffix .o , the in temporary directory. \param name : input C++ source file \param oname : output object file */ int CxxCompilerLinker::Compile(string const & name, string & oname) { if (oname.length() < 1) { size_t l,p,q; l = name.length(); p = name.rfind('/'); if (p >= l) p = 0; else p++; q = name.rfind('.'); if ((q < l) && (q > p)) oname = tmpDir + name.substr(p, q-p) + ".o"; else oname = tmpDir + name.substr(p) + ".o"; } string cmd; cmd = compCmd + cppFlags + compOptions + "-o " + oname + " " + name ; if (verbose) cout << "CxxCompilerLinker::Compile() - Executing \n" << cmd << endl; int rc = system(cmd.c_str()); if (rc != 0) cerr << "CxxCompilerLinker::Compile() Error Rc(" << cmd <<")= "<< rc << endl; return(rc); } /* --Methode-- */ /*! Creates a shared library from the object file \c oname. If no output name \c soname is specified, a default output file name is made from the object name, with the suffix .so , in the temporary directory. \param oname : input object file \param soname : shared library name */ int CxxCompilerLinker::BuildSO(string const & oname, string & soname) { // char * soext = ".dylib"; if defined(Darwin) - pas necessaire Reza 02/2002 char * soext = ".so"; if (soname.length() < 1) { size_t l,p,q; l = oname.length(); p = oname.rfind('/'); if (p >= l) p = 0; else p++; q = oname.rfind('.'); if ((q < l) && (q > p)) soname = tmpDir + oname.substr(p, q-p) + soext; else soname = tmpDir + oname.substr(p) + soext; } string cmd; cmd = linkCmd + " " + oname + " " + linkOptions + " -o " + soname + " " ; if (verbose) cout << "CxxCompilerLinker::BuildSO() - Executing \n" << cmd << endl; int rc = system(cmd.c_str()); if (rc != 0) cerr << "CxxCompilerLinker::BuildSO() Error Rc(" << cmd <<")= "<< rc << endl; return(rc); }