最近因为一些学习的原因,需要使用一款跨平台的轻量级的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. RabbitMQ基础学习Full版

    RabbitMQ 消息队列在软件中的应用场景 异步处理上(优于原先的方式) 为什么优于呢? 首先,通常情况下,如上图我们其实不用消息队列的情况下,其实也可以不用100ms,不用allof即可 那么优势 ...

  2. public private protected 的辨析

    一. public 1.作为类内成员的访问修饰符时,由public修饰的成员数据或者成员函数可以在类外(即派生类内以及实例化的对象后)以及类内进行随意访问 可以看到public成员Data在类外是可访 ...

  3. Vue3学习(16) - 左侧显示分类菜单

    写在前面 和大家不太一样,我觉得今年的自己更加relax,没有亲戚要走,没有朋友相聚,也没有很好的哥们要去叙旧,更没有无知的相亲,甚至可以这么说没有那些闲得慌的邻居. 也可以说是从今天开始,算是可以进 ...

  4. ARM指针寄存器——堆栈指针寄存器SP、程序计数器PC、连接寄存器LR详解

    堆栈的实现方法    在随机存储器区划出一块区域作为堆栈区,数据可以一个个顺序地存入(压入)到这个区域之中,这个过程称为'压栈'(push ).通常用一个指针(堆栈指针 SP-StackPointer ...

  5. 【framework】ATMS启动流程

    1 前言 ​ ATMS 即 ActivityTaskManagerService,用于管理 Activity 及其容器(任务.堆栈.显示等).ATMS 在 Android 10 中才出现,由原来的 A ...

  6. Shiro实战1-介绍

    什么是 Shiro 官网:http://shiro.apache.org/ shiro是一款主流的 Java 安全框架,不依赖任何容器,可以运行在 Java SE和 Java EE 项目中,它的主要作 ...

  7. OCP试题解析之053-61 RMAN set command id to

    61.You frequently have multiple RMAN sessions running, and you want to be able to easily identify ea ...

  8. 【Azure 环境】各种语言版本或命令,发送HTTP/HTTPS的请求合集

    问题描述 写代码的过程中,时常遇见要通过代码请求其他HTTP,HTTPS的情况,以下是收集各种语言的请求发送,需要使用的代码或命令 一:PowerShell Invoke-WebRequest htt ...

  9. 【Azure Notification Hub】创建Notification Hub失败,提示 unrecognized arguments: --sku Free

    问题描述 用Azure CLI命令创建 Notification Hub,报错不识别的参数 --Free SKU 问题解答 经测试发现,在创建Notification Hub前,需要创建 Notifi ...

  10. 【Azure 环境】当Azure Key Vault中存储的证书即将过期时,如何设置Alert邮件警报?

    问题描述 当Azure Key Vault 中存储的证书即将过期时, 如何设置Alert邮件警报? 问题解答 首先,在创建完一个证书后,需要为证书添加一个"证书联系人" 然后,点击 ...