Vim + YouCompleteMe + C: a minimal .ycm_extra_conf.py? - c

I've already got Vim with YouCompleteMe plugin (compiled with semantic support for C-family languages), which I use for Python etc. Now I'd like to try it with C (I've never developed with C before, so I've got a slightly fuzzy idea about some details, like the necessary flags.)
To use YCM's semantic completion features with C, I need to provide it a .ycm_extra_conf.py file; the YCM user guide points to YCM's own .ycm_extra_conf.py as a reference (link).
Would the following (based on the aforesaid .ycm_extra_conf.py) produce "a minimal working setup" for C (to which I could then point g:ycm_global_ycm_extra_conf):
The flags:
flags = [
'-Wall', '-Wextra', '-Werror',
'-std=c11',
'-x', 'c'
]
and FlagsForFile function without the final_flags.remove( '-stdlib=libc++' ) line.
Otherwise the example file would remain as-it-is. I believe that -isystem flags are strictly YCM-related, is that correct?

I was searching for this too and seems here we haven't get a good solution. Even this is a very old question I hope this might help someone. The following works for me,
import os
import ycm_core
flags = [
'-Wall',
'-Wextra',
'-Werror',
'-Wno-long-long',
'-Wno-variadic-macros',
'-fexceptions',
'-ferror-limit=10000',
'-DNDEBUG',
'-std=c99',
'-xc',
'-isystem/usr/include/',
]
SOURCE_EXTENSIONS = [ '.cpp', '.cxx', '.cc', '.c', ]
def FlagsForFile( filename, **kwargs ):
return {
'flags': flags,
'do_cache': True
}
By the way, that long config file by the default bothers me so much. I should give credit for this post, http://cocoaspice.logdown.com/posts/302432-youcompleteme-toss-notes

Nothing at all is perfectly valid as long as the sources can be compiled by simply clang++ -c source (c vs. c++ is decided from extension). YCM happily completes in scratch tests created in random directories for me.
The -x c is not needed. If the source has extension .c or .h, it is assumed to be C and if it has extension .C, .cc, .cpp, .cxx, .H, .hh, .hpp or .hxx it is assumed C++. Only if you have C++ headers with just .h you need -x c++-header.
Newest clang (4.9) already defaults to c11 and c++11, so you shouldn't need those either.
So you only need any -I flags and the warnings are useful.

To give you a working example, here is the configuration I'm using for Arduino projects.
https://github.com/WeAreLeka/Bare-Arduino-Project/blob/master/.ycm_extra_conf.py
In the flags I've put all the Arduino libraries provided by the IDE and needed to compile my code.
I've also written a little function to find the other libraries in my /lib dir that I'm using in my project and to add them automatically to flags. It's line 57.
It's helpful if you use a lot of libs and don't want to modify your conf file each time.
Without the -I /path/to/lib/folder you won't get autocompletion.
Hope this helps :)

Related

Is my understanding of C header files/gcc options related to these correct?

I am currently taking a class on C and I am baffled by gcc options a lot of the time, because the videos/documentation on the options are sparse and those that eixst are hard to understand(for idiots/non-technical majors like myself). Please consider the following scenario:
Lets say I have a header file, myHeader.h and main.c which would like to include myHeader.h. Assume they are in the same directory.
In main.c, I could write #include "myHeader.h". However, according to my professor the "" is permitted because gcc will check in the current directory for anything in the "". However, where I am lost is when it comes to how I could add myHeader.h to the gcc header file search path such that #include <myHeader.h> would work. I am wondering what gcc commands would work, and why they work in specific. I would love any references(that aren't super nerdy) to better understand this.
So far, I researched on stackoverflow and on google, and it said something about -Idir gcc command, where dir is the directory you would like to add to the header file search path, but I am confused as to why this works or how to actually implement it. Since the "path" to myHeader.h is CStuff/workspace/myHeader.h I attempted to do gcc -I/CStuff/workspace/myHeader.h but this didn't really work out. I really thought it would take that directory and add it to the header file search path, but it just gave me an error.
I am a very confused business major so please take it easy on me! I really would love a dumbed-down explanation or a reference to a source that is more "basic" and has more than 1-2 sentences of explanation(if possible).
However, where I am lost is when it comes to how I could add myHeader.h to the gcc header file search path such that #include <myHeader.h> would work.
If you want to add search path directory for system headers, there is -isystem <path>. For ordinary headers — which your header very likely is — there is -I <path>. This supports relative and absolute path formats.
To see which search paths GCC is using, add -v to the options:
> gcc main.c -v ...
...
#include "..." search starts here:
#include <...> search starts here:
/usr/lib/gcc/x86_64-linux-gnu/9/include
/usr/local/include
/usr/include/x86_64-linux-gnu
/usr/include
End of search list.
...
There are more special options, see Directory-Options in the GCC documentation, if it comes to search order, for instance.
To see the outcome of including, i.e. the C-preprosessed file, use -save-temps and have a look at the preprocessed file *.i for C, *.ii for C++, *.s for assembly.
To also see built-in and explicit #define's values in preprocessed code, also add -H -g3.
In main.c, I could write #include "myHeader.h". However, according to my professor the "" is permitted because gcc will check in the current directory for anything in the "". However, where I am lost is when it comes to how I could add myHeader.h to the gcc header file search path such that #include <myHeader.h> would work.
As a preliminary matter, you are already lost when you conceive the idea that you should want to use that form for the private headers associated with your program. The <header.h> form is conventionally and best reserved for use with system headers. That is, exactly those that do not accompany the code being compiled.
That does not moot the question, however. Sometimes one might want to amend the header search path to help the compiler find headers distributed with the source code and referenced via the "header.h" form, too.
I am wondering what gcc commands would work, and why they work in specific. I would love any references(that aren't super nerdy) to better understand this.
You will not earn friends or respect here by eschewing technical references, nor by casting aspersions on those who do read such references. Technical documents can be hard reading at first, but reading and understanding them is a skill that you will need to cultivate if you want to enjoy success as a programmer.
So far, I researched on stackoverflow and on google, and it said
something about -Idir gcc command, where dir is the directory you
would like to add to the header file search path,
Good start.
but I am confused as
to why this works or how to actually implement it. Since the "path" to
myHeader.h is CStuff/workspace/myHeader.h I attempted to do gcc
-I/CStuff/workspace/myHeader.h but [...] it just gave me an error.
It is important to pay attention to details. You yourself wrote:
where dir is the directory you would like to add to the header file search path
(emphasis added). If /CStuff/workspace/myHeader.h is the header you want gcc to find, then that path is not the path of a directory. The directory is /CStuff/workspace, so -I/CStuff/workspace is a viable option.
Alternatively, for gcc runs in which the working directory is also /CStuff/workspace, you can refer to it by the name . (that is, use -I.). It is a general feature of Unix and Windows paths, not specific to gcc, that the . represents the current working directory.

Is there any extension for vscode to make it support C intelligence only (without C++)?

Due to my job, I have to develop software with only C but not C++.
It will be good that when I write class A {}; Vscode will display an error or a warning.
Now I use clangd, it will be great if some settings can satisfy.
Clangd will correctly issue diagnostics for C++-only constructs, if it's parsing your file in C mode.
So it's a matter of making sure clangd is parsing your files in the correct language mode.
If your file's extension is unambiguously a C-language extension (for example, .c), then clang should parse the file in C mode automatically.
If the extension is ambiguous, like .h, then clangd attempts to choose the language heuristically, which can sometimes give a wrong answer. In this case, you can specify the language explicitly in the file's compile command, for example by adding -x c-header to specify "parse as a C header".
One way to do this is using CompileFlags: Add: in the clangd config file. For example, to specify that all .h files in the project are C headers, you might add the following to the project .clangd file:
If:
PathMatch: .*\.h
CompileFlags:
Add: [-xc-header]

Identify version of C file

For a project I need to find if a c file has code that requires >=C11 or C99 compiler. Can this be done with gcc, or ctags?
Basically I need to identify the minimum version of compiler required to compile the file. I have tried different tools including ctags etc.
Use grep -- -std= Makefile
ctags: no way
If you are looking for something smarter... bad luck.

Using 3rd Party C files with C Lion, a beginner perspective

I am in despair for a simple explanation to a simple problem.
I made a program in java that I need to recode in C for performance reasons. So I learned how to program in C. The problem is that C standard libraries do not contain collections (why????) such as a hashtables, treesets, etc. So I found this: https://github.com/srdja/Collections-C.
I use CLion on windows, I know well about coding but NOTHING about compiling, CMake, Linux, etc. My question is: I want to use those external source files my project, why is that so hard ? The tutorial on the link provided above tells me to use Linux command lines and stuff that I don't understand. Online I find stuff about telling me to add commands into CMakelist, none of these work for diverse reasons. I can't even copy all the .c and .h into my project because "they are not part of the project". So can anyone tell me how to make this simple code work ?
#include <stdio.h>
#include "hashtable.h"
int main() {
Hashtable *table;
hashtable_new(&table); //this is a function that creates the new hashtable in the source code of Collections-C
return 0;
}
By the way, because I think it's the same problem, how can I have subdirectories in my project so that I can put my header files away to keep the project tree tidy? I tried to add add_subdirectories($/include) to my CMakelist.txt
I am expecting people telling me that there are many similar questions already, but none of those I found is clear to me.
Thank you if you have the patience to explain this to me.
Henri
This is for C++, but it should work for your C code. In this example, it's defining where to find the OpenSSL and Google Test headers, and how to link with the Google Test library and the OpenSSL library (which is in C, as it turns out):
cmake_minimum_required(VERSION 3.5)
project(stackexample)
set(CMAKE_CXX_STANDARD 11)
find_library(GTest required)
include_directories(${GTEST_INCLUDE_DIRS} /usr/include/openssl)
set(
SOURCE_FILES
StackExample.cpp
StackExample.h
)
add_executable(stackexample ${SOURCE_FILES})
target_link_libraries(stackexample -lgtest -lssl -lcrypto pthread)
Collections-C appears to have an installer, so you would
List the path to its installed headers in the include_directories line
List its installed library in the target_link_libraries line
The solution was to build the library then do stuff with CMake. I followed this tutorial.

YouCompleteMe suggests only "local" used code

I'm trying to use YCM for the first time so in order to make it work I decided to give a chance for the YCM-Generator, which generates the .ycm_extra_conf.py file automatically based on the makefile.
So far my program is just a simple hello world.
#include <stdio.h>
int main()
{
printf("Hello World!");
return 0;
}
I'm using the CMakeLists.txt trick to generate the makefile.
file(GLOB sources *.h *.c)
add_executable(Foo ${sources})
then after executing the YCM-Generator script, I get this output
Running cmake in '/tmp/tmp_YknVy'... $ cmake
/home/pedro/Desktop/Projetos/teste
Running make... $ make -i -j4
Cleaning up...
Build completed in 1.5 sec
Collected 2 relevant entries for C compilation (0 discarded).
Collected 0 relevant entries for C++ compilation (0 discarded).
Created YCM config file with 0 C flags
YCM plugin does find the .ycm_extra_conf.py file, but the auto-completion doesn't work right, for example, if I type "floa", it doesn't suggests "float", but It only suggests things that I used before like "int" or "printf".
Am I missing something or this is working as intended?
So I fixed it.
For c it does require a .ycm_extra_conf.py , while a friend of mine could make it work without one in c++.
The auto complete only suggest automatically functions that were previously used, if you don't remember a function name you have to press <Ctrl-Space>
YCM-Generator didn't do the job, so I modified the example file myself following the comments.
If you are used to Visual Assist, the auto complete works but it's really weak if compared to VA, which is a shame... I really hope someone port that plugin to Linux.

Resources