I have a software project that works with C, Gtk4 and CMake. I am relatively new to working with these pieces and haven’t discovered much documentation on how to properly make use of CMake.
I have somehow pieced together a CMakeLists.txt and have a good start on the software architecture intermingling with each other, but I still have many questions…
The specific focus of this thread is getting my Gtk4 project working with Signal Handlers and to do that I need to include gmodule-export-2.0 according to their documentation.
So far I have included that with find_package
pkg_check-modules by following the examples and past included libraries, but I don’t think I added the necessary flags.
I searched the web for clean Gtk4 CMakeLists.txt examples with Signal Handlers implemented, but haven’t found anything that resonated with me.
I also tried doing set(CMAKE_EXECUTABLE_ENABLE_EXPORTS TRUE)
, but am a bit baffled in the differences of setting that command and or including the C_Flags.
Signal handlers and function pointers
“applications should instead be compiled with the -Wl,–export-dynamic argument inside their compiler flags, and linked against gmodule-export-2.0.”
Below, I have added my current CMakeLists.txt file.
# This is a Drogon Content Management System(CMS) built on GTK4.
# Copyright (C) 2024-PRESENT SHARPETRONICS, LLC
# Copyright (C) 2024-PRESENT ODINZU WENKI(CHARLES)
# This is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# This software is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# Under Section 7 of GPL version 3, you are granted additional
# permissions described in the GCC Runtime Library Exception, version
# 3.1, as published by the Free Software Foundation.
#
# You should have received a copy of the GNU General Public License along with
# this program; see the files LICENSE and LICENSE_EXCEPTION respectively.
# If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# AUTHORED DATE: 01.14.2024
# Almost all CMake files should start with this
# You should always specify a range with the newest
# and oldest tested versions of CMake. This will ensure
# you pick up the best policies.
cmake_minimum_required(VERSION 3.1...3.28)
file(GLOB_RECURSE SOURCES RELATIVE ${CMAKE_SOURCE_DIR} "src/*.c")
# If you set any CMAKE_ variables, that can go here.
# (But usually don't do this, except maybe for C++ standard)
set(CMAKE_PROJECT_DESCRIPTION "A GTK Drogon CMS")
set(CMAKE_PROJECT_HOMEPAGE_URL "https://github.com/odinzu/drogoncms")
set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/vendors/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Adds support for working with Gtk4 <signals> and Cambalache
# https://cmake.org/cmake/help/latest/variable/CMAKE_EXECUTABLE_ENABLE_EXPORTS.html
set(CMAKE_EXECUTABLE_ENABLE_EXPORTS TRUE)
# add CPM Deps. for C
# Note: only packages that have a CMakeLists.txt..
include(vendors/cmake/CPM_0.38.7.cmake)
#CPMAddPackage("gh:postgres/postgres#7.1.3")
#CPMAddPackage("gh:nlohmann/json@3.10.5")
# This is your project statement. You should always list languages;
# Listing the version is nice here since it sets lots of useful variables
# we removed LANGUAGES C from project to allow for automatic compiler/linker checks; we will use C and C++ libraries for this project.
project(
DrogonCMS
VERSION 1.0.0
)
# Adding something we can run - Output name matches target name
add_executable(DrogonCMS ${SOURCES})
#===============================================================================
# Setting compilation flags for various compilers and build types:
#===============================================================================
# some test warning levels for GCC
set(WARNING_LEVELS_GCC
#-Werror
)
set(WARNING_LEVELS_GCC_DEBUG
#-Wfloat-equal
#-Wextra
-Wall
-Wdeprecated-declarations
#-Wundef
#-Wshadow
#-Wpointer-arith
#-Wcast-align
#-Wstrict-overflow=5
#-Wwrite-strings
#-Waggregate-return
#-Wcast-qual
#-Wswitch-default
#-Wswitch-enum
#-Wconversion
)
# Print system, compiler CMake ID, version and path:
#message(STATUS "System: ${CMAKE_SYSTEM_NAME} ${CMAKE_SYSTEM_VERSION} ${CMAKE_SYSTEM_PROCESSOR}")
#message(STATUS "Compiler: ${CMAKE_Fortran_COMPILER_ID} ${CMAKE_Fortran_COMPILER_VERSION} ${CMAKE_Fortran_COMPILER}")
#message(STATUS "Build type is: ${CMAKE_BUILD_TYPE}")
#===============================================================================
# Default build type is release
# Uncomment this to debug or use "cmake -D CMAKE_BUILD_TYPE=debug .."
#===============================================================================
# External projects go here i.e. a project that isn't using cmake build
#include(ExternalProject)
#ExternalProject_Add(PostgreSQL
# GIT_REPOSITORY https://github.com/postgres/postgres.git
# GIT_TAG REL_16_1
# SOURCE_DIR ${CMAKE_SOURCE_DIR}/vendors/database/
# CONFIGURE_COMMAND ./configure
# CMAKE_ARGS ""
# INSTALL_COMMAND ""
# BUILD_IN_SOURCE 1
# BUILD_COMMAND $(MAKE) MAKELEVEL=0
# LOG_CONFIGURE 1
# LOG_BUILD 1
# LOG_INSTALL 1
#)
# set(CMAKE_BUILD_TYPE debug)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug CACHE STRING
"Choose build type: None Debug Release"
FORCE)
endif()
# Find PkgConfig.
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK4 REQUIRED gtk4>=4.16.5)
message("GTK4 include dir: ${GTK4_INCLUDE_DIRS}")
message("GTK4 libraries: ${GTK4_LIBRARY_DIRS}")
message("GTK4 other Cflags: ${GTK4_CFLAGS_OTHER}")
pkg_check_modules(ADW REQUIRED libadwaita-1>=1.6.1)
message("ADW include dir: ${ADW_INCLUDE_DIRS}")
message("ADW libraries: ${ADW_LIBRARY_DIRS}")
message("ADW other Cflags: ${ADW_CFLAGS_OTHER}")
pkg_check_modules(GMODULE-EXPORT-2.0 REQUIRED gmodule-export-2.0>=2.82.2)
message("GMODULE-EXPORT-2.0 include dir: ${GMODULE-EXPORT-2.0_INCLUDE_DIRS}")
message("GMODULE-EXPORT-2.0 libraries: ${GMODULE-EXPORT-2.0_LIBRARY_DIRS}")
message("GMODULE-EXPORT-2.0 other Cflags: ${GMODULE-EXPORT-2.0_CFLAGS_OTHER}")
message(STATUS "Flags: ${CMAKE_C_FLAGS}")
#pkg_check_modules(SSL REQUIRED openssl>=3.1.2)
#message("SSL libraries: ${SSL_LIBRARY_DIRS}")
#pkg_check_modules(SSL REQUIRED zlib>=1.3)
# Make use of PostgreSQL if FOUND, else use SQLite3
find_package (PostgreSQL)
if (PostgreSQL_FOUND)
message("POSTGRESQL include dir: ${PostgreSQL_INCLUDE_DIRS}")
message("POSTGRESQL libraries: ${PostgreSQL_LIBRARIES}")
include_directories(${PostgreSQL_INCLUDE_DIRS} ${PostgreSQL_SERVER_INCLUDE_DIRS})
target_link_libraries (${PROJECT_NAME} PUBLIC ${PostgreSQL_LIBRARIES})
#pkg_check_modules(SQLite3 REQUIRED sqlite3>=3.43.1)
elseif (SQLITE3_FOUND)
find_package (SQLite3)
message("SQLITE3 include dir: ${SQLITE3_INCLUDE_DIRS}")
message("SQLITE3 libraries: ${SQLITE3_LIBRARIES}")
include_directories(${SQLITE3_INCLUDE_DIRS})
target_link_libraries (${PROJECT_NAME} PUBLIC ${SQLITE3_LIBRARIES})
endif (PostgreSQL_FOUND)
# Setup CMake to use GTK+, tell the compiler where to look for headers
# and to the linker where to look for libraries
include_directories(${GTK4_INCLUDE_DIRS} ${ADW_INCLUDE_DIRS} ${GMODULE-EXPORT-2.0_INCLUDE_DIRS})
link_directories(${GTK4_LIBRARY_DIRS} ${ADW_LIBRARY_DIRS} ${GMODULE-EXPORT-2.0_LIBRARY_DIRS})
add_definitions(${GTK4_CFLAGS_OTHER} ${ADW_CFLAGS_OTHER} ${GMODULE-EXPORT-2.0_CFLAGS_OTHER})
# Include the local drogon server source code for testing and development
add_subdirectory(vendors/api-server/)
add_subdirectory(vendors/simple-reverse-proxy/)
# This is a "default" library, and will match the *** variable setting.
# Other common choices are STATIC, SHARED, and MODULE
# Including header files here helps IDEs but is not required.
# Output libname matches target name, with the usual extensions on your system
#add_library(MyLibExample simple_lib.cpp simple_lib.hpp)
# Link each target with other targets or add options, etc.
# Make sure you link your targets with this command. It can also link libraries and
# even flags, so linking a target that does not exist will not give a configure-time error.
target_include_directories(${PROJECT_NAME} PUBLIC ${GTK4_LIBRARIES} ${ADW_LIBRARIES} ${GMODULE-EXPORT-2.0_LIBRARIES})
target_link_libraries(${PROJECT_NAME} PRIVATE ${GTK4_LIBRARIES} ${ADW_LIBRARIES} ${GMODULE-EXPORT-2.0_LIBRARIES})
# Target Compile Options
target_compile_options(${PROJECT_NAME} PRIVATE ${WARNING_LEVELS_GCC} $<$<CONFIG:DEBUG>:${WARNING_LEVELS_GCC_DEBUG}>)
#===============================================================================
# Package generation:
#===============================================================================
#set(CPACK_PACKAGE_CHECKSUM SHA256)
#set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE")
#set(CPACK_RESOURCE_FILE_README "${PROJECT_SOURCE_DIR}/README.md")
#set(CPACK_GENERATOR "TGZ")
#set(CPACK_SOURCE_GENERATOR "TGZ")
#include(CPack)
#===============================================================================
# Add subdirectories to build:
#===============================================================================
#add_subdirectory(src)
# include directory for third party libraries
include_directories(vendors/)
###############################################################################
## PACKAGING ##################################################################
###############################################################################
# all install commands get the same destination. this allows us to use paths
# relative to the executable.
#install(TARGETS example DESTINATION example_destination)
# this is basically a repeat of the file copy instruction that copies the
# resources in the build directory, but here we tell CMake that we want it
# in the package
#install(DIRECTORY resources DESTINATION example_destination)
#set(CPACK_PACKAGE_CHECKSUM SHA256)
#set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE")
#set(CPACK_RESOURCE_FILE_README "${PROJECT_SOURCE_DIR}/README.md")
#set(CPACK_GENERATOR "TGZ")
#set(CPACK_SOURCE_GENERATOR "TGZ")
# now comes everything we need, to create a package
# there are a lot more variables you can set, and some
# you need to set for some package types, but we want to
# be minimal here
#set(CPACK_PACKAGE_NAME "MyExample")
#set(CPACK_PACKAGE_VERSION "1.0.0")
# we don't want to split our program up into several things
#set(CPACK_MONOLITHIC_INSTALL 1)
# This must be last
#include(CPack)