Reputation: 631
I would like to use external libraries in my project. For example the apache log4cxx. I'm compiling for windows.
I know i have to compile first:
I saw only these three dependencies on the main page.
I'm using MinGW-64 as compiler and CodeBlocks as IDE. Simply importing in my project all the files of each dependency does not work.
For example: if i add ALL the files of Apache APR i get "File not found error":
If I try to do the same with the other libraries other errors occur.
I'm sure i am not understanding how to build external libraries by using their source code.
UPDATE
I installed Visual studio, now i'm trying to compile the libraries but (obviosly...) compiler returns errors (error code C2513):
Folder structure is the following:
Upvotes: 1
Views: 1770
Reputation: 1
The problem for:
APR_DECLARE_LATE_DLL_FUNC(DLL_IPHLPAPI, PCHAR, NETIOAPI_API_, if_indextoname, 0, (
is not APR_DECLARE_LATE_DLL_FUNC but NETIOAPI_API_ or netioapi.h cannot be seen at that point.
I used CMake to generate Windows7 build and converted all to VS2019 then 2022. I am using apr/lib for build and see I have an apr.h in apr/lib but apr/lib/apr.h and apr/include/apr.h are different - apr/include/apr.h:
#define _WIN32_WINNT 0x0501
while the lib/apr.h has:
#define _WIN32_WINNT 0x0601
if you build apr/lib/APR.sln's project one by one, not the whole solution (so that include/apr.h is not generated), you will be able to build all okay, if include/apr.h is not present. My project has ../lib in its include directory, meaning it was using apr/lib/apr.h. This lead me to conclude that 0x0501 in the generated header is a problem. So I fixed the generated include/apr.h, or precisely fixed include/apr.h.in (not affecting apr.h) and apr.hw (affecting apr.h) by replacing 0x0501 with 0x0601, that issue was solved.
I still have other issues in apr-util/iconv build, not having enough time to look at that yet.
Upvotes: 0
Reputation: 2635
There are several options for how to build log4cxx, depending on your setup. The current way is to use the provided cmake files in order to build it.
The only dependencies requires are APR and APR-util(which depends on either expat or libxml).
If you're on Windows and using CMake to build your project, the easiest way is to simply install vcpkg and use the recipe that is already included in vcpkg. This can be done simply as follows:
git clone https://github.com/microsoft/vcpkg
.\bootstrap-vcpkg.bat
.\vcpkg install log4cxx
This will download log4cxx and all of the dependencies required(APR, APR-util, expat, etc). From there, you can then use the generated CMake toolchains file that vcpkg creates(see the vcpkg documentation for more information)
All of the required dependencies can be built with CMake. When you install and configure the dependencies, the best way is to make sure that they are all installed in the same root folder on your system(e.g. the installation directory is set to the same for all dependencies). This makes it easier to configure the build systems.
See this JIRA issue for some more information and some clues as to how to build separately.
Upvotes: 0
Reputation: 96166
Instead of giving you the answer right away, I'll first explain my thought process.
I'll only go through one of the libraries, but repeating the same thing for other ones should be easy.
Since I'm not on Windows, I can't use MSYS2 itself and will have to use its bastard child (which I'm the author of). So there may be minor inaccuracies in the instructions.
MSYS2 is a way to get GCC on Windows. In addition to the compiler, in its package manager it provides some prebuilt libraries, and ports of command-line utilities such as bash
or make
(which are available on Linux out of the box, but normally don't work on Windows).
First, uninstall any versions on MinGW/GCC you might currently have. After you install GCC from MSYS2, you can tell CodeBlocks to use it instead of whatever it uses now.
Download and install MSYS2 from here. You don't want the installation path to contain spaces or any weird symbols.
Start it, you should see a terminal.
-- Updating MSYS2 --
MSYS2 should be updated after its installed. To update, run pacman -Syuu
.
It might warn you that it will close itself to finish the update. If it happens, restart it and run the same command again the finish the update.
You might want to run this command from time to time to keep your installation up-to-date.
Now you can run pacman -Ss SomeText
to search for packages and pacman -S PackageNames
to install packages.
-- Three sides of MSYS2 --
MSYS2 can be started in three different modes, the current mode is shown in the terminal in magenta letters.
One way to select modes is by using different exe files in the installation directory (mingw64.exe
, and so on).
In the package manager, there are three sets of packages corresponding to those modes. It doesn't matter which mode is active when you install the packages, but it matters for actual compilation.
MINGW32
- for compiling 32-bit applications. Package names are prefixed with mingw-w64-i686-
.MINGW64
- for compiling 64-bit applications. Package names are prefixed with mingw-w64-x86_64-
MSYS
- for compiling applications with POSIX emulation. Packages have no prefix.Normally you don't want to use the last one. It's used to compile non-portable applications originally written for Linux-like systems, that don't work on Windows otherwise. Programs such as bash
and make
that come with MSYS2 were compiled with it.
Often you'll see three variants of a package, one for each mode. For example, if you do pacmake -Ss gcc
(to search for "gcc" packages), you'll see mingw-w64-i686-gcc
, mingw-w64-x86_64-gcc
, and just gcc
.
How do you select a package from the three? Here's the rule of thumb:
First, look for a prefixed package. (mingw-w64-x86_64-...
if you're compiling for 64 bits, or mingw-w64-i686-...
for 32 bits).
If there's no prefixed package, and you were looking for a compiler or a library, you're out of luck, there's no such package.
If you weren't looking for a compiler or a library, you can settle for an unprefixed package.
-- Installing tools --
With this knowledge, you're ready to install the tools from MSYS2 pacakge manager.
pacman -S mingw-w64-x86_64-gcc
for GCC.
pacman -S mingw-w64-x86_64-gdb
for GDB, the debugger. Might be useful.
pacman -S mingw-w64-x86_64-cmake make patch
for some other tools. Hopefully I didn't forget anything.
Note that make
is the exception from the rule of thumb. There's another package called mingw-w64-x86_64-make
, but long story short it's jank, and you want to use the unprefixed make
instead.
I used to have some problems with the CMake package. If it starts acting up, uninstall it and download the official CMake installer. If you use it, don't forget to add it to the PATH
.
I'm going to compile APR, the other libraries should be similar.
First, I search for it in the packages: pacman -Ss apr
- the package is there. I tried to install it and compile a test program (it worked), so we know for sure it can be used on Windows.
But since you want to compile it yourself, we'll continue. If you decided to install the APR package to try it out, now is a good time to uninstall it, to avoid any interference.
Make sure MSYS2 is running in MINGW64
mode (look at the magenta text in the terminal). If it's not, restart it using mingw64.exe
. When you were installing the packages, it didn't matter what mode was active, but now when you're compiling things it becomes important.
I'll first show my failed attempts first, to explain the thought process.
-- Failed attempt 1 --
I downloaded the APR source from here. There are separate downloads for Windows and Linux, I decided to go for apr-1.7.0-win32-src.zip
.
Extracted the archive. Opened the resulting directory in the terminal (using cd
, I hope you know what this is).
What exactly you do next depends on the files you see.
Since there's CMakeLists.txt
, I tried building with 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
On the last command I got cryptic errors. Let's try something else. I erased the _build
and started looking for a different approach.
-- Failed attempt 2 --
I downloaded apr-1.7.0.tar.gz
instead (the non-Windows variant of the sources). There's CMakeLists.txt
, so I tried CMake again - nope, no luck.
I'm also seeing a configure
file, so it's also possible to build with Autotools. (Normally it's either CMakeLists.txt
or configure
. If you see neither, then the build process is more exotic and should be explained in the readme.)
Let's try Autotools:
# Configure
./configure
# Build
make -j12
Got errors on first step, so we need a different approach.
-- Successful attempt --
Normally by this point you already succeed, but APR refuses to build out of the box. Yet MSYS2 folks managed to build it, how?
Let's figure out. Go to MSYS2 package sources, and look for APR.
Here we see several .patch
files. They explain what modifications MSYS2 developers made to the APR source code to be able to build it. They are in a computer-readable format, and there's a program that applies them to the code automatically.
Download the .patch
files, they will be useful later.
Now look at the PKGBUILD
file. It contains computer-readable instructions on building APR. There is a way to execute them automatically, but I'll rather do it by hand for educational purposes.
I don't understand all of the PKGBUILD
contents, but it's not necessary. You see following in it:
pkgver=1.6.5
They are using slightly outdated 1.6.5 instead of 1.7.0.
I tried building 1.7.0 and failed, so get rid of 1.7.0 and download 1.6.5 from here.
makedepends=("${MINGW_PACKAGE_PREFIX}-gcc"
"${MINGW_PACKAGE_PREFIX}-libtool"
"${MINGW_PACKAGE_PREFIX}-python")
To be able to build this package, they have installed gcc
, libtool
, and python
. We already have GCC, now we just need the rest. Run:
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
}
This is how they "prepare" for the build. Lets do something similar. Copy the patch files to the apr-1.6.5
directory and run:
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
}
So they use configure
and make
like we tried to do, but with some extra flags. Let's not worry about the flags, just do:
./configure
make -j12
And... it builds successfully!
You compiled the library, which created some files for you to use. What are they?
You need .a
(static libraries) and .dll
(dynamic libraries). Quick search shows they are in the .libs
directory.
You also need the headers, which seem to be in the include
directory. Everything else is no longer needed.
Now you need to know what compiler and linkers flags to use. Those can be found in a .pc
file (apr.pc
in this case) which for me looks like this:
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}
Looking at the last two lines and ignoring some of the optional flags, we get this:
-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
Now we can try compiling a simple program from the terminal. Create a file called 1.cpp
with following contents:
#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';
}
Build it using:
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
Since we're building from the terminal, our compiler and linker flags are in the same place. But when you'll be using CodeBlocks, you'll have to put them in two different places in the project settings.
In this command, you have to replace paths after -I
and -L
with the actual paths to your APR sources.
If the command runs successfully, you get your a.exe
.
To run it, you first need to copy all .dll
s from apr-1.6.5/.libs
to the directory where the .exe
is. Now you should be able to type ./a.exe
and see it print Hello,world!
.
If you want to do the same thing from CodeBlocks, you need to create a project, and in the project settings specify the same compiler and linker flags you used here.
Also, in CodeBlocks settings you'll have to specify the path to the GCC compiler you installed from MSYS2 (it should be in C:/msys64/mingw64/bin/
).
Upvotes: 1