When I compile this c++ code with g++ 4.8.5 with -O0 -std=c++11,
#include <stdio.h>
__extern_inline float func(float x) { return x*x; }
int main(int argc, char *argv[])
{
printf("%d\n", func(100));
}
I get this link error
/tmp/ccMiVRIL.o: In function `main':
test.cpp:(.text+0x18): undefined reference to `func(float)'
collect2: error: ld returned 1 exit status
however, if I add -O1 or -O2 to the compiler option, it builds successfully.
Also if I change "__extern_inline" to "extern __inline" or "__extern_always_inline", it also builds. I see similar behavior with clang.
I want to have that code (keep __extern_inline, since the definition lives in a third-party lib and I don't want to touch) to be able to link even under -O0. What can I do? Is there any compiler option or #defines to work this error around?
I've read this document, but it doesn't seem to help for my case
https://clang.llvm.org/compatibility.html#inline
Also it looks like __extern_inline is defined as follows in sys/cdefs.h
#define __extern_inline extern __inline __attribute__ ((__gnu_inline__))
I think it's because following macro in features.h:
/* Decide whether we can define 'extern inline' functions in headers. */
#if __GNUC_PREREQ (2, 7) && defined __OPTIMIZE__ \
&& !defined __OPTIMIZE_SIZE__ && !defined __NO_INLINE__ \
&& defined __extern_inline
# define __USE_EXTERN_INLINES 1
#endif
As you can see, extern inlines are explicitly allowed only for optimized builds.
Related
Try to build the following gcc plugin on linux for windows with mingw cross compiler. The plugins are from the built avr compiler also for windows. Adapted the following plugin https://github.com/jcmvbkbc/avr-flash-vtbl.
#include <gcc-plugin.h>
#include <cp/cp-tree.h>
#ifdef _WIN32
__declspec(dllexport)
#endif
int plugin_is_GPL_compatible = 1;
void fn(void *gcc_data, void *user_data)
{
TYPE_ADDR_SPACE (TREE_TYPE (vtbl_type_node)) = 1;
TYPE_ADDR_SPACE (TREE_TYPE (vtbl_ptr_type_node)) = 1;
}
#ifdef _WIN32
__declspec(dllexport)
#endif
int plugin_init (struct plugin_name_args *plugin_info,
struct plugin_gcc_version *version)
{
register_callback("", PLUGIN_START_UNIT, fn, NULL);
return 0;
}
Output during compile and linking:
i686-w64-mingw32-g++ -shared -I/home/andreas/omgwtfbbq/win64/bin/../lib/gcc/avr/9.2.0/plugin/include -Wl,--export-all-symbols /home/andreas/
omgwtfbbq/win64/bin/../lib/gcc/avr/9.2.0/plugin/cc1plus.exe.a avr-flash-vtbl.c -o avr-flash-vtbl.so -I./
/usr/bin/i686-w64-mingw32-ld: /tmp/cc28ZVde.o:avr-flash-vtbl.c:(.text+0x4): undefined reference to `cp_global_trees'
/usr/bin/i686-w64-mingw32-ld: /tmp/cc28ZVde.o:avr-flash-vtbl.c:(.text+0x10): undefined reference to `cp_global_trees'
/usr/bin/i686-w64-mingw32-ld: /tmp/cc28ZVde.o:avr-flash-vtbl.c:(.text+0x44): undefined reference to `register_callback'
collect2: error: ld returned 1 exit status
make: *** [Makefile:11: avr-flash-vtbl.so] Fehler 1
The compiler flags are adapted from https://gcc.gnu.org/onlinedocs/gccint/Plugins-building.html. Has anybody already faced such a issue?
Problem is solved. Changed host compiler from i686-w64-mingw32-g++ to x86_64-w64-mingw32-g++ and changed the order of the options. /home/andreas/omgwtfbbq/win64/bin/../lib/gcc/avr/9.2.0/plugin/cc1plus.exe.a must go after avr-flash-vtbl.c.
Related topic:
Why does const imply internal linkage in c++, when it doesn't in C?
I was following GCC visibility wiki to add visibility to my shared library.
It generates a warning when I'm compiling my source file
warning: 'visibility' attribute ignored [-Wattributes]
Here's my code:
// my_shared_lib.h
#if __GNUC__ >= 4
#define DLL_API __attribute__((visibility("default")))
#define DLL_LOCAL __attribute__((visibility("hidden")))
#else
#define DLL_API
#define DLL_LOCAL
#endif
DLL_LOCAL const int my_local_var;
It generate following warning while compiling:
my_shared_lib.h: 'visibility' attribute ignored [-Wattributes]
DLL_LOCAL const int my_local_var;
^
Here's the entire building message:
make all
Building file: ../src/my_shared_lib.cc
Invoking: Cross G++ Compiler
g++-mp-4.8 -O3 -Wall -c -fmessage-length=0 -std=c++11 -MMD -MP -MF"src/my_shared_lib.d" -MT"src/my_shared_lib.d" -o "src/my_shared_lib.o" "../src/my_shared_lib.cc"
my_shared_lib.h: 'visibility' attribute ignored [-Wattributes]
DLL_LOCAL const int my_local_var;
^
Finished building: ../src/my_shared_lib.cc
Can anyone tell me how to silent this warning and why this warning happened?
Is it because const variable are hidden by default?
PS.
I'm using g++ 4.8
You can silence the warning by passing -Wno-attributes to the compilation.
The warning is happening because, as the related question and answer mentions, in C++ const objects automatically have internal linkage unless they're explicitly marked as extern; i.e. they're hidden by default. The rationale is to encourage putting these const values into header files as-is (i.e. in the form const int x = value;). If they were public by default, then you would suffer multiple-linkage issues if the same variable appeared across multiple .cpp or .o files, which is what would happen if they were placed in .h files without the local linkage rule.
You should also be seeing a warning/error:
my_shared_lib.h:...: error: uninitialized const 'my_local_var' [-fpermissive]
which is a variation of the error because the const is implicitly static unless otherwise mentioned.
How do you fix this?
Firstly, use the const properly in the header when using C++, it's:
const int my_local_var = VALUE;
If you're sharing this .h file amongst C and C++ code then your choices are:
Don't make it const - that's actually meaningless for the C code, and prevents you from accomplishing the private, declared in the header and defined in a .c file but not exposed in the resulting .so
Use a #define - yes, it's ugly, but this is more semantically correct than using a const for C code as it prevents you from accidentally changing the value by erroneous assignment.
declare it in the .h as:
...
DLL_LOCAL extern const int my_local_var;
and then define it in the .cc/.cpp file as:
#include "my_shared_lib.h"
const int my_local_var = 42;
You need to add in the #include or else it doesn't get the extern which allows it to be exposed for linking in the .o files that make up the .so without getting it exposed in the .so itself.
and so we have (on a mac, but the premise is the same):
Header:
$ cat wodge.h
#define PRIVATE __attribute__((visibility("hidden")))
#define PUBLIC __attribute__((visibility("default")))
PRIVATE extern const int my_local_var;
int do_with_x(int x);
First C++ file:
$ cat wodge.cc
#include "wodge.h"
int
do_with_x(int y)
{
return my_local_var * y;
}
Second C++ file - definition of value:
$ cat wodge2.cc
#include "wodge.h"
const int my_local_var = 42;
Compile and show the resulting symbol table:
$ g++-4.8 -c -O3 -Wall -o wodge.o wodge.cc
$ g++-4.8 -c -O3 -Wall -o wodge2.o wodge2.cc
$ g++-4.8 -shared -o foo.dylib *.o
$ nm foo.dylib
0000000000000fb0 T __Z9do_with_xi
0000000000000fbc s _my_local_var
U dyld_stub_binder
I am trying to use a C static library but getting the following error while compiling/linking in gcc. The main file test.c needs to call a function from the static library libtest.a
Header file : testcplusplus.h
void print_cplusplus(int b);
testcplusplus.c :
#include <stdio.h>
#include "testcplusplus.h"
void print_cplusplus(int b) {
printf ("Value of b is %d \n",b);
}
Main C file : test.c
#include <stdio.h>
#include "testcplusplus.h"
int main() {
int a = 2 ;
print_cplusplus(a);
}
Commands Used :
g++ -c -o testcplusplus.o testcplusplus.c
ar rvs libtest.a testcplusplus.o
gcc -o test test.c -L. -ltest **// Error comes here**
Error:
In function `main':
test.c:(.text+0x15): undefined reference to `print_cplusplus'
collect2: ld returned 1 exit status
You only specify function parameter types when you declare/define the function, not when you call it. The function call should look like
print_cplusplus(a);
You also need to include testcplusplus.h from test.c so that the declaration is available when you call it. The return type of main needs to be int; and print_cplusplus should either have void return type, or should return a value.
Finally, you'll need to declare the function extern "C" for it to be callable from a C program - but only when compiling C++.
// testcplusplus.h
#ifdef __cplusplus
extern "C" {
#endif
void print_cplusplus(int b);
#ifdef __cplusplus
}
#endif
You don't rewrite a variables type when you use it, it's only used in declarations:
print_cplusplus(a);
I want investigate how is it possible to link C++ program without libstdc++, but with support of rtti. I tried compile it in the way described below. Any necessary but absent symbol I can define like function strcmp in the example, but is it possible to define typeinfo symbols without explicit mangle/demangle magic? And if possible how?
cd /tmp && cat << 'eof' >rtti.cpp && g++ -nodefaultlibs -lc rtti.cpp
extern "C" int strcmp(const char *s1, const char *s2) { return 0; };
#include "typeinfo"
int main(){
return typeid(int) == typeid(char);
}
Linker says:
/tmp/cc6rBAef.o: In function `main':
rtti.cpp:(.text+0x18): undefined reference to `typeinfo for char'
rtti.cpp:(.text+0x1d): undefined reference to `typeinfo for int'
collect2: error: ld returned 1 exit status
So, how can I define 'typeinfo of char'(_ZTIc##CXXABI_1.3) in source file using g++ or clang++?
PS. Don't ask me why do I need it. Just a curiosity.
Since the symbols needed for RTTI seem to be in the libstdc++ library, you cannot do completely without it. Note that I found this by running
readelf -Ws `g++ -print-file-name=libstdc++.so` | awk '{print $8}' | c++filt | grep 'typeinfo for'
What you can do, however, is statically link with libstdc++:
g++ -static-libstdc++ rtti.cpp
In this way, you won't have any dynamic dependencies on libstdc++ and only the symbols you actually need are pulled in to your executable. (Well, all symbols from the object file that contains the needed symbols, fundamental_type_info.o in you example, I suppose.)
Thanks to gcc community for hint.
The answer is:
"gcc use some magic to substitute destructor of __fundamental_type_info to a set of typeinfo symbols"
Substitution code is placed in file: gcc-4.7.2/gcc/cp/rtti.c, void emit_support_tinfos(void);
rtti.cc:
#include <typeinfo>
namespace __cxxabiv1 {
class __fundamental_type_info:public std::type_info{
public:
explicit __fundamental_type_info(const char* __n) : std::type_info(_n) { }
virtual ~__fundamental_type_info(){};
};
}
int main(){
return typeid(int) == typeid(char);
}
All fundamental typeinfos are inserted into object file during compilation.
$g++ -c ./rtti.cc;readelf -sW ./rtti.o |c++filt|grep typeinfo|wc -l
$153
So the question is answered.
I want to build a dynamic library containing haskell functions. I work on linux and want to call this dynamic library from C++ code.
I used the example at http://wiki.python.org/moin/PythonVsHaskell and have the following files:
Test.hs:
{-# LANGUAGE ForeignFunctionInterface #-}
module Test where
import Foreign.C.Types
hsfun :: CInt -> IO CInt
hsfun x = do
putStrLn "Hello World"
return (42 + x)
foreign export ccall
hsfun :: CInt -> IO CInt
module_init.c:
#define CAT(a,b) XCAT(a,b)
#define XCAT(a,b) a ## b
#define STR(a) XSTR(a)
#define XSTR(a) #a
#include <HsFFI.h>
extern void CAT (__stginit_, MODULE) (void);
static void library_init (void) __attribute__ ((constructor));
static void
library_init (void)
{
/* This seems to be a no-op, but it makes the GHCRTS envvar work. */
static char *argv[] = { STR (MODULE) ".so", 0 }, **argv_ = argv;
static int argc = 1;
hs_init (&argc, &argv_);
hs_add_root (CAT (__stginit_, MODULE));
}
static void library_exit (void) __attribute__ ((destructor));
static void
library_exit (void)
{
hs_exit ();
}
Now I compile this files to a dynamic library:
$ ghc -dynamic -shared -fPIC -optc '-DMODULE=Test' Test.hs module_init.c -o libTest.so
[1 of 1] Compiling Test ( Test.hs, Test.o )
Linking libTest.so ...
This creates among other things the file Test_stub.h:
#include "HsFFI.h"
#ifdef __cplusplus
extern "C" {
#endif
extern HsInt32 hsfun(HsInt32 a1);
#ifdef __cplusplus
}
#endif
and Test_stub.c:
#define IN_STG_CODE 0
#include "Rts.h"
#include "Stg.h"
#ifdef __cplusplus
extern "C" {
#endif
extern StgClosure Test_zdfhsfunzua165_closure;
HsInt32 hsfun(HsInt32 a1)
{
Capability *cap;
HaskellObj ret;
HsInt32 cret;
cap = rts_lock();
cap=rts_evalIO(cap,rts_apply(cap,(HaskellObj)runIO_closure,rts_apply(cap,&Test_zdfhsfunzua165_closure,rts_mkInt32(cap,a1))) ,&ret);
rts_checkSchedStatus("hsfun",cap);
cret=rts_getInt32(ret);
rts_unlock(cap);
return cret;
}
static void stginit_export_Test_zdfhsfunzua165() __attribute__((constructor));
static void stginit_export_Test_zdfhsfunzua165()
{getStablePtr((StgPtr) &Test_zdfhsfunzua165_closure);}
#ifdef __cplusplus
}
#endif
Then I create a cpp file main.cpp:
#include "Test_stub.h"
#include <iostream>
using namespace std;
int main()
{
cout << hsfun(5);
}
and want to compile and link it. But when I call g++, it says:
$ g++ -I/usr/lib/ghc-7.0.3/include -L. -lTest main.cpp
/tmp/ccFP2AuB.o: In function `main':
main.cpp:(.text+0xa): undefined reference to `hsfun'
collect2: ld gab 1 als Ende-Status zurück
So I added the Test_stub.o file to the command line (although I think the hsfun function should already be defined in libTest.so which is added via the -lTest parameter. I don't think, I should link the Test_stub.o file into the executable because I want to use dynamic linking), but this also doesn't work:
$ g++ -I/usr/lib/ghc-7.0.3/include -L. -lTest main.cpp Test_stub.o
Test_stub.o: In function `hsfun':
Test_stub.c:(.text+0x9): undefined reference to `rts_lock'
Test_stub.c:(.text+0x16): undefined reference to `rts_mkInt32'
Test_stub.c:(.text+0x1d): undefined reference to `Test_zdfhsfunzua165_closure'
Test_stub.c:(.text+0x28): undefined reference to `rts_apply'
Test_stub.c:(.text+0x2f): undefined reference to `base_GHCziTopHandler_runIO_closure'
Test_stub.c:(.text+0x3a): undefined reference to `rts_apply'
Test_stub.c:(.text+0x4a): undefined reference to `rts_evalIO'
Test_stub.c:(.text+0x5c): undefined reference to `rts_checkSchedStatus'
Test_stub.c:(.text+0x66): undefined reference to `rts_getInt32'
Test_stub.c:(.text+0x70): undefined reference to `rts_unlock'
Test_stub.o: In function `stginit_export_Test_zdfhsfunzua165':
Test_stub.c:(.text.startup+0x3): undefined reference to `Test_zdfhsfunzua165_closure'
Test_stub.c:(.text.startup+0x8): undefined reference to `getStablePtr'
collect2: ld gab 1 als Ende-Status zurück
Do I have to link the Test_stub.o? If yes, why? And which arguments should I pass to the linker?
Probably easier than wrestling with g++ is letting ghc do the work,
ghc main.cpp -o hithere -L. -lTest -lstdc++
did the job for me after creating the shared lib the way you did. I have tested it with 7.2.2 and 7.0.2, both worked here.