├── .gitignore
├── .travis.yml
├── README.md
├── appveyor.yml
├── doc
└── cmake.txt
├── plugin
└── cmake.vim
└── test
├── .vimrc
├── cmake.vader
└── test project
├── CMakeLists.txt
├── configure.h.cmake
└── main.cpp
/.gitignore:
--------------------------------------------------------------------------------
1 | test/test project/build/
2 | doc/tags
3 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: vim
2 |
3 | addons:
4 | apt:
5 | sources:
6 | - ubuntu-toolchain-r-test
7 | - kubuntu-backports
8 | packages:
9 | - g++-4.7
10 | - cmake
11 |
12 | before_script: |
13 | git clone https://github.com/junegunn/vader.vim.git
14 |
15 | script: |
16 | vim -Nu 'test/.vimrc' -c 'Vader! test/cmake.vader'
17 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # vim-cmake
2 | [](https://travis-ci.org/vhdirk/vim-cmake)
3 | [](https://ci.appveyor.com/project/vhdirk/vim-cmake)
4 |
5 | vim-cmake is a Vim plugin to make working with CMake a little nicer.
6 |
7 | I got tired of navigating to the build directory each time, and I also
8 | disliked setting makeprg manually each time. This plugin does just that.
9 |
10 | ## Usage
11 |
12 | ### Commands
13 |
14 | * `:CMake` searches for the closest directory named build in an upwards search,
15 | and whenever one is found, it runs the cmake command there, assuming the CMakeLists.txt
16 | file is just one directory above. Any arguments given to :CMake will be directly passed
17 | on to the cmake command. It also sets the working directory of the make command, so
18 | you can just use quickfix as with a normal Makefile project.
19 | If you have the [AsyncRun plugin](https://github.com/skywind3000/asyncrun.vim)
20 | installed, it will be used automatically and you will be able to check the
21 | result of the cmake command in the quickfix as well.
22 |
23 | * `:CMakeClean` deletes all files in the build directory. You can think of this as a CMake version of make clean.
24 |
25 | * `:CMakeFindBuildDir` resets the build directory path set for the current buffer and then tries to find a new one. Useful if it previously found a wrong path to then reset it after a new build folder has been created for example.
26 |
27 | ### Variables
28 |
29 | * `g:cmake_install_prefix` same as `-DCMAKE_INSTALL_PREFIX`
30 |
31 | * `g:cmake_build_type` same as `-DCMAKE_BUILD_TYPE`
32 |
33 | * `g:cmake_cxx_compiler` same as `-DCMAKE_CXX_COMPILER`. Changes will have no effect until you run :CMakeClean and then :CMake.
34 |
35 | * `g:cmake_c_compiler` same as `-DCMAKE_C_COMPILER`. Changes will have no effect until you run :CMakeClean and then :CMake.
36 |
37 | * `g:cmake_build_shared_libs` same as `-DBUILD_SHARED_LIBS`
38 |
39 | * `g:cmake_toolchain_file` same as `-DCMAKE_TOOLCHAIN_FILE`
40 |
41 | * `g:cmake_project_generator` same as `-G`. Changes will have no effect until you run :CMakeClean and then :CMake.
42 |
43 | * `g:cmake_export_compile_commands` same as `-DCMAKE_EXPORT_COMPILE_COMMANDS`.
44 |
45 | * `g:cmake_ycm_symlinks` create symlinks to the generated compilation database for use with [YouCompleteMe](https://github.com/Valloric/YouCompleteMe/).
46 |
47 | * `b:build_dir` is the path to the cmake build directory for the current buffer. This variable is set with the first :CMake or :CMakeFindBuildDir call. Once found, it will not be searched for again unless you call :CMakeFindBuildDir. If automatic finding is not sufficient you can set this variable manually to the build dir of your choice.
48 |
49 |
50 | ## Installation
51 |
52 |
53 | ### Vim-pathogen
54 |
55 | With [pathogen.vim](https://github.com/tpope/vim-pathogen) simply copy and paste:
56 |
57 | cd ~/.vim/bundle
58 | git clone git://github.com/vhdirk/vim-cmake.git
59 |
60 | Once help tags have been generated, you can view the manual with
61 | `:help cmake`.
62 |
63 | ### Vundle
64 |
65 | With [Vundle.vim](https://github.com/VundleVim/Vundle.vim) simply add this repository to your plugins list:
66 |
67 | Plugin 'vhdirk/vim-cmake'
68 |
69 | ## Acknowledgements
70 |
71 | * Thanks to [Tim Pope](http://tpo.pe/), his plugins are really awesome.
72 | * Thanks to [Junegunn Choi](https://junegunn.kr/), for [vader.vim](https://github.com/junegunn/vader.vim), which is the testing framework used for this plugin.
73 | * Also thanks to
74 | * @SteveDeFacto for extending this with more fine grained control.
75 | * @snikulov for enhancing makeprg.
76 | * @dapicester for allowing specifying targets.
77 | * @thomasgubler for the build dir option.
78 | * @antmd for fixing a bug with handing of spaces in directory names.
79 | * @jmirabel for fixing concatenation of cmake arguments.
80 | * @T4ng10r for the project generator option.
81 | * @Squareys for a small overhaul of the project, the initial test and travis setup.
82 |
83 | ## License
84 |
85 | Copyright (c) Dirk Van Haerenborgh, @SteveDeFacto. Distributed under the same terms as Vim itself.
86 | See `:help license`.
87 |
--------------------------------------------------------------------------------
/appveyor.yml:
--------------------------------------------------------------------------------
1 | os: Visual Studio 2015
2 |
3 | install:
4 | - cinst vim
5 | - cinst cmake
6 | - set PATH=%PATH%;C:\Program Files\CMake\bin
7 | - git clone https://github.com/junegunn/vader.vim
8 |
9 | build_script:
10 | - vim -Nu test/.vimrc -c 'Vader! test/cmake.vader' --not-a-term
11 |
--------------------------------------------------------------------------------
/doc/cmake.txt:
--------------------------------------------------------------------------------
1 | *cmake.txt* Vim plugin to make working with CMake a little nicer
2 |
3 | Authors: Dirk Van Haerenborgh
4 | Steven Batchelor
5 | Jonathan Hale
6 | License: Same terms as Vim itself (see |license|)
7 |
8 |
9 | INTRODUCTION *cmake*
10 |
11 | When working on a CMake project, this plugin provides a single command that
12 | changes the makeprg make command's working directory to the closest 'build'
13 | directory (see g:cmake_build_dir) upwards
14 |
15 | COMMANDS *cmake-commands*
16 |
17 | :CMake [args] Runs the cmake command as 'cmake ..', starting in
18 | first directory called 'build', found in an upwards
19 | search. All arguments are directly passed on to CMake.
20 | Also modifies the :make command to build in
21 | that directory.
22 |
23 | :CMakeClean deletes all files in the build directory. You can
24 | think of this as a CMake version of make clean.
25 |
26 | :CMakeFindBuildDir resets the build directory path set for the current buffer
27 | and then tries to find a new one. Useful if it previously
28 | found a wrong path to then reset it after a new build folder
29 | has been created for example.
30 |
31 | VARIABLES *cmake-variables*
32 |
33 | g:cmake_install_prefix same as -DCMAKE_INSTALL_PREFIX
34 |
35 | g:cmake_build_type same as -DCMAKE_BUILD_TYPE
36 |
37 | g:cmake_cxx_compiler same as -DCMAKE_CXX_COMPILER, however, this will have
38 | no effect until you run :CMakeClean and :CMake.
39 |
40 | g:cmake_c_compiler same as -DCMAKE_C_COMPILER, however, this will have
41 | no effect until you run :CMakeClean and :CMake.
42 |
43 | g:cmake_build_shared_libs same as -DBUILD_SHARED_LIBS
44 |
45 | g:cmake_toolchain_file same as -DCMAKE_TOOLCHAIN_FILE
46 |
47 | g:cmake_build_dir set the cmake 'build' directory, default: 'build'
48 |
49 | g:cmake_project_generator set project generator, however, this will have
50 | no effect until you run :CMakeClean and :CMake.
51 |
52 | g:cmake_usr_args custom user arguments. Ex: 'let g:cmake_usr_args="-DDEBUG=YES"'
53 |
54 | b:build_dir the path to the cmake build directory for the current buffer.
55 | This variable is set with the first :CMake or :CMakeFindBuildDir call.
56 | Once found, it will not be searched for again unless you call
57 | :CMakeFindBuildDir. If automatic finding is not sufficient you can set
58 | this variable manually to the build dir of your choice.
59 |
60 | OPTIONS *cmake-options*
61 |
62 | g:cmake_export_compile_commands same as -DCMAKE_EXPORT_COMPILE_COMMANDS=ON, useful for
63 | exporting a compilation database to be used with YCM
64 | (https://github.com/Valloric/YouCompleteMe#c-family-semantic-completion)
65 | CMake only supports this flag with Ninja and Makefile generators.
66 |
67 | g:cmake_ycm_symlinks create a symlink to the compile_commands.json file in the
68 | root of the project (build/..) if the file is found.
69 |
70 |
--------------------------------------------------------------------------------
/plugin/cmake.vim:
--------------------------------------------------------------------------------
1 | " cmake.vim - Vim plugin to make working with CMake a little nicer
2 | " Maintainer: Dirk Van Haerenborgh
3 | " Version: 0.2
4 |
5 | let s:cmake_plugin_version = '0.2'
6 |
7 | if exists("loaded_cmake_plugin")
8 | finish
9 | endif
10 |
11 | " We set this variable here even though the plugin may not actually be loaded
12 | " because the executable is not found. Otherwise the error message will be
13 | " displayed more than once.
14 | let loaded_cmake_plugin = 1
15 |
16 | " Set option defaults
17 | if !exists("g:cmake_export_compile_commands")
18 | let g:cmake_export_compile_commands = 0
19 | endif
20 | if !exists("g:cmake_ycm_symlinks")
21 | let g:cmake_ycm_symlinks = 0
22 | endif
23 | if !exists("g:cmake_use_smp")
24 | let g:cmake_use_smp = 0
25 | endif
26 |
27 | if !executable("cmake")
28 | echoerr "vim-cmake requires cmake executable. Please make sure it is installed and on PATH."
29 | finish
30 | endif
31 |
32 | function! s:find_build_dir()
33 | " Do not overwrite already found build_dir, may be set explicitly
34 | " by user.
35 | if exists("b:build_dir") && b:build_dir != ""
36 | return 1
37 | endif
38 |
39 | let g:cmake_build_dir = get(g:, 'cmake_build_dir', 'build')
40 | let b:build_dir = finddir(g:cmake_build_dir, ';')
41 |
42 | if b:build_dir == ""
43 | " Find build directory in path of current file
44 | let b:build_dir = finddir(g:cmake_build_dir, s:fnameescape(expand("%:p:h")) . ';')
45 | endif
46 |
47 | if b:build_dir != ""
48 | " expand() would expand "" to working directory, but we need
49 | " this as an indicator that build was not found
50 | let b:build_dir = fnamemodify(b:build_dir, ':p')
51 | echom "Found cmake build directory: " . s:fnameescape(b:build_dir)
52 | return 1
53 | else
54 | echom "Unable to find cmake build directory."
55 | return 0
56 | endif
57 |
58 | endfunction
59 |
60 | " Configure the cmake project in the currently set build dir.
61 | "
62 | " This will override any of the following variables if the
63 | " corresponding vim variable is set:
64 | " * CMAKE_INSTALL_PREFIX
65 | " * CMAKE_BUILD_TYPE
66 | " * CMAKE_BUILD_SHARED_LIBS
67 | " If the project is not configured already, the following variables will be set
68 | " whenever the corresponding vim variable for the following is set:
69 | " * CMAKE_CXX_COMPILER
70 | " * CMAKE_C_COMPILER
71 | " * The generator (-G)
72 | function! s:cmake_configure(cmake_vim_command_args)
73 | exec 'cd' s:fnameescape(b:build_dir)
74 |
75 | let l:argument = []
76 | " Only change values of variables, if project is not configured
77 | " already, otherwise we overwrite existing configuration.
78 | let l:configured = filereadable("CMakeCache.txt")
79 |
80 | if !l:configured
81 | if exists("g:cmake_project_generator")
82 | let l:argument += [ "-G \"" . g:cmake_project_generator . "\"" ]
83 | endif
84 | if exists("g:cmake_cxx_compiler")
85 | let l:argument += [ "-DCMAKE_CXX_COMPILER:FILEPATH=" . g:cmake_cxx_compiler ]
86 | endif
87 | if exists("g:cmake_c_compiler")
88 | let l:argument += [ "-DCMAKE_C_COMPILER:FILEPATH=" . g:cmake_c_compiler ]
89 | endif
90 |
91 | if exists("g:cmake_usr_args")
92 | let l:argument+= [ g:cmake_usr_args ]
93 | endif
94 | endif
95 |
96 | if exists("g:cmake_install_prefix")
97 | let l:argument += [ "-DCMAKE_INSTALL_PREFIX:FILEPATH=" . g:cmake_install_prefix ]
98 | endif
99 | if exists("g:cmake_build_type" )
100 | let l:argument += [ "-DCMAKE_BUILD_TYPE:STRING=" . g:cmake_build_type ]
101 | endif
102 | if exists("g:cmake_build_shared_libs")
103 | let l:argument += [ "-DBUILD_SHARED_LIBS:BOOL=" . g:cmake_build_shared_libs ]
104 | endif
105 | if exists("g:cmake_toolchain_file")
106 | let l:argument += [ "-DCMAKE_TOOLCHAIN_FILE:FILEPATH=" . g:cmake_toolchain_file ]
107 | endif
108 | if g:cmake_export_compile_commands
109 | let l:argument += [ "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON" ]
110 | endif
111 |
112 | let l:argumentstr = join(l:argument, " ")
113 | let l:escaped_build_dir=s:fnameescape(b:build_dir)
114 | let l:home_dir = "-H".l:escaped_build_dir."/.."
115 | let l:build_dir_path = "-B".l:escaped_build_dir
116 | let s:cmd = 'cmake '.l:home_dir.' '.l:build_dir_path.' '.l:argumentstr . " " . join(a:cmake_vim_command_args)
117 |
118 | echo s:cmd
119 | if exists(":AsyncRun")
120 | execute 'copen'
121 | execute 'AsyncRun ' . s:cmd
122 | execute 'wincmd p'
123 | else
124 | silent let s:res = system(s:cmd)
125 | silent echo s:res
126 | endif
127 |
128 | " Create symbolic link to compilation database for use with YouCompleteMe
129 | if g:cmake_ycm_symlinks && filereadable("compile_commands.json")
130 | if has("win32")
131 | exec "mklink" "../compile_commands.json" "compile_commands.json"
132 | else
133 | silent echo system("ln -s " . s:fnameescape(b:build_dir) ."/compile_commands.json ../compile_commands.json")
134 | endif
135 | echom "Created symlink to compilation database"
136 | endif
137 |
138 | exec 'cd -'
139 | endfunction
140 |
141 | " Utility function
142 | " Thanks to tpope/vim-fugitive
143 | function! s:fnameescape(file) abort
144 | if exists('*fnameescape')
145 | return fnameescape(a:file)
146 | else
147 | return escape(a:file," \t\n*?[{`$\\%#'\"|!<")
148 | endif
149 | endfunction
150 |
151 | function! s:find_smp()
152 | if executable('nproc')
153 | let l:nproc = system('nproc')
154 | let b:smp = '-j' . substitute(l:nproc, '\n\+$', '', '')
155 | return 1
156 | endif
157 | return 0
158 | endfunction
159 |
160 | command! -complete=customlist,ListTargets -nargs=1 Make :make
161 | function! ListTargets(A, L, C)
162 | if !exists("b:build_dir")
163 | return []
164 | endif
165 | let all_targets = split(system("cmake --build ". b:build_dir . " --target help | awk ' NR > 1 {print $2}'"), '\n')
166 | let targets = filter(all_targets, "v:val =~ '^" .. a:A .. "'")
167 | return targets
168 | endfunction
169 |
170 | " Public Interface:
171 | command! -nargs=? CMake call s:cmake()
172 | command! CMakeClean call s:cmakeclean()
173 | command! CMakeFindBuildDir call s:cmake_find_build_dir()
174 |
175 | function! s:cmake_find_build_dir()
176 | unlet! b:build_dir
177 | call s:find_build_dir()
178 | endfunction
179 |
180 | function! s:cmake(...)
181 | if !s:find_build_dir()
182 | return
183 | endif
184 |
185 | if g:cmake_use_smp && s:find_smp()
186 | let l:smp = ' ' . shellescape(b:smp)
187 | else
188 | let l:smp = ''
189 | endif
190 |
191 | let &makeprg = 'cmake --build ' . shellescape(b:build_dir) . l:smp . ' --target'
192 | call s:cmake_configure(a:000)
193 | endfunction
194 |
195 | function! s:cmakeclean()
196 | if !s:find_build_dir()
197 | return
198 | endif
199 |
200 | silent echo system("rm -r '" . b:build_dir. "'/*")
201 | echom "Build directory has been cleaned."
202 | endfunction
203 |
204 |
--------------------------------------------------------------------------------
/test/.vimrc:
--------------------------------------------------------------------------------
1 | filetype off
2 |
3 | set rtp+=vader.vim
4 | set rtp+=.
5 | filetype plugin indent on
6 | syntax enable
7 |
8 |
--------------------------------------------------------------------------------
/test/cmake.vader:
--------------------------------------------------------------------------------
1 | Before:
2 | " Ensure we are in the test directory
3 | if isdirectory("test")
4 | cd test
5 | endif
6 |
7 | if !exists("test_dir")
8 | let test_dir = fnamemodify(getcwd(), ':p')
9 | endif
10 |
11 | Assert !isdirectory("test project/tmp-build"), "TEST ERROR: build directory was not properly deleted"
12 | echo system("mkdir 'test project/tmp-build'")
13 | Assert isdirectory("test project/tmp-build"), "TEST ERROR: build directory was not created"
14 |
15 | " Under travis CI the entire project is in a build/ directory
16 | " which will make the search from cwd always return a result.
17 | " To be able to test searching build dir from current file, the
18 | " build dir needs to be named differently as a workaround.
19 | let g:cmake_build_dir = "tmp-build"
20 | After:
21 | exec "cd" fnameescape(test_dir)
22 | echo system("rm -rf 'test project/tmp-build'")
23 | echo system("rm -f 'test project/compile_commands.json'")
24 |
25 | Execute (Find build directory from working dir):
26 | cd test\ project
27 | CMake
28 |
29 | Assert filereadable("tmp-build/CMakeCache.txt"), "CMakeCache.txt should be generated"
30 | Assert !filereadable("tmp-build/compile_commands.json"), "Compile commands should not be exported by default"
31 |
32 | Execute (Find build directory from currently open file):
33 | e test\ project/CMakeLists.txt
34 | CMake
35 | Assert filereadable("test project/tmp-build/CMakeCache.txt"), "CMakeCache.txt should be generated"
36 |
37 | Execute (Create symlink to compilation database):
38 | let g:cmake_export_compile_commands = 1
39 | let g:cmake_ycm_symlinks = 1
40 | cd test\ project
41 | CMake
42 |
43 | " Exporting compile commands does not work with Visual Studio generator
44 | if !has("win32") && !has("win32unix")
45 | Assert filereadable("tmp-build/compile_commands.json"), "Compile commands should be exported"
46 | Assert filereadable(resolve("compile_commands.json")), "A symlink should be generated"
47 | endif
48 |
49 | Execute (Open already configured cmake project):
50 | cd test\ project/tmp-build
51 | silent !cmake .. -DWITH_BYE=ON
52 | e ../CMakeLists.txt
53 | CMake
54 | silent make
55 |
56 | enew
57 | if has("win32") || has("win32unix")
58 | read !Debug/hello.exe
59 | else
60 | read !./hello
61 | endif
62 | Expect:
63 |
64 | Hello World
65 | Bye World
66 |
--------------------------------------------------------------------------------
/test/test project/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 2.8.12)
2 |
3 | project(HelloWorld)
4 |
5 | option(WITH_BYE "Print bye world" OFF)
6 |
7 | configure_file(configure.h.cmake configure.h)
8 | add_executable(hello main.cpp)
9 | target_include_directories(hello PRIVATE ${CMAKE_BINARY_DIR})
10 |
--------------------------------------------------------------------------------
/test/test project/configure.h.cmake:
--------------------------------------------------------------------------------
1 | #cmakedefine WITH_BYE
2 |
--------------------------------------------------------------------------------
/test/test project/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include "configure.h"
3 |
4 | int main() {
5 | std::cout << "Hello World" << std::endl;
6 | #ifdef WITH_BYE
7 | std::cout << "Bye World" << std::endl;
8 | #endif
9 | return 0;
10 | }
11 |
--------------------------------------------------------------------------------