如何为C语言CMake项目创建库?GTK4应用编译链接错误求助
解决GTK4 C应用CMake构建的链接错误
问题背景
使用CMake构建GTK4 C语言应用时,CMake配置执行成功,但运行make时出现链接错误,提示activate_mainwindow函数未定义。项目包含根目录的main.c和gui子目录的窗口实现代码。
相关文件内容
main.c
#include "mainwindow.h" int main(int argc, char *argv[]){ GtkApplication *app; int status; app = gtk_application_new("org.tasklist", G_APPLICATION_DEFAULT_FLAGS); g_signal_connect(app, "activate", G_CALLBACK(activate_mainwindow), NULL); status = g_application_run(G_APPLICATION(app), argc, argv); g_object_unref(app); return status; }
根目录CMakeLists.txt
cmake_minimum_required(VERSION 3.31.5) project(tasklist LANGUAGES C) add_executable(tasklist main.c) add_subdirectory(gui) target_link_libraries(tasklist PUBLIC gui) target_include_directories(tasklist PUBLIC "${PROJECT_BINARY_DIR}" "${PROJECT_SOURCE_DIR}/gui" )
gui目录CMakeLists.txt
add_library(gui mainwindow.c) find_package(PkgConfig REQUIRED) pkg_check_modules(GTK4 REQUIRED IMPORTED_TARGET gtk4) target_link_libraries(gui PUBLIC PkgConfig::GTK4)
mainwindow.h
#include <gtk/gtk.h> static void activate_mainwindow(GtkApplication *app, gpointer user_data);
mainwindow.c
#include "mainwindow.h" static void activate_mainwindow(GtkApplication *app, gpointer user_data){ GtkWidget *window; window = gtk_application_window_new (app); gtk_window_set_title (GTK_WINDOW (window), "Window"); gtk_window_set_default_size (GTK_WINDOW (window), 200, 200); gtk_window_present (GTK_WINDOW (window)); }
编译错误信息
make -C ./build make: Entering directory '/home/dima/programming/side-projects/tasklist/build' [ 50%] Built target gui [ 75%] Building C object CMakeFiles/tasklist.dir/main.c.o In file included from /home/dima/programming/side-projects/tasklist/main.c:1: /home/dima/programming/side-projects/tasklist/gui/mainwindow.h:3:13: warning: ‘activate_mainwindow’ used but never defined 3 | static void activate_mainwindow(GtkApplication *app, gpointer user_data); | ^~~~~~~~~~~~~~~~~~~ [100%] Linking C executable tasklist /usr/bin/ld: CMakeFiles/tasklist.dir/main.c.o: warning: relocation against `activate_mainwindow' in read-only section `.text' /usr/bin/ld: CMakeFiles/tasklist.dir/main.c.o: in function `main': main.c:(.text+0x3f): undefined reference to `activate_mainwindow' /usr/bin/ld: warning: creating DT_TEXTREL in a PIE collect2: error: ld returned 1 exit status make[2]: *** [CMakeFiles/tasklist.dir/build.make:114: tasklist] Error 1 make[1]: *** [CMakeFiles/Makefile2:109: CMakeFiles/tasklist.dir/all] Error 2 make: *** [Makefile:91: all] Error 2 make: Leaving directory '/home/dima/programming/side-projects/tasklist/build'
错误原因
C语言中,static修饰的函数仅在当前编译单元(单个.c文件)内可见。这里activate_mainwindow被声明为static,它的实现位于gui/mainwindow.c编译单元中,而main.c是独立的编译单元,虽然包含了头文件的声明,但链接阶段无法跨编译单元访问到这个static函数的实现,因此出现未定义错误。
修复步骤
直接去掉activate_mainwindow的static修饰符,让它成为全局可见的函数即可解决问题:
- 修改
gui/mainwindow.h,移除声明中的static:
#include <gtk/gtk.h> void activate_mainwindow(GtkApplication *app, gpointer user_data);
- 修改
gui/mainwindow.c,移除定义中的static:
#include "mainwindow.h" void activate_mainwindow(GtkApplication *app, gpointer user_data){ GtkWidget *window; window = gtk_application_window_new (app); gtk_window_set_title (GTK_WINDOW (window), "Window"); gtk_window_set_default_size (GTK_WINDOW (window), 200, 200); gtk_window_present (GTK_WINDOW (window)); }
- 重新执行构建流程:
cd build make clean cmake .. make
修改后,activate_mainwindow成为全局函数,main.c所在的编译单元就能在链接阶段找到它的实现,链接错误即可消除。你的CMake配置本身没有问题,只需保证函数作用域正确即可正常链接GTK4库和自定义的gui库。
内容的提问来源于stack exchange,提问作者Dima
相关产品推荐
相关产品推荐

