Makefile for linking an extern global - c++

I'm trying to use the g_struct variable that's defined in struct.cpp and declared in struct.hpp inside the test.cpp, but the linking fails. Why is that?
// test.cpp
#include "struct.hpp"
int main(void)
{
g_struct.a = 1;
return 0;
}
// struct.cpp
#include "struct.hpp"
Struct g_struct;
// struct.hpp
#pragma once
struct Struct {
int a;
};
extern Struct g_struct;
# Makefile
CC = g++
all: struct.o test
test: test.cpp
$(CC) -o test test.cpp
struct.o: struct.cpp
$(CC) -c -o struct.o struct.cpp
.PHONY: clean
clean:
rm -f *.o test
Linking error:
$ make
g++ -c -o struct.o struct.cpp
g++ -o test test.cpp
/tmp/ccgSoJhd.o: In function `main':
test.cpp:(.text+0xd): undefined reference to `g_struct'
collect2: error: ld returned 1 exit status
Makefile:6: recipe for target 'test' failed
make: *** [test] Error 1
If I link without the -c flag, I get:
$ make
g++ -o struct.o struct.cpp
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status
Makefile:9: recipe for target 'struct.o' failed
make: *** [struct.o] Error 1

You have to link struct.o, which has Struct g_struct;.
test: test.cpp
$(CC) -o test test.cpp struct.o

Related

makefile error lib/Scrt1.o undefined reference to `main'

I glanced tons of similar topic, but I couldn't recognize solution
I tried mine and many variations. Even below the simplest code compiling doesn't work. I think skipping little thing...
Could you help me?
# Make file for test.c file dependencies external C libraries
CC = g++
C = gcc
FLAGS = -Wextra -g
INCLUDES = -lm
test: randomArray.o test.o
$(CC) $(FLAGS) $(INCLUDES) randomArray.o -o test
test.o: randomArray.o
$(C) $(FLAGS) $(INCLUDES) -c test.cpp
randomArray.o: randomArray.c
$(C) $(FLAGS) $(INCLUDES) -c randomArray.c
Error message
make
g++ -Wextra -g -lm randomArray.o -o test
/usr/bin/ld: /usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../lib/Scrt1.o: in function `_start':
(.text+0x24): undefined reference to `main'
collect2: error: ld returned 1 exit status
make: *** [makefile:9: test] Error 1
#include <iostream>
#include "randomArray.h"
using namespace std;
int main(int argc, char const *argv[])
{
int *bit=randomArray(64);
for (int i = 0; i < 64; i++)
{
cout<<bit[i]<< "\n";
}
return 0;
}
You forgot to link in test.o:
test: randomArray.o test.o
$(CC) $(FLAGS) $(INCLUDES) randomArray.o test.o -o test
Also note that test.o: randomArray.o is probably wrong. It says test.o depends on randomArray.o, which it doesn't. It depends on test.cpp.
test.o: test.cpp
$(CC) $(FLAGS) $(INCLUDES) -c test.cpp

linux C++. Link shared objects and main

I write simple testing program in C++, which will tell Hello, Alex and exit.
Here it's code:
main.cpp:
#include <iostream>
#include <dlfcn.h>
int main()
{
void* descriptor = dlopen("dll.so", RTLD_LAZY);
std::string (*fun)(const std::string name) = (std::string (*)(const std::string)) dlsym(descriptor, "sayHello");
std::cout << fun("Alex") << std::endl;
dlclose(descriptor);
return 0;
}
dll.h:
#ifndef UNTITLED_DLL_H
#define UNTITLED_DLL_H
#include <string>
std::string sayHello(const std::string name);
#endif
dll.cpp:
#include "dll.h"
std::string sayHello(const std::string name)
{
return ("Hello, " + name);
}
makefile:
build_all : main dll.so
main : main.cpp
$(CXX) -c main.cpp
$(CXX) -o main main.o -ldl
dll.so : dll.h dll.cpp
$(CXX) -c dll.cpp
$(CXX) -shared -o dll dll.o
But when I build my code with make, I have such error:
/usr/bin/ld: dll.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
dll.o: error adding symbols: Bad value
collect2: error: ld returned 1 exit status
makefile:8: recipe for target 'dll.so' failed
make: *** [dll.so] Error 1
What did I make not correct?
P.S. I use GNU Make 3.81 on Ubuntu Server 14.04.3 with GNU GCC 4.8.4
Update
If I link dll.so file with -fPIC param, I have the same error
Firstly, a bit off topic, but in your makefile, it would be better to specify build_all as a phony target
.PHONY: build_all
Next, you are compiling dll.cpp without relocatable code. You need to add -fpic or -fPIC (see here for an explanation of the difference).
$(CXX) -c dll.cpp -fpic
Lastly, unix doesn't automatically add file suffixes, so here you need to specify .so:
$(CXX) -shared -o dll.so dll.o

undefined reference in linking against C++ library

I write a C++ library and when linking against the library the symbols in it cannot be found. Here's what I've got:
a.cpp:
void zak()
{
}
test.cpp:
extern void zak();
int main(int argc, const char ** argv)
{
zak();
}
Makefile:
all:
g++ -c -o a.o a.cpp
ar r libzak.a a.o
g++ -L. -lzak test.cpp -o test
Here is what make says on my (Linux Mint 13) box:
g++ -c -o a.o a.cpp
ar r libzak.a a.o
g++ -L. -lzak test.cpp -o test
/tmp/ccC4cnLV.o: In function `main':
test.cpp:(.text+0x7): undefined reference to `zak()'
collect2: error: ld returned 1 exit status
make: *** [all] Error 1
I am sure I am missing something obvious, but what is it?
Link order matters. Put -lzak after test.cpp on the link line.
I think that -l is for shared libraries (.so). Try this: g++ libzak.a test.cpp -o test

Cannot make Cuda program

I have got in the same directory 3 files:
hellomake.cu
#include<hellofunc.h>
int main(){
myPrintHelloMake();
return 0;
}
hellofunc.c
#include<stdio.h>
#include<stdlib.h>
void myPrintHelloMake(void){
printf("Hello dummy!\n");
return;
}
hellofunc.h
void myPrintHelloMake(void)
Makefile
CC=/usr/local/cuda-5.5/bin/nvcc
CFLAGS=-I.
hellomake: hellomake.cu hellofunc.c
$(CC) -o hellomake hellomake.cu hellofunc.c -I.
But when I run through terminal make it prints out:
/usr/local/cuda-5.5/bin/nvcc -o hellomake hellomake.cu hellofunc.c -I.
/tmp/tmpxft_000013bf_00000000-14_hellomake.o: In function main':
tmpxft_000013bf_00000000-3_hellomake.cudafe1.cpp:(.text+0x5): undefined reference tomyPrintHelloMake()'
collect2: ld returned 1 exit status
make: * [hellomake] Error 1
What might be the problem?
You could change the filename hellofunc.c to hellofunc.cpp.
If the filename cannot be changed, you could search more information about how to invoke C functions in C++ code.
You should change the name of hellofunc.c to hellofunc.cu. You may also use #include "hellofunc.h".

Getting Undefined Reference to Perl on C++

Well, first of all, sorry about my bad english!
I'm new to linux, g++ and perl, and I'm getting some problems here.
I have a code in G++ which calls a perl .pl file to return a information. Right now, I'm just returning 1 or 0 from the perl .pl file for tests and to understand how does it works. But the problem is that I'm getting this from the $make:
sathlervbn Spam C # make clean;make
rm -f *.o
g++ -Wall -D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fstack-protector -fno-strict-aliasing -pipe -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/lib/perl/5.14/CORE -c -o filedir.o filedir.cpp
g++ -Wall -D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fstack-protector -fno-strict-aliasing -pipe -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/lib/perl/5.14/CORE -c -o main.o main.cpp
main.cpp: In function ‘int main(int, char**, char**)’:
main.cpp:112:41: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
main.cpp:112:41: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
g++ -L/usr/lib -Wall -Wl,-E -fstack-protector -L/usr/local/lib -L/usr/lib/perl/5.14/CORE - lperl -ldl -lm -lpthread -lc -lcrypt -o main filedir.o main.o
main.o: In function `getInfoPerl(std::string)':
main.cpp:(.text+0x1a): undefined reference to `Perl_push_scope'
main.cpp:(.text+0x33): undefined reference to `Perl_save_int'
main.cpp:(.text+0x73): undefined reference to `Perl_markstack_grow'
main.cpp:(.text+0xcd): undefined reference to `Perl_stack_grow'
main.cpp:(.text+0xfa): undefined reference to `Perl_newSVpv'
main.cpp:(.text+0x10d): undefined reference to `Perl_sv_2mortal'
main.cpp:(.text+0x13b): undefined reference to `Perl_call_pv'
main.cpp:(.text+0x18f): undefined reference to `Perl_sv_2iv_flags'
main.cpp:(.text+0x1bd): undefined reference to `Perl_free_tmps'
main.cpp:(.text+0x1ca): undefined reference to `Perl_pop_scope'
main.o: In function `main':
main.cpp:(.text+0x206): undefined reference to `Perl_sys_init3'
main.cpp:(.text+0x20b): undefined reference to `perl_alloc'
main.cpp:(.text+0x21d): undefined reference to `perl_construct'
main.cpp:(.text+0x265): undefined reference to `perl_parse'
main.cpp:(.text+0x272): undefined reference to `perl_run'
main.cpp:(.text+0x2fd): undefined reference to `perl_destruct'
main.cpp:(.text+0x30a): undefined reference to `perl_free'
main.cpp:(.text+0x30f): undefined reference to `Perl_sys_term'
collect2: error: ld returned 1 exit status
make: *** [main] Error 1
The main.cpp code is:
#include <EXTERN.h>
#include <perl.h>
#include <iostream>
#include <cstdio>
#include "filedir.h"
using namespace std;
PerlInterpreter *my_perl;
int getInfoPerl(string email){
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSVpv(email.c_str(),0)));
PUTBACK;
call_pv("spamTeste", G_SCALAR);
SPAGAIN;
int resultado = POPi;
PUTBACK;
FREETMPS;
LEAVE;
return resultado;
}
int main(int argc, char **argv, char **env) {
char *my_argv[] = { " ", "spamPerl.pl" };
PERL_SYS_INIT3 (&argc, &argv, &env);
my_perl = perl_alloc();
perl_construct ( my_perl );
PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
perl_parse(my_perl, NULL, 2, my_argv, (char **)NULL);
perl_run(my_perl);
cout << "Resultado " << getInfoPerl("email/email.txt") << endl;
perl_destruct(my_perl);
perl_free(my_perl);
PERL_SYS_TERM();
foobar bla bla bla another part from the code: doesn't matter.
}
Here is the makefile:
#CC= /usr/bin/g++
CPP = g++
CPPFLAGS = -Wall $(shell perl -MExtUtils::Embed -e ccopts)
#LD= /usr/bin/g++
LD = g++
LFLAGS = -Wall $(shell perl -MExtUtils::Embed -e ldopts)
#LFLAGS = -Wall -Wl,-E -fstack-protector -L/usr/local/lib -L/usr/lib/perl/5.14/CORE -lperl -ldl -lm -lpthread -lc -lcrypt
MAINOBJS = filedir.o main.o
EMAILS = main
EXECS = $(EMAILS)
#Regra Implicita:
.c.o:
$(CPP) $(CPPFLAGS) -c $<
all: emails
emails: $(EMAILS)
main: $(MAINOBJS)
$(LD) -L/usr/lib $(LFLAGS) -o $# $(MAINOBJS)
clean:
rm -f *.o
What I did? I've tried installing libperl-dev package, update the perl, and nothing solved.
I really need to fix this! Can someone help me?
UPDATE:
Changed the Header from main.cpp to:
#ifdef __cplusplus
extern "C" {
#endif
#include "EXTERN.h"
#include "perl.h"
#ifdef __cplusplus
}
#endif
#include <iostream>
#include <cstdio>
#include "filedir.h"
Didn't work...
The answer previous is right, it is cause by the sequence of gcc parameters. I test a sample code provided by the official perlembed tutorial:
http://perldoc.perl.org/perlembed.html
if the compile option is
cc -o interp interp.c perl -MExtUtils::Embed -e ccopts -e ldopts
as provided by the tutorial, it is right.
But any other sequence is wrong, for example:
cc interp.c -o interp perl -MExtUtils::Embed -e ccopts -e ldopts
cc perl -MExtUtils::Embed -e ccopts -e ldopts interp.c -o interp
so make sure in your Makefile -o goes the first and source file goes the second.
The problem was in the makefile:
#CC= /usr/bin/g++
CPP = g++
CPPFLAGS = -Wall $(shell perl -MExtUtils::Embed -e ccopts)
#LD= /usr/bin/g++
LD = g++
LFLAGS = -Wall $(shell perl -MExtUtils::Embed -e ldopts)
#LFLAGS = -Wall -Wl,-E -fstack-protector -L/usr/local/lib -L/usr/lib/perl/5.14/CORE -lperl -ldl -lm -lpthread -lc -lcrypt
MAINOBJS = filedir.o main.o
EMAILS = main
EXECS = $(EMAILS)
#Regra Implicita:
.c.o:
$(CPP) $(CPPFLAGS) -c $<
all: emails
emails: $(EMAILS)
main: $(MAINOBJS)
$(LD) -L/usr/lib $(LFLAGS) -o $# $(MAINOBJS)
clean:
rm -f *.o
As you can see, in this line, the code:
main: $(MAINOBJS)
$(LD) -L/usr/lib $(LFLAGS) -o $# $(MAINOBJS)
Should have the $(LFLAGS) after the $(MAINOBJS), so it should be:
main: $(MAINOBJS)
$(LD) -L/usr/lib -o $# $(MAINOBJS) $(LFLAGS)
Now, the linker is working perfectly. I'm sorry, but I can't say exactly why this is necessary, I've just discovered.