1

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:

  1. Apache APR
  2. Apache APR-util
  3. Apache iconv.

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":

Error #1

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): Error

Folder structure is the following: Error3

Francesco Rizzi
  • 631
  • 6
  • 24
  • This means your include path is not properly setup. – drescherjm Feb 01 '21 at 23:19
  • Could you help me to understand? should i set some kind of folder for the linker? – Francesco Rizzi Feb 01 '21 at 23:19
  • hi, interesting, perhaps add the path? https://www.learncpp.com/cpp-tutorial/a3-using-libraries-with-codeblocks/ – IronMan Feb 01 '21 at 23:19
  • No it's about telling your compiler where you put the headers for the third party library. It has nothing to do with the linker. – drescherjm Feb 01 '21 at 23:20
  • ***For example: if i add ALL the files of Apache APR*** I assume you mean add to codeblocks. This is most likely the wrong way to build a third party library dependency. Most likely you need to use the instructions from the site for the library on how to build and install for your compiler. – drescherjm Feb 01 '21 at 23:22
  • I'm really confused. I just "added" all the files to my project expecting that evrything is ok. What am I missing here? thanks! – Francesco Rizzi Feb 01 '21 at 23:22
  • @drescherjm On the website i read something for Visual studio, but what if i do not have it? – Francesco Rizzi Feb 01 '21 at 23:23
  • Visual Studio instructions or binaries will most likely be incorrect for mingw. – drescherjm Feb 01 '21 at 23:24
  • Yes, so how can I import all those sources in codeblocks and compile them accordingly? It's just source code, so it should compile. If needed i will update my question in order for you to know better what i'm doing – Francesco Rizzi Feb 01 '21 at 23:26
  • Downloading the source of a library and importing it into your IDE is what you'd to if you wanted to modify that library. If you just want to use it, you need to compile it independently of your own project, and _then_ tell your IDE where to find the public header files and the library (.a, .so, .dll or whatever) files it produced. – Useless Feb 01 '21 at 23:30
  • Trying to cram Linux/Unix originated software, like gcc or apache, into a foreign operating system that wasn't designed to run Linux/Unix-originated code is a major, major time sink. Even experienced developers will struggle with this, not to mention those who are new to C++. Most of the time it takes much less time to simply install Linux from scratch, and get a fully working, fully configured, modern C++ compiler and all libraries. It took me just an hour and a half, last time. Now, I'd just buy a Lenovo laptop with preloaded Linux. How much time did you already spend on this? – Sam Varshavchik Feb 01 '21 at 23:30
  • I just wanted to code something in c++ since i'm new with this language (coming from Java). Some libraries do not come with prebuilt binaries, furthermore i would like to know how to handle this situation. I'm working on windows since I want to use win32 api. It seems there's no way I can compile these libraries... Is it possible to have some kind of step-by-step guide? – Francesco Rizzi Feb 01 '21 at 23:33
  • I'm downloading it and I will attach it as default compiler on codeblocks. But maybe the problem is on how I am setting the project itself. I'm not setting any folders for compiler/linker. What should I check? how can i know where the library header files are located? – Francesco Rizzi Feb 01 '21 at 23:40
  • Did you check the documentation for these libraries? If they are available and are documented as working on Windows, I would expect them to have a README or something along the same lines that gives instructions for building them under Windows. It's possible that their documentation is rather scant, and assumes that the builder is an experienced Windows C++ developer and knows exactly what to do. Building these libraries is just not something that's expected to be done by someone who's new to C++, that's just really how it is, sorry. – Sam Varshavchik Feb 01 '21 at 23:40
  • @SamVarshavchik it's ok to be a non-trivial task, I have time for this. But whenever libraries get involved in my projects I cannot import them if they are not pre-built and it's annoying. In the website it's listed visual studio as tool for compiling libraries. There should be something which can make me compile those libraries in windows, but is there any actual reason to use only visual studio? – Francesco Rizzi Feb 01 '21 at 23:43
  • If their docs give instructions for building their libraries on visual studio, it might be possible to sift through them and figure out what each step does, then figure out the equivalent steps or configuration settings in your compiler. On Linux all software libraries come as source, and not prebuilt. Experienced Linux distribution devs build the libraries from source, and you install their pre-built packages. But you simply don't have anything like that on Windows, but software libraries still expect their Windows ports also to be built by experienced C++ devs, like on Linux. – Sam Varshavchik Feb 01 '21 at 23:50
  • Maybe I should just follow the exact steps from the website without questions, and maybe once compiled could use again my ide codeblocks. – Francesco Rizzi Feb 01 '21 at 23:52
  • If you're using MinGW then it's likely you'll want to use the Unix/Linux build instructions rather than the Windows ones. MinGW is essentially a minimal Unix system running on top of Windows. For instance, APR has instructions [here](https://apr.apache.org/compiling_unix.html) though you'll likely need to pass some extra flags to the 'configure' script to get the binaries somewhere you can use them. Or it may not be supported at all. Every library is different, and not all will support all systems. In general there are commonly used tools, but no one process that will work for every lib. – Miles Budnek Feb 02 '21 at 04:02
  • I disagree with those saying "GCC in Windows is hard", etc. Install MSYS2, you can download prebuilt APR and Iconv from its package manager. (As a bonus, you get the latest version of GCC.) Then use `pkg-config` to know what compiler and linker flags to put into CodeBlocks settings to use the libraries. – HolyBlackCat Feb 02 '21 at 20:45
  • @HolyBlackCat The point here is to learn how to compile libraries from their sources but every path i take leads me to errors. – Francesco Rizzi Feb 02 '21 at 20:52
  • Even if you want to compile from source, MSYS2 is probably the way to go. If those libraries don't have build instructions for MinGW, follow Linux instructions. – HolyBlackCat Feb 02 '21 at 20:56
  • 1
    After looking a bit into this, it seems MSYS2 folks had to slightly patch those libraries to get them working on MinGW. Some more popular libraries support MinGW out of the box, but these don't seem to. So much for "portable". You might want to start learning how to build libraries on some other libraries, but if you really want to build those yourself, I'd use the patches and build scripts from MSYS2 (e.g. [here are the ones for APR](https://github.com/msys2/MINGW-packages/tree/master/mingw-w64-apr)). – HolyBlackCat Feb 02 '21 at 21:12

3 Answers3

1

Preface

  • 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.

Installing MSYS2

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.

Compiling the library

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!

Using the compiled library

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:

  • Compiler flags: -DWIN32 -D__MSVCRT__ -D_LARGEFILE64_SOURCE -Ipath/to/apr-1.6.5/include
  • Linker flags: -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 .dlls 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!.

CodeBlocks

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/).

HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
  • Thank you very much for your answer, i'm trying to reproduce yours steps. I'm assuming that this kind of things will work only for MinGW projects and not for Visual studio ones, right? – Francesco Rizzi Feb 04 '21 at 21:11
  • @FrancescoRizzi Yes, Visual Studio is completely different. – HolyBlackCat Feb 04 '21 at 21:23
  • I am trying to compile it using cmake but no success. @HolyBlackCat I would appreciate a moment of your time. https://stackoverflow.com/questions/73293422/building-apache-log4cxx-with-cmake – Orlay Garcia Duconge Aug 09 '22 at 15:29
0

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).

Option 1: vcpkg

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)

Option 2: Build all dependencies separately

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.

rm5248
  • 2,590
  • 3
  • 17
  • 16
0

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.