Something odd happened to C++ 11 in Mavericks? - c++

I am using gcc 4.8 installed via MacPorts, and old C++11 code would not compile anymore
if I use the compiler without the -std=c++11 flag, it works just fine with this test code
#include <cctype>
int main() {
std::isalnum('c');
return 0;
}
[bash] g++48 test.cpp
But after the Mavericks upgrade I get the following compile error:
[bash] g++48 -std=c++11 test.cpp
Undefined symbols for architecture x86_64:
"isalnum(int)", referenced from:
_main in ccvsKeqJ.o
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status
Does anyone have a clue what might cause this issue?
I appreciate any help

OSX Mavericks upgrade will wipe out a number of XCode installation directories. In order to restore them, you need to reinstall the XCode command-line tools.
xcode-select --install
Then agree to the download prompt.
If this fails, you can try and install by hand from here: OSX: Xcode Downloads

This doesn't relate to mis-installed osx cmdline tools, but, as clearly explained in this SO question, to some inline-related macros changed in 10.9 SDK headers, in particular in usr/include/sys/cdefs.h.
As a quick workaround, you can leverage GCC's "fixed include" mechanisms and provide a slightly tweaked version of /usr/include/sys/cdefs.h that prevents the problem when compiling c++ code as follows:
Find where your installed GCC is, I'll use GCCROOT
mdkir $GCCROOT/lib/gcc/x86_64-apple-darwinXXX/4.X.Y/include-fixed/sys (where darwinXXX depends on where you compiled GCC on and 4.X.Y is the GCC version you compiled)
Edit the just copied file ..../include-fixed/sys/cdefs.h to apply the following patch:
## -216,7 +215,7 ##
#if __STDC_VERSION__ >= 199901L && (!defined(__GNUC__) || defined(__clang__))
# define __header_inline inline
-#elif defined(__GNUC__) && defined(__GNUC_STDC_INLINE__)
+#elif defined(__GNUC__) && defined(__GNUC_STDC_INLINE__) && !defined (__cplusplus)
# define __header_inline extern __inline __attribute__((__gnu_inline__))
#elif defined(__GNUC__)
# define __header_inline extern __inline
This causes, when compiling c++ code, the expansion
__header_inline --> extern __inline
instead of
__header_inline --> extern __inline __attribute__((__gnu_inline__))
which would apparently cause GCC not to really inline isalnum and hence leave a link-time dependency on the symbol, i.e. it would try to find it in some library, leading to the link error.

Maybe you only installed the 32 bit part of gcc? Try -m32.

I tried to reinstall Xcode command line tools, since yesterday using
xcode-select --install
Unfortunately it doesn't work anymore, too
But then I was able to get it from
https://developer.apple.com/downloads/index.action
Unfortunately, reinstalling the command line tools didn't help either :(
I guess I will no go with
clang++ -std=c++11 -stdlib=libc++
until there is a official solution.

Related

Does llvm 9 support std::filesystem on versions of the mac prior to 10.15?

I have an old Mac (circa 2009) running El Capitan version 10.11.6. Apple doesn't allow further updates of its OS on my machine, but through Macports it serves as a fine development environment for non-Apple-specific software.
I'm compiling with g++ 9.2, which supports std::filesystem out of the box, and with clang 8.0, which doesn't. (Using each compiler's native standard library, in each case.) And I'm compiling with --std=c++2a.
I've noticed the llvm 9 is supposed to support std::filesystem out of the box (https://libcxx.llvm.org/docs/UsingLibcxx.html#using-filesystem), so I downloaded clang/llvm 9 through Macports. Unfortunately, I'm hitting a snag.
Minimal code to reproduce error is a simplification of the example from cppreference.com (https://en.cppreference.com/w/cpp/filesystem/path/path)
#include <filesystem>
#include <iostream>
namespace fs = std::filesystem;
int
main()
{
fs::path p1 = "/usr/lib/sendmail.cf";
std::cout << "p1 = " << p1 << '\n';
}
And here's the CmakeLists.txt
cmake_minimum_required(VERSION 3.15.5)
project(bug LANGUAGES CXX)
add_executable (bug main.cpp)
target_compile_options(bug PRIVATE "-std=c++2a")
And here's the compiler's complaints:
[build] Starting build
[proc] Executing command: /opt/local/bin/cmake --build ~/temp/build/debug/clang --config debug --target all -- -j 10
[build] [1/2 50% :: 1.598] Building CXX object CMakeFiles/bug.dir/main.cpp.o
[build] FAILED: CMakeFiles/bug.dir/main.cpp.o
[build] /opt/local/bin/clang++ -g -std=c++2a -MD -MT CMakeFiles/bug.dir/main.cpp.o -MF CMakeFiles/bug.dir/main.cpp.o.d -o CMakeFiles/bug.dir/main.cpp.o -c ../../../main.cpp
[build] ../../../main.cpp:9:8: error: 'path' is unavailable: introduced in macOS 10.15
[build] fs::path p1 = "/usr/lib/sendmail.cf";
[build] ^
[build] /opt/local/libexec/llvm-9.0/bin/../include/c++/v1/filesystem:738:24: note: 'path' has been explicitly marked unavailable here
[build] class _LIBCPP_TYPE_VIS path {
...
Working backward, I find this bit of code in /opt/local/libexec/llvm-9.0/include/c++/v1/__config:
# define _LIBCPP_AVAILABILITY_FILESYSTEM \
__attribute__((availability(macosx,strict,introduced=10.15))) \
__attribute__((availability(ios,strict,introduced=13.0))) \
__attribute__((availability(tvos,strict,introduced=13.0))) \
__attribute__((availability(watchos,strict,introduced=6.0)))
As far as I can determine, this #define is the ultimate cause of the above error message.
So, my questions are:
Is this a bug with LLVM? After all, GCC doesn't introduce a dependency between std::filesystem and the OS version.
Is this a bug with Macports? Maybe they didn't use the correct flags when building?
If I were to build LLVM and Clang natively, can I work around this issue?
Is it an issue at all? Maybe the good folks at LLVM know something that the good folks at GCC don't.
NOTE: There's a similar question involving clang/llvm downloaded through Homebrew. Unfortunately, the commentary was not helpful. [LLVM-9 clang-9 OSX]: std::filesystem::path unrecognized
I've been looking through LLVM and encountered the following lines:
// Decide whether to use availability macros.
#if !defined(_LIBCPP_BUILDING_LIBRARY) && \
!defined(_LIBCPP_DISABLE_AVAILABILITY) && \
__has_feature(attribute_availability_with_strict) && \
__has_feature(attribute_availability_in_templates)
# ifdef __APPLE__
# define _LIBCPP_USE_AVAILABILITY_APPLE
# endif
#endif
So I passed -D_LIBCPP_DISABLE_AVAILABILITY to the compiler and it worked! I doubt that it's a valid solution, but it may help someone. Another option could be sticking to https://github.com/gulrak/filesystem which is basically std::filesystem, but outside of the standard library.
Answering some of your questions:
Is this a bug with LLVM? After all, GCC doesn't introduce a dependency between std::filesystem and the OS version.
Well, it's not a bug, but yes, it's a feature of LLVM and it seems that it's made especially for Apple.
Is this a bug with Macports? Maybe they didn't use the correct flags when building?
No, it's not a bug of Macports or Homebrew.
If I were to build LLVM and Clang natively, can I work around this issue?
As you could see this availability feature is in the sources, so it seems that it doesn't matter if you build it from sources or using a package manager.
Is it an issue at all? Maybe the good folks at LLVM know something that the good folks at GCC don't.
Unfortunately, I can't state anything here, but it should've been done for a reason.

lli: LLVM ERROR: Cannot select: X86ISD::WrapperRIP TargetGlobalTLSAddress:i64

Running the following code with clang++ -S -emit-llvm main.cpp && lli main.ll on Linux(Debian)
#include <future>
int main () {
return std::async([]{return 1;}).get();
}
fails to run on lli due to the following error:
LLVM ERROR: Cannot select: 0xd012e0:
i64 = X86ISD::WrapperRIP TargetGlobalTLSAddress:i64<i8** #_ZSt15__once_callable> 0 [TF=10]
0xd020c0: i64 = TargetGlobalTLSAddress<i8** #_ZSt15__once_callable> 0 [TF=10]
In function: _ZSt9call_onceIMNSt13__future_base13_State_baseV2EFvPSt8functionIFSt10unique_ptrINS0_12_Result_baseENS4_8_DeleterEEvEEPbEJPS1_S9_SA_EEvRSt9once_flagOT_DpOT0_
Questions:
What does it mean?
Are there any compiler-flags that fix this problem?
using -stdlib=libc++ compiles and runs successfully*; what specific features is libstdc++ using that cause this issue ?
EDIT:
The motivation behind this question is to understand the differences between libc++ and libstdc++ that leads to this specific error message (on Linux) in llvm's orcjit.
On OSX gcc has been deprecated and clang uses by default libc++.
To reproduce this error on OSX you probably have to install gcc & use -stdlib=libstdc++.
Here is the llvm-ir (it's unfortunately to big to embed it here directly)
EDIT:
The error turned out to be caused by the lack of TLS support in the JITer. This answer describes another problem concerned with linking and lli.
If you have a look at the generated IR from clang++ -std=c++11 -S -emit-llvm test.cpp, you will find that many of the symbols, e.g. _ZNSt6futureIiE3getEv, are only declared, but never defined. The linker is never called, since -S "Only run[s] preprocess and compilation steps" (clang --help).
lli only executes the IR Module and does no "implicit" linking, how is it supposed to know which libraries to link in?
There are different solutions to this, depending on why you are using lli:
compile and link the IR Module: llc main.cpp && clang++ -lpthread main.s (pthread is required s. What is the correct link options to use std::thread in GCC under linux?)
(unconfirmed) use LD_PRELOAD="x.so y.so" to force-load the libraries before running lli
JIT the module programmatically and use LoadLibraryPermanently(nullptr) (adds symbols of the program into the search space) and LoadLibraryPermanently(file, err) for additional libs (s. http://llvm.org/docs/doxygen/html/classllvm_1_1sys_1_1DynamicLibrary.html)
I can only guess as to why libc++ works for you since it fails on my machine, but presumably it's the case because it is loaded into lli already and lli calls sys::DynamicLibrary::LoadLibraryPermanently(nullptr) to add the program's symbols to its JIT search space (s. https://github.com/llvm-mirror/llvm/blob/release_40/tools/lli/OrcLazyJIT.cpp#L110).
The LLVM-dev mailinglist pointed out:
What does it mean?
The llvm-backend in orcjit does currently not support thread-local storage(TLS)
a minimal example is:
extern thread_local int tls;
int main() {
tls = 42;
return 0;
}
using -stdlib=libc++ compiles and runs successfully*; what specific features is libstdc++ using that cause this issue ?
this works because libc++ future::get implementation does not use thread_local keyword.
Are there any compiler-flags that fix this problem?
currently there is no solution.
Using lli -relocation-model=pic trades this problem with a relocation failure.

Undefined symbols for architecture x86_64: _memalign: TCMalloc

I have made some changes and I am trying to compile google-perf(TCMalloc) on Mac OS X Yosemite 10.10.3, I followed step return here Install gperf. But, I am getting below linking error.
./autogen.sh basically autoreconf -i -> successful no error
./configure -> successful no error
make -> below error
libtool: link: g++ -D_THREAD_SAFE -Wall -Wwrite-strings -Woverloaded-virtual -Wno-sign-compare -fno-builtin-malloc -fno-builtin-free -fno-builtin-realloc -fno-builtin-calloc -fno-builtin-cfree -fno-builtin-memalign -fno-builtin-posix_memalign -fno-builtin-valloc -fno-builtin-pvalloc -Wno-unused-result -fno-builtin -g -O2 -D_THREAD_SAFE -o .libs/tcmalloc_minimal_unittest src/tests/tcmalloc_minimal_unittest-tcmalloc_unittest.o src/tests/tcmalloc_minimal_unittest-testutil.o -Wl,-bind_at_load ./.libs/libtcmalloc_minimal.dylib ./.libs/liblogging.a
Undefined symbols for architecture x86_64:
"_memalign", referenced from:
testing::RunAllTests(int, char**) in tcmalloc_minimal_unittest-tcmalloc_unittest.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I installed gcc but didn't help.
Can any one help me to resolve this issue?
I'm not OSX expert. I do have some access to older OSX version where I test things from time to time. But I do know a bit of gperftools as one of maintainers of this code. So let me try to help you with some ideas.
Please make sure that everything compiles without your changes. I.e. lets exclude your changes as potential source of your issue.
See if source release (.tar.gz) compiles. I.e. it already includes configure which bundles autoconf & automake & libtool that is known to work. So just download .tar.gz release into separate place, unpack, ./configure && make (so without ./autogen.sh step) and see if it works.
It is possible that issue you're experiencing is something specific to newer version of OSX (I think yosemite is latest but not sure since apple stuff is not my cup of tea). One way to avoid this possibility is testing your change under GNU/Linux virtual machine (while continuing to investigate why things don't work on OSX ).
The problem is that something went wrong with the configuration. Mac OS X does not support memalign, which is why the build is failing (see OSX lacks memalign).
Here are two easy options that should almost certainly work:
Download a release tarball rather than building from the source. This way, you should avoid any issues with autoconf and friends not doing what you hoped they would do.
Install it using Homebrew. Homebrew is a Mac package manager that should be your go-to for most of your Unix software needs: it just works, unlike building packages from source. If you've used apt-get or something similar, it will feel quite familiar. There are "formulas"(packages) for tons of things, including tcmalloc; install MacBrew, then do this:
sudo brew install google-perftools
I am using a slightly newer version of Yosemite, and I just verified that this works.

Compiling CodeViz patch for GCC on 64 bit debian

I am trying to compile CodeViz on 64 bit Debian. However, I am finding that the included patch for GCC causes GCC not to compile. When I extract GCC 4.6 and compile it manually (by running
$ ../gcc-4.6.4/configure --prefix=/home/jeremy/gcc-codeviz --enable-languages=c,c++ --disable-bootstrap
$ make
) it compiles without error. However, when I apply the included patch, it fails with the error
/usr/bin/ld: ../libsupc++/.libs/libsupc++convenience.a(cp-demangle.o): relocation R_X86_64_32S against `.rodata' can not be used when making a shared object; recompile with -fPIC
../libsupc++/.libs/libsupc++convenience.a(cp-demangle.o): error adding symbols: Bad value
collect2: ld returned 1 exit status
The patch can be seen here http://pastebin.com/djSQYe5a . It's really not that complicated, doesn't change any build options or includes, and doesn't use any advanced language features. I really don't understand how this causes a linking error which doesn't show up in the vanilla gcc build. Furthermore, the error itself occurs in "cp-demangle.o", which I don't think should even be touched by the patch! My best guess is that it has something to do with the extern int cdepn_dump which is declared, or the declaration of the functions in tree.h.
Any help is appreciated.
This patch can be applied to the source of Debian gcc-4.6
apt-get source gcc-4.6
cp gcc-4.6.2-cdepn.diff gcc-4.6-4.6.3/debian/patches
to rules.patch
nano gcc-4.6-4.6.3/debian/rules.patch
debian_patches += \
libstdc++-pic \
...
gcc-4.6.2-cdepn \
The main error occurs because the function fprintf.
The default compiler flags includes -Wformat -Wformat-security which is what gives this error. Disabled with -Wformat=0 or -Wno-format-security in CPPFLAGS or/and CFLAGS.
Also look to gcc-4.6-4.6.3/debian/patches/fix-warnings.diff for src/gcc/toplev.c and to gcc-4.6-4.6.3/debian/rules2, dpkg-buildflags
just for information.
export DEB_BUILD_MAINT_OPTIONS=hardening=-all,-format
export DEB_CFLAGS_MAINT_APPEND=-fPIC,-Wformat=0,-Wno-format-security
export DEB_CPPFLAGS_MAINT_APPEND=-fPIC,-Wformat=0,-Wno-format-security
export DEB_CXXFLAGS_MAINT_APPEND=-fPIC,-Wformat=0,-Wno-format-security
dpkg-buildflags
dpkg-buildpackage -b -d -rfakeroot -us -uc

Gcc searches for header files under the wrong directory

I have two versions of gcc/g++ installed: gcc-4.5(installed from package manager, binary files are under /usr/bin, header files are under /usr/include) and gcc-4.4.3(compiled by myself, put under /opt/gcc-4.4.3).
When I made gcc/g++ 4.4.3 to be the default version (using "update-alternatives" to make /usr/bin/gcc and /usr/bin/g++ point to the corresponding one under directory "/opt/gcc-4.4.3/bin") and compiled the files, it always reported the following errors:
/usr/include/c++/4.5/bits/basic_string.h:1659: undefined reference to
`std::basic_string,
std::allocator::_S_construct_aux_2(unsigned long, char,
std::allocator const&)'
It seems that the compiler is trying to find the header files for c++ under /usr/include/c++/4.5, which causes the link error. When I changed the default version of gcc to gcc-4.5, the errors disappeared.
So how could I make the compiler search for the header files under the correct directory "/opt/gcc-4.4.3/include"? I have tried to export CPLUS_INCLUDE_PATH, but it seems not work.
PS: gcc -v
Using build-in specs
Target: x86_64-suse-linux
Configured with: ./configure --prefix=/opt/gcc-4.4.3
Thread model: posix
gcc version 4.4.3 (GCC)
Try compiling gcc 4.4.3 again, but use the --with-gxx-include-dir=/opt/gcc-4.4.3/include option in the configure step.
It might be an issue with what update-alternatives has done, or not done.
When I build an alternate compiler I tend to use a --prefix and --program-suffix=-XY just so I can spot problems. Check which cpp is being run:
/opt/gcc-4.4.3/bin/g++ --print-prog-name=cpp
cpp -v </dev/null
/opt/gcc-4.4.3/bin/cpp -v < /dev/null
/opt/gcc-4.4.3/bin/g++ -print-search-dirs | grep '^programs:'
(you can also check ld and as with --print-prog-name)
Setting CPPFLAGS="-v -H" during a build may help track things down too.
An ugly workaround might be CPPFLAGS="-nostdinc -nostdinc++ -I/opt/gcc-4.4.3/include/" but it's better to fix your compile environment, as that's likely to cause as many problems as it solves. There are also options -isystem and -sysroot to help in certain cases, see http://gcc.gnu.org/onlinedocs/cpp/Invocation.html .