最近因为一些学习的原因,需要使用一款跨平台的轻量级的GUI+图像绘制 C/C++库。经过一番调研以后,最终从GTK+、FLTK中选出了FLTK,跨平台、够轻量。本文将在Windows、macOS以及Linux Debian三套操作系统环境,对FLTK进行编译,并搭建简单Demo。这其中也有少许的坑,也在此文进行记录。

前期准备

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>
^~~~~~~~~~~~~~~~~~

库、头文件准备总结

至此,我们准备好了:

  1. build/lib下的fltk相关静态库(.a/.lib );

  2. 在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目录

  1. 将上一步中的fltk-dist-1.3.8文件夹整体复制到fltk-demo目录中
  2. 项目根目录创建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();
}
  1. 创建一个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)的更多相关文章

  1. 判断OpenCV是否为共享库,Windows基于CMake编译Caffe需要opencv共享库

    判断OpenCV是否为共享库,Windows基于CMake编译Caffe需要opencv共享库 TLDR 只考虑windows下opencv预编译包的情况. 对于opencv2.4.x系列,cmake ...

  2. 基于cmake编译安装MySQL-5.5

    cmake的重要特性之一是其独立于源码(out-of-source)的编译功能,即编译工作可以在另一个指定的目录中而非源码目录中进行,这可以保证源码目录不受任何一次编译的影响,因此在同一个源码树上可以 ...

  3. 基于cmake编译glew

    cmake已经成为了C/C++开源项目的主流构建工具.glew也提供了cmake的脚本,但用cmake编译glew容易采坑:glew的github上的代码,无论是master分支还是glew-2.1. ...

  4. cmake编译opencv时指定cuda版本

    之前有网友提问说,基于cmake编译时如果切换cuda版本,比如我同时装了cuda8和cuda9,opencv总是找到cuda9,我想用cuda8怎么办?实际上,手头上要配置的工程是基于opencv3 ...

  5. windows10下vscode+cmake编译Qt5代码

    概述 本文演示环境: windows10 cmake version:3.18 qt version: 5.14 vscode version: 1.54.1 本文演示环境基于在线模式, 离线使用VS ...

  6. Unity跨平台C/CPP动态库编译---可靠UDP网络库kcp基于CMake的各平台构建实践

    1.为什么需要动态库 a)提供原生代码(native code)的支持,也叫原生插件,但是我实践的是c/cpp跨平台动态库,这里不具体涉及安卓平台java库和ios平台的objectc库构建. b)某 ...

  7. 基于Cmake+QT+VS的C++项目构建开发编译简明教程

    目录 一.工具下载与安装 1.     Qt 2.     Visual Studio 2015 3.     Cmake 二.C++及Qt项目构建 1.     基于VS构建Qt项目 2.     ...

  8. Unity3D跨平台动态库编译---记kcp基于CMake的各平台构建实践

    一 为什么需要动态库 1)提供原生代码(native code)的支持,也叫原生插件,但是我实践的是c/cpp跨平台动态库,这里不具体涉及安卓平台java库和ios平台的objectc库构建. 2)某 ...

  9. Windows下使用mingw+cmake编译C/C++程序

    按照正常流程安装好mingw和cmake后,仍然是无法直接使用cmake编译处MakeFile文件的,我们需要在CMakeLists.txt中做一些配置. 首先,在PROJECT之前,设置: SET( ...

  10. cmake 编译windows程序

    cmake 编译windows程序 cmake 编译windows程序 cmake 编译windows程序 尽量使用  尽量使用 尽量使用 https://www.cnblogs.com/liujia ...

随机推荐

  1. Nginx实战-公网LB限流配置等

    前提: Nginx要实现根据ip地址进行限流与不限流的区分需要通过源码包安装GeoIP模块 找到与yum安装版本相同的源码包,通过configure进行安装 ./configure --prefix= ...

  2. NC50243 小木棍

    题目链接 题目 题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50.现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度.给出每段小木 ...

  3. NC16655 [NOIP2005]过河

    题目链接 题目 题目描述 在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧.在桥上有一些石子,青蛙很讨厌踩在这些石子上.由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙可 ...

  4. Office Online Server Windows Server 2016 部署

    一.准备"武器" 本文是通过虚拟机搭建 OOS 测试环境的,4567是3的前提,武器提取 le73 1.VMWare Workstation 17 Player 2.Windows ...

  5. Apache HTTP Server、IIS反向代理设置

    Apache HTTP Server 在 Apache 中设置反向代理,需要使用 mod_proxy 和相关的模块,如 mod_proxy_http.以下是一个基本的配置示例: 确保已经安装并启用了  ...

  6. Lambda 表达式总结

    1 Lambda 表达式简介 ​ Lambda 表达式是 JDK 8 的新特性,主要用于简化匿名内部类的定义,帮助用户方便.高效地书写优雅的代码. ​ Lambda 表达式实现的必须是一个接口,并且接 ...

  7. Python之初级RPG小游戏

    在国外网站上找到一个练习Python的小游戏感觉不错,自己实现了一下. 通过该练习你能学到: 元组 字典 简单定义函数和封装 条件控制语句 游戏说明 以下是3个房间和1个花园: Hall 客厅 有一把 ...

  8. WriteFile 奇怪的现象

    项目中有个需求是要对文本内容检索并重写,我们使用的是 WriteFile 覆盖旧的文本内容 最小示例: #include <Windows.h> #include <iostream ...

  9. VS2019 添加三方文件夹遇到的坑

    在开发新项目时需要用到一些三方 API,这些三方 API 没有生成 lib,所以我们在 VS 编译器中添加这些三方文件夹的头文件路径后 会出现 ERROR LNK2019 的错误提示,这些提示通常都是 ...

  10. MySQL Boolean类型的坑

    MySQL中,Boolean只是 tinyint(1) 的别名,也就是说,MySQL中并没有真正的bool类型. 而SQLAlchemy生成SQL的时候并没有检测到 这一点,这就导致一个问题,当使用 ...