How to use pkg-config in CMake (juCi++) - c++

I've been happily programming in C++ and compiling with g++ for quite a while. Not long ago, I'd decided to get an IDE, and I came accross juCi++.
This IDE is absolutely brilliant, but it uses CMake (or Meson) to build projects. This wasn't a problem, until I had to include a library (GTK+ 3.0 if you're wondering) using pkg-config. This could be done quite easily when compiling with g++, but, as I am completely new to CMake, I have no idea how to do it in the new IDE.
Can somebody please explain?

If your IDE handles CMake and Meson, it should be able to detect your project files. I'd say go for Meson, it's the future, and CMake syntax has a few quirks that Meson doesn't.
Meson:
Meson documentation
He's a basic meson.build that expects to find your application code in main.c and produces a binary named gtk3-test.
project('gtk3-test', 'c')
cc = meson.get_compiler('c')
deps = dependency ('gtk+-3.0')
sources = ['main.c']
executable('gtk3-test', sources, dependencies: deps)
CMake
CMake documentation
For CMake, just give a look at my answer to How do I link gtk library more easily with cmake in windows? (which also works under Linux). It was for GTK+2, but adapting it to GTK+3 is easy, so here's the CMakeLists.txt to use:
project (gtk3-test)
cmake_minimum_required (VERSION 2.4)
find_package (PkgConfig REQUIRED)
pkg_check_modules (GTK3 REQUIRED gtk+-3.0)
include_directories (${GTK3_INCLUDE_DIRS})
link_directories (${GTK3_LIBRARY_DIRS})
add_executable (gtk3-test main.c)
add_definitions (${GTK3_CFLAGS_OTHER})
target_link_libraries (gtk3-test ${GTK3_LIBRARIES})

Related

Very slow intellisense for CMake-configured Vulkan-project

I have a Vulkan project configured with the following CMakeLists.txt on Windows:
cmake_minimum_required(VERSION 3.20)
project(Custom_Vulkan)
set(MINGW_INCLUDE "C:\\msys64\\mingw64\\include")
find_package(Vulkan REQUIRED)
find_package(glfw3 REQUIRED HINTS "C:\\msys64\\mingw64\\lib\\cmake")
add_subdirectory(shaders)
add_executable(AppTest main.cpp)
target_link_libraries(AppTest PUBLIC Vulkan::Vulkan glfw)
include_directories(${MINGW_INCLUDE})
Extensions for CMake (CMake & CMake Tools), and C++ (C/C++, C/C++ Extension Pack, C/C++ Themes) are installed, and I have configured and built my executable using the CMake Tools-extension.
Intellisense can at times be unreasonably slow and freezes completely, resulting in 0 autocompletion suggestions for both constants from built-in libraries like M_PI from cmath, but also for the Vulkan/GLFW-APIs which have been located by CMake.
Where should I search in order to locate the dependency that stalls Intellisense?
Is it possible to monitor/profile the Intellisense-search in order to find the issue?
The CMake-tools project is fully able to detect the dependencies, and compiles fine.
The Intellisense-freezes were in this case caused by dependency-issues between a FetchContent repository dependency in CMake and the C# vscode extension pack which caused an OmniSharp server-handle to remain open.
This was a standard FetchContent-pull:
FetchContent_Declare(
imgui_repo
GIT_REPOSITORY "https://github.com/ocornut/imgui.git"
)
FetchContent_MakeAvailable(imgui_repo)
Right-clicking the extension followed by disable(workspace) solved the issue.

Android Studio Compiles With Gcc, how to change that to G++ ? (Using CMake)

i have a Android studio project which uses Native C++ code with JNI, however when i try to Build my project, it throws error: undefined reference to 'std::basic_ostream<char...
errors.
I am using ubuntu and i believe the problem is caused by IDE using gcc compiler and tries to compile it as C code. When i try to run simple hello world program by running gcc -o foo foo.cpp in terminal, it gives same error. When i change gcc to g++, everything works fine.
But how do i change the compiler in IDE? I'm kinda new to using CMake and i think i need to use cmake's enable_language function but even i add enable_language(CPP) line to my CMakeLists.txt, it gives same errors.
Here is my CMakeLists.txt :
cmake_minimum_required(VERSION 3.4.1)
include_directories("/usr/include/x86_64-linux-gnu/c++/9")
include_directories("/usr/include/c++/9")
include_directories("/usr/include/x86_64-linux-gnu")
include_directories("/usr/include")
file(GLOB srcs *.cpp *.c)
file(GLOB hdrs *.hpp *.h)
include_directories(${OpenCV_DIR}/jni/include)
include_directories(${TESSERACT_INCLUDE_DIRS})
include_directories(${LEPTONICA_INCLUDE_DIRS})
add_library( lib_opencv SHARED IMPORTED )
set_target_properties(lib_opencv PROPERTIES IMPORTED_LOCATION ${OpenCV_DIR}/libs/${ANDROID_ABI}/libopencv_java4.so)
add_library(
native-lib
SHARED
#
native-lib.cpp )
find_library(
log-lib
log )
target_link_libraries(
native-lib
lib_opencv
${log-lib}
${TESSERACT_LIBRARIES}
${LEPTONICA_LIBRARIES})
Thanks!
ps: My G++ and Gcc versions are 9.3.0, build-essentials are already installed.
Your CMakeLists.txt is a whole lot of mess. Lets go through some potential problems, one by one, and see if it starts working.
The solution is probably in point 7, but I already wrote it all so I am leaving it here. Let me know if my answer helped you.
1. Does Android Studio really use this CMakeLists.txt file for building?
There are two usual build systems for NDK - older ndk-build and newer CMake. Check your Gradle build file to see if this CMakeLists.txt is really used. Here is documentation about how it should work: https://developer.android.com/studio/projects/gradle-external-native-builds.
And of course, you can make a deliberate syntax error in your CMakeLists.txt file to see if the build systems starts complaining about it.
And note that CMake should not by invoked separately when building for Android. It should be invoked from inside the Gradle script that is used by Android Studio for building the whole project.
2. Do all source files that use C++ libraries have .cpp extension?
CMake determines what compiler to use (C or C++) based on the extension of the file. If it is a .c file, then C compiler is used. If it is a .cpp file, then C++ compiler is used.
Also note that Android NDK now uses Clang (from LLVM project) instead of GCC, so GCC version or custom GCC invocations might not be that relevant.
You can also make CMake verbose - to print all the build commands, to see which commands are exactly executed. Add set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") to your CMakeLists.txt file to make it verbose.
3. Is correct C++ library used?
Symbols you are missing (something from std::basic_ostream) are defined in C++ library (I think) that needs to be linked to your library. By default, libc++ should be linked and that is the right choice. But there is an option that can mess with that. So check your gradle build file for a ANDROID_STL variable and remove any assignments to that variable. The issue of C++ library in NDK is explained here: https://developer.android.com/ndk/guides/cpp-support#cmake
4. Missing source files.
When you call add_library, you are only adding one source file - native-lib.cpp. So only this one file will be compiled in the library (apart from lib_opencv that is linked to it). The line file(GLOB srcs *.cpp *.c) assigns all cpp and c files to the ${srcs} variable but that variable is then left unused. You could change add_library to use that variable: add_library( native-lib SHARED ${srcs} ).
If you want to also include files from subdirectories, use GLOB_RECURSE instead of GLOB in your file(GLOB srcs *.cpp *.c) command.
The line file(GLOB hdrs *.hpp *.h) is completely useless as far as I can tell. I don't see how a list of all header files could be useful in a CMake script.
5. Use new target-based CMake configuration.
Older CMake used file-based configuration, now target-based configuration is encouraged. File-based commands are for example link_libraries and include_directories, their target-based alternatives are target_link_libraries and target_include_directories. You are mixing those two styles. Basically, when a command has its target_ variant, you always want to use it.
You need to first create your target using add_library( native-lib SHARED ${srcs} ), the targets name is native-lib. Then add all include directories and link all libraries to it using target-based commands.
Also the way you add lib_opencv is missing a find_package command. Use find_package(OpenCV REQUIRED) and then target_link_libraries( native-lib PUBLIC ${OpenCV_LIBS} ) to link it.
The way you are adding logging library is OK, because the log-lib library is part of native API (https://developer.android.com/ndk/guides/stable_apis#logging) so it is more straightforward.
With CMake, you need to search internet or documentation to find out, which commands are needed to add each library to your target (unless you are compiling the library from sources). Tthough it is almost always some combination of find_package and target_link_libraries.
6. Missing project information.
I am not sure how important that is, but usually you start your main CMakeLists.txt with something like this:
cmake_minimum_required( VERSION 3.4.1 )
project( my_special_project )
set( CMAKE_CXX_STANDARD 14 )
set( CMAKE_CXX_STANDARD_REQUIRED True )
7. Don't manually include system directories.
Thinking about it, this is probably the problem. Toss out all of these lines:
include_directories("/usr/include/x86_64-linux-gnu/c++/9")
include_directories("/usr/include/c++/9")
include_directories("/usr/include/x86_64-linux-gnu")
include_directories("/usr/include")
Ndk uses its own toolchain, so never manualy add paths from your system toolchain to your NDK project.
I would discourage doing this also on any other project. It is not portable and things like that should be taken care of indirectly, by CMake itself.

CMake on Windows 10 doesn't generate executable

So I have a tiny C++ project that I code on both Windows 10 and Ubuntu 16.04, and I'm using CMake to coordinate relatively platform-independent build processes. I'm no master of CMake, but it worked up until recently, however now I cannot get the solution generated by CMake-gui to actually compile into an executable to run, despite my usage of add_executable. Here is my CMakeLists (there's a hideous mix of platform-specific stuff in there, however it appears that CMake simply ignores it):
cmake_minimum_required(VERSION 3.10)
set (CMAKE_CXX_STANDARD 17)
project (TestProject)
include_directories(C:/include/CImg-2.2.2)
ADD_LIBRARY(LibsModule Game.cpp Game.h TestGame.cpp TestGame.h)
target_link_libraries(LibsModule -lpthread)
target_link_libraries(LibsModule -lm)
target_link_libraries(LibsModule -lX11)
add_executable(TestProject TestGame.h)
target_link_libraries(TestProject LibsModule)
This compiles and runs fine on Ubuntu using CLion, however on 64-bit Windows 10 using VS17 it fails upon trying to run the executable it expects to be generated because the executable doesn't exist in the build folder (but the .lib file noted is generated just fine).
I've seen some mention that a third party antivirus program could cause this, but I have no such thing installed.
Now I'm pretty new to CMake so if this file is completely off the mark I would really appreciate a clear explanation as to what I'm doing wrong, this code is made from a short study of basic CMake usage.

C++ How to run programs in Clion when you need to include OpenGL libraries?

Hello I need to work with OpenGL and want to create my project in Clion. But Clion cannot compile and run my projects because of the libraries I need to include. I can create my own makefile and run the program in terminal, but I want to do it in the IDE. How can I make this happen?
First make sure you installed all libraries correctly using the compiler you configured in clion/cmake. Assuminf you have a fresh CMakeLists.txt like
cmake_minimum_required(VERSION 3.3.2)
project(MyGL CPP)
add_executable(demo-run main.cpp)
For linking your libraries you need two things. First tell the compiler where to find the include files and second which libraries to link. You could just hard code you local installation like
target_link_libraries(demo-run path/to/glfw.lib path/to/opengl.lib path/to/jpeg.lib ...)
target_include_directories(demo-run PRIVATE path/to/glfw/include path/to/opengl/include path/to/jpeg/include ...)
however this is not very portable and if you want to work with another compiler or on another machine your project file will fail. Instead you can use the package system of cmake
find_package(PkgConfig REQUIRED)
pkg_search_module(GLFW REQUIRED glfw3)
find_package(JPEG REQUIRED)
find_package(GLEW REQUIRED)
find_package (OpenGL REQUIRED)
find_package (GLM REQUIRED)
target_link_libraries(demo-run ${GLFW_LIBRARIES} ${GLEW_LIBRARIES} ${JPEG_LIBRARIES} ${OPENGL_LIBRARIES})
target_include_directories(demo-run PRIVATE ${GLFW_INCLUDE_DIRS} ${GLEW_INCLUDE_DIR} ${JPEG_INCLUDE_DIR} ${OPENGL_INCLUDE_DIR} ${GLM_INCLUDE_DIR})
The glfw part is a bit tricky and works only on linux i guess see http://www.glfw.org/docs/3.0/build.html.
This code is not tested at all and you may need to specify some enviroment variables so cmake can find the packages or provide additional find scripts like https://github.com/lighttransport/nanogi/blob/master/cmake/FindGLM.cmake.
I would recommend to use the CMake build tool which does the work generating Makefiles for you and is also directly supported by clion. When you open the directory containing a CMakeLists.txt (CMake Project File) with clion, it should be automatically be loaded and compiled (if not just hit build)
A very simple example CMake project would look like this
cmake_minimum_required (VERSION 2.8.9)
project (OpenGl-Stuff)
include_directories(src)
add_executable(your-binary src/your-code.c src/your-code.h)
target_link_libraries(your-binary opengl)
# target_link_libraries will search for libopengl on standard system paths,
# maybe the library is not called libopengl, then you have to adjust the name above
this cmake project will generate the binary for you and link it against opengl

Compile Linux OpenGL Application on Windows?

I have made a OpenGL application which I can compile fine on Linux. It uses static .a librarys. Now I tried compiling with MinGW (and .lib libraries) and g++, but the resulting main.exe displays this error when I try to execute it: https://i.imgur.com/dpidmsw.png.
g++.exe -std=c++11 -Wall -o main.exe Main.cpp FastNoise.cpp shader.cpp texture.cpp glew32.lib glfw3.dll -lglu32 -lopengl32
When using cmake with the CMakeGUI to create a Visual Studio Project it works fine:
cmake_minimum_required(VERSION 3.5)
add_definitions(-DGLEW_STATIC)
set (CMAKE_CXX_STANDARD 11)
add_executable(main Main.cpp texture.cpp shader.cpp FastNoise.cpp)
find_package(OpenGL REQUIRED)
include_directories( ${OPENGL_INCLUDE_DIRS} )
IF (WIN32)
target_link_libraries(main ${CMAKE_CURRENT_SOURCE_DIR}/GLEW_1130.lib ${CMAKE_CURRENT_SOURCE_DIR}/glfw3.lib ${OPENGL_LIBRARIES} ${GLUT_LIBRARY} ${X11_LIBRARIES})
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/vertex.glsl ${CMAKE_CURRENT_BINARY_DIR}/Debug/vertex.glsl COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fragment.glsl ${CMAKE_CURRENT_BINARY_DIR}/Debug/fragment.glsl COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/dirt.bmp ${CMAKE_CURRENT_BINARY_DIR}/Debug/dirt.bmp COPYONLY)
ELSE()
include_directories( ${X11_INCLUDE_DIRS} )
find_package(X11 REQUIRED)
target_link_libraries(main ${CMAKE_CURRENT_SOURCE_DIR}/libGLEW.a ${CMAKE_CURRENT_SOURCE_DIR}/libglfw3.a ${OPENGL_LIBRARIES} ${GLUT_LIBRARY} ${X11_LIBRARIES} X11 Xxf86vm pthread dl Xrandr Xinerama Xcursor)
ENDIF()
Just because you have static libraries that doesn't mean that these are in any way system independent. The static libraries you have are all built for a Linux target. They expect to talk with Linux operating system functions using the a calling convention (i.e. the way functions are to be called) that's different from Windows. Essentially you're trying to shove a square peg through a round hole here. It doesn't work that way.
To build for Windows you need also all the prerequisites being ported and built for Windows, too. Luckily all the libraries you mention have Windows ports, so that's not a problem.
I fixed it by adding these praeprocessor definitions:
…
You fixed nothing. You just lied to something (compiler, your program source code, etc.) about the toolchain it's built with and the target it's built for.
If you start redefining system level preprocessor definitions, you're doing something very, very wrong.
Here's what you should do (well, what I recommend): Head over to http://www.msys2.org/ and grab the MSys2 installer. Install it, launch the MinGW… environment (there's a 32 bit and a 64 bit environment). MSys2 uses the Pacman package manager of the Arch Linux distribution. Use that to install the toolchain (make, binutils, gcc) – make sure you install the right variant, the package database has packages for msys, mingw32 and mingw64 – and all the development libraries you need. There are packages for GLEW, GLFW3 and so on available.
Next install CMake. I strongly recommend not to use the MSys2 package, but the standalone installer from https://cmake.org/ – the CMake installed this way knows how to work with MSys/MinGW …and more.
Then create a CMakeLists.txt for your project, and use that to create the build environment. The nice thing about CMake is, that it's cross platform and knows a ton of build systems and compiler environments. If your project is structured sanely and you don't do crazy stuff (or you do crazy stuff and put the right straightjackets around it so it doesn't go on a rampage) you'll get something that you can build effortlessly on or for most target environments.