Clear way to setup LSP (vim-lsc) with vim + CMake? - c++

I am trying to set up LSP with vim + cmake. I am using vim-lsc plugin as client and clangd as the server.
Folder structure:
Test/
test.cpp
test.h
CMakeLists.txt
test.h:
#ifndef TEST_H
#define TEST_H
class Apple {
public:
int size;
};
#endif
test.cpp:
#include <iostream>
#include "test.h"
int main() {
Apple apple;
return 0;
}
CMakeLists.txt:
cmake_minimum_required(VERSION 3.10)
project(my_test)
add_executable(test test.cpp)
target_include_directories(test PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
~/.vimrc:
let g:lsc_server_commands = {'c': 'clangd', 'cpp': 'clangd'}
I build with
mkdir build
cd build
cmake ..
make
This compiles fine with no errors and warnings.
However, while editing test.cpp in vim, vim-lsc shows errors not detecting user defined header files and types defined within them. For example, in the above project, the following two errors are shown:
test.cpp|3 col 10 error| 'test.h' file not found [pp_file_not_found]
test.cpp|6 col 5 error| Unknown type name 'Apple' [unknown_typename]
How do I set this up so that headers in the project are identified properly?
EDIT: The problem has changed somewhat. I added a compile_commands.json file to the top level directory to no avail. I suspect that it has to do with the way paths are represented in Git Bash on windows.
The compile_commands.json has the inlcude paths like so:
-IE:\\C:\\Test
If the class is defined in the same file, the lsp protocol seems to be working. Can clang not work with such paths? Could someone shed some light on this?

Related

CMake + ninja - exe file shows no output if header file is included in a source file

I am learning to use CMake and I'm using ninja as a build system. I have created a very simple program, but I have one issue. I have only two files main.cpp and constants.h. Whenever I include constants.h in main.cpp, after building a .exe file, I see no output from it after running it through bash. When i remove the include, it works just fine. Can anybody please guide.
main.cpp
#include <stdio.h>
#include "constants.h" // does not even show output when i add this
int main() {
printf("hello world");
return 0;
}
constants.h
#pragma once
const int WIDTH = 1000;
CMakeLists.txt
cmake_minimum_required(VERSION 3.23)
set(CMAKE_CXX_COMIPLER "g++")
set(CMAKE_C_COMPILER "gcc")
project(BoidSimulation)
set(CMAKE_CXX_STANDARD 17)
add_executable(BoidSimulation main.cpp)
Can someone please guide what I'm doing wrong. I have tried to add constants.h in add_exectuable and also used target_include_directories by keeping the header file in some directory.
I build and run through the following commands:
cmake -G "Ninja" -S . -B ./out/build/
cd out/build
ninja
./BoidSimulation
Running this with header file shows no output and no errors on bash, it just moves on to next line. It runs fine through powershell and shows the output with or without header files.
You never print a newline. In some shells this will cause the prompt to be printed over it. This has nothing to do with your constants.h header.

How to include 'jni.h' file using CMake [duplicate]

This question already has answers here:
How to use FIND_JNI on cmake
(2 answers)
Closed 9 months ago.
I am trying to compile my C++ project using CMake on my Mac M1 Pro 12.0.1.
This is my simple directory structure:
In my foo.cpp, I am including jni.h header file:
#include <iostream>
#include "foo.h"
#include <vector>
#include <jni.h>
void foo()
{
std::cout << "Hello World!\n";
}
This is my CMakeLists.txt:
cmake_minimum_required(VERSION 3.4.1)
project("myapplication")
add_library(my_app SHARED main.cpp foo.cpp)
target_include_directories(my_app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
if(APPLE)
set(JAVA_INCLUDE_PATH "$ENV{JAVA_HOME}/include")
set(JAVA_INCLUDE_PATH2 "$ENV{JAVA_HOME}/include/darwin")
set(JAVA_AWT_INCLUDE_PATH "$ENV{JAVA_HOME}/include")
message("JAVA_INCLUDE_PATH = ${JAVA_INCLUDE_PATH}")
find_package(JNI REQUIRED)
if (JNI_FOUND)
message (STATUS "JNI_INCLUDE_DIRS=${JNI_INCLUDE_DIRS}")
message (STATUS "JNI_LIBRARIES=${JNI_LIBRARIES}")
endif()
target_include_directories(my_app PUBLIC ${JNI_INCLUDE_DIRS})
endif()
I am getting CMake output as:
-- Found JNI: /System/Library/Frameworks/JavaVM.framework
-- JNI_INCLUDE_DIRS=/Users/vmangal/Library/Java/JavaVirtualMachines/jdk1.8.0_202.jdk/Contents/Home/include;/Users/vmangal/Library/Java/JavaVirtualMachines/jdk1.8.0_202.jdk/Contents/Home/include/darwin;/Users/vmangal/Library/Java/JavaVirtualMachines/jdk1.8.0_202.jdk/Contents/Home/include
-- JNI_LIBRARIES=/System/Library/Frameworks/JavaVM.framework;/System/Library/Frameworks/JavaVM.framework
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/vmangal/my/practice/cmake/build
My JAVA_HOME environment variable is set to /Users/vmangal/Library/Java/JavaVirtualMachines/jdk1.8.0_202.jdk
But during make command, I am getting compilation error:
/Users/vmangal/my/practice/cmake/foo.cpp:4:10: fatal error: 'jni.h' file not found
#include <jni.h>
Am I missing something in CMakeLists.txt ?
I had a similar problem and found that when setting variables this way
set(JAVA_INCLUDE_PATH "$ENV{JAVA_HOME}/include")
i was getting wrong imports for C_INCLUDES and CXX_INCLUDES. Like this (see in CMakeFiles/my_app.dir/flags.make):
C_INCLUDES = -I/include -I/include/darwin
CXX_INCLUDES = -I/include -I/include/darwin
Which basically which meant that $ENV{JAVA_HOME} was an empty string.
After I set the full paths in CMakeLists
set(JAVA_INCLUDE_PATH /usr/local/Cellar/openjdk#17/17.0.3/libexec/openjdk.jdk/Contents/Home/include)
everything started working correctly.
So the conclusion is that if you want to run cmake and use $ENV{JAVA_HOME} – use syntax JAVA_HOME=/path/to/java/home cmake ...

Yaml-cpp configuration parser testing with CppUTest issue "expected type-specifier before ‘(’ token"

I am using yaml-cpp library (v 0.6.0) to parse yaml configuration file. Yaml-cpp is installed as system library.
I have made a class Parser which checks for key-value pairs in yaml node. The Parser class is built as ConfigParserLibrary static library.
Now I want to test the Parser class using CppUTest. Building the project with CMake. Example code:
CMakeLists:
cmake_minimum_required(VERSION 3.9)
project(yaml-parser VERSION 0.1.0)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# ConfigParserLibrary lib
include_directories(${PROJECT_SOURCE_DIR}/include/config_parser_lib)
file(GLOB_RECURSE LIB_CONFIG_PARSER_SRC "config_parser_lib/Parser.cpp")
add_library(ConfigParserLibrary STATIC ${LIB_CONFIG_PARSER_SRC})
target_link_libraries(ConfigParserLibrary yaml-cpp)
# Executable that uses ConfigParserLibrary
add_executable(conf_reader "config_reader.cpp")
target_link_libraries(conf_reader yaml-cpp ConfigParserLibrary)
message(STATUS "Library tests will be built.")
add_library(ConfigParserTests STATIC tests/ConfigParserTests.cpp)
target_link_libraries(ConfigParserTests ConfigParserLibrary yaml-cpp)
add_executable(RunLibTests tests/RunTests.cpp)
target_link_libraries(RunLibTests CppUTest CppUTestExt
ConfigParserTests ConfigParserLibrary yaml-cpp)
add_test(NAME test_library COMMAND RunLibTests)
When I use the Parser class in another executable it is compiling without errors. But when I include the config_parser_lib/Parser.hpp file in the ConfigParserTests.cpp file it raises: /usr/include/c++/8/optional:208: error: expected type-specifier before ‘(’ token
::new ((void *) std::__addressof(this->_M_payload))
^.
Parser.hpp
#pragma once
#include <yaml-cpp/yaml.h>
class Parser{
public:
int parseNode(YAML::Node configNode);
};
Parser.cpp
#include "config_parser_lib/Parser.hpp"
int Parser::parseNode(YAML::Node configNode){
return valueA = configNode["keyA"].as<int>();
}
ConfigParserTests.cpp
#include <CppUTest/TestHarness.h>
#include "config_parser_lib/Parser.hpp"
TEST_GROUP(ConfigParserTests) {
};
TEST(ConfigParserTests, ParseConfigNode){
}
RunTests.cpp
#include <CppUTest/CommandLineTestRunner.h>
IMPORT_TEST_GROUP(ConfigParserTests);
int main(int ac, const char** av)
{
return CommandLineTestRunner::RunAllTests(ac, av);
}
In CMakeLists.txt: when I change the CMAKE_CXX_STANDARD from 17 to 11, I am getting the following error /usr/include/c++/8/bits/stl_tree.h:636: error: ‘__node’ does not name a type
::new(__node) _Rb_tree_node<_Val>;
^~~~~~.
If I comment out the #include "config_parser_lib/Parser.hpp" line in ConfigParserTests.cpp, there is no error. Thus I think the error comes from including the <yaml-cpp/yaml.h> file. If I include <yaml-cpp/node/node.h> instead of yaml.h>, there is no error, but I need the <yaml-cpp/yaml.h> file which includes other headers I need to use.
gcc version 8.3.1 20190226.
Changing the include order in ConfigParserTests.cpp solved the problem.
#include "config_parser_lib/Parser.hpp"
#include <CppUTest/TestHarness.h>
I assume that #include <yaml-cpp/yaml.h> should be at the beginning of every translation unit.

cmake: add directory to be searched for header files

I am writing c++ code to run tests on an arduino project I've written. In order to run it, I need it to include mockups of a couple libraries (the original libraries don't work in c++). The mockups are in my src directory, along with the tests in main.cpp. The files that rely on the mockups are in the parent directory of src, and I cannot modify them to refer to src without breaking their ability to run when uploaded to an arduino. I also cannot add the mockups or main.cpp to the parent directory, as this would interfere with the operation of the arduino code.
So, I need to add the child directory with the mockups to the directories that are searched when compiling the files in the parent directory.
Directory Outline:
parent
forTest.h
forTest.cpp
src
parson.h
parson.c
String.h
String.cpp
main.cpp
CMakeLists.txt
build
In this case, main.cpp has "#include ../forTest.cpp", and forTest.cpp has "#include parson.h" and "#include String.h"
I am currently running the following code in CMakeLists.txt:
cmake_minimum_required (VERSION 2.6)
project(makeTest)
include_directories(../ )
set (makeTest_VERSION_MAJOR 1)
set (makeTest_VERSION_MINOR 0)
add_executable(makeTest main.cpp ../forTest.cpp String.cpp parson.c)
I then build it in the build directory from the command line with
cmake -G "Unix Makefiles" ../src
make
The cmake command resolves successfully, but the make command hits "fatal error: parson.h not found" when building forTest.cpp
How can I resolve this?
edit: my apologies if this has an obvious answer, I'm very new to Cmake
edit the second: using the changes suggested by Gergely Nyiri and changing #include to #include "/usr/include/string.h" resolves several errors, but introduces a new error : "implicit instantiation of undefined template" during the make step.
It refers to the following code in by string.h mockup file:
#ifndef STRING_H
#define STRING_H
#include "/usr/include/string.h"
using namespace std;
class String {
private:
std::string thisString;
char chars[];
...
#endif
which returns the error:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/cstring:61:
/Users/douglas/Desktop/parts/makeHolder/testMake/src/string.h:9:14: error:
implicit instantiation of undefined template 'std::__1::basic_string<char,
std::__1::char_traits<char>, std::__1::allocator<char> >'
std::string thisString;
This is followed by:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/iosfwd:193:32: note:
template is declared here
class _LIBCPP_TEMPLATE_VIS basic_string;
First of all, I would propose to put CMakeLists.txt in your source root. Then:
cmake_minimum_required (VERSION 2.6)
project(makeTest)
include_directories(src)
set (makeTest_VERSION_MAJOR 1)
set (makeTest_VERSION_MINOR 0)
add_executable(makeTest src/main.cpp forTest.cpp src/String.cpp src/parson.c)
Configure & build:
cd build
cmake ../
make
Even better if you use target_include_directories instead of include_directories:
..
add_executable(makeTest src/main.cpp forTest.cpp src/String.cpp src/parson.c)
target_include_directories(makeTest PRIVATE src)

CMake project for Emscripten

I want to make CMake and Emscripten friends. Didn't find more or less informative documentation on the Emscripten project website, but they provide CMake toolchain file so I think it should be possible.
So far very basic compilation without advanced parameters works fine, but I have issues while using embind and preloading files.
Linking process seems to miss Emscripten "binaries" and produces warnings for all embind related functions like this one: warning: unresolved symbol: _embind_register_class which results in respective errors while loading compiled JS file in rowser.
No .data file is generated during the compilation.
I've created a minimalistic example which includes two targets: one "normal" (client) and one manual (manual-client) which simply runs emcc as I expect it to be run: https://github.com/xwaffelx/minimal-cmake-emscripten-project/blob/master/README.md
Although manual way works, I don't think it is a proper way to do it...
--- Update ---
As requested, here is even more short example:
CMakeLists.txt file
cmake_minimum_required(VERSION 2.8)
cmake_policy(SET CMP0015 NEW)
project(emtest)
set(CMAKE_VERBOSE_MAKEFILE on)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/build.emscripten)
include_directories("lib/assimp/include")
link_directories("lib/assimp/lib-js")
link_libraries("assimp")
file(GLOB_RECURSE CORE_HDR src/.h)
file(GLOB_RECURSE CORE_SRC src/.cpp)
add_definitions("-s DEMANGLE_SUPPORT=1 --preload-file ${CMAKE_SOURCE_DIR}/assets --bind")
add_executable(client ${CORE_SRC} ${CORE_HDR})
Result should be equivalent to running the following command manualy:
emcc
-Ilib/assimp/include
-s DEMANGLE_SUPPORT=1
--preload-file assets
--bind
Application.cpp
lib/assimp/lib-js/libassimp.so
-o client.js
Here is the Application.cpp:
#include "Application.h"
#include <iostream>
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
void Application::Initialize() {
std::cout << "Initializing application." << std::endl;
Assimp::Importer importer; // For test purpose
}
void Application::SayHello() {
std::cout << "Hello!" << std::endl;
}
and Application.h:
#ifndef APPLICATION_H
#define APPLICATION_H
#include <emscripten/html5.h>
#include <emscripten/bind.h>
namespace e = emscripten;
class Application {
public:
void Initialize();
void SayHello();
};
EMSCRIPTEN_BINDINGS(EMTest) {
e::class_<Application>("Application")
.constructor()
.function("Initialize", &Application::Initialize)
.function("SayHello", &Application::SayHello);
}
#endif
THen I run cmake as follows:
cmake -DCMAKE_TOOLCHAIN_PATH=path/to/Emscripten.cmake .. && make
However, warnings like warning: unresolved symbol: _embind_register_class are produced during linking and running the code and no preloaded data in client.data file is created while compiling CMake project. At the same time no warnings and everything runs OK while compiling manually.
The solution was to specify all the flags during the linking by providing following CMake instruction:
set_target_properties(client PROPERTIES LINK_FLAGS "-s DEMANGLE_SUPPORT=1 --preload-file assets --bind")
Thanks to developers of emscripten who helped in the github issues tracker.