File indexing completed on 2024-12-01 11:20:39
0001 /*************************************************************************** 0002 * Copyright (C) 2005 by David Saxton * 0003 * david@bluehaze.org * 0004 * * 0005 * This program is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU General Public License as published by * 0007 * the Free Software Foundation; either version 2 of the License, or * 0008 * (at your option) any later version. * 0009 ***************************************************************************/ 0010 0011 #include "gplink.h" 0012 #include "languagemanager.h" 0013 #include "logview.h" 0014 #include "microinfo.h" 0015 #include "microlibrary.h" 0016 0017 #include <KLocalizedString> 0018 #include <KMessageBox> 0019 #include <KProcess> 0020 0021 #include <QDir> 0022 #include <QFile> 0023 0024 #include <ktlconfig.h> 0025 #include <ktechlab_debug.h> 0026 0027 Gplink::Gplink(ProcessChain *processChain) 0028 : ExternalLanguage(processChain, "Gpasm") 0029 { 0030 m_successfulMessage = i18n("*** Linking successful ***"); 0031 m_failedMessage = i18n("*** Linking failed ***"); 0032 0033 // search for SDCC 0034 0035 m_sdccLibDir = ""; 0036 #define SEARCH_FOR_SDCC(dir) \ 0037 { \ 0038 if (m_sdccLibDir.isEmpty()) { \ 0039 QFile f(dir); \ 0040 qCDebug(KTL_LOG) << " SDCC lib testing " << dir; \ 0041 if (f.exists()) { \ 0042 qCDebug(KTL_LOG) << " SDCC lib found " << dir; \ 0043 m_sdccLibDir = dir; \ 0044 } \ 0045 } \ 0046 } 0047 0048 // consider adding more paths here, if necessary 0049 if (!KTLConfig::sDCC_install_prefix().isEmpty()) { 0050 SEARCH_FOR_SDCC(KTLConfig::sDCC_install_prefix().append("/share/sdcc/lib")); 0051 } 0052 SEARCH_FOR_SDCC("/usr/local/share/sdcc/lib") 0053 SEARCH_FOR_SDCC("/usr/share/sdcc/lib") 0054 SEARCH_FOR_SDCC("/usr/sdcc/lib") 0055 SEARCH_FOR_SDCC("/usr/sdcc/share/lib") 0056 SEARCH_FOR_SDCC("/opt/sdcc/lib") 0057 SEARCH_FOR_SDCC("/opt/sdcc/share/lib") 0058 SEARCH_FOR_SDCC(QDir::homePath() + "/share/sdcc/lib"); 0059 #undef SEARCH_FOR_SDCC 0060 if (m_sdccLibDir == "") { 0061 qCWarning(KTL_LOG) << "SDCC lib not found. Expect linking errors"; 0062 } 0063 { 0064 QFile f(m_sdccLibDir + "/../non-free/lib"); 0065 if (!f.exists()) { 0066 qCWarning(KTL_LOG) << "SDCC non-free lib not found. Expect linking errors"; 0067 } 0068 } 0069 } 0070 0071 Gplink::~Gplink() 0072 { 0073 } 0074 0075 void Gplink::processInput(ProcessOptions options) 0076 { 0077 resetLanguageProcess(); 0078 m_processOptions = options; 0079 0080 *m_languageProcess << ("gplink"); 0081 0082 // note: needed for newer GPUtils: relocate to shared memory if necessary 0083 *m_languageProcess << ("--use-shared"); 0084 0085 if (!options.m_hexFormat.isEmpty()) { 0086 *m_languageProcess << ("--hex-format"); 0087 *m_languageProcess << (options.m_hexFormat); 0088 } 0089 0090 if (options.m_bOutputMapFile) 0091 *m_languageProcess << ("--map"); 0092 0093 if (!options.m_libraryDir.isEmpty()) { 0094 *m_languageProcess << ("--include"); 0095 *m_languageProcess << (options.m_libraryDir); 0096 } 0097 0098 if (!options.m_linkerScript.isEmpty()) { 0099 *m_languageProcess << ("--script"); 0100 *m_languageProcess << (options.m_linkerScript); 0101 } 0102 0103 if (!options.m_linkOther.isEmpty()) 0104 *m_languageProcess << (options.m_linkOther); 0105 0106 // Output hex file 0107 *m_languageProcess << ("--output"); 0108 *m_languageProcess << (options.intermediaryOutput()); 0109 0110 // Input object file 0111 const QStringList inputFiles = options.inputFiles(); 0112 QStringList::const_iterator end = inputFiles.end(); 0113 for (QStringList::const_iterator it = inputFiles.begin(); it != end; ++it) 0114 *m_languageProcess << (*it); 0115 0116 // Other libraries 0117 end = options.m_linkLibraries.end(); 0118 for (QStringList::const_iterator it = options.m_linkLibraries.begin(); it != end; ++it) 0119 *m_languageProcess << (*it); 0120 0121 // if selected to automatically link to SDCC libraries, add some options. 0122 if (KTLConfig::gplink_link_shared()) { 0123 // set up the include directory 0124 MicroInfo *info = MicroLibrary::self()->microInfoWithID(options.m_picID); 0125 if (!info) { 0126 // be program won't link anyway, but the user can't say that the program didn't try 0127 qCCritical(KTL_LOG) << "Couldn't find the requested PIC" << options.m_picID; 0128 qCWarning(KTL_LOG) << "Supposing that the pic is pic12 or pic14"; 0129 *m_languageProcess << "-I" << m_sdccLibDir + "/pic"; 0130 } else { 0131 QString picLibSubdir; 0132 switch (info->instructionSet()->set()) { 0133 // note: is PIC12 supported by SDCC? 0134 case AsmInfo::PIC12: 0135 picLibSubdir = "pic12"; 0136 break; 0137 case AsmInfo::PIC14: 0138 picLibSubdir = "pic14"; 0139 break; 0140 case AsmInfo::PIC16: 0141 picLibSubdir = "pic16"; 0142 break; 0143 default: 0144 qCWarning(KTL_LOG) << "Inexpected instruction set: " << int(info->instructionSet()->set()); 0145 break; 0146 } 0147 *m_languageProcess << "-I" << m_sdccLibDir + "/" + picLibSubdir; 0148 // non-free libraries are needed; beware the Debian/Ubuntu/derivatives' packages 0149 *m_languageProcess << "-I" << m_sdccLibDir + "/../non-free/lib/" + picLibSubdir; 0150 // to pic to link against 0151 *m_languageProcess << options.m_picID.toLower().replace("p", "pic") + ".lib"; 0152 } 0153 *m_languageProcess << "libsdcc.lib"; 0154 } 0155 0156 if (!start()) { 0157 KMessageBox::error(LanguageManager::self()->logView(), i18n("Linking failed. Please check you have gputils installed.")); 0158 processInitFailed(); 0159 return; 0160 } 0161 } 0162 0163 bool Gplink::isError(const QString &message) const 0164 { 0165 return message.contains("Error", Qt::CaseInsensitive); 0166 } 0167 0168 bool Gplink::isWarning(const QString &message) const 0169 { 0170 return message.contains("Warning", Qt::CaseInsensitive); 0171 } 0172 0173 MessageInfo Gplink::extractMessageInfo(const QString &text) 0174 { 0175 if (text.length() < 5 || !text.startsWith("/")) 0176 return MessageInfo(); 0177 #if 0 0178 const int index = text.indexOf( ".asm", 0, Qt::CaseInsensitive )+4; 0179 if ( index == -1+4 ) 0180 return MessageInfo(); 0181 const QString fileName = text.left(index); 0182 0183 // Extra line number 0184 const QString message = text.right(text.length()-index); 0185 const int linePos = message.indexOf( QRegExp(":[\\d]+") ); 0186 int line = -1; 0187 if ( linePos != -1 ) 0188 { 0189 const int linePosEnd = message.indexOf( ':', linePos+1 ); 0190 if ( linePosEnd != -1 ) 0191 { 0192 const QString number = message.mid( linePos+1, linePosEnd-linePos-1 ).trimmed(); 0193 bool ok; 0194 line = number.toInt(&ok)-1; 0195 if (!ok) line = -1; 0196 } 0197 } 0198 return MessageInfo( fileName, line ); 0199 #endif 0200 return MessageInfo(); 0201 } 0202 0203 ProcessOptions::ProcessPath::Path Gplink::outputPath(ProcessOptions::ProcessPath::Path inputPath) const 0204 { 0205 switch (inputPath) { 0206 case ProcessOptions::ProcessPath::Object_PIC: 0207 return ProcessOptions::ProcessPath::Program_PIC; 0208 0209 case ProcessOptions::ProcessPath::Object_Program: 0210 return ProcessOptions::ProcessPath::None; 0211 0212 case ProcessOptions::ProcessPath::AssemblyAbsolute_PIC: 0213 case ProcessOptions::ProcessPath::AssemblyAbsolute_Program: 0214 case ProcessOptions::ProcessPath::AssemblyRelocatable_Library: 0215 case ProcessOptions::ProcessPath::AssemblyRelocatable_Object: 0216 case ProcessOptions::ProcessPath::AssemblyRelocatable_PIC: 0217 case ProcessOptions::ProcessPath::AssemblyRelocatable_Program: 0218 case ProcessOptions::ProcessPath::C_AssemblyRelocatable: 0219 case ProcessOptions::ProcessPath::C_Library: 0220 case ProcessOptions::ProcessPath::C_Object: 0221 case ProcessOptions::ProcessPath::C_PIC: 0222 case ProcessOptions::ProcessPath::C_Program: 0223 case ProcessOptions::ProcessPath::FlowCode_AssemblyAbsolute: 0224 case ProcessOptions::ProcessPath::FlowCode_Microbe: 0225 case ProcessOptions::ProcessPath::FlowCode_PIC: 0226 case ProcessOptions::ProcessPath::FlowCode_Program: 0227 case ProcessOptions::ProcessPath::Microbe_AssemblyAbsolute: 0228 case ProcessOptions::ProcessPath::Microbe_PIC: 0229 case ProcessOptions::ProcessPath::Microbe_Program: 0230 case ProcessOptions::ProcessPath::Object_Disassembly: 0231 case ProcessOptions::ProcessPath::Object_Library: 0232 case ProcessOptions::ProcessPath::PIC_AssemblyAbsolute: 0233 case ProcessOptions::ProcessPath::Program_Disassembly: 0234 case ProcessOptions::ProcessPath::Program_PIC: 0235 case ProcessOptions::ProcessPath::Invalid: 0236 case ProcessOptions::ProcessPath::None: 0237 return ProcessOptions::ProcessPath::Invalid; 0238 } 0239 0240 return ProcessOptions::ProcessPath::Invalid; 0241 }