{"action":"created","issue":{"url":"https://api.github.com/repos/RobotLocomotion/drake/issues/1887","repository_url":"https://api.github.com/repos/RobotLocomotion/drake","labels_url":"https://api.github.com/repos/RobotLocomotion/drake/issues/1887/labels{/name}","comments_url":"https://api.github.com/repos/RobotLocomotion/drake/issues/1887/comments","events_url":"https://api.github.com/repos/RobotLocomotion/drake/issues/1887/events","html_url":"https://github.com/RobotLocomotion/drake/issues/1887","id":141770596,"number":1887,"title":"Linker Complains of Duplicate Symbols from Inclusion of drake/util/testUtil.h","user":{"login":"liangfok","id":1388098,"avatar_url":"https://avatars.githubusercontent.com/u/1388098?v=3","gravatar_id":"","url":"https://api.github.com/users/liangfok","html_url":"https://github.com/liangfok","followers_url":"https://api.github.com/users/liangfok/followers","following_url":"https://api.github.com/users/liangfok/following{/other_user}","gists_url":"https://api.github.com/users/liangfok/gists{/gist_id}","starred_url":"https://api.github.com/users/liangfok/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/liangfok/subscriptions","organizations_url":"https://api.github.com/users/liangfok/orgs","repos_url":"https://api.github.com/users/liangfok/repos","events_url":"https://api.github.com/users/liangfok/events{/privacy}","received_events_url":"https://api.github.com/users/liangfok/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":{"login":"liangfok","id":1388098,"avatar_url":"https://avatars.githubusercontent.com/u/1388098?v=3","gravatar_id":"","url":"https://api.github.com/users/liangfok","html_url":"https://github.com/liangfok","followers_url":"https://api.github.com/users/liangfok/followers","following_url":"https://api.github.com/users/liangfok/following{/other_user}","gists_url":"https://api.github.com/users/liangfok/gists{/gist_id}","starred_url":"https://api.github.com/users/liangfok/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/liangfok/subscriptions","organizations_url":"https://api.github.com/users/liangfok/orgs","repos_url":"https://api.github.com/users/liangfok/repos","events_url":"https://api.github.com/users/liangfok/events{/privacy}","received_events_url":"https://api.github.com/users/liangfok/received_events","type":"User","site_admin":false},"milestone":null,"comments":10,"created_at":"2016-03-18T04:11:03Z","updated_at":"2016-03-22T22:26:16Z","closed_at":null,"body":"I want to use [valuecheckMatrix(...)](https://github.com/RobotLocomotion/drake/blob/fa5cbb18d703fe133ede5ea01f7a0a4953bc9c21/drake/util/testUtil.h#L79) in multiple compilation units, specifically [RigidBody](https://github.com/RobotLocomotion/drake/blob/fa5cbb18d703fe133ede5ea01f7a0a4953bc9c21/drake/systems/plants/RigidBody.cpp) and [RigidBodyTree](https://github.com/RobotLocomotion/drake/blob/fa5cbb18d703fe133ede5ea01f7a0a4953bc9c21/drake/systems/plants/RigidBodyTree.cpp). Unfortunately, including testUtil.h in both .cpp files resulted in the following linker error:\r\n\r\n```\r\nLinking CXX shared library ../../lib/libdrakeRBM.so\r\nCMakeFiles/drakeRBM.dir/RigidBody.cpp.o: In function `Eigen::DenseBase<Eigen::CwiseBinaryOp<Eigen::internal::scalar_sum_op<double>, Eigen::Block<Eigen::Matrix<double, 6, 6, 0, 6, 6> const, 3, 3, false> const, Eigen::Transpose<Eigen::Block<Eigen::Matrix<double, 6, 6, 0, 6, 6> const, 3, 3, false> > const> >::isZero(double const&) const':\r\n/home/liang/dev/drake/build/include/eigen3/Eigen/src/Core/products/GeneralBlockPanelKernel.h:1263: multiple definition of `valuecheck(double, double, double)'\r\nCMakeFiles/drakeRBM.dir/RigidBodyTree.cpp.o:/home/liang/dev/drake/drake/../drake/util/testUtil.h:116: first defined here\r\n```\r\nThe problem is because [valuecheck(...)](https://github.com/RobotLocomotion/drake/blob/fa5cbb18d703fe133ede5ea01f7a0a4953bc9c21/drake/util/testUtil.h#L116) is implemented in the same header file resulting in the implementation being included twice. To work around this problem, I modified the method to be `inline`. Here is the commit: https://github.com/liangfok/drake/commit/58d3bb12827f84da2d9b1dbc4367d1e38ffdca7f.\r\n\r\nIs this a valid fix?"},"comment":{"url":"https://api.github.com/repos/RobotLocomotion/drake/issues/comments/200061018","html_url":"https://github.com/RobotLocomotion/drake/issues/1887#issuecomment-200061018","issue_url":"https://api.github.com/repos/RobotLocomotion/drake/issues/1887","id":200061018,"user":{"login":"david-german-tri","id":17437069,"avatar_url":"https://avatars.githubusercontent.com/u/17437069?v=3","gravatar_id":"","url":"https://api.github.com/users/david-german-tri","html_url":"https://github.com/david-german-tri","followers_url":"https://api.github.com/users/david-german-tri/followers","following_url":"https://api.github.com/users/david-german-tri/following{/other_user}","gists_url":"https://api.github.com/users/david-german-tri/gists{/gist_id}","starred_url":"https://api.github.com/users/david-german-tri/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/david-german-tri/subscriptions","organizations_url":"https://api.github.com/users/david-german-tri/orgs","repos_url":"https://api.github.com/users/david-german-tri/repos","events_url":"https://api.github.com/users/david-german-tri/events{/privacy}","received_events_url":"https://api.github.com/users/david-german-tri/received_events","type":"User","site_admin":false},"created_at":"2016-03-22T22:26:15Z","updated_at":"2016-03-22T22:26:15Z","body":"@liangfok points out that #1916 is closely related to this thread.  Ideally, we would have a [custom googlemock matcher](https://github.com/google/googletest/blob/master/googlemock/docs/CookBook.md#extending-google-mock) for Eigen matrix equality:\r\n\r\nEXPECT_THAT(actual_matrix, EigenMatrixIsApproximatelyEqual(expected_matrix));\r\n\r\nI've never written a matcher for a template class before, but I think it's possible (in the long form, not with the convenience macros).  \r\n\r\nIf the matcher doesn't pan out, I would propose simply moving the implementation of valuecheckMatrix into a .cc file as @sammy-tri originally suggested.  As a rule of thumb, if you want to initialize some resources a particular way and make them available to all the test cases, you need a test fixture.  If you merely want to share reentrant code across test cases, vanilla functions and libraries do the job."}}