Search code examples
c++boostshared-librariesaixxlc

Compiling the boost C++ library on AIX 7.1 using xlC 13.1.2


I am trying to compile the regex part of the boost C++ library on AIX using the xlC compiler and use it as a 64-bit dynamic library, because I need to compare the performance of several C++ regex libraries and built-in solutions, and boost seemed like a viable candidate.

Here are my exact OS and compiler versions:

$ uname -a
AIX host_name 1 7 00F9A2144C00
$ xlC -qversion
IBM XL C/C++ for AIX, V13.1.2 (5725-C72, 5765-J07)
Version: 13.01.0002.0000

Since I do not have root priviliges, I cannot actually install the boost library, I am only trying to compile the regex part into a shared object file and to obtain all of the needed headers for my test application. I have tried to compile the latest available version (1.59.0), and also version 1.55.0, because I found that IBM has released a source code patch for boost:

http://www-01.ibm.com/support/docview.wss?uid=swg27042921

I compile boost and copy the headers and the shared object file to my development folder using the following commands:

bootstrap.sh --with-toolset=vacpp --prefix=/my/user/directory --exec-prefix=/my/user/directory
./b2 address-model=64 cxxflags=-q64 cflags=-q64
b2 tools/bcp
./dist/bin/bcp boost/regex.hpp /my/include/directory
cp stage/lib/libboost_regex.so /my/library/directory

I know i could add the --with-libraries=regex flag to compile only the regex part, but it is irrelevant to my problems.

With both versions, with or without patching the boost source code, I encounter the same problems.

First: I already have some libraries compiled, and linked to my simple test application, for example the PCRE C++ regex library. When I also try to link the boost regex library, with the -lboost_regex compile flag, I get the following error:

ld: 0706-006 Cannot find or open library file: -l boost_regex
ld:open(): No such file or directory
make: The error code from the last command is 255.

This is resolved by adding the -brtl compile flag, which as far as I know would only be needed if I would try to link a static library, so it looks like to me as if libboost_regex.so would actually be libboost_regex.a

Second: When I add the line #include "boost/regex.hpp" to my code, I get a compilation error:

"/opt/IBM/xlC/13.1.2/include/xtr1common", line 217.19: 1540-0130 (S) "false_type" is not declared.
"/opt/IBM/xlC/13.1.2/include/xtr1common", line 223.19: 1540-0130 (S) "true_type" is not declared.
"/opt/IBM/xlC/13.1.2/include/xtr1common", line 229.19: 1540-0130 (S) "true_type" is not declared.
"/opt/IBM/xlC/13.1.2/include/xtr1common", line 235.19: 1540-0130 (S) "true_type" is not declared.
"/opt/IBM/xlC/13.1.2/include/xtr1common", line 244.11: 1540-0130 (S) "false_type" is not declared.
"/opt/IBM/xlC/13.1.2/include/xtr1common", line 250.11: 1540-0130 (S) "true_type" is not declared.
make: The error code from the last command is 1.

My test application is really simple. These are the contents of my Makefile:

all:
    /opt/IBM/xlC/13.1.2/bin/xlC -q64 -Iinclude -Llibs -lpcrecpp main.cpp -o regexp_test

clean:
    rm regexp_test

Here is the source code of my very basic test application:

#include <iostream>
#include <string.h>

#ifndef __IBMCPP_TR1__
#define __IBMCPP_TR1__ 1
#include <regex>
#undef __IBMCPP_TR1__
#endif

#define __IBMCPP_TR1__ 1

/* Regular expression libraries to be included */
#include <sys/types.h>
#include <regex.h>
#include "pcrecpp.h"
// #include "boost/regex.hpp"
#include "deelx.h"

int main(int argc, char **argv)
{
    if(argc != 4){
        std::cerr << "Use: ./regexp_test <posix|tr1|pcre|deelx> value regexp" << std::endl;
        return 1;
    }

    int status;
    char buffer[256], regexp[256];
    snprintf(buffer,sizeof(buffer),argv[2]);
    snprintf(regexp,sizeof(regexp),argv[3]);
    std::string buffer_string = buffer;
    bool match = false;

    if(strcmp(argv[1],"posix")==0){

        regex_t comp;
        if (regcomp(&comp, regexp, REG_EXTENDED) != 0) {
            std::cerr << "The regular expression '" << regexp << "' could not be compiled!" << std::endl;
            return 1;
        } else {
            status = regexec(&comp, buffer, (size_t) 0, NULL, 0);
            regfree(&comp);
            if (status == 0) {
                match = true;
            }
        }

    } else if(strcmp(argv[1],"tr1")==0){

        try {
            std::tr1::smatch matches;
            std::tr1::regex rgx(regexp);
            status = std::tr1::regex_search(buffer_string, matches, rgx);
            if(status){
                match = true;
            }
        }
        catch(std::tr1::regex_error& re)
        {
            std::cerr << "TR1 exception caught!" << std::endl;
        }

    } else if(strcmp(argv[1],"pcre")==0){

        pcrecpp::RE re(regexp);
        if(re.PartialMatch(buffer)){
            match = true;
        }

    } else if(strcmp(argv[1],"deelx")==0){

        static CRegexpT <char> deelx_regexp(regexp, IGNORECASE | MULTILINE);
        MatchResult result = deelx_regexp.Match(buffer);
        if(result.IsMatched()){
            match = true;
        }

    } else {
        std::cerr << "Use: ./regexp_test <posix|tr1|pcre|deelx> value regexp" << std::endl;
        return 1;
    }

    if (!match) {
        std::cout << "The regular expression '" << regexp << "' does NOT match the value '" << buffer << "'." << std::endl;
    } else {
        std::cout << "The regular expression '" << regexp << "' matches the value '" << buffer << "'." << std::endl;
    }

    return 0;
}

How can these problems be resolved? Any hints or advice would be appreciated.


Solution

  • I have found a soltuion for both of my problems.

    The problem with linking:

    I have found this post: https://web.archive.org/web/20100514132209/http://durgaprasad.wordpress.com/2006/09/28/problems-with-linking-of-shared-libraries-in-aix/

    Problems with linking of shared libraries in AIX September 28, 2006 at 8:13 am (AIX, C/C++) Normally, in Solaris, Linux and other common platforms, shared libraries are represented with .so/.sl suffix. Static libraries are represented with .a suffix in filenames. But in AIX, static libraries have .a suffix and shared libraries can have either .so or .a suffix.

    when we try to compile a c file which uses shared library with .so suffix, it wont succeed by default. It gives a compilation error. Additionally we have to pass “-Wl,-brtl” flag to the compiler. “-Wl” is to say that it is a flag to the linker, so “-brtl” is internally passed to the linker [ld]. “-brtl” says that it should consider files with .so suffix also as shared libraries. There is no need to pass this flag when your shared library contains .a suffix. This type of linking is loadtime linking.

    When we want to access a shared library at runtime using dlopen & dlsym calls, it is called runtime linking. In this case, we wont get any compilation errors. If the shared library contains .a suffix, we wont get any errors at runtime also. But if the shared library contains .so suffix, we get segmentation fault at runtime. Confusing thing is, it succesfully executes dlopen call, but at the time of dlsym, it exits with segmentation fault. If we give “-Wl-brtl” flag to compiler at compilation time, runtime linking goes fine.

    It details that on AIX, shared libraries can have both .so and .a suffix, and to instruct the compiler to search for .so files you'll need to include the -brtl flag. It also instructs to include the -Wl flag, in order to pass the linkage flags directly to the linker (ld), but I have found that with this version of xlC this functionality is deprecated.

    The problem with the code:

    The preprocessor instruction #define __IBMCPP_TR1__ 1 caused the boost regex library to fail with a compilation error. This define was only needed for the built-in tr1 regular expressions of AIX I am also using, but it turns out it is only required for the #include <regex> part, I can omit the second define.