avr32-gcc: Global variable not initialized with function output - c++

I try to initialize a global variable with the output of a function. It works as expected for gnu-gcc, but when compiled with avr32-gcc, the variable is initialized with 0. I want the variable to be initialized by a function since in the real scenario it is a reference (MyClass& myclass = MyClass::getInstance().
Here is the code:
extern "C"
{
#include "led.h"
}
int getInteger()
{
return 10;
}
int my_int = getInteger();
int main (void)
{
LED_On(LED2);
//my_int = getInteger(); //* This line really sets my_int = 10;
if(my_int == 10)
{
LED_On(LED1);
}
while(1){
__asm__ ("nop");
}
return 0;
}
and here is my Makefile:
PROJ_NAME=TEST
# Include paths for project folder
SRCS_INC += -I. -I./preprocessor
# Sources files for project folder (*.c and *.cpp)
SRCS += main.cpp exception_noNMI.S startup_uc3.S trampoline_uc3.S intc.c led.c
AS = avr32-gcc
ASFLAGS = -x assembler-with-cpp -c -mpart=uc3c1512c -mrelax
ASFLAGS += ${SRCS_INC}
CC = avr32-gcc
CFLAGS += -mpart=uc3c1512c
CFLAGS += ${SRCS_INC}
CXX = avr32-g++
LINKER = avr32-g++
OBJCOPY = avr32-objcopy
LDFLAGS = -nostartfiles -mpart=uc3c1512c
LDFLAGS += ${SRCS_INC}
OBJS += $(addsuffix .o, $(basename $(SRCS)))
# Main rule
all: $(PROJ_NAME).elf
# Linking
${PROJ_NAME}.elf: ${OBJS}
#echo Linking...
#$(CXX) $(LDFLAGS) $^ -o $#
#$(OBJCOPY) -O ihex ${OBJCOPYFLAGS} $(PROJ_NAME).elf $(PROJ_NAME).hex
#$(OBJCOPY) -O binary $(PROJ_NAME).elf $(PROJ_NAME).bin
# Assembly files in source folder
%.o: ./%.S
#mkdir -p $(dir $#)
#$(AS) $(ASFLAGS) -c $< -o $#
# C files in source folder
%.o: ./%.c
#mkdir -p $(dir $#)
#$(CC) -c $< -o $# $(CFLAGS)
# CPP files in SRC folder
%.o: ./%.cpp
#mkdir -p $(dir $#)
#$(CXX) -c $< -o $# $(CFLAGS)
.PHONY: clean
clean:
#rm -f $(OBJS) $(PROJ_NAME).elf $(PROJ_NAME).hex $(PROJ_NAME).bin
I also tried to make an init function with __attribute(constructor) as explained in this answer.
Still it is not excuted.

As far as I can see, you're not having optimization enabled. Thus, the compiler may actually make a call to getInteger during startup. Now, you're replacing the default startup with something that you do not show. Maybe you just need to make sure that this is done during startup? Also, you could try to enable optimization and see if the call is resolved.

Related

How do I keep the following makefiles from recompiling all source code when one or more source files are changed?

How do I keep the Makefiles that are at https://github.com/Zero3K/hpsx64 from recompiling all source code when only one or more of the source code files have changed so that way people can be able to make changes to it without having to wait for it to compile the changes? Here's one of them:
DIR_COMMON = ./common
DIR_PLATFORM = $(DIR_COMMON)/WindowsAPI
DIR_HPS1X64 = ./hps1x64/src
INC_COMMON = -I$(DIR_COMMON) -I$(DIR_COMMON)/StringUtilities -I$(DIR_COMMON)/breakpoint/src -I$(DIR_COMMON)/debug/src -I$(DIR_COMMON)/DiskImage/cd/src -I$(DIR_COMMON)/x64Encoder/src -I$(DIR_COMMON)/config/src
INC_PS1_PLATFORM = -I$(DIR_HPS1X64)/hps1x64/src/ -I$(DIR_PLATFORM)/GUIHandler/src/ -I$(DIR_PLATFORM)/WinFile/src/ -I$(DIR_PLATFORM)/DebugValueList/src/ -I$(DIR_PLATFORM)/DisassemblyViewer/src/ -I$(DIR_PLATFORM)/InputBox/src/ -I$(DIR_PLATFORM)/DebugMemoryViewer/src/ -I$(DIR_PLATFORM)/BreakpointWindow/src/ -I$(DIR_PLATFORM)/Joystick/src/
DIR_PS1 = $(DIR_HPS1X64)
DIR_PS1_R3000A = $(DIR_PS1)/r3000a/src
DIR_PS1_CD = $(DIR_PS1)/cd/src
DIR_PS1_GPU = $(DIR_PS1)/gpu/src
DIR_PS1_DMA = $(DIR_PS1)/dma/src
DIR_PS1_INTC = $(DIR_PS1)/intc/src
DIR_PS1_MDEC = $(DIR_PS1)/mdec/src
DIR_PS1_SPU = $(DIR_PS1)/spu/src
DIR_PS1_SIO = $(DIR_PS1)/sio/src
DIR_PS1_PIO = $(DIR_PS1)/pio/src
DIR_PS1_TIMER = $(DIR_PS1)/timer/src
DIR_PS1_BUS = $(DIR_PS1)/databus/src
DIR_PS1_SYSTEM = $(DIR_PS1)/system/src
INC_PS1_R3000A = -I$(DIR_PS1_R3000A) -I$(DIR_PS1_R3000A)/execute -I$(DIR_PS1_R3000A)/lookup -I$(DIR_PS1_R3000A)/print -I$(DIR_PS1_R3000A)/COP2 -I$(DIR_PS1_R3000A)/recompile -I$(DIR_PS1_R3000A)/cache
INC_PS1_CD = -I$(DIR_PS1_CD)
INC_PS1_GPU = -I$(DIR_PS1_GPU)
INC_PS1_DMA = -I$(DIR_PS1_DMA)
INC_PS1_INTC = -I$(DIR_PS1_INTC)
INC_PS1_MDEC = -I$(DIR_PS1_MDEC)
INC_PS1_SPU = -I$(DIR_PS1_SPU)
INC_PS1_SIO = -I$(DIR_PS1_SIO)
INC_PS1_PIO = -I$(DIR_PS1_PIO)
INC_PS1_TIMER = -I$(DIR_PS1_TIMER)
INC_PS1_BUS = -I$(DIR_PS1_BUS)
INC_PS1_SYSTEM = -I$(DIR_PS1_SYSTEM)
INC_PS1 = $(INC_PS1_R3000A) $(INC_PS1_CD) $(INC_PS1_GPU) $(INC_PS1_DMA) $(INC_PS1_INTC) $(INC_PS1_MDEC) $(INC_PS1_SPU) $(INC_PS1_SIO) $(INC_PS1_PIO) $(INC_PS1_TIMER) $(INC_PS1_BUS) $(INC_PS1_SYSTEM)
SRC_PS1_PLATFORM = $(wildcard $(DIR_HPS1X64)/hps1x64/src/*.cpp) $(wildcard $(DIR_PLATFORM)/GUIHandler/src/*.cpp) $(wildcard $(DIR_PLATFORM)/WinFile/src/*.cpp) $(wildcard $(DIR_PLATFORM)/DisassemblyViewer/src/*.cpp) $(wildcard $(DIR_PLATFORM)/InputBox/src/*.cpp) $(wildcard $(DIR_PLATFORM)/DebugMemoryViewer/src/*.cpp) $(wildcard $(DIR_PLATFORM)/BreakpointWindow/src/*.cpp) $(wildcard $(DIR_PLATFORM)/Joystick/src/*.cpp)
SRC_COMMON = $(wildcard $(DIR_COMMON)/StringUtilities/*.cpp) $(wildcard $(DIR_COMMON)/breakpoint/src/*.cpp) $(wildcard $(DIR_COMMON)/debug/src/*.cpp) $(wildcard $(DIR_COMMON)/DiskImage/cd/src/*.cpp) $(wildcard $(DIR_COMMON)/x64Encoder/src/*.cpp) $(wildcard $(DIR_COMMON)/config/src/*.cpp)
SRC_PS1_R3000A = $(wildcard $(DIR_PS1_R3000A)/*.cpp) $(wildcard $(DIR_PS1_R3000A)/execute/*.cpp) $(wildcard $(DIR_PS1_R3000A)/lookup/*.cpp) $(wildcard $(DIR_PS1_R3000A)/print/*.cpp) $(wildcard $(DIR_PS1_R3000A)/COP2/*.cpp) $(wildcard $(DIR_PS1_R3000A)/recompile/*.cpp)
SRC_PS1_CD = $(wildcard $(DIR_PS1_CD)/*.cpp)
SRC_PS1_GPU = $(wildcard $(DIR_PS1_GPU)/*.cpp)
SRC_PS1_DMA = $(wildcard $(DIR_PS1_DMA)/*.cpp)
SRC_PS1_INTC = $(wildcard $(DIR_PS1_INTC)/*.cpp)
SRC_PS1_MDEC = $(wildcard $(DIR_PS1_MDEC)/*.cpp)
SRC_PS1_SPU = $(wildcard $(DIR_PS1_SPU)/*.cpp)
SRC_PS1_SIO = $(wildcard $(DIR_PS1_SIO)/*.cpp)
SRC_PS1_PIO = $(wildcard $(DIR_PS1_PIO)/*.cpp)
SRC_PS1_TIMER = $(wildcard $(DIR_PS1_TIMER)/*.cpp)
SRC_PS1_BUS = $(wildcard $(DIR_PS1_BUS)/*.cpp)
SRC_PS1_SYSTEM = $(wildcard $(DIR_PS1_SYSTEM)/*.cpp)
SRC_PS1 = $(SRC_PS1_R3000A) $(SRC_PS1_CD) $(SRC_PS1_GPU) $(SRC_PS1_DMA) $(SRC_PS1_INTC) $(SRC_PS1_MDEC) $(SRC_PS1_SPU) $(SRC_PS1_SIO) $(SRC_PS1_PIO) $(SRC_PS1_TIMER) $(SRC_PS1_BUS) $(SRC_PS1_SYSTEM)
INC = $(INC_PS1) $(INC_COMMON) $(INC_PS1_PLATFORM)
SRC = $(SRC_PS1) $(SRC_COMMON) $(SRC_PS1_PLATFORM)
LIBS = -lglew32 -lopengl32 -lglu32 -lgdi32 -lComctl32 -lkernel32 -lwinmm -ldinput8 -ldxguid
CFLAGS = -w -Wl,-subsystem,console -mwindows -static -static-libgcc -static-libstdc++ -DGLEW_STATIC -O3 -DUSE_PS1_GPU_TEMPLATES
#-Wl,--stack,134217728
#-Wl,--stack,16777216
OBJ = hps1x64
$(OBJ): $(SRC)
g++ $(CFLAGS) $(INC) -o $# $^ $(LIBS)
The problem is this:
$(OBJ): $(SRC)
g++ $(CFLAGS) $(INC) -o $# $^ $(LIBS)
Frankly, that's a terrible rule.
Instead, you can do something like this:
${OBJDIR}/%.o : src/%.cpp
g++ $(CFLAGS) $(INC) -o $# $^ $(LIBS)
Okay, adding this. This is an actual Makefile I just wrote:
SRC = foo.cpp bar.cpp
OBJS := $(patsubst %.cpp,%.o,${SRC})
echo:
echo ${OBJS}
%.o: %.cpp
g++ -c --std=c++17 $^ -o $#
foo: ${OBJS}
g++ ${OBJS} -o foo
So, if we apply this to your Makefile above, near the bottom:
OBJS := $(patsubst %.cpp,%.o,${SRC})
%.o: %.cpp
g++ ${CFLAGS} ${INC} -c $^ -o $#
$(OBJ): $(OBJS)
g++ $(CFLAGS) $(INC) -o $# $^ $(LIBS)
Note that the last pair of lines has a change. $(OBJ): $(SRC) becomes $(OBJ): $(OBJS).
What this does:
OBJS := $(patsubst %.cpp,%.o,${SRC})
This creates a new variable named OBJS that takes the SRC variable and changes every xxx.cpp to xxx.o.
%.o: %.cpp
g++ ${CFLAGS} ${INC} -c $^ -o $#
This is a generic rule for compiling xxx.cpp into xxx.o
$(OBJ): $(OBJS)
g++ $(CFLAGS) $(INC) -o $# $^ $(LIBS)
This is the original rule, but instead of depending upon SRC, it depends on the individual .o files.

function define in .h declared in .cu

I made a project split in three folders : src, include, obj
I am using CImg.h and cuda.h library.
I declare void convolve(cimg_library::CImg<float>&, cimg_library::CImg<float> const &);in convolve.h
and define it in convolve.cu
my files :
main.cpp :
#include "CImg.h"
#include "../include/convolve.h"
using namespace cimg_library;
int main(){
CImg<float> var1("/*path*/");
CImg<float> var2("/*path2*/");
convolve(var1,var2);
//some code
}
convolve.h :
1 #ifndef CONVOLVE_H
2 #define CONVOLVE_H
//some define
10 void convolve(cimg_library::CImg<float>&, cimg_library::CImg<float> const &);
11 #endif //CONVOLVE_H
convolve.cu :
1 void convolve(CImg<float>& img, const CImg<float>& kernel){
//some code
24 kernel<<<dimGrid,dimBlocks>>>(/*some arg*/);
}
and my new makefile :
1 CC=nvcc
2 CX=g++
3 IDIR =../include
4 special_IDIR = /usr/local/cuda-9.0/include
5 LDIR = /usr/local/cuda-9.0/lib64
6 CFLAGS=-I$(special_IDIR) -L$(LDIR)
7
8 LIBS = -lX11 -lpthread -lcudart
9 ODIR = ../obj
10
11
12 _DEPS = convolve.h kernel.cuh
13 DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
14
15 _OBJ = main.o convolve.o kernel.o
16 OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
17
18 $(ODIR)/%.o: %.cpp $(DEPS)
19 $(CX) -x c++ -o $# $< $(CFLAGS) $(LIBS)
20
21 $(ODIR)/%.o: %.cu $(DEPS)
22 $(CC) -cu -o $# $< $(CFLAGS)
23
24 all: $(OBJ)
25 $(CC) -o $# $^ $(CFLAGS)
26
27
28 .PHONY: clean
29
30 clean:
31 rm -f $(ODIR)/*.o *~ core $(INCDIR)/*~
Here is my issue : it says the reference to void convolve(cimg_library::CImg<float>&, cimg_library::CImg<float> const &) is undefined.
I think this is because I never clearly say to the compiler that the definition of convolve is in convolve.cu. But I do not find how to make this link properly.
Thanks for your help !
please don't post code (or Makefile contents) with line numbers. It just gets in the way, usually.
The compilation process here follows a compile...link process. The first stage is the compile stage, and you should be using -c for both g++ and nvcc during this stage (i.e. for both types of Makefile targets)
nvcc has no -cu option. I think maybe you meant -x cu
I also removed the ampersands on the function call.
Here is a simplified example based on what you have shown, primarily removing the CImg stuff and some other unnecessary items:
$ cat main.cpp
#include "convolve.h"
int main(){
int var1 = 0;
int var2 = 1;
convolve(var1, var2);
}
$ cat convolve.h
void convolve(int &, int &);
$ cat convolve.cu
#include "convolve.h"
__global__ void kernel(){};
void convolve(int & i1, int & i2){
kernel<<<1,1>>>();
}
$ cat Makefile
CC=nvcc
CX=g++
IDIR = .
special_IDIR = /usr/local/cuda-9.1/include
LDIR = /usr/local/cuda-9.1/lib64
CFLAGS=-I$(special_IDIR) -L$(LDIR)
LIBS =
ODIR = .
_DEPS = convolve.h
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
_OBJ = main.o convolve.o
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
$(ODIR)/%.o: %.cu $(DEPS)
$(CC) -c -x cu -o $# $< $(CFLAGS)
$(ODIR)/%.o: %.cpp $(DEPS)
$(CX) -c -x c++ -o $# $< $(CFLAGS) $(LIBS)
all: $(OBJ)
$(CC) -o $# $^ $(CFLAGS)
.PHONY: clean
clean:
rm -f $(ODIR)/*.o *~ core $(INCDIR)/*~
$ make clean
rm -f ./*.o *~ core /*~
$ make
g++ -c -x c++ -o main.o main.cpp -I/usr/local/cuda-9.1/include -L/usr/local/cuda-9.1/lib64
nvcc -c -x cu -o convolve.o convolve.cu -I/usr/local/cuda-9.1/include -L/usr/local/cuda-9.1/lib64
nvcc -o all main.o convolve.o -I/usr/local/cuda-9.1/include -L/usr/local/cuda-9.1/lib64
$
change the instances of cuda-9.1 to cuda-9.0 in the above Makefile if you have CUDA 9.0 in your setup. The linker libs (-L) are not really needed for the compile commands, however. When linking with nvcc as we are doing here, it's also unnecessary to pass the -I and -L switches that refer to the CUDA includes and CUDA libraries that are part of the toolkit. nvcc already knows how to find those.
There may be any number of additional recommendations or tweaks to the Makefile, for instance the -x cu and -x c++ switches are probably unnecessary (at least they are unnecessary for my simplified example) but my objective here is not to create the perfect Makefile, but to give you a roadmap to get past the issue you are currently witnessing.

Makefile compilation error from cuda/cpp program [duplicate]

I made a project split in three folders : src, include, obj
I am using CImg.h and cuda.h library.
I declare void convolve(cimg_library::CImg<float>&, cimg_library::CImg<float> const &);in convolve.h
and define it in convolve.cu
my files :
main.cpp :
#include "CImg.h"
#include "../include/convolve.h"
using namespace cimg_library;
int main(){
CImg<float> var1("/*path*/");
CImg<float> var2("/*path2*/");
convolve(var1,var2);
//some code
}
convolve.h :
1 #ifndef CONVOLVE_H
2 #define CONVOLVE_H
//some define
10 void convolve(cimg_library::CImg<float>&, cimg_library::CImg<float> const &);
11 #endif //CONVOLVE_H
convolve.cu :
1 void convolve(CImg<float>& img, const CImg<float>& kernel){
//some code
24 kernel<<<dimGrid,dimBlocks>>>(/*some arg*/);
}
and my new makefile :
1 CC=nvcc
2 CX=g++
3 IDIR =../include
4 special_IDIR = /usr/local/cuda-9.0/include
5 LDIR = /usr/local/cuda-9.0/lib64
6 CFLAGS=-I$(special_IDIR) -L$(LDIR)
7
8 LIBS = -lX11 -lpthread -lcudart
9 ODIR = ../obj
10
11
12 _DEPS = convolve.h kernel.cuh
13 DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
14
15 _OBJ = main.o convolve.o kernel.o
16 OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
17
18 $(ODIR)/%.o: %.cpp $(DEPS)
19 $(CX) -x c++ -o $# $< $(CFLAGS) $(LIBS)
20
21 $(ODIR)/%.o: %.cu $(DEPS)
22 $(CC) -cu -o $# $< $(CFLAGS)
23
24 all: $(OBJ)
25 $(CC) -o $# $^ $(CFLAGS)
26
27
28 .PHONY: clean
29
30 clean:
31 rm -f $(ODIR)/*.o *~ core $(INCDIR)/*~
Here is my issue : it says the reference to void convolve(cimg_library::CImg<float>&, cimg_library::CImg<float> const &) is undefined.
I think this is because I never clearly say to the compiler that the definition of convolve is in convolve.cu. But I do not find how to make this link properly.
Thanks for your help !
please don't post code (or Makefile contents) with line numbers. It just gets in the way, usually.
The compilation process here follows a compile...link process. The first stage is the compile stage, and you should be using -c for both g++ and nvcc during this stage (i.e. for both types of Makefile targets)
nvcc has no -cu option. I think maybe you meant -x cu
I also removed the ampersands on the function call.
Here is a simplified example based on what you have shown, primarily removing the CImg stuff and some other unnecessary items:
$ cat main.cpp
#include "convolve.h"
int main(){
int var1 = 0;
int var2 = 1;
convolve(var1, var2);
}
$ cat convolve.h
void convolve(int &, int &);
$ cat convolve.cu
#include "convolve.h"
__global__ void kernel(){};
void convolve(int & i1, int & i2){
kernel<<<1,1>>>();
}
$ cat Makefile
CC=nvcc
CX=g++
IDIR = .
special_IDIR = /usr/local/cuda-9.1/include
LDIR = /usr/local/cuda-9.1/lib64
CFLAGS=-I$(special_IDIR) -L$(LDIR)
LIBS =
ODIR = .
_DEPS = convolve.h
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
_OBJ = main.o convolve.o
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
$(ODIR)/%.o: %.cu $(DEPS)
$(CC) -c -x cu -o $# $< $(CFLAGS)
$(ODIR)/%.o: %.cpp $(DEPS)
$(CX) -c -x c++ -o $# $< $(CFLAGS) $(LIBS)
all: $(OBJ)
$(CC) -o $# $^ $(CFLAGS)
.PHONY: clean
clean:
rm -f $(ODIR)/*.o *~ core $(INCDIR)/*~
$ make clean
rm -f ./*.o *~ core /*~
$ make
g++ -c -x c++ -o main.o main.cpp -I/usr/local/cuda-9.1/include -L/usr/local/cuda-9.1/lib64
nvcc -c -x cu -o convolve.o convolve.cu -I/usr/local/cuda-9.1/include -L/usr/local/cuda-9.1/lib64
nvcc -o all main.o convolve.o -I/usr/local/cuda-9.1/include -L/usr/local/cuda-9.1/lib64
$
change the instances of cuda-9.1 to cuda-9.0 in the above Makefile if you have CUDA 9.0 in your setup. The linker libs (-L) are not really needed for the compile commands, however. When linking with nvcc as we are doing here, it's also unnecessary to pass the -I and -L switches that refer to the CUDA includes and CUDA libraries that are part of the toolkit. nvcc already knows how to find those.
There may be any number of additional recommendations or tweaks to the Makefile, for instance the -x cu and -x c++ switches are probably unnecessary (at least they are unnecessary for my simplified example) but my objective here is not to create the perfect Makefile, but to give you a roadmap to get past the issue you are currently witnessing.

Undefined referece to class constructor

I'm getting the following error:
> /tmp/ccYbdvB8.o: In function `main':
> /home/caleb/Documents/dev/cs438/tote2/mp2/manager.cpp:5: undefined
> reference to `TCPConnection::TCPConnection(char const*, char const*)'
> collect2: error: ld returned 1 exit status make: *** [manager] Error 1
I've included the header to the class I'm trying to initialize.. so I'm thinking maybe it's my makefile? I'm pretty new to writing custom makefiles...
cpp:
#include "tcpcon.h"
const string TCPConnection::Client = "client";
const string TCPConnection::Server = "server";
TCPConnection::TCPConnection(const char* t, const char* p) : target(t), port(p)
{ }
h:
class TCPConnection{
public:
TCPConnection(const char *target, const char *port);
main:
#include "tcpcon.h"
int main()
{
TCPConnection *TCPCon = new TCPConnection("localhost", "7777");
cout << "Hi\n";
return 0;
}
makefile:
CC=g++
CCOPTS=-Wall -Wextra -g
OBJS = tcpcon.o
TARGETS = manager
.PHONY: all clean
$(TARGET) : $(OBJS)
$(CC) -o $# $^ $(CFLAGS) $(LIBS)
all: $(OBJS) $(TARGETS)
clean:
rm -f $(TARGETS) $(OBJS)
%: %.cpp
$(CC) $(CCOPTS) -o $# $<
It turns out that the issue may have been related to a couple of things:
Use of $(TARGET) instead of $(TARGETS) in one place
Did not include the main file (manager.cpp) to the OBJS list
My updated makefile is below:
CC=g++
CCOPTS=-Wall -Wextra -g
OBJS = manager.o tcpcon.o
TARGETS = manager
.PHONY: all clean
$(TARGETS) : $(OBJS)
$(CC) -o $# $^ $(CFLAGS) $(LIBS)
all: $(TARGETS) $(OBJS)
clean:
rm -f $(TARGETS) $(OBJS)
%: %.cpp
$(CC) $(CCOPTS) -o $# $<

C++ Ruby Extension with External Libraries

I started a little experiment today: I wrote a C++ class which depends on some other libraries (ALGLIB, Eigen, internal tools) and I wanted to create a Ruby wrapper for that class. I'm currently using Rice to do that. First I wrote a very simple C++ wrapper for my class:
// #file MLPWrapper.h
#pragma once
#include "mlp/MLP.h"
#include <ruby.h>
class MLPWrapper
{
MLP mlp; // <- my C++ class
public:
...
void fit()
{
...
mlp.fit(stop);
}
};
The library's cpp-file is this:
// #file cmlp.cpp
#include "rice/Data_Type.hpp"
#include "rice/Constructor.hpp"
#include "MLPWrapper.h"
using namespace Rice;
extern "C"
void Init_cmlp()
{
Data_Type<MLPWrapper> rb_cMLPWrapper = define_class<MLPWrapper>("MLP")
.define_constructor(Constructor<MLPWrapper>())
...
.define_method("fit", &MLPWrapper::fit);
}
And this is the extconf.rb:
require "mkmf-rice"
$CFLAGS << "-O3"
HEADER_DIRS = [
"..",
"../../external/libraries/eigen-eigen-3.0.1",
"../../external/libraries/alglib/cpp/src",
"../../external/libraries/CMA-ESpp"
]
LIB_DIRS = [
"../../build/external/libraries/alglib/cpp/src",
"../../build/external/libraries/CMA-ESpp/cma-es",
"../../build/src/tools"
]
dir_config("libs", HEADER_DIRS, LIB_DIRS)
have_library("libtools")
have_library("libalglib")
create_makefile("cmlp")
Everything works fine except linking. Obviously the header files of the libraries are included, otherwise it would not compile. But when I run a little test program ("require "cmlp"; mlp = MLP.new") in Ruby it does not find the symbol _ZN6LoggerC1ENS_6TargetESs, which is part of libtools (an enum). This is what happens when I build the C++ extension and execute the test program:
$ ruby extconf.rb
checking for main() in -lrice... yes
checking for main() in -llibtools... no
checking for main() in -llibalglib... no
checking for main() in -llibcmaes... no
creating Makefile
$ make
g++ -I. -I. -I/usr/lib/ruby/1.8/x86_64-linux -I. -I.. -I../../external/libraries/eigen-eigen-3.0.1 -I../../external/libraries/alglib/cpp/src -I../../external/libraries/CMA-ESpp -I/var/lib/gems/1.8/gems/rice-1.4.3/ruby/lib/include -fPIC -fno-strict-aliasing -g -g -O2 -fPIC -O3 -Wall -g -c cmlp.cpp
g++ -shared -o cmlp.so cmlp.o -L. -L/usr/lib -L../../build/external/libraries/alglib/cpp/src -L../../build/external/libraries/CMA-ESpp/cma-es -L../../build/src/tools -L. -Wl,-Bsymbolic-functions -rdynamic -Wl,-export-dynamic -L/var/lib/gems/1.8/gems/rice-1.4.3/ruby/lib/lib -lrice -lruby1.8 -lpthread -lrt -ldl -lcrypt -lm -lc
$ ruby test.rb
ruby: symbol lookup error: ./cmlp.so: undefined symbol: _ZN6LoggerC1ENS_6TargetESs
The libraries are all compiled with CMake (add_library(...)) and are located at
../../build/src/tools/libtools.so
../../build/external/libraries/alglib/cpp/src/libalglib.so
../../build/external/libraries/CMA-ESpp/cma-es/libcmaes.so
I don't know how to solve this problem on my own and I could not find any helpful documentation for my problem. How do i fix this extconf.rb? I appreciate every hint.
edit: OK, I changed the extconf.rb:
require "rubygems"
require "mkmf-rice"
BASE_DIR = "/bla/"
$CFLAGS << " -O3"
dir_config("tools", [BASE_DIR + "src", BASE_DIR + "external/libraries/eigen-eigen-3.0.1"], BASE_DIR + "build/src/tools")
unless have_library("tools")
abort "tools are missing. please compile tools"
end
dir_config("alglib", BASE_DIR + "external/libraries/alglib/cpp/src", BASE_DIR + "build/external/libraries/alglib/cpp/src")
unless have_library("alglib")
abort "alglib is missing. please compile alglib"
end
dir_config("cmaes", BASE_DIR + "external/libraries/CMA-ESpp", BASE_DIR + "build/external/libraries/CMA-ESpp/cma-es")
unless have_library("cmaes")
abort "cmaes is missing. please compile cmaes"
end
create_makefile("cmlp")
The generated Makefile is:
SHELL = /bin/sh
#### Start of system configuration section. ####
srcdir = .
topdir = /usr/lib/ruby/1.8/x86_64-linux
hdrdir = $(topdir)
VPATH = $(srcdir):$(topdir):$(hdrdir)
exec_prefix = $(prefix)
prefix = $(DESTDIR)/usr
sharedstatedir = $(prefix)/com
mandir = $(prefix)/share/man
psdir = $(docdir)
oldincludedir = $(DESTDIR)/usr/include
localedir = $(datarootdir)/locale
bindir = $(exec_prefix)/bin
libexecdir = $(prefix)/lib/ruby1.8
sitedir = $(DESTDIR)/usr/local/lib/site_ruby
htmldir = $(docdir)
vendorarchdir = $(vendorlibdir)/$(sitearch)
includedir = $(prefix)/include
infodir = $(prefix)/share/info
vendorlibdir = $(vendordir)/$(ruby_version)
sysconfdir = $(DESTDIR)/etc
libdir = $(exec_prefix)/lib
sbindir = $(exec_prefix)/sbin
rubylibdir = $(libdir)/ruby/$(ruby_version)
docdir = $(datarootdir)/doc/$(PACKAGE)
dvidir = $(docdir)
vendordir = $(libdir)/ruby/vendor_ruby
datarootdir = $(prefix)/share
pdfdir = $(docdir)
archdir = $(rubylibdir)/$(arch)
sitearchdir = $(sitelibdir)/$(sitearch)
datadir = $(datarootdir)
localstatedir = $(DESTDIR)/var
sitelibdir = $(sitedir)/$(ruby_version)
CC = gcc
LIBRUBY = $(LIBRUBY_SO)
LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
LIBRUBYARG_SHARED = -l$(RUBY_SO_NAME)
LIBRUBYARG_STATIC = -lruby1.8-static
RUBY_EXTCONF_H =
CFLAGS = -fPIC -fno-strict-aliasing -g -g -O2 -fPIC $(cflags) -O3
INCFLAGS = -I. -I. -I/usr/lib/ruby/1.8/x86_64-linux -I.
DEFS =
CPPFLAGS = -I/bla/external/libraries/CMA-ESpp -I/bla//external/libraries/alglib/cpp/src -I//bla/src -I/bla/external/libraries/eigen-eigen-3.0.1 -I/var/lib/gems/1.8/gems/rice-1.4.3/ruby/lib/include
CXXFLAGS = $(CFLAGS) -Wall -g
ldflags = -L. -Wl,-Bsymbolic-functions -rdynamic -Wl,-export-dynamic -L/var/lib/gems/1.8/gems/rice-1.4.3/ruby/lib/lib
dldflags =
archflag =
DLDFLAGS = $(ldflags) $(dldflags) $(archflag)
LDSHARED = g++ -shared
AR = ar
EXEEXT =
RUBY_INSTALL_NAME = ruby1.8
RUBY_SO_NAME = ruby1.8
arch = x86_64-linux
sitearch = x86_64-linux
ruby_version = 1.8
ruby = /usr/bin/ruby1.8
RUBY = $(ruby)
RM = rm -f
MAKEDIRS = mkdir -p
INSTALL = /usr/bin/install -c
INSTALL_PROG = $(INSTALL) -m 0755
INSTALL_DATA = $(INSTALL) -m 644
COPY = cp
#### End of system configuration section. ####
preload =
CXX = g++
libpath = . $(libdir) /bla/external/libraries/CMA-ESpp/cma-es /bla/build/external/libraries/alglib/cpp/src /bla/build/src/tools
LIBPATH = -L. -L$(libdir) -L/bla/build/external/libraries/CMA-ESpp/cma-es -L/bla/build/external/libraries/alglib/cpp/src -L/bla/build/src/tools
DEFFILE =
CLEANFILES = mkmf.log
DISTCLEANFILES =
extout =
extout_prefix =
target_prefix =
LOCAL_LIBS =
LIBS = -lcmaes -lalglib -ltools -lrice -lruby1.8 -lpthread -lrt -ldl -lcrypt -lm -lc
SRCS = cmlp.cpp
OBJS = cmlp.o
TARGET = cmlp
DLLIB = $(TARGET).so
EXTSTATIC =
STATIC_LIB =
BINDIR = $(bindir)
RUBYCOMMONDIR = $(sitedir)$(target_prefix)
RUBYLIBDIR = $(sitelibdir)$(target_prefix)
RUBYARCHDIR = $(sitearchdir)$(target_prefix)
TARGET_SO = $(DLLIB)
CLEANLIBS = $(TARGET).so $(TARGET).il? $(TARGET).tds $(TARGET).map
CLEANOBJS = *.o *.a *.s[ol] *.pdb *.exp *.bak
all: $(DLLIB)
static: $(STATIC_LIB)
clean:
#-$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES)
distclean: clean
#-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
#-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
realclean: distclean
install: install-so install-rb
install-so: $(RUBYARCHDIR)
install-so: $(RUBYARCHDIR)/$(DLLIB)
$(RUBYARCHDIR)/$(DLLIB): $(DLLIB)
$(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR)
install-rb: pre-install-rb install-rb-default
install-rb-default: pre-install-rb-default
pre-install-rb: Makefile
pre-install-rb-default: Makefile
$(RUBYARCHDIR):
$(MAKEDIRS) $#
site-install: site-install-so site-install-rb
site-install-so: install-so
site-install-rb: install-rb
.SUFFIXES: .c .m .cc .cxx .cpp .C .o
.cc.o:
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
.cxx.o:
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
.cpp.o:
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
.C.o:
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
.c.o:
$(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) -c $<
$(DLLIB): $(OBJS) Makefile
#-$(RM) $#
$(LDSHARED) -o $# $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
$(OBJS): ruby.h defines.h
../../build/src/tools/libtools.so
../../build/external/libraries/alglib/cpp/src/libalglib.so
../../build/external/libraries/CMA-ESpp/cma-es/libcmaes.so
could be the problem. I would try absolute paths here, I could imagine that the pwd is a different one than you expected while running ruby extconf.rb.
Also, I assume you need a dir_config entry for each library you'd like to link in. So
dir_config('libs', HEADER_DIRS, LIB_DIRS)
should be replaced by
dir_config('tools', '<Path to include dir>', '<Path to lib dir>')
dir_config('alglib', '<Path to include dir>', '<Path to lib dir>')
Note that the leading 'lib' should be omitted, just like you would in the -l linker option.
Next, if you want to be absolutely sure that a library is found, replace
have_library('libtools')
by
have_library('tools') or raise
Again, 'lib' is omitted.
If you still can't solve the problem, please post the Makefile generated by `ruby extconf.rb'.