Skip to content

unittest's pkg-config file is incompatible with Debian/Ubuntu's #145

Open

Description

@rrthomas

Debian & Ubuntu currently ship UnitTest++ 1.4.0, and have added their own pkg-config file, which unfortunately does things differently in two ways:

  1. The file is named in all lower case, unittest++.pc.
  2. The include flag output is -I/usr/include/unittest++, so that the way to use UnitTest++ is #include <UnitTest++.h>. Note that the installation path is lower case, so #include "UnitTest++/UnitTest++.h", as used in UnitTest++ documentation, will not work on Debian.

I noticed this problem while working on a project with another developer who is using UnitTest++ 1.6, while I'm using Ubuntu's 1.4.

I guess it's too late for UnitTest++ to change its own pkg-config file, so unfortunately programs wanting to build on Debian and derivatives will for the foreseeable future have to do a double test, for both unittest++ and UnitTest++.

Further, to avoid #ifdeffery when including the header, one of the pkg-config-supplied include paths will have to be changed by the build system, so the code can just #include <UnitTest++.h>.

This problem and the least invasive workaround should at least be documented, if there isn't a solution.

Activity

  1. pjohnmeyer commented on Jan 20, 2017

    @pjohnmeyer
    Member

    Thanks for the note. I'm tempted to say this is just a documentation issue, and we put something in the docs that say "if your distribution comes with UnitTest++ 1.4.0 pre-installed... do this thing different." Not sure there's a better way. Thoughts?

  2. rrthomas commented on Jan 20, 2017

    @rrthomas
    Author

    My perspective is of someone writing code with tests that has to build on such systems, and on other systems, so really one has to do "both", not "different".

  3. grahamreeds commented on Jan 20, 2017

    @grahamreeds
    Contributor
  4. rrthomas commented on Jan 20, 2017

    @rrthomas
    Author

    @grahamreeds There is already a Debian bug: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=784665

    (Ubuntu gets libunittest++ from Debian). This will probably be fixed sooner or later. That is not really the problem; the problem is that old unittest++ will continue to be available in supported versions of Debian and Ubuntu for some years.

  5. pjohnmeyer commented on Jan 21, 2017

    @pjohnmeyer
    Member

    My perspective is of someone writing code with tests that has to build on such systems

    I'm going to assume that you are not able (for some reason) to bring along your own dependencies. Wouldn't it be fairly easy to, as part of your build process, bootstrap with some symlinks that make your project's include style work?

    That said, I don't see that there is anything UnitTest++ as a project can do about this. If you are dealing with a 1.6+ UnitTest++, you could always add an additional include path to your project, allowing your code to always just #include <UnitTest++.h> regardless of the available version.

  6. rrthomas commented on Jan 21, 2017

    @rrthomas
    Author

    I'm not sure what you mean by "bring along your own dependencies". It's not common to package dependencies in source unless they're essential; easier to use system-supplied (and system-integrated) libraries and tools.

    In the case of unittest++, I'd certainly not expect to package it as part of a program that uses it for tests.

    Documenting "you could always add an additional include path to your project", with translations into code (e.g. for CMake and autotools) would be a reasonable workaround for code bases that have to deal with this situation. For example, in enchant, we currently have:

    PKG_CHECK_EXISTS([UnitTest++],
        [PKG_CHECK_MODULES(UNITTESTPP, [UnitTest++])
            PKG_CHECK_VAR(UNITTESTPP_INCLUDE, [UnitTest++], [includedir])
            if test "x$UNITTESTPP_INCLUDE" != "x"; then
                UNITTESTPP_CFLAGS="$UNITTESTPP_CFLAGS -I$UNITTESTPP_INCLUDE/UnitTest++"
            fi
        ],
        [PKG_CHECK_EXISTS([unittest++],
            [PKG_CHECK_MODULES(UNITTESTPP, [unittest++])]
        )]
    )
    AC_SUBST(UNITTESTPP_CFLAGS)
    AC_SUBST(UNITTESTPP_LIBS)
    
  7. ohz10 commented on Feb 20, 2017

    @ohz10
    Contributor

    Just today I ran into this issue. Personally, I think the library maintainer trying to work around every OS package maintainer's choices is the road to perdition... so I fixed it in my code.

    I'm using CMake for my project, I'll present the solution here.

    First, I've always had the UnitTest++.h header included through a proxy header in my project so I could suppress warnings as I'm usually compiling with errors maxed out and depending on the version of UT++ it triggers some warnings.

    That header is named platform/UnitTestSupport.hpp in my project and it looks something like this now (I'll snip uninteresting parts):

    #pragma once 
    
    // snipping out windows support and warning suppression for brevity. 
    #if defined UBUNTU || defined DEBIAN
    #include <unittest++/UnitTest++.h>
    #else 
    #include <UnitTest++/UnitTest++.h>
    #endif 
    

    Now in my cmake scripts I have some code to determine the Linux Distro and set the appropriate variables. That looks something like this:

    if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
        # determine Linux Distro
        find_program(LSB_RELEASE lsb_release)
        execute_process(COMMAND ${LSB_RELEASE} -is OUTPUT_VARIABLE LINUX_DISTRO OUTPUT_STRIP_TRAILING_WHITESPACE)
        execute_process(COMMAND ${LSB_RELEASE} -rs OUTPUT_VARIABLE LINUX_DISTRO_VER OUTPUT_STRIP_TRAILING_WHITESPACE)
        message("Linux Distro: ${LINUX_DISTRO}")
        message("Linux Ver:     ${LINUX_DISTRO_VER}")
    
        if(${LINUX_DISTRO} MATCHES "Ubuntu")
            add_definitions(-DUBUNTU=${LINUX_DISTRO_VER})
        endif()
    
        if(${LINUX_DISTRO} MATCHES "Debian")
            add_definitions(-DDEBIAN="${LINUX_DISTRO_VER})
        endif()
    endif()
    

    UPDATE: I forgot to mention I had to modify my Find script.

    Then I had to edit my FindUnitTest++.cmake script so the find_path() call includes unittest++/UnitTest++.h, and the find_library() call includes libunittest++.

    It's a lot of work we shouldn't have had to do... but for whatever reason the Debian package maintainer is installing UT++ in a directory with lowercase naming... so it is what it is.

  8. rrthomas commented on Feb 21, 2017

    @rrthomas
    Author

    Here's the full horror of what we've implemented in Enchant, which uses autoconf. Note that it includes backwards-compatibility with older pkg-config, and an extra tweak to work with Arch Linux, which ships a differently-broken pkgconfig file.

    dnl ===========================================================================
    dnl Travis runs Ubuntu 14.04 LTS, which doesn't include the following macro
    dnl added to pkg-config in January 2013.
    dnl ===========================================================================
    m4_ifndef([PKG_CHECK_VAR], [
    AC_DEFUN([PKG_CHECK_VAR],
      [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
         AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
         _PKG_CONFIG([$1], [variable="][$3]["], [$2])
         AS_VAR_COPY([$1], [pkg_cv_][$1])
         AS_VAR_IF([$1], [""], [$5], [$4])dnl
      ])# PKG_CHECK_VAR
    ])
    
    dnl ===========================================================================
    dnl Very hackish.
    dnl Ubuntu / Debian ship older version of unittest++ with their own pkg-config
    dnl and include
    dnl ===========================================================================
    PKG_CHECK_EXISTS([UnitTest++],
        [PKG_CHECK_MODULES(UNITTESTPP, [UnitTest++])
    dnl and because of the above, we need to tweak the include until we stop
    dnl supporting this old version.
            PKG_CHECK_VAR(UNITTESTPP_INCLUDE, [UnitTest++], [includedir])
            if test "x$UNITTESTPP_INCLUDE" != "x"; then
                UNITTESTPP_CFLAGS="$UNITTESTPP_CFLAGS -I$UNITTESTPP_INCLUDE/UnitTest++"
            fi
        ],
        [PKG_CHECK_EXISTS([unittest++], [
            PKG_CHECK_MODULES(UNITTESTPP, [unittest++])
                dnl Arch ships a broken custom pkgconfig file, try to fix includedir
                dnl https://bugs.archlinux.org/task/44516
                AC_LANG_PUSH([C++])
                CACHED_CXXFLAGS="$CXXFLAGS"
                CXXFLAGS="$CXXFLAGS $UNITTESTPP_CFLAGS"
                AC_CHECK_HEADERS([UnitTest++.h], [], [
                    PKG_CHECK_VAR(UNITTESTPP_INCLUDE, [unittest++], [includedir])
                    UNITTESTPP_CFLAGS="$UNITTESTPP_CFLAGS -I$UNITTESTPP_INCLUDE/UnitTest++"
    
                    CXXFLAGS="$CACHED_CXXFLAGS $UNITTESTPP_CFLAGS"
                    unset ac_cv_header_UnitTestpp_h
                    AC_CHECK_HEADERS([UnitTest++.h], [], [
                        AC_MSG_WARN([Failed to include UnitTest++.h])
                    ])
                ])
                CXXFLAGS="$CACHED_CXXFLAGS"
                AC_LANG_POP
            ]
        )]
    )
    AC_SUBST(UNITTESTPP_CFLAGS)
    AC_SUBST(UNITTESTPP_LIBS)
    
  9. vicentebolea commented on May 21, 2017

    @vicentebolea
    Contributor

    We had a similar discussion in the OpenSuse bugzilla: https://bugzilla.suse.com/show_bug.cgi?id=1010112

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions