System: Centos
I have a C++ file, a assembly file and a GYP file:
C++ file: src/node_main.cc
#include <iostream>
using namespace std;
extern "C" {
extern char __attribute__((weak)) global_variable;
} // extern "C"
int main()
{
printf("global_variable:%p", reinterpret_cast<uintptr_t>(&global_variable));
return 0;
}
Assembly file: src/global_variable.S
.global global_variable
global_variable:
GYP file: node.gyp
{
'targets': [
{
'target_name': 'global_variable',
'type': 'none',
'conditions': [
[ 'OS in "linux freebsd solaris"', {
'type': 'static_library',
'sources': [
'src/global_variable.S'
]
}],
]
},
{
'target_name': 'myexperiment',
'type': 'executable',
'sources': [
'src/node_main.cc'
],
'dependencies': [ 'global_variable' ],
'conditions': [
[ 'OS in "linux freebsd"', {
'dependencies': [ 'global_variable' ],
# 'ldflags+': [
# '<(PRODUCT_DIR)/obj.target/global_variable/src/global_variable.o'
# ]
}]
]
}
]
}
My build command:
python3 main.py
make
My question: When I comment out the "ldflags+", I can't access "global_variable":
./out/Default/myexperiment
Execute "myexperiment" will print "global_variable:(nil)".
When I use the "ldflags", I can access "global_variable", it will print "global_variable:0x4006e6".
I used "make -n" command and tried to see what happened to g++, using "ldflags+":
g++ -o out/Default/myexperiment out/Default/obj.target/global_variable/src/global_variable.o -Wl,--start-group out/Default/obj.target/myexperiment/src/node_main.o out/Default/obj.target/libglobal_variable.a -Wl,--end-group
not using "ldflags+":
g++ -o out/Default/myexperiment -Wl,--start-group out/Default/obj.target/myexperiment/src/node_main.o out/Default/obj.target/libglobal_variable.a -Wl,--end-group
It seems the only difference is: "global_variable.o".
If "global_variable.o" is added, the global variable can be accessed, otherwise the global variable is nil, despite "libglobal_variable.a" is added to both.
Thoroughly confused.
Today I tried a lot of experiments, it took me two days to figure it out.
Finally I found the key:
__attribute__((weak))When using
weakwith static library, the linker will not try to find a definition from static library, so the definition will be discarded.When linking with object file, the linker will unconditionally link it to the output file.
So it's unrelated to Assembler and GYP. It's because I didn't fully understand how
.afile work with linker.This answer helps me a lot: https://stackoverflow.com/questions/51656838/attribute-weak-and-static-libraries#:~:text=The%20weak%20attribute%20causes%20the,targets%2C%20and%20also%20for%20a.
Thank everyone!