问题描述
我想在我的项目中使用外部库。 例如 apache log4cxx。 我正在为 Windows 编译。
我知道我必须先编译:
- Apache APR
- Apache APR-util
- Apache iconv.
我在主页上只看到了这三个依赖项。
我使用 MinGW-64 作为编译器,使用 CodeBlocks 作为 IDE。 简单地在我的项目中导入每个依赖项的所有文件是行不通的。
例如:如果我添加 Apache APR 的所有文件,我会收到“找不到文件错误”:
如果我尝试对其他库执行相同操作,则会出现其他错误。
我确定我不明白如何使用它们的源代码构建外部库。
更新 我安装了 Visual Studio,现在我正在尝试编译库,但是(显然...)编译器返回错误(错误代码 C2513):
文件夹结构如下:
解决方法
前言
-
我不会马上给你答案,而是先解释一下我的思考过程。
-
我只会浏览其中一个库,但对其他库重复同样的事情应该很容易。
-
因为我不在 Windows 上,所以我不能使用 MSYS2 本身,必须使用 its bastard child(我是它的作者)。所以说明中可能有轻微的不准确之处。
安装 MSYS2
MSYS2 是一种在 Windows 上获取 GCC 的方法。除了编译器之外,它的包管理器还提供了一些预构建的库和命令行实用程序的端口,例如 bash
或 make
(在 Linux 上开箱即用,但通常不不适用于 Windows)。
首先,卸载您当前可能拥有的 MinGW/GCC 上的任何版本。从 MSYS2 安装 GCC 后,您可以告诉 CodeBlocks 使用它而不是它现在使用的任何东西。
从 here 下载并安装 MSYS2。您不希望安装路径包含空格或任何奇怪的符号。
启动它,你应该看到一个终端。
-- 更新 MSYS2 --
MSYS2 应在安装后更新。要更新,请运行 pacman -Syuu
。
它可能会警告您它将自行关闭以完成更新。 如果发生这种情况,请重新启动它并再次运行相同的命令以完成更新。
您可能希望不时运行此命令以使您的安装保持最新。
现在您可以运行 pacman -Ss SomeText
来搜索软件包并运行 pacman -S PackageNames
来安装软件包。
-- MSYS2 的三面 --
MSYS2 可以在三种不同的模式下启动,当前模式在终端中以洋红色字母显示。
选择模式的一种方法是使用安装目录中的不同 exe 文件(mingw64.exe
等)。
在包管理器中,有与这些模式对应的三组包。安装包时哪个模式处于活动状态并不重要,但对于实际编译很重要。
-
MINGW32
- 用于编译 32 位应用程序。包名称以mingw-w64-i686-
为前缀。 -
MINGW64
- 用于编译 64 位应用程序。包名称以mingw-w64-x86_64-
为前缀
-
MSYS
- 用于使用 POSIX 仿真编译应用程序。包没有前缀。
通常您不想使用最后一个。它用于编译最初为类 Linux 系统编写的非便携式应用程序,否则无法在 Windows 上运行。 MSYS2 自带的 bash
和 make
等程序都是用它编译的。
通常您会看到一个包的三个变体,每个模式一个。例如,如果您执行 pacmake -Ss gcc
(搜索“gcc”包),您将看到 mingw-w64-i686-gcc
、mingw-w64-x86_64-gcc
和 gcc
。
你如何从三个中选择一个包?这是经验法则:
-
首先,查找带前缀的包。 (
mingw-w64-x86_64-...
如果您要编译 64 位,或mingw-w64-i686-...
为 32 位)。 如果没有带前缀的包,而您正在寻找编译器或库,那么您就不走运了,没有这样的包。
-
如果您不是在寻找编译器或库,您可以选择无前缀的包。
-- 安装工具--
了解这些知识后,您就可以从 MSYS2 pacakge manager 安装工具了。
-
pacman -S mingw-w64-x86_64-gcc
用于 GCC。 -
pacman -S mingw-w64-x86_64-gdb
用于调试器 GDB。可能有用。 -
pacman -S mingw-w64-x86_64-cmake make patch
用于其他一些工具。希望我没有忘记任何事情。请注意,
make
是经验法则的例外。还有一个名为mingw-w64-x86_64-make
的包,但长话短说它很卡,您想改用无前缀的make
。我曾经在使用 CMake 包时遇到过一些问题。如果它开始起作用,请将其卸载并下载官方 CMake 安装程序。如果您使用它,请不要忘记将其添加到
PATH
中。
编译库
我要编译APR,其他库应该类似。
首先,我在包中搜索它:pacman -Ss apr
- 包在那里。我尝试安装它并编译一个测试程序(它有效),所以我们确信它可以在 Windows 上使用。
但既然你想自己编译它,我们就继续。如果您决定安装 APR 包进行试用,现在是卸载它的好时机,以避免任何干扰。
确保 MSYS2 在 MINGW64
模式下运行(查看终端中的洋红色文本)。如果不是,请使用 mingw64.exe
重新启动它。当您安装软件包时,处于活动状态的模式并不重要,但现在当您编译时,这变得很重要。
我将首先展示我失败的尝试,以解释思考过程。
-- 尝试 1 失败 --
我从 here 下载了 APR 源。 Windows 和 Linux 有单独的下载,我决定选择 apr-1.7.0-win32-src.zip
。
提取存档。在终端中打开生成的目录(使用 cd
,希望你知道这是什么)。
接下来要做什么取决于您看到的文件。
因为有 CMakeLists.txt
,所以我尝试使用 CMake 构建:
# Create an arbitrary directory
mkdir _build
cd _build
# Configure
cmake .. -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -G "MSYS Makefiles"
# Build (-j12 is optional,12 is the number of CPU cores you want to use)
make -j12
在最后一个命令中,我遇到了神秘的错误。让我们试试别的。我删除了 _build
并开始寻找不同的方法。
-- 尝试 2 失败 --
我下载了 apr-1.7.0.tar.gz
(源的非 Windows 变体)。有 CMakeLists.txt
,所以我再次尝试了 CMake - 不,不走运。
我还看到了一个 configure
文件,因此也可以使用 Autotools 进行构建。 (通常是 CMakeLists.txt
或 configure
。如果两者都没有,则构建过程更加奇特,应在自述文件中进行解释。)
让我们试试 Autotools:
# Configure
./configure
# Build
make -j12
第一步出错,所以我们需要不同的方法。
-- 成功尝试 --
通常此时您已经成功,但 APR 拒绝开箱即用。然而 MSYS2 的人设法构建了它,是如何构建的?
让我们弄清楚。转到 MSYS2 package sources 和 look for APR。
这里我们看到几个 .patch
文件。他们解释了 MSYS2 开发人员对 APR 源代码进行了哪些修改才能构建它。它们采用计算机可读格式,并且有一个程序可以自动将它们应用到代码中。
下载 .patch
文件,它们稍后会有用。
现在查看 PKGBUILD
文件。它包含有关构建 APR 的计算机可读说明。有一种方法可以自动执行它们,但出于教育目的,我宁愿手动执行。
我不了解所有 PKGBUILD
内容,但这不是必需的。您会在其中看到以下内容:
-
pkgver=1.6.5
他们使用的是稍微过时的 1.6.5 而不是 1.7.0。我尝试构建 1.7.0 并失败了,因此摆脱 1.7.0 并从 here 下载 1.6.5。
-
为了能够构建这个包,他们已经安装了makedepends=("${MINGW_PACKAGE_PREFIX}-gcc" "${MINGW_PACKAGE_PREFIX}-libtool" "${MINGW_PACKAGE_PREFIX}-python")
gcc
、libtool
和python
。我们已经有了 GCC,现在我们只需要剩下的。跑步:pacman -S mingw-w64-x86_64-libtool mingw-w64-x86_64-python
-
这就是他们为构建“准备”的方式。让我们做一些类似的事情。将补丁文件复制到prepare() { cd "${srcdir}/${_realname}-${pkgver}" patch -p0 -i ${srcdir}/apr_ssize_t.patch patch -p0 -i ${srcdir}/apr_wtypes.patch ./buildconf # autoreconf -fi }
apr-1.6.5
目录并运行:patch -p0 -i apr_wtypes.patch patch -p0 -i apr_ssize_t.patch ./buildconf
-
所以他们像我们一样使用build() { [[ -d build-${MINGW_CHOST} ]] && rm -rf build-${MINGW_CHOST} mkdir -p build-${MINGW_CHOST} cd build-${MINGW_CHOST} # Disable IPv6. ../${_realname}-${pkgver}/configure \ --prefix="${MINGW_PREFIX}" \ --build=${MINGW_CHOST} \ --host=${MINGW_CHOST} \ --target=${MINGW_CHOST} \ --enable-static \ --enable-shared \ --includedir="${MINGW_PREFIX}/include/apr-1" \ --with-installbuilddir="${MINGW_PREFIX}/share/apr-1/build" \ --enable-nonportable-atomics \ --with-devrandom=/dev/urandom \ --disable-ipv6 make }
configure
和make
,但有一些额外的标志。让我们不要担心标志,只需执行以下操作:./configure make -j12
而且……它构建成功!
使用编译好的库
您编译了库,它创建了一些文件供您使用。它们是什么?
您需要 .a
(静态库)和 .dll
(动态库)。快速搜索显示它们位于 .libs
目录中。
您还需要标题,它似乎在 include
目录中。不再需要其他所有东西。
现在您需要知道要使用哪些编译器和链接器标志。这些可以在 .pc
文件(在本例中为 apr.pc
)中找到,对我来说看起来像这样:
prefix=/usr/local/apr
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
APR_MAJOR_VERSION=1
includedir=${prefix}/include/apr-${APR_MAJOR_VERSION}
Name: APR
Description: The Apache Portable Runtime library
Version: 1.6.5
Libs: -L${libdir} -lapr-${APR_MAJOR_VERSION} -lshell32 -ladvapi32 -lws2_32 -lrpcrt4 -lmswsock
Cflags: -DWIN32 -D__MSVCRT__ -D_LARGEFILE64_SOURCE -g -O2 -I${includedir}
查看最后两行并忽略一些可选标志,我们得到:
- 编译器标志:
-DWIN32 -D__MSVCRT__ -D_LARGEFILE64_SOURCE -Ipath/to/apr-1.6.5/include
- 链接器标志:
-lapr-1 -lshell32 -ladvapi32 -lws2_32 -lrpcrt4 -lmswsock -Lpath/to-apr-1.6.5/.libs
现在我们可以尝试从终端编译一个简单的程序。创建一个名为 1.cpp
的文件,内容如下:
#include <iostream>
#include <apr_strings.h>
int main()
{
char a[] = " Hello,world ! ";
char b[sizeof a];
apr_collapse_spaces(b,a);
std::cout << b << '\n';
}
使用以下方法构建它:
g++ 1.cpp -DWIN32 -D__MSVCRT__ -D_LARGEFILE64_SOURCE -Iapr-1.6.5/include -lapr-1 -lshell32 -ladvapi32 -lws2_32 -lrpcrt4 -lmswsock -Lapr-1.6.5/.libs
因为我们是从终端构建的,所以我们的编译器和链接器标志在同一个地方。但是当您使用 CodeBlocks 时,您必须将它们放在项目设置中的两个不同位置。
在此命令中,您必须将 -I
和 -L
之后的路径替换为 APR 源的实际路径。
如果命令成功运行,您将获得 a.exe
。
要运行它,首先需要将 .dll
中的所有 apr-1.6.5/.libs
复制到 .exe
所在的目录。现在您应该可以输入 ./a.exe
并看到它打印 Hello,world!
。
代码块
如果你想从 CodeBlocks 做同样的事情,你需要创建一个项目,并在项目设置中指定你在这里使用的相同的编译器和链接器标志。
此外,在 CodeBlocks 设置中,您必须指定从 MSYS2 安装的 GCC 编译器的路径(它应该在 C:/msys64/mingw64/bin/
中)。
如何构建 log4cxx 有多种选择,具体取决于您的设置。目前的方法是使用提供的 cmake 文件来构建它。
唯一需要的依赖项是 APR 和 APR-util(依赖于 expat 或 libxml)。
选项 1:vcpkg
如果您使用的是 Windows 并使用 CMake 构建您的项目,最简单的方法是简单地安装 vcpkg 并使用已包含在 vcpkg 中的配方。这可以简单地完成如下:
git clone https://github.com/microsoft/vcpkg
.\bootstrap-vcpkg.bat
.\vcpkg install log4cxx
这将下载 log4cxx 和所有所需的依赖项(APR、APR-util、expat 等)。然后,您可以使用 vcpkg 创建的生成的 CMake 工具链文件(有关详细信息,请参阅 vcpkg documentation)
选项 2:单独构建所有依赖项
所有必需的依赖项都可以使用 CMake 构建。安装和配置依赖项时,最好的方法是确保它们都安装在系统上的同一个根文件夹中(例如,所有依赖项的安装目录都设置为相同)。这样可以更轻松地配置构建系统。
有关如何单独构建的更多信息和一些线索,请参阅 this JIRA issue。