'make install' considered harmful

7,742 views
Skip to first unread message

Zhanyong Wan (λx.x x)

unread,
Jan 17, 2010, 2:15:59 AM1/17/10
to Google C++ Testing Framework, Google C++ Mocking Framework
Hi, users of gtest and gmock,

In the README file for gtest and gmock, we said that you could install
compiled gtest and gmock libraries on *nix systems using 'make
install'. Then every user of your machine can write tests without
recompiling gtest or gmock.

This seemed like a good idea when we wrote the README, but it has a
got-cha: every user needs to compile his tests using the same compiler
flags used to compile the installed gtest/gmock libraries; otherwise
he may run into undefined behaviors (i.e. the tests can behave
strangely and may even crash for no obvious reasons).

Why? Because C++ has this thing called the One-Definition Rule: if
two C++ source files contain different definitions of the same
class/function/variable, and you link them together, you violate the
rule. The linker may or may not catch the error (in many cases it's
not required by the C++ standard to catch the violation). If it
doesn't, you get strange run-time behaviors that are unexpected and
hard to debug.

If you compile gtest and your test code using different compiler
flags, they may see different definitions of the same
class/function/variable (e.g. due to the use of #if in the code).
Therefore, for your sanity, we recommend to avoid using the installed
gtest/gmock libraries. Instead, each project should compile
gtest/gmock itself such that it can be sure that the same flags are
used for both gtest/gmock and the tests.

For this reason, we now consider it a bad practice to run 'make
install'. We'll remove the instructions from README soon. Thanks,

--
Zhanyong

Zhanyong Wan (λx.x x)

unread,
Mar 25, 2010, 3:34:25 PM3/25/10
to Dmytro Ovdiienko, Google C++ Testing Framework, Google C++ Mocking Framework
(adding the mailing lists back)

Hi Dmytro,

2010/3/25 Dmytro Ovdiienko <dmitriy....@gmail.com>:
> Hi Zhanyong,
>
> According to this logic we should not use installed boost, xerces,
> openssl etc. It is not useful.

Boost is mostly a header-only library, so the logic doesn't apply there.

Not sure about xerces and openssl.

> IMHO it is better to create some guards/fences and not allow user to
> link application or create option-neutral interface.

--
Zhanyong

Josh Kelley

unread,
Mar 26, 2010, 8:46:23 AM3/26/10
to Zhanyong Wan (λx.x x), Google C++ Testing Framework, Google C++ Mocking Framework
2010/3/25 Zhanyong Wan (λx.x x) <w...@google.com>

(adding the mailing lists back)

Hi Dmytro,

2010/3/25 Dmytro Ovdiienko <dmitriy....@gmail.com>:
> Hi Zhanyong,
>
> According to this logic we should not use installed boost, xerces,
> openssl etc. It is not useful.

Boost is mostly a header-only library, so the logic doesn't apply there.

Not sure about xerces and openssl.

Out of curiosity, could you give any examples of flags or compiler options that would result in violating the ODR?

--
Josh Kelley

Zhanyong Wan (λx.x x)

unread,
Mar 26, 2010, 11:32:29 AM3/26/10
to Josh Kelley, Google C++ Testing Framework, Google C++ Mocking Framework
2010/3/26 Josh Kelley <jos...@gmail.com>:

gtest has many classes/functions whose definitions are controlled by
#if. If you pass different -DGTEST_HAS_FOO=1 flags to different
translation units, you'll violate the ODR. Or sometimes people use -D
to select which malloc library to use (debug vs release), and you have
to use the same malloc library across the board.

--
Zhanyong

Zhanyong Wan (λx.x x)

unread,
Jul 6, 2011, 1:34:30 PM7/6/11
to KjellKod, Google C++ Testing Framework
(moving the discussion to googletes...@googlegroups.com, as I
don't work on Google Test any more. Please send future messages --
thanks!)

Hi KjellKod,

2011/7/1 KjellKod <kjell.h...@gmail.com>:
>
> One problem with 1.6 is that previously it was easy to have example
> source code
> with a simple prerequisite that to compile the example you needed
> gtest installed.
>
> With 1.6 this is no longer possible. One way to do it is as you
> suggest, to have
> the example appended with gtest-1.6 and when making the example also
> building and linking gtest.
>
> Well, a small example just grew tremendously and all of a sudden gtest
> is not so easy to use anymore. I understand the reasons you state
> above but I don't think the solution is as good as it should be :(
>
> Regards
> KjellKod
>
> FYI:
>
>
> Simple steps like the ones below is only in my memory now:
> Some www user downloads an example, realizes that he needs gtest as
> well and downloads and unzips it.
>
> cd gtest--some-version
> ./configure
> make
> make install
>
> cd ~/some_example;
> ./make
> ./run_some_example_executable

The new workflow would be:

download a gtest release package and unpack it (no need to configure or make)
download the example
edit Makefile in the example to point to the directory where gtest is unpacked
make
run the example executable

See http://code.google.com/p/googletest/source/browse/trunk/make/Makefile
for an example on what the Makefile in the example should look like.
Thanks,

>
>
>
>
>
>
>
>
>
> On Jan 17 2010, 9:15 am, Zhanyong Wan (λx.x x) <w...@google.com>

--
Zhanyong

Matthew Woehlke

unread,
Jul 31, 2012, 7:51:15 PM7/31/12
to googletes...@googlegroups.com, Dmytro Ovdiienko, Google C++ Mocking Framework
On Thursday, March 25, 2010 3:34:25 PM UTC-4, Zhanyong Wan wrote:

2010/3/25 Dmytro Ovdiienko wrote:
> Hi Zhanyong,
>
> According to this logic we should not use installed boost, xerces,
> openssl etc. It is not useful.

+1. Fedora as an example has thousands of -devel packages. I am confident that at least a good fraction of that number contain C++ shared libraries, that the Fedora developers believe are okay to use with my application in pre-built form. It seems to me (also) that if gtest cannot say the same, that gtest is doing something wrong. (It's also a violation of Fedora packaging guidelines for a package to include a local copy of another project.)

I think it would be much better to look into why this is a problem and fix it. (True, there are edge cases¹ where using ANY pre-built library is a problem, but I don't see why gtest should be problematic more often than any other library.)

(¹ e.g. mixing memory allocators can be a problem, but only if your code is improperly written such that you try to free objects via one allocator that were allocated with a different one.)

-- 
Matthew

Tim St. Clair

unread,
Jul 29, 2013, 11:27:20 AM7/29/13
to googletes...@googlegroups.com, Dmytro Ovdiienko, Google C++ Mocking Framework
So downstream packages that have a dependency will have to incorporate for redistribution?  This is a bad idea!  

It seems like you have a symbol collision problem, and there are multiple ways to get around that, or ensure uniqueness. 

-Tim

Pedram Hadjian

unread,
Feb 3, 2014, 4:26:27 AM2/3/14
to googletes...@googlegroups.com, Google C++ Mocking Framework
Hello GTest developers,

I took a shot at a possible solution. I think your argument concerning the compiler flags are valid, because of the definition flags. I could not really think of a way to break the ODR-thing, though. It would really be helpful to provide a small example of what you mean (example like in 'try-it-yourself in four easy steps').

I work on Ubuntu 10.04 and 12.04 as well as on Mac OS X Mavericks using gtest-1.6.0 (downloaded the zip, SHA1: 00d6be170eb9fc3b2198ffdcb1f1d6ba7fc6e621). Since 1.6.0 doesn't work with Mavericks, I tested my solution only on Ubuntu.

My first goal was to merely use cmake's find_package() command to find the gtest libraries in my project directory and make it import the compiler flags to be used. This should be easily extendable to make it work for a system-wide installation (not tested yet).

For this, I created cmake config files for gtest, using cmake's ProjectConfig.cmake approach (described here: http://www.cmake.org/Wiki/CMake/Tutorials/How_to_create_a_ProjectConfig.cmake_file).

Short version first:
1. Download the attached CMakeLists.cmake, GTestConfig.cmake.in and GTestConfigVersion.cmake.in and put them into the freshly unzipped gtest-1.6.0 directory.
2. Compile gtest-1.6.0.
3. Download the attached FindGTest.cmake and put it somewhere cmake will find it (search path is determined by the CMAKE_MODULE_PATH and default is /usr/share/cmake-<version>/Module on linux).
4. Edit FindGTest.cmake and add the PATHS argument to the find_package() command to point to your gtest directory.
5. In your own project's CMakeLists.cmake file insert the following w/o the quotes: "find_package(GTest 1.6.0 EXACT REQUIRED)".
6. Now you can use the variables imported by find_package() as follows:

add_executable(<name> <sourcefiles>)
target_link_libraries<name> ${GTEST_MAIN_LIBRARIES})
set_target_properties(<name> PROPERTIES
                       COMPILE_FLAGS ${GTEST_CXX_FLAGS})

You can find a working example in my home project. Clone https://github.com/hadjian/ToyProjects.git and run 

cmake .
make


Longer version:

The attached CMakeLists.txt is taken from the root of gtest-1.6.0 and modified to create a fake source file and pass it as an argument to your internal cxx_executable() function. After that, the target is queried for the COMPILE_FLAGS property, which were attached by your function. These flags are then written to the GTestConfig.cmake file to be found by FindGTest.cmake. At first, I used the internal cxx_default variable, but decided against it, because it is internal after all.

CMakeLists.txt also exports the gtest and gtest_main targets, as well as the version number of gtest. Exporting targets is chosen over cmake's find_library() command , because library dependencies of those targets are transitively exported, too (I am talking about -lpthread).

Could you check out this approach and give me feedback, whether I'm missing anything. Otherwise I will go ahead and try to build a package, that installs libs and config files into the system.

Regards,

Pedram
CMakeLists.txt
GTestConfig.cmake.in
GTestConfigVersion.cmake.in
FindGTest.cmake
Reply all
Reply to author
Forward
Message has been deleted
0 new messages