void ClangCodeCompletion::OnBuildStarting(clBuildEvent& e)
{
    e.Skip();
    CHECK_CLANG_ENABLED_RET();

    // Determine the compilation database
    CompilationDatabase cdb;
    cdb.Open();
    cdb.Close();

    // Set the compilation database environment variable
    ::wxSetEnv(wxT("CL_COMPILATION_DB"), cdb.GetFileName().GetFullPath());

    // If this is NOT a custom project, set the CXX and CC environment
    wxString  project = e.GetProjectName();
    wxString  config  = e.GetConfigurationName();
    
    BuildConfigPtr bldConf = WorkspaceST::Get()->GetProjBuildConf(project, config);
    if( bldConf && !bldConf->IsCustomBuild()) {
        wxString cxx = bldConf->GetCompiler()->GetTool(wxT("CXX"));
        wxString cc  = bldConf->GetCompiler()->GetTool(wxT("CC"));
        
        cxx.Prepend(wxT("codelitegcc "));
        cc.Prepend(wxT("codelitegcc "));
        
        ::wxSetEnv("CXX", cxx);
        ::wxSetEnv("CC" ,  cc);
    }
}
chimera::cd_utils::CompileCommandVector
chimera::cd_utils::getCompileCommandsByFilePath(
    const CompilationDatabase &database, StringRef filename) {
  // First search for the correct "file"
  Twine targetFilePath = Twine(filename);
  std::string foundFilePath;
  ChimeraLogger::verboseAndIncr("Retrieving compileCommands for " +
                                targetFilePath.str());
  // Find the foundFilename to access specific compileCommands
  // Get all "file" field of the compilation database
  auto compileFile = database.getAllFiles();
  // Check if it's empty
  if (!compileFile.empty()) {
    // This isn't a FixedCompilationDatabase
    for (auto file = compileFile.begin(); file != compileFile.end(); ++file) {
      // Compare with targetFilename
      Twine filePathToCompare(*file);
      ChimeraLogger::verbose("Comparing with File: " + *file);
      // llvm::sys::fs::equivalent to test the really equivalence
      if (llvm::sys::fs::equivalent(targetFilePath, filePathToCompare)) {
        ChimeraLogger::verbose("Successful. Match found!");
        foundFilePath = *file;
        break;
      }
    }
  } else {
    // This is a FixedCompilationDatabase
    ChimeraLogger::verbose(
        "CompilationDatabase with an empty filelist. Maybe provided by hand");
    foundFilePath = targetFilePath.str();
  }
  ChimeraLogger::decrActualVLevel();
  // Return compileCommands
  return database.getCompileCommands(foundFilePath);
}
void CodeCompletionManager::DoUpdateCompilationDatabase()
{
    // Create a worker thread (detached thread) that 
    // will initialize the database now that the compilation has ended
    CompilationDatabase db;
    ClangCompilationDbThreadST::Get()->AddFile( db.GetFileName().GetFullPath() );
}
TranslationUnit::TranslationUnit(Index& index, const std::string& source,
                                 CompilationDatabase& comp_db) {
    auto commands = comp_db.getCompileCommands(source);
    unsigned cmd_args = commands.getSize();
    if (cmd_args == 0) {
        throw std::runtime_error("No compilation info for file `" + source +
                                 "`");
    }
    auto command = commands.getCommand(0);
    auto arguments = command.GetArguments(1);
    arguments.push_back("-I" + comp_db.GetClangHeadersLocation());
    std::vector<const char*> c_arguments;
    c_arguments.reserve(arguments.size());
    bool skip = false;
    for (auto& arg : arguments) {
        if (skip) {
            skip = false;
            continue;
        }
        if (arg == "-c") {
            skip = true;
            continue;
        }
        c_arguments.push_back(arg.c_str());
    }
    CXErrorCode code = clang_parseTranslationUnit2(
        index.index_, source.c_str(), c_arguments.data(), c_arguments.size(),
        nullptr, 0, CXTranslationUnit_DetailedPreprocessingRecord, &unit_);
    if (code != CXError_Success) {
        throw std::runtime_error("Error while parsing file `" + source + "`: " +
                                 ErrorCodeToString(code));
    }
}
void CodeCompletionManager::OnCompileCommandsFileGenerated(clCommandEvent& event)
{
    event.Skip();
    CL_DEBUG("-- Code Completion Manager: process file 'compile_commands.json' file");
    CompilationDatabase db;
    ClangCompilationDbThreadST::Get()->AddFile(db.GetFileName().GetFullPath());
    clMainFrame::Get()->SetStatusText("Ready");
}
Exemple #6
0
ClangTool::ClangTool(const CompilationDatabase &Compilations,
                     ArrayRef<std::string> SourcePaths)
    : Files(new FileManager(FileSystemOptions())), DiagConsumer(NULL) {
  ArgsAdjusters.push_back(new ClangStripOutputAdjuster());
  ArgsAdjusters.push_back(new ClangSyntaxOnlyAdjuster());
  for (const auto &SourcePath : SourcePaths) {
    std::string File(getAbsolutePath(SourcePath));

    std::vector<CompileCommand> CompileCommandsForFile =
      Compilations.getCompileCommands(File);
    if (!CompileCommandsForFile.empty()) {
      for (CompileCommand &CompileCommand : CompileCommandsForFile) {
        CompileCommands.push_back(
            std::make_pair(File, std::move(CompileCommand)));
      }
    } else {
      // FIXME: There are two use cases here: doing a fuzzy
      // "find . -name '*.cc' |xargs tool" match, where as a user I don't care
      // about the .cc files that were not found, and the use case where I
      // specify all files I want to run over explicitly, where this should
      // be an error. We'll want to add an option for this.
      llvm::errs() << "Skipping " << File << ". Compile command not found.\n";
    }
  }
}
Exemple #7
0
ClangTool::ClangTool(const CompilationDatabase &Compilations,
                     ArrayRef<std::string> SourcePaths)
    : Files((FileSystemOptions())),
      ArgsAdjuster(new ClangSyntaxOnlyAdjuster()) {
  llvm::SmallString<1024> BaseDirectory;
  if (const char *PWD = ::getenv("PWD"))
    BaseDirectory = PWD;
  else
    llvm::sys::fs::current_path(BaseDirectory);
  for (unsigned I = 0, E = SourcePaths.size(); I != E; ++I) {
    llvm::SmallString<1024> File(getAbsolutePath(
        SourcePaths[I], BaseDirectory));

    std::vector<CompileCommand> CompileCommandsForFile =
      Compilations.getCompileCommands(File.str());
    if (!CompileCommandsForFile.empty()) {
      for (int I = 0, E = CompileCommandsForFile.size(); I != E; ++I) {
        CompileCommands.push_back(std::make_pair(File.str(),
                                  CompileCommandsForFile[I]));
      }
    } else {
      // FIXME: There are two use cases here: doing a fuzzy
      // "find . -name '*.cc' |xargs tool" match, where as a user I don't care
      // about the .cc files that were not found, and the use case where I
      // specify all files I want to run over explicitly, where this should
      // be an error. We'll want to add an option for this.
      llvm::outs() << "Skipping " << File << ". Command line not found.\n";
    }
  }
}
void ClangCodeCompletion::OnBuildEnded(clBuildEvent& e)
{
    e.Skip();
    CHECK_CLANG_ENABLED_RET();

    // Clear environment variables previously set by this class
    ::wxUnsetEnv(wxT("CL_COMPILATION_DB"));
    ::wxUnsetEnv(wxT("CXX"));
    ::wxUnsetEnv(wxT("CC"));
    
    // Create a worker thread (detached thread) that 
    // will initialize the database now that the compilation is ended
    CompilationDatabase db;
    ClangCompilationDbThread* thr = new ClangCompilationDbThread( db.GetFileName().GetFullPath() );
    thr->Start();
    
    // Clear the TU cache
    ClearCache();
}
bool CodeCompletionManager::GetDefinitionsAndSearchPaths(LEditor* editor,
                                                         wxArrayString& searchPaths,
                                                         wxArrayString& definitions)
{
    // Sanity
    CHECK_PTR_RET_FALSE(editor);

    if(editor->GetProjectName().IsEmpty())
        return false;
    if(!WorkspaceST::Get()->IsOpen())
        return false;

    // Support only C/C++ files
    if(!FileExtManager::IsCxxFile(editor->GetFileName().GetFullName()))
        return false;

    // Get the file's project and get the build configuration settings
    // for it
    ProjectPtr proj = WorkspaceST::Get()->GetProject(editor->GetProjectName());
    CHECK_PTR_RET_FALSE(proj);

    BuildConfigPtr buildConf = proj->GetBuildConfiguration();
    CHECK_PTR_RET_FALSE(buildConf);

    CompilerPtr compiler = buildConf->GetCompiler();
    CHECK_PTR_RET_FALSE(compiler);

    if(buildConf->IsCustomBuild()) {
        // Custom builds are handled differently
        CompilationDatabase compileDb;
        compileDb.Open();
        if(compileDb.IsOpened()) {
            // we have compilation database for this workspace
            wxString compileLine, cwd;
            compileDb.CompilationLine(editor->GetFileName().GetFullPath(), compileLine, cwd);

            CL_DEBUG("Pre Processor dimming: %s\n", compileLine);
            CompilerCommandLineParser cclp(compileLine, cwd);
            searchPaths = cclp.GetIncludes();

            // get the mcros
            definitions = cclp.GetMacros();
        } else {
            // we will probably will fail...
            return false;
        }
    } else {
        // get the include paths based on the project settings (this is per build configuration)
        searchPaths = proj->GetIncludePaths();
        CL_DEBUG("CxxPreProcessor will use the following include paths:");
        CL_DEBUG_ARR(searchPaths);

        // get the compiler include paths
        // wxArrayString compileIncludePaths = compiler->GetDefaultIncludePaths();

        // includePaths.insert(includePaths.end(), compileIncludePaths.begin(), compileIncludePaths.end());
        definitions = proj->GetPreProcessors();
        CL_DEBUG("CxxPreProcessor will use the following macros:");
        CL_DEBUG_ARR(definitions);
    }

    // Append the compiler builtin macros
    wxArrayString builtinMacros = compiler->GetBuiltinMacros();
    definitions.insert(definitions.end(), builtinMacros.begin(), builtinMacros.end());

    return true;
}
bool CodeCompletionManager::GetDefinitionsAndSearchPaths(clEditor* editor, wxArrayString& searchPaths,
                                                         wxArrayString& definitions)
{
    // Sanity
    CHECK_PTR_RET_FALSE(editor);

    if(editor->GetProjectName().IsEmpty()) return false;
    if(!clCxxWorkspaceST::Get()->IsOpen()) return false;

    // Support only C/C++ files
    if(!FileExtManager::IsCxxFile(editor->GetFileName().GetFullName())) return false;

    // Get the file's project and get the build configuration settings
    // for it
    ProjectPtr proj = clCxxWorkspaceST::Get()->GetProject(editor->GetProjectName());
    CHECK_PTR_RET_FALSE(proj);

    BuildConfigPtr buildConf = proj->GetBuildConfiguration();
    CHECK_PTR_RET_FALSE(buildConf);

    CompilerPtr compiler = buildConf->GetCompiler();
    CHECK_PTR_RET_FALSE(compiler);

#if 0
    if(buildConf->IsCustomBuild()) {
        definitions = proj->GetPreProcessors();
        CL_DEBUG("CxxPreProcessor will use the following macros:");
        CL_DEBUG_ARR(definitions);
        // Custom builds are handled differently
        CompilationDatabase compileDb;
        compileDb.Open();
        if(compileDb.IsOpened()) {
            // we have compilation database for this workspace
            wxString compileLine, cwd;
            compileDb.CompilationLine(editor->GetFileName().GetFullPath(), compileLine, cwd);

            CL_DEBUG("Pre Processor dimming: %s\n", compileLine);
            CompilerCommandLineParser cclp(compileLine, cwd);
            searchPaths = cclp.GetIncludes();

            // get the mcros
            definitions << cclp.GetMacros();
        }
    }
#endif
    // get the include paths based on the project settings (this is per build configuration)
    searchPaths = proj->GetIncludePaths();
    CL_DEBUG("CxxPreProcessor will use the following include paths:");
    CL_DEBUG_ARR(searchPaths);

    // get the compiler include paths
    // wxArrayString compileIncludePaths = compiler->GetDefaultIncludePaths();

    // includePaths.insert(includePaths.end(), compileIncludePaths.begin(), compileIncludePaths.end());
    definitions = proj->GetPreProcessors();

    // get macros out of workspace
    wxString strWorkspaceMacros = clCxxWorkspaceST::Get()->GetParserMacros();
    wxArrayString workspaceMacros = wxStringTokenize(strWorkspaceMacros, wxT("\n\r"), wxTOKEN_STRTOK);
    for(size_t i = 0; i < workspaceMacros.GetCount(); i++)
        definitions.Add(workspaceMacros.Item(i).Trim().Trim(false).c_str());

    CL_DEBUG("CxxPreProcessor will use the following macros:");
    CL_DEBUG_ARR(definitions);

    // Append the compiler builtin macros
    wxArrayString builtinMacros = compiler->GetBuiltinMacros();
    definitions.insert(definitions.end(), builtinMacros.begin(), builtinMacros.end());

    return true;
}
Exemple #11
0
FileTypeCmpArgs_t ClangDriver::DoPrepareCompilationArgs(const wxString& projectName,
                                                        const wxString& sourceFile,
                                                        wxString& projectPath,
                                                        wxString& pchfile)
{
    FileTypeCmpArgs_t cmpArgs;

    cmpArgs.insert(std::make_pair(FileExtManager::TypeSourceC, wxArrayString()));
    cmpArgs.insert(std::make_pair(FileExtManager::TypeSourceCpp, wxArrayString()));

    wxArrayString args;
    wxString errMsg;

    wxArrayString& cppCompileArgs = cmpArgs[FileExtManager::TypeSourceCpp];
    wxArrayString& cCompileArgs = cmpArgs[FileExtManager::TypeSourceC];

    // Build the TU file name
    wxFileName fnSourceFile(sourceFile);
    pchfile << WorkspaceST::Get()->GetWorkspaceFileName().GetPath() << wxFileName::GetPathSeparator() << wxT(".clang");

    {
        wxLogNull nl;
        wxMkdir(pchfile);
    }

    pchfile << wxFileName::GetPathSeparator() << fnSourceFile.GetFullName() << wxT(".TU");

    CompilationDatabase cdb;
    static bool once = false;
    if(!cdb.IsOk() && !once) {
        once = true;

        wxString msg;
        msg << _("Could not locate compilation database or database version is not up-to-date: ")
            << cdb.GetFileName().GetFullPath() << wxT("\n\n")
            << _("This file should be created automatically for you.\nIf you don't have it, please run a full rebuild "
                 "of your workspace\n\n")
            << _("If this is a custom build project (i.e. project that uses a custom makefile),\nplease set the CXX "
                 "and CC environment variables like this:\n") << _("CXX=codelite-cc g++\n")
            << _("CC=codelite-cc gcc\n\n");

        clMainFrame::Get()->GetMainBook()->ShowMessage(
            msg,
            true,
            PluginManager::Get()->GetStdIcons()->LoadBitmap(wxT("messages/48/tip")),
            ButtonDetails(),
            ButtonDetails(),
            ButtonDetails(),
            CheckboxDetails(wxT("CodeCompletionMissingCompilationDB")));

    } else {
        cdb.Open();
        if(cdb.IsOpened()) {
            CL_DEBUG(wxT("Loading compilation flags for file: %s"), fnSourceFile.GetFullPath().c_str());
            wxString compilationLine, cwd;
            cdb.CompilationLine(fnSourceFile.GetFullPath(), compilationLine, cwd);
            cdb.Close();

            CompilerCommandLineParser cclp(compilationLine, cwd);
            cclp.MakeAbsolute(cwd);

            CL_DEBUG(wxT("Loaded compilation flags: %s"), compilationLine.c_str());
            args.insert(args.end(), cclp.GetIncludesWithPrefix().begin(), cclp.GetIncludesWithPrefix().end());
            args.insert(args.end(), cclp.GetMacrosWithPrefix().begin(), cclp.GetMacrosWithPrefix().end());
            args.Add(cclp.GetStandardWithPrefix());
        }
    }

    const TagsOptionsData& options = TagsManagerST::Get()->GetCtagsOptions();

    ///////////////////////////////////////////////////////////////////////
    // add global clang include paths
    wxString strGlobalIncludes = options.GetClangSearchPaths();

    // expand any macros from the include paths
    strGlobalIncludes = MacroManager::Instance()->Expand(strGlobalIncludes, PluginManager::Get(), projectName);

    wxArrayString globalIncludes = wxStringTokenize(strGlobalIncludes, wxT("\n\r"), wxTOKEN_STRTOK);
    for(size_t i = 0; i < globalIncludes.GetCount(); i++) {
        wxFileName fn(globalIncludes.Item(i).Trim().Trim(false), wxT(""));
        fn.MakeAbsolute(projectPath);

        cppCompileArgs.Add(wxString::Format(wxT("-I%s"), fn.GetPath().c_str()));
        cCompileArgs.Add(wxString::Format(wxT("-I%s"), fn.GetPath().c_str()));
    }

    ///////////////////////////////////////////////////////////////////////
    // Workspace setting additional flags
    ///////////////////////////////////////////////////////////////////////

    // Include paths
    wxArrayString workspaceIncls, dummy;
    LocalWorkspaceST::Get()->GetParserPaths(workspaceIncls, dummy);
    for(size_t i = 0; i < workspaceIncls.GetCount(); i++) {
        wxFileName fn(workspaceIncls.Item(i).Trim().Trim(false), wxT(""));
        fn.MakeAbsolute(WorkspaceST::Get()->GetWorkspaceFileName().GetPath());
        cppCompileArgs.Add(wxString::Format(wxT("-I%s"), fn.GetPath().c_str()));
        cCompileArgs.Add(wxString::Format(wxT("-I%s"), fn.GetPath().c_str()));
    }

    // Macros
    wxString strWorkspaceMacros;
    LocalWorkspaceST::Get()->GetParserMacros(strWorkspaceMacros);
    wxArrayString workspaceMacros = wxStringTokenize(strWorkspaceMacros, wxT("\n\r"), wxTOKEN_STRTOK);
    for(size_t i = 0; i < workspaceMacros.GetCount(); i++) {
        cppCompileArgs.Add(wxString::Format(wxT("-D%s"), workspaceMacros.Item(i).Trim().Trim(false).c_str()));
        cCompileArgs.Add(wxString::Format(wxT("-D%s"), workspaceMacros.Item(i).Trim().Trim(false).c_str()));
    }

    // C++ 11 / 14
    size_t workspaceFlags = LocalWorkspaceST::Get()->GetParserFlags();
    if(workspaceFlags & LocalWorkspace::EnableCpp11) {
        cppCompileArgs.Add(wxT("-std=c++11"));
        cCompileArgs.Add(wxT("-std=c++11"));
    }
    if(workspaceFlags & LocalWorkspace::EnableCpp14) {
        cppCompileArgs.Add(wxT("-std=c++14"));
        cCompileArgs.Add(wxT("-std=c++14"));
    }

    ///////////////////////////////////////////////////////////////////////
    // Project setting additional flags
    ///////////////////////////////////////////////////////////////////////

    BuildConfigPtr buildConf = ManagerST::Get()->GetCurrentBuildConf();
    if(buildConf) {
        wxString projSearchPaths = buildConf->GetCcSearchPaths();
        wxArrayString projectIncludePaths = wxStringTokenize(projSearchPaths, wxT("\r\n"), wxTOKEN_STRTOK);
        for(size_t i = 0; i < projectIncludePaths.GetCount(); i++) {
            wxFileName fn(MacroManager::Instance()
                              ->Expand(projectIncludePaths.Item(i),
                                       PluginManager::Get(),
                                       ManagerST::Get()->GetActiveProjectName()),
                          wxT(""));
            fn.MakeAbsolute(WorkspaceST::Get()->GetWorkspaceFileName().GetPath());
            cppCompileArgs.Add(wxString::Format(wxT("-I%s"), fn.GetPath().c_str()));
            cCompileArgs.Add(wxString::Format(wxT("-I%s"), fn.GetPath().c_str()));
        }

        wxString strProjectMacros = buildConf->GetClangPPFlags();
        wxArrayString projectMacros = wxStringTokenize(strProjectMacros, wxT("\n\r"), wxTOKEN_STRTOK);
        for(size_t i = 0; i < projectMacros.GetCount(); i++) {
            cppCompileArgs.Add(wxString::Format(wxT("-D%s"), projectMacros.Item(i).Trim().Trim(false).c_str()));
            cCompileArgs.Add(wxString::Format(wxT("-D%s"), projectMacros.Item(i).Trim().Trim(false).c_str()));
        }

        if(buildConf->IsClangC11()) {
            cppCompileArgs.Add(wxT("-std=c++11"));
            cCompileArgs.Add(wxT("-std=c++11"));
        }
        if(buildConf->IsClangC14()) {
            cppCompileArgs.Add(wxT("-std=c++14"));
            cCompileArgs.Add(wxT("-std=c++14"));
        }
    }

    cppCompileArgs.insert(cppCompileArgs.end(), args.begin(), args.end());
    cCompileArgs.insert(cCompileArgs.end(), args.begin(), args.end());

    // Remove some of the flags which are known to cause problems to clang
    int where = wxNOT_FOUND;

    where = cppCompileArgs.Index(wxT("-fno-strict-aliasing"));
    if(where != wxNOT_FOUND) cppCompileArgs.RemoveAt(where);

    where = cppCompileArgs.Index(wxT("-mthreads"));
    if(where != wxNOT_FOUND) cppCompileArgs.RemoveAt(where);

    where = cppCompileArgs.Index(wxT("-pipe"));
    if(where != wxNOT_FOUND) cppCompileArgs.RemoveAt(where);

    where = cppCompileArgs.Index(wxT("-fmessage-length=0"));
    if(where != wxNOT_FOUND) cppCompileArgs.RemoveAt(where);

    where = cppCompileArgs.Index(wxT("-fPIC"));
    if(where != wxNOT_FOUND) cppCompileArgs.RemoveAt(where);

    // Now do the same for the "C" arguments
    where = cCompileArgs.Index(wxT("-fno-strict-aliasing"));
    if(where != wxNOT_FOUND) cCompileArgs.RemoveAt(where);

    where = cCompileArgs.Index(wxT("-mthreads"));
    if(where != wxNOT_FOUND) cCompileArgs.RemoveAt(where);

    where = cCompileArgs.Index(wxT("-pipe"));
    if(where != wxNOT_FOUND) cCompileArgs.RemoveAt(where);

    where = cCompileArgs.Index(wxT("-fmessage-length=0"));
    if(where != wxNOT_FOUND) cCompileArgs.RemoveAt(where);

    where = cCompileArgs.Index(wxT("-fPIC"));
    if(where != wxNOT_FOUND) cCompileArgs.RemoveAt(where);

    return cmpArgs;
}