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

Doctest is not able to compile on OSX #126

Closed
arnavb opened this issue Apr 16, 2018 · 23 comments
Closed

Doctest is not able to compile on OSX #126

arnavb opened this issue Apr 16, 2018 · 23 comments

Comments

@arnavb
Copy link

arnavb commented Apr 16, 2018

Description

I am trying to get my Travis CI build working with doctest (I'm switching from Catch to this for performance), but my build is not working on OSX (It is for Linux). In my Travis CI logs, I see the following error:

Undefined symbols for architecture x86_64:
  "std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::operator<<<char, std::__1::char_traits<char>, std::__1::allocator<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)", referenced from:
      doctest::String doctest::detail::stringifyBinaryExpr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, char [6]>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, char const*, char const (&) [6]) in hello_world_test.cpp.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [test/test_runner] Error 1
make[1]: *** [test/CMakeFiles/test_runner.dir/all] Error 2
make: *** [all] Error 2

Steps to reproduce

I'm using CMake, and my invocation command is:

cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_CXX_COMPILER=$COMPILER -DBUILD_TESTS=ON ..

(COMPILER is set to clang++ and BUILD_TYPE is set to Debug and Release, both of which fail)

The CMake configuration I am using is (for flags):

if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror")
    set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g")
    set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2")
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
    # ...
endif(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU")

And the test configuration:

set(TEST_SOURCES
    factorial_test.cpp
    hello_world_test.cpp
)

add_library(doctest INTERFACE)
target_include_directories(doctest INTERFACE 
    "${CMAKE_SOURCE_DIR}/third_party/doctest" # Contains single header
)

add_executable(test_runner test_runner.cpp ${TEST_SOURCES})
target_link_libraries(test_runner Project-Name-lib doctest)

add_test(all_tests test_runner)

Extra information

  • doctest version: v1.2.8
  • Operating System: Travis CI OSX XCode image 9.2
  • Compiler+version: AppleClang 9.0.0.9000039
@onqtam
Copy link
Member

onqtam commented Apr 16, 2018

weird... I have an OSX build of doctest on travis with the same version of clang:
https://travis-ci.org/onqtam/doctest/jobs/364548718

I also tried your branch locally on Windows with VS 2017 and GCC 7.2 and its fine - seems like an OSX issue.

Normally I try to resolve serious issues as fast as possible but currently I have no time to spare - I have to prepare 2 full lectures - after 10 days everything will be over and I'll be able to perhaps try this on a Mac - sorry for the inconvenience.

One other note: doctest has REQUIRE asserts just like Catch - its not just CHECK that is available.

@arnavb
Copy link
Author

arnavb commented Apr 16, 2018

@onqtam Thanks for the quick reply. I'll keep trying to fix this ... somehow. For now, I'm going to isolate this issue by remove all extraneous details and then see if the build works. Thanks for that note about the REQUIRE asserts. Turns out, I actually needed CHECK asserts all along (I just found out the difference recently).

@arnavb
Copy link
Author

arnavb commented Apr 16, 2018

@onqtam Ok Update. I've created another repository in which I'm trying to use doctest on OSX, and ... it works fine! Now I have to figure out the difference between it and my repository. The repository is here: https://github.com/arnavb/osx-doctest

@onqtam
Copy link
Member

onqtam commented Apr 16, 2018

Hi there,

So I forked and played with your 2 repositories and here is what I tried:

  • from the original repo: when I removed any use of std::string from the asserts the problem disappeared.
  • moving from xcode9.2 to xcode9.3 or xcode9 didn't change anything.
  • not setting the CXX standard - didn't affect anything.
  • when I moved the implementation of doctest to a separate file however the problem occurred.
  • and after that I included <iostream> in the file with the asserts and std::string usage in them and the problem went away........................

My bet is that this is a toolchain issue - and it saddens me that such problems occur in 2018. I guess I'll have to investigate this further...

@arnavb
Copy link
Author

arnavb commented Apr 16, 2018

@onqtam Hmmm... that's interesting. I've added a #include <string> to hello_world_test.cpp and am now waiting for results. Let's see whether this works or not...

UPDATE:
Nope, adding #include <string> changed nothing. Still getting the same error.

ANOTHER UPDATE:
I can confirm that commenting out everything involving std::string solves the problem and all the tests "pass".

@onqtam
Copy link
Member

onqtam commented Apr 16, 2018

I added <iostream> in that .cpp - not <string> (which is already included by project-abbr/hello_world.hpp)......

including a header should not result in fixing link errors............. I have exactly 0 pleasant memories of native development under OSX...

Windows has the #pragma comment lib stuff where a header can say that a certain library is linked to, but in our case there is no such thing in Unix (atleast to my knowledge)...

Anyway - I don't think I can spare more time on this for now - sorry. The <iostream> header should fix the build problem but I certainly don't like hacks which I don't understand...

@arnavb
Copy link
Author

arnavb commented Apr 16, 2018

@onqtam You're right. I added <iostream> and it works! (Finally). However, this solution is ugly on more than one level. <string> is supposed to have a complete version of std::string since that's what the header is for! Why is <iostream>, which only probably including <string> itself, solving a LINKING PROBLEM while the header that implements std::string isn't? 😶

😖

On a side note...

I really want to thank you for all of your help with this issue! I know it must be hard to take time out of your busy schedule as you mentioned before to help a problem that as we found out isn't even caused by doctest! Many others would just reject people with such problems and I appreciate your help as such. Thanks again!

I'm going to enjoy using doctest (especially the performance boost 😛) and will definitely recommend it to others.

@arnavb arnavb closed this as completed Apr 16, 2018
jacobdufault pushed a commit to jacobdufault/cquery that referenced this issue Apr 24, 2018
Fix the following building error on macOS.
```
Undefined symbols for architecture x86_64:
  "std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::operator<<<char, std::__1::char_traits<char>, std::__1::allocator<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)", referenced from:
      doctest::String doctest::detail::stringifyBinaryExpr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, char [13]>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, char const*, char const (&) [13]) in method.cc.1.o
ld: symbol(s) not found for architecture x86_64
```

See more at doctest/doctest#126.

Fixes #649.
onqtam added a commit that referenced this issue Aug 21, 2018
…em is this: when using clang from xcode - that means libc++. in that case I include <iosfwd> instead of forward-declaring std::ostream myself. Then if the user includes somewhere only the doctest header and <string> and then does a comparison - then and only then will there be some linker issue which I previously had managed to resolve by telling the users to also include <iostream> in that place in their tests. This is a toolchain issue when using the <iosfwd> header - the details are still not clear to me but I managed to get the linker to pull in what is necessary by adding a dummy unused global function in the implementation of doctest that uses operator<< of std::string to print to std::cout.
@onqtam
Copy link
Member

onqtam commented Aug 21, 2018

@arnavb finally resolved "properly" - turns out the problem is this: when using clang from xcode - that means libc++. in that case I include <iosfwd> instead of forward-declaring std::ostream myself. Then if the user includes somewhere only the doctest header and <string> and then does a comparison - then and only then will there be some linker issue which we resolved by including <iostream> in the tests. This is a toolchain issue when using the <iosfwd> header - the details are still not clear to me but I managed to get the linker to pull in what is necessary by adding a dummy unused global function in the implementation of doctest that uses operator<< of std::string to print to std::cout.

the <iostream> header should no longer be necessary - try the version of the header from the dev branch (soon to be released in master as version 2.0!)

onqtam added a commit that referenced this issue Aug 23, 2018
…em is this: when using clang from xcode - that means libc++. in that case I include <iosfwd> instead of forward-declaring std::ostream myself. Then if the user includes somewhere only the doctest header and <string> and then does a comparison - then and only then will there be some linker issue which I previously had managed to resolve by telling the users to also include <iostream> in that place in their tests. This is a toolchain issue when using the <iosfwd> header - the details are still not clear to me but I managed to get the linker to pull in what is necessary by adding a dummy unused global function in the implementation of doctest that uses operator<< of std::string to print to std::cout.
seanmiddleditch added a commit to potatoengine/potato that referenced this issue Jan 14, 2019
@agurtovoy
Copy link

FYI, I just ran into this issue with doctest 2.3.1 (macOS, apple-clang 10.0, libc++), with something as simple as this:

#include <doctest/doctest.h>
#include <string>

TEST_CASE( "[console] console" ) 
{
    REQUIRE( std::string("hello") == "hello" );
}

(see the errors below). Adding explicit #include <iostream> helped.

Undefined symbols for architecture x86_64:
  "std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::operator<<<char, std::__1::char_traits<char>, std::__1::allocator<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)", referenced from:
      doctest::String doctest::detail::stringifyBinaryExpr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, char [6]>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, char const*, char const (&) [6]) in console.test.cpp.o

@onqtam
Copy link
Member

onqtam commented May 13, 2019

@agurtovoy well that's unfortunate..... are you building with LTO? The only explanation I have is that this function gets optimized out:
https://github.com/onqtam/doctest/blob/2.3.2/doctest/doctest.h#L6009

@agurtovoy
Copy link

@onqtam Good guess, I was building a release build and had -Wl,-dead_strip_dylibs in the args. Just tested a debug configuration, and it does not need the explicit <iostream> include.

@onqtam
Copy link
Member

onqtam commented May 14, 2019

Gosh... I'll find a way to "fix" it - perhaps either with some magic attribute to that function or by calling it somewhere within doctest (after making it noinline so it doesn't get inlined and optimized out)

@jenisys
Copy link

jenisys commented Jun 8, 2019

I have the same issue with newer doctest versions (above 2.2.2).
When I build with CMAKE_BUILD_TYPE=Release linking the test executable fails to link due to the missing symbols doctest::detail::stringifyBinaryExpr(...), basically a simple test using assertion macros.

EXAMPLE: Fails to build test executable

#include "doctest/doctest.h"
#include <string>
...

WORK-AROUND 1: Succeeds to build test executable

#include "doctest/doctest.h"
#include <string>
#include <sstream>   // NEEDED-FOR: CMAKE_BUILD_TYPE=Release
...

WORK-AROUND 2: Succeeds to build test executable

#define DOCTEST_CONFIG_DISABLE 1
#include "doctest/doctest.h"
#include <string>
...

Build details:

# -- HINT: Not using -Wl,-dead_strip_dylibs
/Applications/Xcode.app/.../c++ -O3 -DNDEBUG ... 
   -isysroot /Applications/Xcode.app/.../SDKs/MacOSX10.14.sdk 
   -Wl,-search_paths_first -Wl,-headerpad_max_install_names ...

NOTE:
The doctest all_features/assertation_macros.cpp builds without problems with CMAKE_BUILD_TYPE=Release that uses -DDOCTEST_CONFIG_DISABLE while compiling the object.

@onqtam
Copy link
Member

onqtam commented Jun 11, 2019

@jenisys sorry for the late reply. Can you confirm that you are experiencing this with version 2.3.3 (the latest one) as well? That would be really unfortunate... I'm so puzzled as to why the linker would be reporting stringifyBinaryExpr specifically... I'll have to think about this.

Using DOCTEST_CONFIG_DISABLE means that there are no tests and no test runner - it's as if you are not using doctest at all. If even with it you were experiencing these linker errors I would have been even more puzzled.

@onqtam onqtam reopened this Jun 11, 2019
@jenisys
Copy link

jenisys commented Jun 21, 2019

@onqtam
Yes, the problem still exists w/ dockest-2.3.3 (and the current HEAD).
Sorry for the late reply.

@drehren
Copy link

drehren commented Dec 19, 2019

Hi! I'm experiencing similar problems, in macOS and linux (archlinux, gcc 9.2), although not when using strings...
I've created a repo with the sample code here.

@onqtam
Copy link
Member

onqtam commented Dec 19, 2019

@drehren I think in your case the problem could be solved by using DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE - can you try/confirm that it indeed solves the issue?

@drehren
Copy link

drehren commented Dec 19, 2019

Thanks @onqtam ! It did solve the issue.
I hadn't read about those configuration flags before.

@onqtam
Copy link
Member

onqtam commented Dec 19, 2019

@drehren did you look in the FAQ? It's not mentioned there but I wonder if I should add an entry about this specific issue in there...

@drehren
Copy link

drehren commented Dec 19, 2019

@onqtam I did look through it now that I remember... I think an entry there would be great.

Ghabry added a commit to Ghabry/easyrpg-player that referenced this issue May 26, 2020
Ghabry added a commit to Ghabry/easyrpg-player that referenced this issue May 26, 2020
Ghabry added a commit to Ghabry/easyrpg-player that referenced this issue Aug 18, 2020
@lorrden
Copy link

lorrden commented Jan 29, 2021

I had the same issue, but only when I build with optimisations. I tried to update doctest to 2.4.4, but that did not help. So I added the include trick and that worked. The optimised build had asserts enabled, may try it without, but debug with asserts work fine.

This was on macOS 10.13 Catalina.

@blurpy
Copy link

blurpy commented Apr 24, 2021

I had the same issue with doctest 2.4.6 building on macOS in release mode.
The workaround of adding include of <iostream> in the affected test worked fine.

DerThorsten added a commit to DerThorsten/xtl that referenced this issue Jun 22, 2021
onqtam added a commit that referenced this issue Dec 13, 2021
…laring anything from std - hopefully fixing #126 and #356 at last
@onqtam
Copy link
Member

onqtam commented Dec 15, 2021

This has finally been fixed by actually including the right headers with clang & libc++ - already in the dev branch.
Closing this - will release an official version soon!

@onqtam onqtam closed this as completed Dec 15, 2021
hurricane1026 pushed a commit to clapdb/doctest that referenced this issue Nov 3, 2022
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

7 participants