在上一期的文章中介绍了cmake这个可以跨平台的编译工具,为我们编译代码提供了方便。不过在那篇文章中的cmake代码尽管可以在不同的操作系统中运行,但是,却有两点不足之处:
没有添加需要链接的库;
在某些情况下,Windows操作系统和Linux操作系统所需要包含的头文件,以及链接库会有区别。因此,在这种情况下,需要对操作系统进行识别。
在这一期的文章中,将补充这两方面的内容。本文以《使用FLTK进行图形界面设计》这篇文章中的最后一个demo为例,来解释这个问题。这里将头文件包含、类的声明放置在了demo.h头文件中。将类的构造函数的定义放置在了mywindow.cpp文件中,main函数则单独放置在main.cpp文件中。下面是这三个文件的具体内容:
//demo.h#include #include #include #include #include #include #include using namespace std;class MyWindow : public Fl_Window{ public: Fl_Button *button; Fl_Check_Button *cButton; Fl_Return_Button *reButton; MyWindow(int w, int h, const char *t); ~MyWindow(){}};
//mywindow.cpp#include "demo.h"MyWindow :: MyWindow(int w, int h, const char *t): Fl_Window(w, h, t){ begin(); button = new Fl_Button(50, 50, 100, 50, "Fl_Button"); cButton = new Fl_Check_Button(50, 100, 100, 50, "Fl_Check_Button"); reButton = new Fl_Return_Button(50, 150, 200, 50, "Fl_Return_Button"); button->type(FL_NORMAL_BUTTON); cButton->type(FL_NORMAL_BUTTON); reButton->type(FL_NORMAL_BUTTON); end(); resizable(this); show();}
//main.cpp#include "demo.h"int main(){ MyWindow *win = new MyWindow(400, 300, "button fltk"); return Fl :: run();}
下面是 CMakeLists.txt 文档的具体内容,根据操作系统的不同,采取了不同的文件包含以及链接库的方法。
cmake_minimum_required(VERSION 3.5)project(hello)file(GLOB_RECURSE src_list ${PROJECT_SOURCE_DIR}/src/*.cpp)message(STATUS "operation system is ${CMAKE_SYSTEM}")if (CMAKE_SYSTEM_NAME MATCHES "Windows") message(STATUS "current platform: Windows") add_definitions(-Zi -W3 -WX- -Od -Oy- -DWIN32 -D_UNICODE -DUNICODE -Gm -RTC1 -MDd -GS -analyze-) set(EXTRA_LIBS Comctl32.lib) list(APPEND EXTRA_LIBS fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib) list(APPEND EXTRA_LIBS advapi32.lib shell32.lib ole32.lib ole32.lib oleaut32.lib uuid.lib) list(APPEND EXTRA_LIBS odbc32.lib odbccp32.lib) message("EXTRA_LIBS: ${EXTRA_LIBS}") set(CMAKE_EXE_LINKER_FLAGS /NODEFAULTLIB:"libcmtd.lib; libcmt.lib")elseif (CMAKE_SYSTEM_NAME MATCHES "Linux") message(STATUS "current platform: Linux") add_definitions(-g -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_THREAD_SAFE -D_REENTRANT) link_directories("/usr/local/lib") set(EXTRA_LIBS fltk) list(APPEND EXTRA_LIBS Xrender Xfixes Xext Xft fontconfig pthread dl m X11)endif (CMAKE_SYSTEM_NAME MATCHES "Windows")add_executable(hello ${src_list})if (CMAKE_SYSTEM_NAME MATCHES "Windows") message(STATUS "current platform: Windows") target_link_libraries(hello PUBLIC ${EXTRA_LIBS}) target_include_directories(hello PUBLIC "${PROJECT_SOURCE_DIR}/include")elseif (CMAKE_SYSTEM_NAME MATCHES "Linux") message(STATUS "current paltform: Linux") set(EXTRA_INCLUDES "/usr/local/include") list(APPEND EXTRA_INCLUDES "/usr/local/include/FL/images") list(APPEND EXTRA_INCLUDES "/usr/include/freetype2") list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/include") target_link_libraries(hello PUBLIC ${EXTRA_LIBS}) target_include_directories(hello PUBLIC ${EXTRA_INCLUDES})endif (CMAKE_SYSTEM_NAME MATCHES "Windows")
第4行的 message 函数可以打印字符串,CMAKE_SYSTEM 是包含了版本号的操作系统名称,而 CMAKE_SYSTEM_NAME 则是不包含了版本号的操作系统名称。message 函数中的 STATUS 关键字可以在输出的字符串中添加前缀“--”,在后面会看到这里的输出效果。第6行 if 语句中的 MATCHES 关键字可以用来判断左右两侧的字符串是否一致,这样就实现了对操作系统的识别。第9到12行是添加在 Windows 操作系统中需要链接的库,第30行的 target_link_libraries 函数则是在编译的时候将链接库添加到可执行文件中。
需要注意的是,在第19行,针对 Linux操作系统,使用了 link_directories 函数,它相当于在编译的时候添加的 -L 选项,目的是指定链接的路径。之所以没有在 Windows 系统下添加这行代码,是因为当时在 Windows 系统中配置 FLTK 的时候,直接将与 FLTK 有关的库放置到了 VS 的默认搜索路径下面。其他的语法在上一篇文章中已经介绍过,所以就不再详细介绍了。
进入 build 文件夹,运行 cmake .. 命令,如果是在 Windows 系统中,且安装了 VS 的话,则会生成 VS 工程,下图是运行这个命令的结果:
可以看到在屏幕上输出了文档中的字符串,有些字符串前面还添加了“--”作为前缀。再运行 cmake --build . 命令就可以在 Debug 目录下看到可执行文件了。经过测试,这套编译方法在 Linux 系统中也是可以编译并运行成功的。