Cxx11 ABI for a single function call? - c++11

Is it possible to define a piece of your code to be compiled with Cxx11 but the rest is using the compatibility ABI of libstdc++6 ?
Example:
// Compatibility ABI
int myvar = 0;
std::string mystring = "hello";
// This method is from another library
// that has been compiled with Cxx11
call_routine_ext_library(mystring);
// Compatibility ABI
myvar += 2;
My whole system is compiled in compatibility mode except one external library compiled with Cxx11.
Does there exist a preprocessor that allows you to handpick certain part of your code to be compiled using the new ABI just as you would have defined D_GLIBCXX_USE_CXX11_ABI=1 on the compiler line ?
The error I get when calling the method call_routine_ext_library is:
undefined reference to `call_routine_ext_library(std::string const&)'
because the library contains this:
call_routine_ext_library(std::__cxx11::basic_string<char, std::char_traits<char>)
So I was hoping I could force the compiler to use Cxx11 mode when compiling the string I pass into that method.
Are there any means of linking against a binary compiled with Cxx11 when your code is compiled without it ?

Related

Is it possible to link LAPACK, LAPACKE, and BLAS libraries with GCC instead of GFORTRAN?

I have an application that is written in C. I would like to use the LAPACK library to do some linear algebra calculations. I am using LAPACKE, which is the C interface to LAPACK. The C code compiled fine with GCC, but I am having trouble linking the libraries with GCC. It only works with GFORTRAN. I downloaded the lapack-3.11.0.tar.gz file from the LAPACK website. I unpacked the file then I built it. I did not make any changes to the make.inc.example file, which was already configured for a linux machine running GNU compilers. Here is how I built it once in the ~/lapack-3.11.0 directory:
cp make.inc.example make.inc
make
LAPACK built successfully and all of the tests passed. Then, I built LAPACKE. To do this, I simply ran make in the ~/lapack-3.11.0/LAPACKE directory. Similarly, it built successfully and all of the tests passed. Notice that in my case, LAPACK is installed in my home directory and not in a system directory.
To test that I could actually use LAPACKE, I wrote a sample C program that solves a system of equations using LAPACKE_dgesv().
lapack_test.c:
#include <stdio.h>
#include <lapacke.h>
int main()
{
int n = 3;
int nrhs = 1;
int lda = n;
int ipiv[n];
double a[9] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 10.0};
double b[3] = {3.0, 3.0, 4.0};
int info;
info = LAPACKE_dgesv(LAPACK_ROW_MAJOR, n, nrhs, a, lda, ipiv, b, nrhs);
if (info == 0)
{
printf("Solution: %f %f %f\n", b[0], b[1], b[2]);
}
else
{
printf("dgsev failed with error code %d\n", info);
}
return 0;
}
Assuming that lapack_test.c is in my home directory, here is how I compiled it and linked the libraries:
gcc -I./lapack-3.11.0/LAPACKE/include -c -o lapack_test.o lapack_test.c
gfortran -o lapack_test lapack_test.o ./lapack-3.11.0/liblapacke.a ./lapack-3.11.0/liblapack.a ./lapack-3.11.0/librefblas.a
This gave my no errors. However, GFORTRAN is very inconvenient for my case. In my application I have many C libraries that probably will not link using GFORTRAN. Or at least, I do not think that that they will.
If I use GCC, I get linkage errors. For example, if I simply replace GFORTRAN with GCC in the last step I get a bunch of errors:
/usr/bin/ld: ./lapack-3.11.0/liblapack.a(iparmq.o): in function `iparmq_':
iparmq.f:(.text+0x25e): undefined reference to `logf'
/usr/bin/ld: iparmq.f:(.text+0x26b): undefined reference to `lroundf'
/usr/bin/ld: ./lapack-3.11.0/liblapack.a(xerbla.o): in function `xerbla_':
xerbla.f:(.text+0x55): undefined reference to `_gfortran_st_write'
/usr/bin/ld: xerbla.f:(.text+0x60): undefined reference to `_gfortran_string_len_trim'
/usr/bin/ld: xerbla.f:(.text+0x77): undefined reference to `_gfortran_transfer_character_write'
/usr/bin/ld: xerbla.f:(.text+0x87): undefined reference to `_gfortran_transfer_integer_write'
/usr/bin/ld: xerbla.f:(.text+0x8f): undefined reference to `_gfortran_st_write_done'
/usr/bin/ld: xerbla.f:(.text+0x9a): undefined reference to `_gfortran_stop_string'
collect2: error: ld returned 1 exit status
Seems to be linking the static library liblapacke.a with no errors. liblapack.a seems to be where the errors are. It is a FORTRAN library, so it makes sense why it would not link correctly using GCC.
Is there a workaround here? Is it worth using LAPACKE? Or, should I try some other way to interface between FORTRAN and C?
There is no difference in linking else than some libraries being added automatically. gfortran and gcc do the same when linking. Only gfortran links some libraries like libgfortran or libm automatically while with gcc you have to use -lgfortran or -lm. Otherwise they do the exact same thing.
You can even use the gcc command to compile Fortran code and the gfortran command to compile C code. Or C++ code. It really does not matter. Just link all the necessary library when linking, depending whether you link with gcc, gfortran, g++ or ld.
In the end the linking is always done by ld, just with some particular flags added by the compiler command.
Finally, to be precise, distinguish GCC, the GNU compiler collection, and gcc, the command that calls the C frontend or the GCC's C compiler. The gfortran command calls the Fortran frontend. They share the same backend and middlend. When you call, e.g. gcc test.f90, the command recognizes that it is a Fortran source file and will invoke the Fortran frontend for you.

GNU toolchain (newlib): compatibility between toolchain versions (undefined symbol __ctype_ptr__)

Having here a project that is using some external GNU-toolchain built libraries (provided externally, without source-code). I'm compiling an application for embedded systems (FreeRTOS specifically), so I use newlib.
I initially tried using this toolchain https://releases.linaro.org/components/toolchain/binaries/7.4-2019.02/aarch64-elf/
but that failed because of (among others) these linker errors:
undefined reference to `__ctype_ptr__'
It seems that this symbol should be defined by libc. Going into the newlib sysroot, specifically in this case the sysroot-newlib-linaro-2019.02-aarch64-elf\usr\lib directory, tried to find __ctype_ptr__ in libc.a:
aarch64-elf-nm -C --defined-only -g libc.a | grep __ctype_ptr__
No output, so this libc indeed does not define __ctype_ptr__.
Continuing by taking a look into the library that needs the symbol, a notepad++ edit revealed this among the mangled text:
/opt/gcc-linaro-5.4.1-2017.05-x86_64_aarch64-elf/aarch64-elf/libc/usr/include/machine
Which means this library was built using the 5.4.1 aarch64-elf toolchain version and I was trying to use version 7.4 since I need newer C++ standard support.
Downloaded the 5.4.1 version as well (sysroot only): https://releases.linaro.org/components/toolchain/binaries/5.4-2017.05/aarch64-elf/
Again, going into the 5.4.1 sysroot-newlib-linaro-2017.05-aarch64-elf\usr\lib directory this time:
aarch64-elf-nm -C --defined-only -g libc.a | grep __ctype_ptr__
finally reveals:
0000000000000000 D __ctype_ptr__
which means that indeed the 5.4.1 newlib libc exports this symbol.
Questions:
Why this incompatibility between the 2 versions? What category do these kind of changes belong to? Where can I find more detailed information about changes like these and the reasons they are there?
Am I forced to use the old version because those libraries were built with it? Is there no way to use the newer version instead? How are these situations usually handled?
_ctype_ptr_ is simply a pointer to _ctype_ which is a 128 byte table
containing a bitset used by the ctype.h functions like isalpha.
The functions will take a character as a parameter, and will use the
character as an index into the _ctype_ array.
A mask is applied to the read value, and if non-zero the function returns "true"
You can worst case define your own
extern const char _ctype_[];
const char* __ctype_ptr__ = _ctype_;
If _ctype_ is reported undefined by the linker,
you may have to define it in the linker
ctype = _ctype_;
and in the source code.
extern const char ctype[];
const char* __ctype_ptr__ = ctype;

Cross platform compiling using CeGCC

I am trying to compile a C program using CeGCC, the program is written in C using Win32 API, and it's being compiled with MingW like this:
gcc -o "Win32App.exe" obj/winmain.o obj/callbacks.o obj/resource.o -s -lcomctl32 -Wl,--subsystem,windows
As a result the program is successfully compiled and then tested afterwards. The problem occurs when i try to compile it for ARM (Windows-CE) rather than x86-based architecture:
obj/winmain.o:winmain.c:(.text+0x24): undefined reference to InitCommonControlsEx
obj/winmain.o:winmain.c:(.text+0xe0): undefined reference to RegisterClassExW
As you can see the problem is that the two functions called InitCommonControlsEx and RegisterClassExW are not defined in Windows-CE.
My Question is how can i find an equivalent function to use in my code so that i can successfully compile and run my program in Windows-CE. I need help in replacing those two functions with compatible ones which are recognized in CeGCC.

gcc 5.40 doesn't include standard include files?

gcc 5.4.0
cygwin 2.8.0
Win10
I've been been knocking my head around this problem.When I compile a simple program, see below, I get an error in one of the gcc include files. I checked the cygwin mailing list and no one has reported an error in the gcc download so I think it's a misunderstanding on my part but I can't figure what I did wrong. Prior to this point all the gcc include fileswere included automatically. Oh, and the compile is correct for other libraries.
The code is:
gcc -std=c++11 test.cpp or gcc test.cpp
include iostream
using namespace std;
int main(int argc, char** argv) { }
and the error message is:
/tmp/ccfBvaqg.o:test.cpp:(.text+0x44): undefined reference to std::ios_base::Init::Init()'
/tmp/ccfBvaqg.o:test.cpp:(.text+0x44): relocation truncated to fit: R_X86_64_PC32 against undefined symbolstd::ios_base::Init::Init()'
/tmp/ccfBvaqg.o:test.cpp:(.rdata$.refptr._ZNSt8ios_base4InitD1Ev[.refptr._ZNSt8ios_base4InitD1Ev]+0x0): undefined reference to `std::ios_base::Init::~Init()'
gcc is the C compiler driver. The compiler automatically detects the language based on the file name; that is why the compilation succeeded. However, the linker is not affected by the names of the source files. By default, the C compiler driver does not link with the C++ standard library.
Since you used the standard library (<iostream> is a bit atypical header file in such a way that merely including it causes a standard library function to be called at the start of the program), but did not link it, the linker fails. The solution is to link with the C++ standard library. The simplest way to do that is to use the C++ compiler driver (g++) which links the standard library by default.

Coudn't run code used std::async on GCC 5.3.0

I was practicing std::asyn function that introduced in c++11, I wrote a simple example
#include<future>
#include<iostream>
using namespace std;
void check()
{
cout<<"some"<<endl;
}
int main()
{
auto p=std::async(std::launch::async,check);
p.get();
}
Yes very simple to start off with and i am compiling it using GCC 5.3.0
g++ -std=c++11 practise.cpp -lpthread
and the error
practise.cpp: In function 'int main()':
practise.cpp:13:47: error: invalid use of incomplete type 'class std::future<int>'
auto p=std::async(std::launch::async,chech);
^
In file included from practise.cpp:1:0:
C:/Program Files/mingw32/i686-w64-mingw32/include/c++/future:115:11: note: declaration of 'class std::future<int>'
class future;
^
Am i missing anything? is the way i linked lpthread is ok? i am on windows 7.
Your problem looks very similar to the one from this SO:
c++11 std::async doesn't work in mingw
You should check what gcc -v returns for 'Thread model:'. In above SO it returns win32 - and quite possibly mingw still does not support async/future in this mode.
In my mingw installation - also 5.3.0, I have Thread model: posix. I checked the exact same compile flags as yours and your example always compiles fine.
So my suggestion is for you to first check thread model with gcc -v, if its non posix, then reinstall mingw with posix threads. You choose threads model when running mingw-w64-install.exe installer/

Resources