You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为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修饰符,让它成为全局可见的函数即可解决问题:

  1. 修改gui/mainwindow.h,移除声明中的static:
#include <gtk/gtk.h>

void activate_mainwindow(GtkApplication *app, gpointer user_data);
  1. 修改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));
}
  1. 重新执行构建流程:
cd build
make clean
cmake ..
make

修改后,activate_mainwindow成为全局函数,main.c所在的编译单元就能在链接阶段找到它的实现,链接错误即可消除。你的CMake配置本身没有问题,只需保证函数作用域正确即可正常链接GTK4库和自定义的gui库。

内容的提问来源于stack exchange,提问作者Dima

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 06:30:01