Efficiently Using SublimeText with SublimeClang for CMake/C++ Projects - c++

I have been trying to play with SublimeText2 for some time now. While it is very easy to work with Python in it almost out of the box, working with C++ is a bit more tricky. I can manage to set up a CMake build script by copying and modifying the existing Makefile script, but there are many things that just don't work as they do in a CMake supported IDE, like Eclipse CDT. SublimeText 2 does not seem to understand the concept of a separate build directory, it also cannot get me autocomplete through SublimeClang, if I include the libraries with reference to the directories added in CMake. SublimeClang keeps complaining that it cannot find the libraries, and when I try to #include, it cannot even offer me autocomplete on standard STL header file names, e.g., algorithm. If someone has a pipeline figured out, I would be obliged to hear about it.
I have asked this question in more general purpose usage-related forums before, where I did not get any response, which is why I thought of posting it here.

I use Sublime Text 2 with CMake and SublimeClang. I also use SublimeGDB. My build directory is under [project root]/build. Have a look at my project file and see if it helps you:
{
"folders":
[
{
"path": "."
}
],
"build_systems":
[
{
"name": "Build",
"cmd": [ "make", "-C", "build" ],
"file_regex": "/([^/:]+):(\\d+):(\\d+): "
}
],
"settings":
{
"sublimegdb_commandline": "gdb --interpreter=mi myapp",
"sublimegdb_workingdir": "build",
"sublimeclang_options" :
[
"-Wno-reorder"
],
"sublimeclang_options_script": "${project_path:scripts/compileflags.rb} ${project_path:build}"
}
}
The compileflags.rbscript is used to search for flags.make files in the CMake build tree which is where CMake keeps its compile flags. These flags are needed so that SublimeClang knows where to find your includes.
Here is that script, located under scripts/:
#!/usr/bin/env ruby
# Searches for a flags.make in a CMake build tree and prints the compile flags.
def search_dir(dir, &block)
Dir.foreach(dir) do |filename|
next if (filename == ".") || (filename == "..")
path ="#{dir}/#{filename}"
if File.directory?(path)
search_dir(path, &block)
else
search_file(path, &block)
end
end
end
def search_file(filename)
return if File.basename(filename) != "flags.make"
File.open(filename) do |io|
io.read.scan(/[a-zA-Z]+_(?:FLAGS|DEFINES)\s*=\s*(.*)$/) do |match|
yield(match.first.split(/\s+/))
end
end
end
root = ARGV.empty? ? Dir.pwd : ARGV[0]
params = to_enum(:search_dir, root).reduce { |a, b| a | b }
puts params

Related

Node addon development - cannot open source file "napi.h"

Just started fiddling around with developing an addon for Node in C++ using Node API (for the first time, I might just add). Everything is working great for the most part - I'm using the built-in compiler in Visual Studio for starting it, debugging and playing around, and node-gyp for building it for requiring it in Node. I have an entrypoint for local testing, let's call it main.cpp, where my int main() function is defined - which is executed when I run/debug my solution in Visual Studio (using Ctrl+F5/F5).
I also have a source file where the 'node communication' is defined (NodeCommunication.cpp), and it is this file (among others) that is listed in the sources array in my binding.gyp file. It is here that napi.h is included as well, and its APIs are used. Mousing over the include however, there is error text saying "cannot open source file napi.h" - which makes sense, I guess (?) that header file is something that is only injected on build time in node-gyp somehow. However it'd be really nice, DX-wise, to be able to resolve those somehow, because right now I have to comment out all the source code in that file before compiling and running the solution in visual studio for testing purposes.
What are my options here? Might as well also attach my binding.gyp file for reference.
{
"targets": [
{
"target_name": "foobar",
"sources": [ "NodeCommunication.cpp", "Sample.cpp", "Sample.h" ],
"libraries": ["../SDK/Library/EDSDK.lib"],
'include_dirs': ["<!#(node -p \"require('node-addon-api').include\")"],
'dependencies': ["<!(node -p \"require('node-addon-api').gyp\")"],
'defines': [ 'NAPI_CPP_EXCEPTIONS' ]
}
]
}

VSCode C++ IntelliSense works fine except for PCL (Point Cloud Library)

On SO itself, there are already many questions about VSCode IntelliSense, e.g., que1, que2, que3, etc. However, they mainly talk about IntelliSense not working in general; not working for STL; and so on.
On the other hand, in my case, I'm already using VSCode C/C++ Extension by Microsoft and IntelliSense works fine for all the different in-built classes, functions, STLs, etc. But, when it comes to PCL (Point Cloud Library), somehow, mysteriously, IntelliSense doesn't work.
If you are familiar with PCL then must be knowing that most of its syntaxes are too big. And as the IntelliSense not working for it, there are very high chances of making typos if you don't pay close attention while typing every single character, e.g.,
pcl::PointCloud<pcl::PointXYZRGB>::Ptr point_cloud_ptr (new pcl::PointCloud<pcl::PointXYZRGB>);
In fact, auto-completion for even those variables and functions do not work--i.e., from the above example, I have to manually type every single character of point_cloud_ptr every time I want to use it.
So, how can I fix this? or it's not possible for PCL?
Note: I'm facing this issue on my Ubuntu 16 as well as on Ubuntu 18. I have installed PCL using sudo apt install libpcl-dev and the header files are located in /usr/include/ directory.
After trying out different things and getting help from Microsoft VSCode (and C/C++ extension) team on GitHub, it looks like the IntelliSense is not working probably because the extension is not able to find PCL headers.
In the case of Ubuntu, the PCL headers are generally stored at /usr/include/pcl-<version>. In my Ubuntu 18.04, I have pcl-1.8. So, ideally, adding "/usr/include/pcl-1.8/**" under "includePath" in c_cpp_properties.json file should work. e.g.
{
"configurations": [
{
.
.
"includePath": [
"${workspaceFolder}/**",
"/usr/include/pcl-1.8/**"
],
.
.
.
}
],
"version": 4
}
In "/usr/include/pcl-1.8/**", ** is for recursive search under /usr/include/pcl-1.8/ directory. However, by the time when I had posted the question (and I think as of today as well), it doesn't work. It's not able to go through the subdirectories under pcl-<version> directory. So, alternate solutions are below:
Solution 01: (Use this one if you want to apply changes only to the current project)
Open C/C++ Extension Configuration file: c_cpp_properties.json (On Linux, press Ctrl + Shift + P and select C/C++: Edit Configurations (JSON))
Now, as the recursive search is not working, an alternate way is to specify all the subdirectories under includePath:
{
"configurations": [
{
.
.
"includePath": [
"${workspaceFolder}/**",
"/usr/include/eigen3",
"/usr/include/pcl-1.8",
"/usr/include/pcl-1.8/pcl",
"/usr/include/pcl-1.8/pcl/2d",
"/usr/include/pcl-1.8/pcl/apps",
"/usr/include/pcl-1.8/pcl/common",
"/usr/include/pcl-1.8/pcl/compression",
"/usr/include/pcl-1.8/pcl/console",
"/usr/include/pcl-1.8/pcl/features",
"/usr/include/pcl-1.8/pcl/filters",
"/usr/include/pcl-1.8/pcl/geometry",
"/usr/include/pcl-1.8/pcl/impl",
"/usr/include/pcl-1.8/pcl/in_hand_scanner",
"/usr/include/pcl-1.8/pcl/io",
"/usr/include/pcl-1.8/pcl/kdtree",
"/usr/include/pcl-1.8/pcl/keypoints",
"/usr/include/pcl-1.8/pcl/ml",
"/usr/include/pcl-1.8/pcl/modeler",
"/usr/include/pcl-1.8/pcl/octree",
"/usr/include/pcl-1.8/pcl/outofcore",
"/usr/include/pcl-1.8/pcl/people",
"/usr/include/pcl-1.8/pcl/range_image",
"/usr/include/pcl-1.8/pcl/recognition",
"/usr/include/pcl-1.8/pcl/registration",
"/usr/include/pcl-1.8/pcl/ros",
"/usr/include/pcl-1.8/pcl/sample_consensus",
"/usr/include/pcl-1.8/pcl/search",
"/usr/include/pcl-1.8/pcl/segmentation",
"/usr/include/pcl-1.8/pcl/stereo",
"/usr/include/pcl-1.8/pcl/surface",
"/usr/include/pcl-1.8/pcl/tracking",
"/usr/include/pcl-1.8/pcl/visualization"
],
.
.
.
}
],
"version": 4
}
Solution 02: (Use this one if you want to apply changes globally -- across all the projects)
As C/C++ Configuration File: c_cpp_properties.json is specific to each project, editing that will only apply changes to the current project. So, to apply changes across all the projects, one has to update settings.json and then c_cpp_properies.json.
Open settings.json and add the following text:
"C_Cpp.default.includePath": [
"/usr/include/eigen3",
"/usr/include/pcl-1.8",
"/usr/include/pcl-1.8/pcl",
"/usr/include/pcl-1.8/pcl/2d",
"/usr/include/pcl-1.8/pcl/apps",
"/usr/include/pcl-1.8/pcl/common",
"/usr/include/pcl-1.8/pcl/compression",
"/usr/include/pcl-1.8/pcl/console",
"/usr/include/pcl-1.8/pcl/features",
"/usr/include/pcl-1.8/pcl/filters",
"/usr/include/pcl-1.8/pcl/geometry",
"/usr/include/pcl-1.8/pcl/impl",
"/usr/include/pcl-1.8/pcl/in_hand_scanner",
"/usr/include/pcl-1.8/pcl/io",
"/usr/include/pcl-1.8/pcl/kdtree",
"/usr/include/pcl-1.8/pcl/keypoints",
"/usr/include/pcl-1.8/pcl/ml",
"/usr/include/pcl-1.8/pcl/modeler",
"/usr/include/pcl-1.8/pcl/octree",
"/usr/include/pcl-1.8/pcl/outofcore",
"/usr/include/pcl-1.8/pcl/people",
"/usr/include/pcl-1.8/pcl/range_image",
"/usr/include/pcl-1.8/pcl/recognition",
"/usr/include/pcl-1.8/pcl/registration",
"/usr/include/pcl-1.8/pcl/ros",
"/usr/include/pcl-1.8/pcl/sample_consensus",
"/usr/include/pcl-1.8/pcl/search",
"/usr/include/pcl-1.8/pcl/segmentation",
"/usr/include/pcl-1.8/pcl/stereo",
"/usr/include/pcl-1.8/pcl/surface",
"/usr/include/pcl-1.8/pcl/tracking",
"/usr/include/pcl-1.8/pcl/visualization"
]
Open, c_cpp_properties.json and update includePath:
{
"configurations": [
{
.
.
"includePath": [
"${workspaceFolder}/**",
"${default}"
],
.
.
.
}
],
"version": 4
}
P.S. I had asked the same question on the official GitHub issues page of the C/C++ Extension by Microsoft and eventually, found the solution (but, not an ideal one) I mentioned above.
Here is the link for more info: https://github.com/microsoft/vscode-cpptools/issues/5843
Because VSCode always told me that it could not find some dependency like pcl/PCLHeader.h. So I tried copying /usr/include/pcl-1.10/pcl to /usr/include/ and it worked.

how to add include path for language servers in coc-settings.json file?

I am using neovim plugin "coc-nvim", as the IntelliSense tool for C/C++. as I know this plugin is actually a client of language servers like ccls, clangd and cquery. I have all of these language servers installed on my system and configured them to work with coc-nvim. so I can get autocompletion and list of general headers(e.g. stdio and ...) in my c/c++ files. but since I work in ros platform I want to add the headers of the ros(/opt/ros/kinetic/include/**) to my default include path of language servers. with out this option, at the beginning of each project I must add a dummy ros node and compile with catkin_make -DCMAKE_EXPORT_COMPILE_COMMANDS=YES to generate the compile_commands.json file to get access to ros headers.
the settings of coc.nvim is alongside the init.vim file, in a file called "coc-settings.json" and the contents of my coc setting file is as below:
{
"languageserver": {
"clangd": {
"command": "clangd",
"rootPatterns": ["compile_flags.txt", "compile_commands.json"],
"filetypes": ["c", "cpp", "objc", "objcpp"]
},
"cquery": {
"command": "/home/amirrezasadeghi/ManBuildLibs/cquery/build/cquery",
"args": ["--log-file=/tmp/cq.log"],
"filetypes": ["c", "cpp"],
"rootPatterns": ["compile_flags.txt", "compile_commands.json", ".git/", ".hg/"],
"initializationOptions": {
"cacheDirectory": "/tmp/cquery"
}
},
"ccls": {
"command": "ccls",
"filetypes": ["c", "cpp", "objc", "objcpp"],
"rootPatterns": [".ccls", "compile_commands.json", ".git/", ".hg/"],
"initializationOptions": {
"cache": {
"directory": "/tmp/ccls"
}
}
}
},
"clangd.semanticHighlighting": true
}
So my major question is how to add ros include path to these settings. I checked the wiki page of coc.nvim but can't find any option for user include path. also, I checked the option of clangd and tried to add,
"args":["-I/opt/ros/kinetic/include/"],
to the corresponding block but it did not work. also, I added .cquery file, but still no effect on the list of the proposed headers.
sorry for long story, and thanks for your time.
Edit: it would be better to use the clangd LSP rather than ccls. because it is faster and has better documentation. thanks!
Edit(12 April 2020): the best solution which I found is using ccls language server by using the extraArgs which is provided by ccls. so if you add "clang" field to ccls configs we can have ros headers in autocompletion.
"initializationOptions": {
"cache": {
"directory": "/tmp/ccls"
},
"clang": {
"extraArgs": [
"-I",
"/opt/ros/kinetic/include/"
]
}
}
but as I mentioned I would like to use clangd if possible. I checked everywhere but no answer. can anyone help me? (please!).
This doesn't fix the problem in the way you asked, but I found it to be a useful solution.
Like you, I used catkin_make to generate the compile_commands.json using:
catkin_make --cmake-args -DCMAKE_EXPORT_COMPILE_COMMANDS=1
However, I created a symlink between <catkin_ws>/build/compile_commands.json and <catkin_ws>/compile_commands.json. Since clangd searches parent directories for compile_commands.json, this is accessible by any package/node within the workspace.
Therefore, only one compile_commands.json needs to be generated for the whole workspace, and only needs to be re-generated whenever dependencies change.
It looks like there is no option in coc-nvim for setting that.
Best option is to rely on your LSP options.
I just solved it for ccls by defining a custom .ccls file and added a -I option pointing at my boost includes. That .ccls file must be at the root of my project. e.g.:
clang
%c
-I/usr/local/include
There must be the same option for clangd.

Sublime Text 2 file include pattern

I know that a file exclude pattern can be set in Sublime Text's project/default settings, but is it also possible to only include files based on a pattern?
For example, when working with my C++ projects, I tend to have files in the same folder that are not necessarily source files.
Can I explicitly tell Sublime Text to show me only *.cpp, *.h, and *.txt files while ignoring everything else?
List the extensions you want included in file_include_patterns. The following works for me with ST3 project files, don't have ST2 handy to test.
{
"folders":
[
{
"name": "My Project",
"path": ".",
"file_include_patterns": [
"*.cpp",
"*.h"
]
}
]
}

Sublime Text 3 Build Many Source Files

Well all I've seen for build systems for C++ is the following:
"build_systems":
[
{
"name: "g++ test",
"cmd": ["g++", "${file}"],
"shell": true
}
{
"name": "echo test",
"cmd": ["echo", "${file}"],
"shell": true
}
]
Just as a test, this only works for the currently opened file, which might not even be a source file nor part of the sublime project. So this is good for a test program that only has one source but it isn't that useful otherwise.
Question 1:
Is there any ${project_files} variable with regex to accept only .cpp files ?
Question 2:
I would want to pass these files to qmake, such that it generates a .pro project file. Such that if I add a file to a sublime project it and build the file will be added to the project file. How would I do this without shell script or otherwise such that it's cross platform ?