FLTK基于cmake编译以及使用(Windows、macOS以及Linux)
最近因为一些学习的原因,需要使用一款跨平台的轻量级的GUI+图像绘制 C/C++库。经过一番调研以后,最终从GTK+、FLTK中选出了FLTK,跨平台、够轻量。本文将在Windows、macOS以及Linux Debian三套操作系统环境,对FLTK进行编译,并搭建简单Demo。这其中也有少许的坑,也在此文进行记录。
前期准备
- FLTK 1.3.8(最新稳定版)FLTK 1.3.8: FLTK Programming Manual
- CMake 3.5+
- Windows 11(VS2022)/ macOS 12.6 / Linux Debian 11
- CLion工具
PS:后续操作系统差异带来的配置/代码差异我会特别指明
编译FLTK
编译静态库文件
首先从官方地址下载FLTK 1.3.8代码:Download - Fast Light Toolkit (FLTK)。
下载完成后,将文件内容解压至某个自定义目录,例如在macOS下,我存放在"用户主目录/Projects/third-lib-projects/fltk-1.3.8"目录。
进入该目录后,我们创建一个build目录,并进入build目录,然后使用CMake进行配置。
上述一些列命令操作整理如下:
# 进入fltk跟目录
cd "用户主目录/Projects/third-lib-projects/fltk-1.3.8"
# 创建 build 文件夹
mkdir build
# 进入 build 文件夹
cd build
# 执行 cmake 配置操作(注意,cmake后面跟空格,再跟"..",cmake中"外部构建"方式)
# 执行该命令前,请先阅读下面的cmake前置条件
cmake ..
# Windows下建议使用PowerShell,上述的命令基本没有差别。
cmake配置前置条件
Windows
无
macOS
无
Linux
在Linux下,使用cmake进行项目生成前,务必确保一些基础库的安装:
# 安装gcc/g++等核心开发构建工具和库(必备)
sudo apt-get install build-essential
# openGL库安装(可选,建议。OpenGL的Library、Utilities以及ToolKit)
sudo apt-get install libgl1-mesa-dev
sudo apt-get install libglu1-mesa-dev
sudo apt-get install freeglut3-dev
# openSSL库(可选)
sudo apt-get install libssl-dev
# x11库(必备)
sudo apt-get install libx11-dev
对于必备的X11库,安装完成后是以动态链接库(.so)的方式存放于/usr/lib/x86_64-linux-gnu/libX11.so。在上面的cmake ..命令执行后,你也会看到控制台输出的一些关键内容:
# cmake .. 执行后的输出内容
... ...
-- Looking for XOpenDisplay in /usr/lib/x86_64-linux-gnu/libX11.so; ... - found
... ...
调用对应平台工具链完成FLTK编译
cmake进行项目构建完成后,在我们当前的build目录中,对于macOS/Linux类操作系统,CMake会为我们生成了对应的makefile文件,所以我们直接使用make命令调用本地的clang或则gcc进行编译。
# 在build目录下,默认就是release版
make
在Windows操作系统,请直接使用vs打开build中的解决方案FLTK.sln,打开后对项目ALL_BUILD进行Release模式编译。
编译完成后,build目录中会生成一个lib文件夹,这里面存放的就是fltk编译出来的静态链接库。
在macOS/Linux中是lib前缀,.a结尾:
# macOS/Linux(Release模式)
build/lib
├── libfltk.a
└── ... ...
在windows中是.lib结尾:
# Windows(Release模式文件名结尾不会有"d")
build/lib
└── Release
├── fltk.lib
└── ... ...
准备头文件
对于我的方式,在build文件夹中,我们创建一个inlude文件夹,并且将build上一层的fltk根目录中的FL文件夹复制到build/include中,形成如下结构:
build/include
└── FL
├── Enumerations.H
├── FL.H
└── ... ...
注意,请同时务必将build目录下FL/abi-version.h复制到include/FL/abi-version.h。原因在于FL.h -> Enumerations.h头文件会用到该头文件里面的一些定义,不添加则会报错:
fatal error: 'FL/abi-version.h' file not found
#include <FL/abi-version.h>
^~~~~~~~~~~~~~~~~~
库、头文件准备总结
至此,我们准备好了:
build/lib下的fltk相关静态库(
.a/.lib);在build/include里面的头文件。
为了方便我们后续的使用,创建一个文件夹fltk-dist-1.3.8,并将lib、include复制到dist中:
fltk-dist-1.3.8/
include
└── FL
├── Enumerations.H
├── FL.H
└── ... ...
lib
└── macOS-release
├── libfltk.a
└── ... ...
└── linux-release
├── libfltk.a
└── ... ...
└── Windows-release
├── fltk.lib
└── ... ...
基础项目搭建
创建一个名为fltk-demo目录
- 将上一步中的fltk-dist-1.3.8文件夹整体复制到fltk-demo目录中
- 项目根目录创建src文件夹,并在其中创建main.cpp:
#include <iostream>
#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Box.H>
int main (int argc, char *argv[]) {
Fl_Window *window;
Fl_Box *box;
window = new Fl_Window(300, 180);
window->label("HelloWorld!");
box = new Fl_Box(20, 40, 260, 100, "Hello World!");
box->box(FL_UP_BOX);
box->labelsize(36);
box->labelfont(FL_BOLD + FL_ITALIC);
(FL_SHADOW_LABEL);
window->end();
window->show(argc, argv);
return Fl::run();
}
- 创建一个CMakeLists.txt内容:
CMAKE_MINIMUM_REQUIRED(VERSION 3.23)
PROJECT(fltk_demo)
SET(CMAKE_CXX_STANDARD 11)
# 可执行程序名称,下面统一使用
SET(my_app_name fltk_demo)
# 指定头文件查找目录
INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/fltk-dist-1.3.8/include")
# 将src下面的所有头文件路径保存至 all_head_files 数组变量中
# 将src下面的所有源文件路径保存至 all_source_files 数组变量中
FILE(GLOB_RECURSE all_source_files "src/*.cpp" "src/*.c")
FILE(GLOB_RECURSE all_head_files "src/*.hpp" "src*.h")
# 指定库文件查找路径,根据操作系统区分:
IF (CMAKE_SYSTEM_NAME MATCHES "Windows")
# Windows 操作系统,需要查找 Windows-release
MESSAGE(STATUS "current platform: Windows")
LINK_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/fltk-dist-1.3.8/lib/Windows-release")
ADD_EXECUTABLE(
${my_app_name}
WIN32 # Windows 非命令行程序
${all_head_files}
${all_source_files}
)
TARGET_LINK_LIBRARIES(
${my_app_name}
PRIVATE
fltk # 链接的静态库名称,这里只需要写fltk,在运行时自动查找.a/.lib
)
ELSEIF (CMAKE_SYSTEM_NAME MATCHES "Darwin")
# macOS 操作系统,查找 macOS-release
MESSAGE(STATUS "current platform: macOS")
LINK_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/fltk-dist-1.3.8/lib/macOS-release")
ADD_EXECUTABLE(
${my_app_name}
${all_head_files}
${all_source_files}
)
TARGET_LINK_LIBRARIES(
${my_app_name}
PRIVATE
fltk # 链接的静态库名称,这里只需要写fltk,在运行时自动查找.a/.lib
# macOS 该选项必填
"-framework Cocoa"
)
ELSEIF (CMAKE_SYSTEM_NAME MATCHES "Linux")
# Linux 操作系统,查找 Linux-release
MESSAGE(STATUS "current platform: Linux ")
LINK_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/fltk-dist-1.3.8/lib/Linux-release")
ADD_EXECUTABLE(
${my_app_name}
${all_head_files}
${all_source_files}
)
TARGET_LINK_LIBRARIES(
${my_app_name}
PRIVATE
fltk # 链接的静态库名称,这里只需要写fltk,在运行时自动查找.a/.lib
X11 # Linux环境需要指定X11以及dl两个库才能正常显示
dl
)
ELSE ()
# 其他操作系统
MESSAGE(STATUS "other platform: ${CMAKE_SYSTEM_NAME}")
ENDIF ()
对于CMake的配置,我们针对不同的操作系统,我们从dist中指定的操作系统的目录查找静态库文件。此外,还有一些需要注意的:
Windows
Windows操作系统中,请在ADD_EXECUTABLE的应用名称后面添加WIN32,否则部分Windows操作系统窗口显示的时候,还会有一个命令行界面显示出来。
macOS
macOS操作系统中,请在TARGET_LINK_LIBRARIES最后添加参数:"-framework Cocoa",否则fltk链接过程会有如下报错:
[1/1] Linking CXX executable fltk_demo
FAILED: fltk_demo
: &&
... ...
Undefined symbols for architecture x86_64:
... ...
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
ninja: build stopped: subcommand failed.
Linux
对于Linux操作系统,由于桌面窗体程序是基于X11进行的,所以实际运行的过程中是依赖X11库的。所以,我们还需要将X11的动态库也链接到咱们程序。我们的Demo中的CMakeLists.txt针对Linux系统,如果不进行特殊处理,会出现如下类似的错误:
undefined reference to `XGetDefault'等类似问题
[ 50%] Building CXX object CMakeFiles/fltk_demo.dir/src/main.cpp.o
[100%] Linking CXX executable fltk_demo
/usr/bin/ld: /home/w4ngzhen/Desktop/fltk-demo/fltk-dist-1.3.8/lib/Linux-release/libfltk.a(Fl_get_system_colors.o): in function `getsyscolor(char const*, char const*, char const*, char const*, void (*)(unsigned char, unsigned char, unsigned char))':
Fl_get_system_colors.cxx:(.text._ZL11getsyscolorPKcS0_S0_S0_PFvhhhE+0x24): undefined reference to `XGetDefault'
/usr/bin/ld: Fl_get_system_colors.cxx:(.text._ZL11getsyscolorPKcS0_S0_S0_PFvhhhE+0x47): undefined reference to `XParseColor'
... ...
Fl_Double_Window.cxx:(.text._ZN16Fl_Double_Window4hideEv+0x21): undefined reference to `XFreePixmap'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/fltk_demo.dir/build.make:97: fltk_demo] Error 1
make[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/fltk_demo.dir/all] Error 2
make: *** [Makefile:91: all] Error 2
所以,我们需要进行配置,在链接阶段,链接X11动态链接库。
此外,除了X11库以外,我们还需要一个dl库。不配置则会有如下类似错误:
undefined reference to symbol 'dlsym@@GLIBC_2.2.5'
[ 50%] Building CXX object CMakeFiles/fltk_demo.dir/src/main.cpp.o
[100%] Linking CXX executable fltk_demo
/usr/bin/ld: /home/w4ngzhen/Desktop/fltk-demo/fltk-dist-1.3.8/lib/Linux-release/libfltk.a(Fl_Window_shape.o): undefined reference to symbol 'dlsym@@GLIBC_2.2.5'
/usr/bin/ld: /lib/x86_64-linux-gnu/libdl.so.2: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/fltk_demo.dir/build.make:97: fltk_demo] Error 1
make[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/fltk_demo.dir/all] Error 2
make: *** [Makefile:91: all] Error 2
综合来说,基于Linux环境下的CMakeLists.txt基础配置,和其他平台的差异体现在要增加额外的两个库:
TARGET_LINK_LIBRARIES(
${my_app_name}
PRIVATE
fltk # 链接的静态库名称,这里只需要写fltk,在运行时自动查找.a/.lib
+ X11 # Linux环境需要指定X11以及dl两个库才能正常显示
+ dl
)
效果演示
下图是本人分别在Windows、macOS以及Linux环境下的运行效果:

附录
本文项目代码已经提交至Github
w4ngzhen/fltk-demo (github.com)
FLTK基于cmake编译以及使用(Windows、macOS以及Linux)的更多相关文章
- 判断OpenCV是否为共享库,Windows基于CMake编译Caffe需要opencv共享库
判断OpenCV是否为共享库,Windows基于CMake编译Caffe需要opencv共享库 TLDR 只考虑windows下opencv预编译包的情况. 对于opencv2.4.x系列,cmake ...
- 基于cmake编译安装MySQL-5.5
cmake的重要特性之一是其独立于源码(out-of-source)的编译功能,即编译工作可以在另一个指定的目录中而非源码目录中进行,这可以保证源码目录不受任何一次编译的影响,因此在同一个源码树上可以 ...
- 基于cmake编译glew
cmake已经成为了C/C++开源项目的主流构建工具.glew也提供了cmake的脚本,但用cmake编译glew容易采坑:glew的github上的代码,无论是master分支还是glew-2.1. ...
- cmake编译opencv时指定cuda版本
之前有网友提问说,基于cmake编译时如果切换cuda版本,比如我同时装了cuda8和cuda9,opencv总是找到cuda9,我想用cuda8怎么办?实际上,手头上要配置的工程是基于opencv3 ...
- windows10下vscode+cmake编译Qt5代码
概述 本文演示环境: windows10 cmake version:3.18 qt version: 5.14 vscode version: 1.54.1 本文演示环境基于在线模式, 离线使用VS ...
- Unity跨平台C/CPP动态库编译---可靠UDP网络库kcp基于CMake的各平台构建实践
1.为什么需要动态库 a)提供原生代码(native code)的支持,也叫原生插件,但是我实践的是c/cpp跨平台动态库,这里不具体涉及安卓平台java库和ios平台的objectc库构建. b)某 ...
- 基于Cmake+QT+VS的C++项目构建开发编译简明教程
目录 一.工具下载与安装 1. Qt 2. Visual Studio 2015 3. Cmake 二.C++及Qt项目构建 1. 基于VS构建Qt项目 2. ...
- Unity3D跨平台动态库编译---记kcp基于CMake的各平台构建实践
一 为什么需要动态库 1)提供原生代码(native code)的支持,也叫原生插件,但是我实践的是c/cpp跨平台动态库,这里不具体涉及安卓平台java库和ios平台的objectc库构建. 2)某 ...
- Windows下使用mingw+cmake编译C/C++程序
按照正常流程安装好mingw和cmake后,仍然是无法直接使用cmake编译处MakeFile文件的,我们需要在CMakeLists.txt中做一些配置. 首先,在PROJECT之前,设置: SET( ...
- cmake 编译windows程序
cmake 编译windows程序 cmake 编译windows程序 cmake 编译windows程序 尽量使用 尽量使用 尽量使用 https://www.cnblogs.com/liujia ...
随机推荐
- 手把手带你上手swagger3
配置POM 只需要加一个依赖,并且要注意,swagger3在springboot2.5版本以上会出现问题 <dependency> <groupId>io.springfox& ...
- JDK + Tomcat 安装 + 制作自定义镜像【第 2.1 篇 Tomcat 日志满问题】
更好的方法,跨平台(不依赖平台,比如阿里云的后台)的方法是:spring boot 定时任务,直接在程序里写定时清除日志的任务:以后再说: ============================== ...
- ubuntu之jupyter notebook配置
ubuntu之jupyter notebook配置 安装jupyter: 前提:安装pip pip install jupyter jupyter notebook 配置: 生成配置文件: jupyt ...
- JS leetcode 反转字符串 题解分析
壹 ❀ 引 今天做的一道题非常简单,原题来自leetcode第344题反转字符串,题目如下: 编写一个函数,其作用是将输入的字符串反转过来.输入字符串以字符数组 char[] 的形式给出. 不要给另外 ...
- NC16541 [NOIP2013]车站分级
题目链接 题目 题目描述 一条单向的铁路线上,依次有编号为1, 2, -, n 的n 个火车站.每个火车站都有一个级别,最低为1 级.现有若干趟车次在这条线路上行驶,每一趟都满足如下要求:如果这趟车次 ...
- Python——检测Popen返回的stdOutMsg中是否是否包含指定字符,并提取指定位置的信息
问题背景: Python 中经常会需要通过subprocess.PoPen函数下发Shell Command,与操作系统进行交互.一些情况下,还需要分析shell command的返回值,提取有用信息 ...
- ElasticSearch入门安装与SpringBoot集成实战
介绍 Elasticsearch 是一个实时分布式搜索和分析引擎,一般用于全文搜索.结构化搜索,分析或者三者混用. 它的底层是基于Apache Lucene(TM)的开源搜索引擎,但是lucene只是 ...
- Fiddler捕获Java发送的HttpURLConnection请求
1.说明 平常使用Fiddler抓包工具查看浏览器的请求和响应信息很方便, 但有时候我们也需要拦截java代码执行的http请求. 以便更好的调试程序.具体方法如下: 2.编写Java代码 // 配置 ...
- 【Android逆向】脱壳项目frida_dump 原理分析
脱dex核心文件dump_dex.js 核心函数 function dump_dex() { var libart = Process.findModuleByName("libart.so ...
- Kotlin 协程四 —— Flow 和 Channel 的应用
目录 一. Flow 与 Channel 的相互转换 1.1 Flow 转换为 Channel 1.1.1 ChannelFlow 1.1.2 produceIn -- 将 Flow 转换为单播式 C ...