How do I add compiler arguments using CMake?
I am using Clion IDE and am trying to put together a simple GTK program to compile it. I found that Clion is using CMake, so the problems are here and not with the IDE itself. I can successfully compile and run the program directly from the terminal, but CMake has failed.
The problem is simple: when I try to compile, the compiler cannot find the gtk.h that is in /usr/include/gtk-3.0/gtk/gtk.h
. I found that somehow the command compiler argument 'pkg-config --libs --cflags gtk+-3.0'
fixes this issue, but I was unable to add that argument using CMake.
I tried:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} `pkg-config --libs --cflags gtk+-3.0`")
But I met with:
Linking CXX executable test
c++: error: `pkg-config: No such file or directory
c++: error: gtk+-3.0`: No such file or directory
c++: error: unrecognized command line option โ--libsโ
c++: error: unrecognized command line option โ--cflagsโ
make[3]: *** [test] Error 1
make[2]: *** [CMakeFiles/test.dir/all] Error 2
make[1]: *** [CMakeFiles/test.dir/rule] Error 2
make: *** [test] Error 2
Any suggestions?
Further research has shown this tutorial on exactly the problem I am having. It works like a charm, but it seems to throw a lot of seemingly undefined variables into the mix. Can anyone explain how and why this works?
# Set the name and the supported language of the project
project(hello-world C)
# Set the minimum version of cmake required to build this project
cmake_minimum_required(VERSION 2.6)
# Use the package PkgConfig to detect GTK+ headers/library files
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
# Setup CMake to use GTK+, tell the compiler where to look for headers
# and to the linker where to look for libraries
include_directories(${GTK3_INCLUDE_DIRS})
link_directories(${GTK3_LIBRARY_DIRS})
# Add other flags to the compiler
add_definitions(${GTK3_CFLAGS_OTHER})
# Add an executable compiled from hello.c
add_executable(hello main.c)
# Link the target to the GTK+ libraries
target_link_libraries(hello ${GTK3_LIBRARIES})
source to share
Use FindPkgConfig Module
cmake_minimum_required(VERSION <your cmake version>)
project(myproject CXX)
# Find the GTK module using pkg-config
include(FindPkgConfig)
pkg_check_modules(GTK REQUIRED "gtk+-3.0")
# Add the path to its header files to the compiler command line
include_directories(${GTK_INCLUDE_DIRS})
# Add any compiler flags it requires
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GTK_CFLAGS} <other flags>")
# Add the makefile target for your executable and link in the GTK library
add_executable(${CMAKE_PROJECT_NAME} <list of source files>)
target_link_libraries(${CMAKE_PROJECT_NAME} ${GTK_LDFLAGS} <other libraries>)
bit in chevrons ( <...>
) must be replaced with real values
you can find out more with
cmake --help-module FindPkgConfig
Basically the line include(FindPkgConfig)
contains a few macros - this also ensures that pkg-config is available in the environment. The call then pkg_check_modules
effectively triggers pkg-config
, parses the output, and creates a set of variables using the first argument as a basis.
From the help, this is the master list (XPREFIX is usually the base you supply)
<XPREFIX>_FOUND ... set to 1 if module(s) exist
<XPREFIX>_LIBRARIES ... only the libraries (w/o the '-l')
<XPREFIX>_LIBRARY_DIRS ... the paths of the libraries (w/o the '-L')
<XPREFIX>_LDFLAGS ... all required linker flags
<XPREFIX>_LDFLAGS_OTHER ... all other linker flags
<XPREFIX>_INCLUDE_DIRS ... the '-I' preprocessor flags (w/o the '-I')
<XPREFIX>_CFLAGS ... all required cflags
<XPREFIX>_CFLAGS_OTHER ... the other compiler flags
<XPREFIX> = <PREFIX> for common case
<XPREFIX> = <PREFIX>_STATIC for static linking
source to share
You should understand that when you manually enter the compilation command
`pkg-config โฆ`
is not actually an argument to the compiler, but forces the shell to execute pkg-config with arguments and uses the output of that execution, which is used as commands for the compiler. I suggest you only enter the pkg-config command into your shell to see what it outputs. For example. on my laptop
dw@narfi ~/ % pkg-config --libs --cflags gtk+-3.0
-pthread -I/usr/include/gtk-3.0 -I/usr/include/at-spi2-atk/2.0
-I/usr/include/gtk-3.0 -I/usr/include/gio-unix-2.0/ -I/usr/include/cairo
-I/usr/include/pango-1.0 -I/usr/include/harfbuzz -I/usr/include/pango-1.0
-I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pixman-1
-I/usr/include/freetype2 -I/usr/include/libdrm -I/usr/include/gdk-pixbuf-2.0
-I/usr/include/libpng16 -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include
-lgtk-3 -lgdk-3 -lpangocairo-1.0 -lpango-1.0 -latk-1.0 -lcairo-gobject -lcairo
-lgdk_pixbuf-2.0 -lgio-2.0 -lgobject-2.0 -lglib-2.0
and these are the actual arguments passed to the compiler.
CMake is not a shell. It has its own package detection and configuration mechanism. See @kdopen's answer for details.
source to share