Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
rrthomas opened this issue Jan 14, 2017 · 9 comments
Open

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

rrthomas opened this issue Jan 14, 2017 · 9 comments

Comments

@rrthomas
Copy link

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.

@pjohnmeyer
Copy link
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?

@rrthomas
Copy link
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".

@grahamreeds
Copy link
Contributor

grahamreeds commented Jan 20, 2017 via email

@rrthomas
Copy link
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.

@pjohnmeyer
Copy link
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.

@rrthomas
Copy link
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)

@ohz10
Copy link
Contributor

ohz10 commented Feb 20, 2017

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.

@rrthomas
Copy link
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)

@vicentebolea
Copy link
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
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants