#!/usr/bin/env perl use strict; use warnings; # This script updates the .ycm_extra_conf.py in $LLVM_SRC to work with # $LLVM_BLD's compile_commands.json and include/library paths. # # Syntax: llvm-ycm # # It will: # * automatically detect $LLVM_SRC/BLD and change the paths. # * also bail if those variables or .ycm_extra_conf.py don't exist. # * exit successfully and silently if the file has already changed. my ($SRC, $BLD) = ($ENV{'LLVM_SRC'}, $ENV{'LLVM_BLD'}); if (!$SRC || !$BLD || $ARGV[0] || ! -d $SRC || ! -d $BLD) { die "Syntax: llvm-ycm\n\nUse llvm-env to set \$LLVM_SRC/BLD\n"; } my ($ycm_conf, $compile_db) = (".ycm_extra_conf.py", "compile_commands.json"); # If the file doesn't exist, don't try to guess the location of YCM-Generator # Vim can do that on its own, if properly setup. Educate the user. if (! -f "$SRC/$ycm_conf") { die "$SRC/$ycm_conf doesn't exist!\n". "You need to generate it using YCM-Generator.\n". "\nTo install, run:\n". " mkdir -p ~/.vim/ext\n". " cd ~/.vim/ext\n". " git clone https://github.com/rdnetto/YCM-Generator.git\n". "\nTo enable in vim, add this line to your .vimrc:\n". " set rtp+=~/.vim/ext/YCM-Generator\n". "\nTo generate the file, open Vim inside your project and type:\n". " :YcmGenerateConfig\n". "\nIf all goes well, you should have an $ycm_conf in $SRC\n"; } # If the compile database doesn't exist, there's no point in even trying. # Educate the user. if (! -f "$BLD/$compile_db") { die "$BLD/$compile_db doesn't exist!\n". "You need to generate it using LLVM's CMake file.\n". "\nTo create the compile database every build, add this option to CMake:\n". " -DCMAKE_EXPORT_COMPILE_COMMANDS=ON\n". "\nRebuild, and check if the file is there, then run this script again.\n"; } my @lines = (); my $bld_re = $BLD; $bld_re =~ s/\//\\\//g; # We need to open the file, buffer and close, so we can write back to the same # file again. open(FH, "$SRC/$ycm_conf") || die "Can't open file '$SRC/$ycm_conf': $!\n"; foreach my $line () { # If the file has already been changed, let go. if (&is_changed($line)) { close FH; exit(0); } # Change lines if needed &change(\$line); # Buffer push @lines, $line; } close FH; # Now we write back and all should be good. open(FH, ">$SRC/$ycm_conf") || die "Can't open file '$SRC/$ycm_conf': $!\n"; foreach my $line (@lines) { print FH $line; } close FH; # All is good. exit(0); ################################ Methods # is_changed($line): checks whether the line has been changed by this script. sub is_changed($) { my ($line) = @_; return ($line =~ /-I$bld_re/); } # change($$line): change the line in-place to make it work with YCM. sub change($) { my ($line) = @_; # from: -I/tmp/tmpUF9s_w/include # to: -I$LLVM_BLD/include my $changed = ($$line =~ s/\/tmp\/\w+/$BLD/); return if ($changed); # Changing this line will make header and include files not work for # completion, since they're not in the compilation database. Just using the # whole lot of flags above works fine. # from: compilation_database_folder = '' # to: compilation_database_folder = '$LLVM_BLD' #$$line =~ s/(compilation_database_folder) = ''/$1 = '$BLD'/; }