Boost.asio compilation problem: undefined reference to `__sync_add_and_fetch_8 - boost

Hey guys,
This could be a noob question, but I really can't find any useful solution through Google.
I'm testing a hello world with boost.asio, the program is quite simple:
#include <iostream>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
int main()
{
boost::asio::io_service io;
boost::asio::deadline_timer t(io, boost::posix_time::seconds(5));
t.wait();
std::cout << "Hello, world!\n";
return 0;
}
I passed the compilation and run well on my Intel Pentium PC (Ubuntu 10.10, gcc 4.4.5, Boost 1.46.0). The command line I used was
g++ -o a a.cpp -I /Boost-Include-Path/ -L /Boost-lib-Path/ -lboost_system
But when I compile the same code on another machine(which is a big one, I'll explain it later), it can't pass the compilation and gives such errors:
/tmp/ccOZxZBX.o: In function boost::asio::detail::gcc_sync_fenced_block::gcc_sync_fenced_block()': a.cpp:(.text._ZN5boost4asio6detail21gcc_sync_fenced_blockC1Ev[boost::asio::detail::gcc_sync_fenced_block::gcc_sync_fenced_block()]+0x4c): undefined reference to__sync_lock_test_and_set_4' /tmp/ccOZxZBX.o: In function boost::detail::atomic_count::operator++()': a.cpp:(.text._ZN5boost6detail12atomic_countppEv[boost::detail::atomic_count::operator++()]+0x30): undefined reference to__sync_add_and_fetch_8' /tmp/ccOZxZBX.o: In function boost::detail::atomic_count::operator--()': a.cpp:(.text._ZN5boost6detail12atomic_countmmEv[boost::detail::atomic_count::operator--()]+0x30): undefined reference to__sync_add_and_fetch_8' /tmp/ccOZxZBX.o: In function boost::detail::atomic_count::operator long() const': a.cpp:(.text._ZNK5boost6detail12atomic_countcvlEv[boost::detail::atomic_count::operator long() const]+0x30): undefined reference to__sync_fetch_and_add_8'
The machine I used was a SiCortex SC5832,which use MIPS64 instruction set processors, OS is changed CentoOS. Gcc 4.2.3, Boost1.46.0. Is it possible that there are problems about the compatibility of the MIPS? I added -mips64 option, but it still give the same errors.
I know this environment could not be very usual, but I think some people who are using similar big machines may face the same problem.
Any help would be appreciated. By the way, I don't have sudo permission.
Thanks,
Tony

This function is a GCC built-in function, and it was introduced around GCC 4.2 (iirc) see documentation.
According to the documentation it's not available on all target processors.
If you look at boost/smart_ptr/detail/atomic_count.hpp it looks like it would fall into the #elif defined(BOOST_SP_HAS_SYNC) block. i.e. boost/smart_ptr/detail/atomic_count_sync.hpp.
Support for this is determined in boost/smart_ptr/detail/sp_has_sync.hpp. This header essentially assumes that GCC supports this on all platforms except for a few exceptions. You might want to insert MIPS as another exception here and submit a patch to boost.
You'll also see that one workaround is to define BOOST_AC_USE_PTHREADS. This will use a mutex around the atomic count, which probably is significantly less efficient, but at least it will work until you can figure out what atomic operations are supported on MIPS64.

Related

Anyone know the location of SetProcessDpiAwarenessContext() in windows?

I need to turn off DPI scaling in my Win32 application. The recommended way to do this programmatically is via the call:
SetProcessDpiAwarenessContext()
I am using the mingw windows environment. I verified that mingw headers don't have the call, but then several newer calls are missing from the mingw headers. Its a lot of work to update those, I am sure.
I created a local definition of that:
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 3
extern BOOL SetProcessDpiAwarenessContext(int value);
int main()
{
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
}
I still get:
C:\projects\petit_ami>gcc -g3 -Iinclude -Ilibc -static tests/widget_test.c -Wl,--whole-archive bin/petit_ami_graph.a -Wl,--no-whole-archive -lwinmm -lgdi32 -lcomdlg32 -lwsock32 -luser32 -o bin/widget_test
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: bin/petit_ami_graph.a(graphics.o): in function `pa_init_graph':
C:\projects\petit_ami/windows/graphics.c:15662: undefined reference to `SetProcessDpiAwarenessContext'
collect2.exe: error: ld returned 1 exit status
The best documentation I can find says it is in user32.dll.
This is using Windows 10 and recently updated, build: 19042.1052
Thanks for any help.
Scott Franco
San Jose, CA
Almost there. I did:
typedef BOOL (WINAPI *PGNSI)(int);
pGNSI = (PGNSI) GetProcAddress(GetModuleHandle(TEXT("user32.dll")),
"SetProcessDpiAwarenessContext");
if(NULL != pGNSI) {
dbg_printf(dlinfo, "Procedure found\n");
r = pGNSI(2);
dbg_printf(dlinfo, "r: %d\n", r);
if (!r) winerr();
}
And got:
C:\projects\petit_ami>graphics_test
windows/graphics.c:pa_init_graph():15686: Procedure found
windows/graphics.c:pa_init_graph():15688: r: 0
Error: Graph: Windows error: The parameter is incorrect.
The description of the parameter is here:
https://learn.microsoft.com/en-us/windows/win32/hidpi/dpi-awareness-context
I saw elsewhere that 2 was a valid value, but clearly that may not be correct. The suggestion by Simon to get the Visual studio environment may be operative just to get the proper value. Apologies to Simon, I can't at the moment take the rest of your suggestion. There is a long list of reasons I don't want to bore people with here.
Continued:
I installed and ran the visual studio with sample code. It works, now I am trying to figure out what DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 is, it is not a simple integer.
Anyways, its late. I try to find the final answer tomorrow.
Continued:
The working code is:
/* function call for direct to dll */
typedef BOOL (WINAPI *PGNSI)(int);
/* select for highest DPI */
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 0xfffffffc
...
/* turn off scaling. The following call gets around the lack of a
declaration in mingw */
pGNSI = (PGNSI) GetProcAddress(GetModuleHandle(TEXT("user32.dll")),
"SetProcessDpiAwarenessContext");
if (NULL != pGNSI) {
r = pGNSI(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
if (!r) winerr();
}
As you could probably guess, I am going to tie this to a user option. Now I just need to research what the effect of this new mode is on widgets and other OS features.
Thanks for all the help.
GetProcAddress works and is the recommended method when you cannot be certain if the user's OS will have the function.
If you want to resolve the symbol at link time, you need to ensure that (1) the import library has the symbol, and (2) that the calling convention and name decoration and mangling are correct.
I'm not very familiar with mingw, but I believe it comes with import libraries for some version of common Windows DLLs. Since this is a newer function, it might not be in the import library. There are tools to scan an existing DLL and create a corresponding import library, so perhaps you need to build a fresh one.
The calling convention for Win32 is __stdcall. If your compiler is using a different calling convention by default, you'll have to set it explicitly on your forward declaration of the function. Also, if you're compiling in C++ mode, you'll need to wrap the forward declaration in an extern "C" to prevent name mangling. If either of these are wrong, you'll get an "undefined reference" diagnostic from the linker because the symbol will be "decorated" differently.

Manual linking to Windows library in LLVM

I'm writing my own programming language, and am wanting to compile it to native binaries by compiling to LLVM IR, then letting the rest of the LLVM toolchain take over. Eventually, I will target multiple platforms, but for now I'm just focusing on Windows.
For starters, I have the empty program compiling, which implies that in general my toolchain is set up and working, and I get a no op executable out of it. The next logical step is doing "Hello World", but after looking at the LLVM IR output of clang of the C program that simply calls puts("Hello World!") it looks like a slightly easier first step is to simply _exit();. When reviewing the clang output of that C program, it looks like the relevant line is to do call void #_exit(i32 0). I've distilled it down to what I think is the bare minimum program which calls exit:
define i64* #main() {
%1 = alloca i32, align 4
store i32 0, i32* %1, align 4
call void #_exit(i32 0)
unreachable
}
declare dso_local void #_exit(i32)
When trying to run the equivalent C program directly, of course it works when I use clang directly, but the steps after creation of the LLVM IR are opaque to me, and I believe I'm using the wrong linker options or something, as I get lld-link: error: undefined symbol: _exit during the lld-link step. (Actually, this also occurs when I try to manually link the output of clang -S --emit-llvm, so I have no reason to believe my IR is the problem). The current invocation I'm using for lld-link is lld-link /out:"exit.exe" /entry:main exit.obj. I've tried playing around with adding various flavors of the /defaultlib switch, including manually linking to libcmt both libucrt which I do believe contain _exit after looking through the symbols with dumpbin, but that doesn't seem to help. Looking at the IR output of the clang program, it doesn't seem like there's any particular reference to <stdlib.h>, so I guess that information is lost after the IR generation stage, so I don't think I'm missing anything in my IR.
This appears to be a general Windows linker problem, rather than anything to do with LLVM, since if I do link /out:exit.exe /entry:main exit.obj I get basically the same error.
Anyways, there's clearly some step here during the linking that I don't understand, around how to find the actual library that a given external call lives in, so if anyone could point me in the right direction of how to figure this out for any given C runtime call, that would be great. Particularly in this case, I guess I need to find the library which contains the _exit function. Thanks!
Turns out the libcmt has been replaced. The replacement is ucrt, and so doing /defaultlib:ucrt seems to fix the problem!

Error: function template already inherited - with icpc

I am writing a class that inherits from std::vector (*) and I want to be able to construct it in all the ways that are available for its base, so I use
#include <vector>
struct B : public std::vector<double>
{
using std::vector<double>::vector;
};
This compiles fine with the g++ and clang, but the Intel compiler gives me (with flag -std=c++11)
error: function template "B::B(_ForwardIterator, _ForwardIterator, const std::__1::allocator<double> &)" already inherited from "std::__1::vector<double, std::__1::allocator<double>>"
at the using directive.
Any ideas why this is happening and/or how to solve it?
Update: it would seem this is OS dependent, works fine on Linux and Windows platforms but fails on OS X. A discussion is ongoing on the Intel forums.
(*) I don't want to use polymorphism, please avoid "this is bad practice" answers if not directly relevant - there are in fact numerous posts that agree this is acceptable.

Storing pairs in a GCC rope with c++11

I'm using a GCC extension rope to store pairs of objects in my program and am running into some C++11 related trouble. The following compiles under C++98
#include <ext/rope>
typedef std::pair<int, int> std_pair;
int main()
{
__gnu_cxx::rope<std_pair> r;
}
but not with C++11 under G++ 4.8.2 or 4.8.3.
What happens is that the uninitialised_copy_n algorithm is pulled in from two places, the ext/memory and the C++11 version of the memory header. The gnu_cxx namespace is pulled in by rope and the std namespace is pulled in by pair and there are now two identically defined methods in scope leading to a compile error.
I assume this is a bug in a weird use case for a rarely used library but what would be the correct fix? You can't remove the function from ext/memory to avoid breaking existing code and it now required to be in std. I've worked around it using my own pair class but how should this be fixed properly?
If changing the libstdc++ headers is an option (and I asked in the comments whether you were looking for a way to fix it in libstdc++, or work around it in your program), then the simple solution, to me, seems to be to make sure there is only one uninitialized_copy_n function. ext/memory already includes <memory>, which provides std::uninitialized_copy_n. So instead of defining __gnu_cxx::uninitialized_copy_n, it can have using std::uninitialized_copy_n; inside the __gnu_cxx namespace. It can even conditionalize this on C++11 support, so that pre-C++11 code gets the custom implementation of those functions, and C++11 code gets the std implementation of those functions.
This way, code that attempts to use __gnu_cxx::uninitialized_copy_n, whether directly or through ADL, will continue to work, but there is no ambiguity between std::uninitialized_copy_n and __gnu_cxx::uninitialized_copy_n, because they are the very same function.

What to do if tgamma() function is not defined?

I am trying to use tgamma() from the standard library. When I try to compile, I get the error message:
Call to undefined function tgamma
I have the directive #include <cmath>. I use Embarcadero C++ Builder XE3, which claims to support C++11 standards. What could be my problem, and how to fix it?
Boost contains a tgamma function.
#include <boost/math/special_functions/gamma.hpp>
...
double rootPi = boost::math::tgamma<double>(0.5);
Of course, you can always switch to a different compiler, like gcc.

Resources