Windows系统编译GSL2.7用于C语言编程(2022.5.8)
Windows系统利用MSYS2编译GSL库CodeBlocks和Visual Studio 皆可调用GSL库实现C语言相关运算
Windows系统编译GSL2.7用于C语言编程(2022.5.8)
1、 GSL(GNU Scientific Library)
1.1 GSL简介
GSL(GNU Scientific Library)是一个面向C
和C++
编程语言的数值计算库,它是GNU General Public License通用公共许可下的开放软件。GSL
库提供了大量的数学日常运算函数,涉及领域如随机数生成器、复数、向量、矩阵、排序、快速傅里叶变换、随机分布、统计、插值、离散小波变换、稀疏矩阵、线性代数、最小二乘拟合
等,还允许自己与他人自由分享程序,代码开源,开发者可对用户社区贡献改进代码。GSL
是在GNU/Linux
平台上由gcc编译器所开发,满足GNU Coding Standards标准,同时其源码已被证实可以在Linux(gcc编译器)、Unix(gcc编译器) 和 Microsoft Windows等平台进行编译使用,但Window
系统下编译较为困难,最好还是选择Linux
系统编译,便捷快速。
GSL
库具有以下五个特点:
- 采用面向对象的设计,不同的算法可以很容易地插入或在运行时更改,而无需重新编译程序;
- 面向普通用户,任何了解
C
编程的人都可立即开始使用该库; - 界面设计简单,可链接到非常高级的语言,如
GNU Guile
或Python
; - 具有线程安全性;
- 易于编译,且不依赖于其他包。
截至目前,GSL
已经发布了很多版本,从gsl-1.0
到gsl-2.7
,当前最新且稳定的版本为gsl-2.7
,各版本的下载地址有两个:https://mirrors.tripadvisor.com/gnu/gsl/和https://ftp.gnu.org/gnu/gsl/。官网的帮助文档地址有html 帮助文档、pdf 帮助文档和技术报告。
|
|
|
|
1.2 前人在Windows平台下已编译好的GSL库(版本太低)
进入Gsl for Windows网站可看到1.8版本的GSL
编译库,在该页面点击Complete package, except sources
右侧的Setup
,进入Gnu Win Files,下载gsl-1.8.exe
后安装并配置成功后应该就可使用了。
|
|
另外GSL
官网也明确指出一些开发者提供了一些方法可轻松地在Windows
平台上构建GSL
库,详情见Building GSL on Windows Using Native Tools中的四种方法。个人感觉前两种方法过于陈旧,而NuGet安装包的方法版本只到GSL2.3.0
,如果觉得版本还可以接受则可采用;个人感觉基于CMake
的方法可以尝试,毕竟其Star
数不少。
|
|
|
|
曾经的开发者们尽管采用了众多方法在Windows
上构建GSL
库,但这些方法已经编译的GSL
库版本太低,没有及时更新,或许无法满足个人对新版本GSL
库的需求,因此还是需要自己动手编译最新版本的GSL库(看个人喜好)。
2、Windows下利用MSYS2编译GSL库
2.1 MSYS2 简介
MSYS2并不是“一个统治所有人的工具”,而是试图专注于它擅长的东西。它提供了一个基于开源软件的本地构建环境,当用户已经熟悉Linux
时,它会让您感到宾至如归。有充分的理由在Windows上为不同的任务使用多种不同的环境和工具。MSYS2
是一个工具和库的集合,能为构建、安装和运行本机Windows
软件提供一个易于使用的Linux
环境。它包括一个名为mintty
、bash
的命令行终端、git
和subversion
等版本控制系统、tar
和awk
等工具,甚至还有autotools
等构建系统,所有这些都是基于Cygwin的修改版本。尽管其中一些核心部件基于Cygwin
,但MSYS2的重点是为本机Windows软件提供构建环境,并且使用Cygwin
的部件保持在最低限度。
MSYS2的包管理器为pacman
。MSYS2
软件发行版使用pacman
来管理(安装、删除和更新)二进制软件包,并首先构建这些软件包。MSYS2
中的包与流行的Linux
发行版中的包类似。软件包是包含一段软件的存档,这通常意味着可执行文件、运行库、数据、共享和静态链接库、头文件、配置文件和手册页。软件包还包含元数据,如软件名称、用途描述、版本号、供应商、校验和,以及软件正常运行所需的依赖项列表。
MSYS2
为GCC
、mingw-w64
、CPython
、CMake
、Meson
、OpenSSL
、FFmpeg
、Rust
、Ruby
等提供了最新的本机版本。为了方便安装软件包并保持更新,它提供了一个名为Pacman的软件包管理系统,Arch Linux用户应该熟悉该系统。它带来了许多强大的功能,如依赖解析和简单的完整系统升级,以及直接和可复制的包构建,软件包存储库包含2500多个准备安装的预构建软件包。安装后,包含的文件将被提取到MSYS2
安装目录中,元数据存储在本地数据库中。它有6个软件包存储库,如经典的msys2、mingw32和mingw64,以及更新的ucrt64、clang32和clang64。msys2
中的包与Linux
发行版中的包一样命名,其他版本中的包的前缀为mingw-w64-i686
(适用于32位包)或mingw-w64-x86_64
(适用于带有辅助前缀clang
或ucrt
的64位包)。
2.2 Windows系统安装MSYS2
首先到MSYS2
官网下载安装包msys2-x86_64-20220503.exe,双击进行安装,在安装程序窗口点击下一步,选择安装文件夹为D:\msys64
后直接安装即可。
|
|
安装完成后,由于MSYS2
需要安装依赖库,考虑到网络访问等原因,将MSYS2镜像改为清华源镜像,也就是说,所有依赖库都优先从国内清华源镜像网站下载。具体设置步骤为:(1)打开/etc/pacman.conf
文件,分别设置mingw32、mingw64、ucrt64、clang32、clang64、msys
的Include
路径为各自对应的/etc/pacman.d
下的mirrorlist文件名;(2)分别打开这6个mirrorlist文件,将清华源镜像网址放在第一行,如下图所示。
然后为了在MSYS2
中安装相关的依赖,打开开始菜单,可以看到MSYS 2 64bit
文件夹下有5个快捷方式,运行MSUS2 MSYS
后弹出bash
窗口,依次输入如下命令:
pacman -help
pacman -Syu
pacman -Syu
pacman -Su
pacman -S mingw-w64-x86_64-gcc
pacman -S make
pacman -S vim
pacman -S git
pacman -S python
pacman -S winpty
which g++
which gcc
which make
which vim
which git
which python
which winpty
现在MSYS2的基本环境就搭建好了,如下图所示,在D:\msys64\mingw64\bin
文件夹下可以看到有c++.exe
、g++.exe
、gcc.exe
和一些dll
等文件,这也能表明mingw64
下的gcc
环境搭建成功。
2.3 下载GSL源码进行编译构建
在MSYS2环境搭建成功后,为了编译GSL源码,首先需要获得GSL
较新版本的源码,下载gsl-2.7.tar.gz压缩包并解压,解压后的文件夹为D:\搜狗高速下载\gsl-2.7\gsl-2.7
,该文件夹下的文件如图所示,其中需要重点关注两个文件:INSTALL文件和README文件,可以选中文件点击鼠标右键选择用记事本打开查看文件内容。
通过查看INSTALL和README这两个文件中的说明内容,可知GSL
的编译最好使用gcc编译器,需要依次输入./configure
、make
、make install
这三个命令来完成GSL
的编译、构建和安装。如果直接使用上述三个命令,那么默认会将GSL编译后的bin、include文件放到/usr/local/bin
和/usr/local/include
目录下。为了将GSL
安装到其他目录,这里新建文件夹D:\搜狗高速下载\gsl-2.7\gsl-2.7-build作为GSL
的安装目录,需要利用./configure --prefix=/D/搜狗高速下载/gsl-2.7/gsl-2.7-build
命令来进行设置。具体的configure
命令帮助如下,可参考:
$ ./configure --help
`configure' configures gsl 2.7 to adapt to many kinds of systems.
Usage: ./configure [OPTION]... [VAR=VALUE]...
To assign environment variables (e.g., CC, CFLAGS...), specify them as
VAR=VALUE. See below for descriptions of some of the useful variables.
Defaults for the options are specified in brackets.
Configuration:
-h, --help display this help and exit
--help=short display options specific to this package
--help=recursive display the short help of all the included packages
-V, --version display version information and exit
-q, --quiet, --silent do not print `checking ...' messages
--cache-file=FILE cache test results in FILE [disabled]
-C, --config-cache alias for `--cache-file=config.cache'
-n, --no-create do not create output files
--srcdir=DIR find the sources in DIR [configure dir or `..']
Installation directories:
--prefix=PREFIX install architecture-independent files in PREFIX
[/usr/local]
--exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
[PREFIX]
By default, `make install' will install all the files in
`/usr/local/bin', `/usr/local/lib' etc. You can specify
an installation prefix other than `/usr/local' using `--prefix',
for instance `--prefix=$HOME'.
For better control, use the options below.
Fine tuning of the installation directories:
--bindir=DIR user executables [EPREFIX/bin]
--sbindir=DIR system admin executables [EPREFIX/sbin]
--libexecdir=DIR program executables [EPREFIX/libexec]
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
--runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
--libdir=DIR object code libraries [EPREFIX/lib]
--includedir=DIR C header files [PREFIX/include]
--oldincludedir=DIR C header files for non-gcc [/usr/include]
--datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
--datadir=DIR read-only architecture-independent data [DATAROOTDIR]
--infodir=DIR info documentation [DATAROOTDIR/info]
--localedir=DIR locale-dependent data [DATAROOTDIR/locale]
--mandir=DIR man documentation [DATAROOTDIR/man]
--docdir=DIR documentation root [DATAROOTDIR/doc/gsl]
--htmldir=DIR html documentation [DOCDIR]
--dvidir=DIR dvi documentation [DOCDIR]
--pdfdir=DIR pdf documentation [DOCDIR]
--psdir=DIR ps documentation [DOCDIR]
Program names:
--program-prefix=PREFIX prepend PREFIX to installed program names
--program-suffix=SUFFIX append SUFFIX to installed program names
--program-transform-name=PROGRAM run sed PROGRAM on installed program names
System types:
--build=BUILD configure for building on BUILD [guessed]
--host=HOST cross-compile to build programs to run on HOST [BUILD]
Optional Features:
--disable-option-checking ignore unrecognized --enable/--with options
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
--enable-silent-rules less verbose build output (undo: "make V=1")
--disable-silent-rules verbose build output (undo: "make V=0")
--enable-maintainer-mode
enable make rules and dependencies not useful (and
sometimes confusing) to the casual installer
--enable-dependency-tracking
do not reject slow dependency extractors
--disable-dependency-tracking
speeds up one-time build
--enable-shared[=PKGS] build shared libraries [default=yes]
--enable-static[=PKGS] build static libraries [default=yes]
--enable-fast-install[=PKGS]
optimize for fast installation [default=yes]
--disable-libtool-lock avoid locking (might break parallel builds)
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
--with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use
both]
--with-aix-soname=aix|svr4|both
shared library versioning (aka "SONAME") variant to
provide on AIX, [default=aix].
--with-gnu-ld assume the C compiler uses GNU ld [default=no]
--with-sysroot[=DIR] Search for dependent libraries within DIR (or the
compiler's sysroot if not specified).
Some influential environment variables:
CC C compiler command
CFLAGS C compiler flags
LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
nonstandard directory <lib dir>
LIBS libraries to pass to the linker, e.g. -l<library>
CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
you have headers in a nonstandard directory <include dir>
CPP C preprocessor
LT_SYS_LIBRARY_PATH
User-defined run-time library search path.
Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations.
Report bugs to the package provider.
然后打开MSYS2 MinGW x64
窗口,依次输入如下bash命令来编译GSL源码:
which gcc
which g++
gcc -v
g++ -v
cd /D/搜狗高速下载/gsl-2.7/gsl-2.7
./configure --help
./configure --prefix=/D/搜狗高速下载/gsl-2.7/gsl-2.7-build
make
make install
GSL
编译过程中的执行界面如下图所示:
最终GSL
编译构建成功后,在安装目录D:\搜狗高速下载\gsl-2.7\gsl-2.7-build
下可看到bin、include、lib和share四个文件夹,各个文件夹中的文件如下图所示,至此gsl-2.7
编译构建成功。
|
|
|
3、基于GSL库编写C语言代码(CodeBlocks / Visual Studio)
下面分别采用CodeBlocks
和Visual Studio
这两种IDE来编写利用GSL
库的C
项目,主要对GSL
库在两种IDE中的配置过程进行简单介绍。
3.1 在CodeBlocks中基于GSL库编写C语言代码
3.1.1 安装CodeBlocks(自带gcc编译器)
首先CodeBlocks作为一种开源的IDE,可用来编写C、C++和Fortran语言,且跨平台具有良好的扩展性,能安装插件,可满足大多开发者的需求。下载codeblocks-20.03mingw-setup.exe后,双击进行安装,接受GPL许可协议,选择安装目录为D:\program files\CodeBlocks,之后一直点击Next
默认安装即可,安装过程如下图所示。
安装结束后,在桌面会看到CodeBlocks快捷方式,同时对应安装目录D:\program files\CodeBlocks
下的文件包含MinGW
文件夹,该文件夹下有bin、include和lib目录,bin
目录下g++.exe
、gcc.exe
和mingw32-make.exe
,可见MinGW自带gcc环境。
当然,如果想要配置make
命令,需要将D:\program files\CodeBlocks\MinGW\bin
文件夹下的mingw32-make.exe
复制一份并重命名为make.exe
,同时将D:\program files\CodeBlocks\MinGW\bin添加到系统的环境变量Path
中。
|
|
最后Win+R打开cmd
命令行窗口,依次输入如下命令检验gcc
编译器环境,结果如下图所示则配置成功。
gcc -v
g++ -v
make -v
3.1.2 利用CodeBlocks新建C项目
打开CodeBlocks
软件,点击File->New->Project,选择Projects->Console->Console application后点击go
,编程语言选择C
,之后输入项目名称和项目文件夹,编译器选择GNU GCC Compiler后点击Finish
,这样就成功创建了一个C
项目。
新建的C
项目会自动生成main.c
文件,将里面的代码替换为GSL
相关的代码(注:自己可以到GSL文档中找Examples
中的例子代码)。
main.c
代码:
#include <stdio.h>
#include <gsl/gsl_sf_bessel.h>
#include <gsl/gsl_fit.h>
int main (void)
{
int i, n = 4;
double x[4] = { 1970, 1980, 1990, 2000 };
double y[4] = { 12, 11, 14, 13 };
double w[4] = { 0.1, 0.2, 0.3, 0.4 };
double c0, c1, cov00, cov01, cov11, chisq;
gsl_fit_wlinear (x, 1, w, 1, y, 1, n,
&c0, &c1, &cov00, &cov01, &cov11,
&chisq);
printf ("# best fit: Y = %g + %g X\n", c0, c1);
printf ("# covariance matrix:\n");
printf ("# [ %g, %g\n# %g, %g]\n",cov00, cov01, cov01, cov11);
printf ("# chisq = %g\n", chisq);
for (i = 0; i < n; i++)
printf ("data: %g %g %g\n",
x[i], y[i], 1/sqrt(w[i]));
printf ("\n");
for (i = -30; i < 130; i++)
{
double xf = x[0] + (i/100.0) * (x[n-1] - x[0]);
double yf, yf_err;
gsl_fit_linear_est (xf,
c0, c1,
cov00, cov01, cov11,
&yf, &yf_err);
printf ("fit: %g %g\n", xf, yf);
printf ("hi : %g %g\n", xf, yf + yf_err);
printf ("lo : %g %g\n", xf, yf - yf_err);
}
double x1 = 5.0;
double y1 = gsl_sf_bessel_J0 (x1);
printf ("J0(%g) = %.18e\n", x1, y1);
return 0;
}
另外,为了让GCC编译器找到GSL相关的头文件和库文件,还需要在CodeBlocks
中设置GCC编译器的链接库目录、搜索包含目录,即在Compiler settings窗口设置Linker settings为GSL安装目录下lib文件夹中的所有.a文件
,设置Search Directories为GSL安装目录下的include文件夹
,检查GCC编译器的位置为CodeBlocks下的MinGW文件夹。
最后,在CodeBlocks
的菜单栏中点击Build
下的Build来编译生成项目,编译成功后点击Run对应的绿色朝右三角形按钮即可运行,在弹出的控制台窗口中查看运行结果。
3.2 dll转lib用于VS 2015 中编写C项目调用(pexports + dlltool)
为了在Visual Studio
中利用编译好的GSL
库,则需要GSL
安装目录lib
文件夹下存在.lib文件
,而上述编译的lib
文件夹下仅存在.a文件
(gcc编译器所用的lib文件),因此需要考虑将GSL安装目录bin
文件夹下的.dll文件转换为.lib文件
。而目前已知的转换方式主要有两种:(1)pexports.exe + MinGW
自带的dlltool.exe;(2)pexports.exe +VS
自带的lib.exe。
方式一:需要下载pexports.exe,dlltool.exe可在CodeBlocks安装目录下的MinGW\bin文件夹 或 MSYS2安装目录下的MinGW\bin文件夹下找到,将这两个exe
文件复制到同一个目录下,然后将要转换的dll文件复制到该目录,并执行以下命令进行转换:
pexports libgls-25.dll >libgsl-25.def
pexports libgslcblas-0.dll >libgslcblas-0.def
dlltool --dllname libgsl-25.dll --def libgsl-25.def --output-lib libgsl-25.lib
dlltool --dllname libgslcblas-0.dll --def libgslcblas-0.def --output-lib libgslcblas-0.lib
可见,pexports负责将dll转换为def文件,而dlltool负责将dll和def一起转换为lib文件,具体执行过程如下图所示:
方式二:在VS安装目录下的VC\bin文件夹下可以找到lib.exe
文件(这里以VS 2015为例),将要转换的dll文件复制到此文件夹,然后在此文件夹处打开cmd
窗口,输入的具体命令如下(32位和64位自己对应),将生成的两个lib文件放到GSL安装目录下的lib文件夹
下。
lib /machine:i386 /def:libgsl-27.def # 32位
lib /machine:i386 /def:libgslcblas-0.def # 32位
# 由于电脑是64位,这里选择64位的进行转换
lib /machine:X64 /def:libgsl-27.def # 64位
lib /machine:X64 /def:libgslcblas-0.def # 64位
考虑到GSL库的底层实现是基于C语言,这里打开VS 2015
,新建C++控制台项目,将项目配置为Release
和64位
后,在右侧的解决方案资源管理器窗口中,在项目名称上右键选择属性,在弹出的属性窗口中分别对附加包含目录、附加库目录、链接器->输入->附加依赖项进行设置。
之后在源文件上右键选择添加->新建项,在弹出的添加新项窗口中点击C++文件,在文本框中输入main.c
作为文件名后点击添加即可,然后打开main.c
文件,输入以下代码:
#include <stdio.h>
#include <gsl/gsl_sf_bessel.h>
#include <gsl/gsl_fit.h>
int main(void)
{
int i, n = 4;
double x[4] = { 1970, 1980, 1990, 2000 };
double y[4] = { 12, 11, 14, 13 };
double w[4] = { 0.1, 0.2, 0.3, 0.4 };
double c0, c1, cov00, cov01, cov11, chisq;
gsl_fit_wlinear(x, 1, w, 1, y, 1, n,&c0, &c1, &cov00, &cov01, &cov11,&chisq);
printf("# best fit: Y = %g + %g X\n", c0, c1);
printf("# covariance matrix:\n");
printf("# [ %g, %g\n# %g, %g]\n", cov00, cov01, cov01, cov11);
printf("# chisq = %g\n", chisq);
for (i = 0; i < n; i++)
printf("data: %g %g %g\n",
x[i], y[i], 1 / sqrt(w[i]));
printf("\n");
for (i = -30; i < 130; i++)
{
double xf = x[0] + (i / 100.0) * (x[n - 1] - x[0]);
double yf, yf_err;
gsl_fit_linear_est(xf,c0, c1,cov00, cov01, cov11,&yf, &yf_err);
printf("fit: %g %g\n", xf, yf);
printf("hi : %g %g\n", xf, yf + yf_err);
printf("lo : %g %g\n", xf, yf - yf_err);
}
double x1 = 5.0;
double y1 = gsl_sf_bessel_J0(x1);
printf("J0(%g) = %.18e\n", x1, y1);
return 0;
}
在GSL
库设置完成,代码编写完成后,点击菜单栏中的生成->生成解决方案完成项目的编译,在下方的输出窗口中显示成功,得到了可执行的exe文件,然后Ctrl+F5运行后发现报错,提示找不到libgsl-25.dll
。针对此问题的解决方案有两种:第一种是将GSL安装目录下的bin文件夹下的dll文件复制到项目生成的exe文件夹下;第二种是将dll所在文件夹添加到系统环境变量Path中。这里选择了第一种解决方案,将libgsl-25.dll和libgslcblas-0.dll复制到项目生成的exe文件夹下后即可成功运行。
4、总结
许多基于C
语言和C++
语言的开源项目库都是在Linux
系统中采用gcc
编译器开发的,因而在Windows
环境下确实较难重新构建,这里利用MSYS2
提供的Linux
环境便于对开源项目GSL
进行生成构建,得到动态链接库dll
,利用pexports.exe+dlltool.exe(gcc)或者pexports.exe+lib.exe(vs)(这两种方式任选一种)可将dll
转换为lib
,从而在Microsoft Visual Studio
中进行链接和调用,经过实测,这两种方式生成的lib文件尽管大小不同,但都能够调用执行,因为运行时本质上都有dll
文件。
MinGW
(gcc)可支持静态库.a和动态链接库**.dll**;而Visual Studio
(msvc)仅支持动态链接库.dll,因此需要使用导入库.lib。
5、参考WIki
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)