Makefile to create an executable .mexa64 file from matlab - c

I try to write a makefile to create an executable .mexa64 file. I have to use the gcc compiler. My current working folder looks like this:
FFTW_build.c
FFTW_func.c
Makefile.c
obj (Folder, here are my object files *.o which are created)
Source code FFTW_build.c:
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
FFTW_perform();
return;
}
Source code FFTW_func.c:
#include <math.h>
#include <stdio.h>
#include <complex.h>
#include <fftw3.h>
#include "mex.h"
void FFTW_perform() {
int i;
int Npoints=10;
fftw_complex *in, *out;
fftw_plan plan;
in = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*Npoints);
out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*Npoints);
plan = fftw_plan_dft_1d(Npoints, in, out, FFTW_FORWARD, FFTW_ESTIMATE);
mexPrintf("\nCoefficcients of the expansion:\n\n");
for(i = 0; i < Npoints; i++)
{
in[i] = (i+1)+(3*i-1)*I;
mexPrintf("%d %11.7f %11.7f\n", i, creal(in[i]), cimag(in[i]));
}
mexPrintf("\n");
fftw_execute(plan);
mexPrintf("Output:\n\n");
for(i = 0; i < Npoints; i++)
{
mexPrintf("%d %11.7f %11.7f\n", i, creal(out[i]), cimag(out[i]));
}
}
Source code for Makefile.c:
################## Compiler ##################
CXX = gcc
####################################################
################## MEXSUFFIX ################
MEXSUFFIX = mexa64
####################################################
################## Home of my matlab version #####
MATLABHOME = /home/tuebel/matlab
####################################################
################## Object_File_Declaration_Folder ################
OBJS_MEX = FFTW_build.o
OBJS_FFTW_FUNC = FFTW_func.o
ODIR=obj
_OBJ = $(OBJS_MEX) $(OBJS_FFTW_FUNC)
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
####################################################
################## Header_Files ################
# Header for mex
DIR_MEX_HEADER = /home/tuebel/matlab/extern/include
_DEPS_MEX = mex.h
DEPS_MEX = $(patsubst %,$(DIR_MEX_HEADER)/%,$(_DEPS_MEX))
# Header for fftw3
DIR_FFTW_HEADER = /usr/local/include
_DEPS_FFTW = fftw3.h
DEPS_FFTW = $(patsubst %,$(DIR_FFTW_HEADER)/%,$(_DEPS_FFTW))
####################################################
################## Library_Files ################
# Libraries for mex
MEX_LIB = /home/tuebel/matlab/bin/glnxa64/libmex.so
# Libraries for FFTW
FFTW_LIB = /usr/local/lib/libfftw3.a
# Libraries for math_function
MATH_LIB = -lm
####################################################
################## Flags ################
# MEXFLAGS = -shared -Wl,--no-undefined -Wl,-rpath-link,$(MATLABHOME)/bin/glnxa64 -L$(MATLABHOME)/bin/glnxa64 -lmex -lmat -lmx -lm
MEXFLAGS = -shared -Wl,-rpath-link,$(MATLABHOME)/bin/glnxa64 -L$(MATLABHOME)/bin/glnxa64 -lmex -lmat -lmx -lm
COMPILERFLAGS = -fPIC -pthread -DMATLAB_MEX_FILE -ansi -D_GNU_SOURCE -fno-omit-frame-pointer -O3 -DNDEBUG
FFTW_FLAGS_INCLUDE = -I$(DIR_FFTW_HEADER)
MEX_FLAGS_INCLUDE = -I$(DIR_MEX_HEADER)
####################################################
#################### Final_Part ######################
TARGET = FFTW_MEX
all: $(TARGET)
echo ALL DONE
clean:
rm -f $(ODIR)/*.o
rm -f $(TARGET).mexa64
echo CLEAN DONE
$(ODIR)/%.o: %.c $(DEPS_MEX) $(DEPS_FFTW)
$(CXX) -c -o $# $< $(COMPILERFLAGS) $(MEX_FLAGS_INCLUDE) $(FFTW_FLAGS_INCLUDE)
# Final_Linking
$(TARGET) : $(OBJ) $(MATH_LIB) $(FFTW_LIB)
$(CXX) -o $#.$(MEXSUFFIX) $(MEX_FLAGS_INCLUDE) $(FFTW_FLAGS_INCLUDE) $^ $(MEXFLAGS)
####################################################
####################################################
####################################################
The idea is to make a FFTW using fftw3. The code works fine in the command window, but if I try to make it executable from matlab (.mexa64 file) it is not working. I get the following error message using make:
gcc -c -o obj/FFTW_build.o FFTW_build.c -fPIC -pthread -DMATLAB_MEX_FILE -ansi -D_GNU_SOURCE -fno-omit-frame-pointer -O3 -DNDEBUG -I/home/tuebel/matlab/extern/include -I/usr/local/include
gcc -c -o obj/FFTW_func.o FFTW_func.c -fPIC -pthread -DMATLAB_MEX_FILE -ansi -D_GNU_SOURCE -fno-omit-frame-pointer -O3 -DNDEBUG -I/home/tuebel/matlab/extern/include -I/usr/local/include
gcc -o FFTW_MEX.mexa64 -I/home/tuebel/matlab/extern/include -I/usr/local/include obj/FFTW_build.o obj/FFTW_func.o /usr/lib64/libm.so /usr/local/lib/libfftw3.a -shared -Wl,-rpath-link,/home/tuebel/matlab/bin/glnxa64 -L/home/tuebel/matlab/bin/glnxa64 -lmex -lmat -lmx -lm
/usr/lib64/gcc/x86_64-suse-linux/4.8/../../../../x86_64-suse-linux/bin/ld: /usr/local/lib/libfftw3.a(lt4-problem.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC
/usr/local/lib/libfftw3.a: error adding symbols: Bad value
collect2: error: ld returned 1 exit status
Makefile:92: recipe for target 'FFTW_MEX' failed
make: *** [FFTW_MEX] Error 1
Can someone help me out? This is my first Makefile and I would be glad for any help... I am also glad for corrections to the Makefile...
Thanks a lot!

It is a bit unclear what you mean by an "executable" .mexa64 file.
MATLAB's mex compiler will let you compile C/C++ code with MATLAB libraries into a mex file (with 64 bit architecture for you here) that you can then "execute" via MATLAB's command line. This seems to be what you have gotten to work already.
However, if you want to have a stand alone "executable" outside of MATLAB, you need to work with MATLAB's mcr compiler (see the reference here). There are flags that you can set in the process to be build an object file which you can then link with later on with your makefile as you are trying to now.
So, don't mix mex compiled files which are runnable within MATLAB and mcr compiled code that is executable outside of it.
Apart from this, gcc is complaining that there is no main() function. I don't see one in your code here either, but you need a main() function for a standalone executable.

Related

Did a Mac update ruin my ability to use gcc?

I am trying to compile two c files into one executable. In the directory I have only three files; Makefile, main.c and myfunction.c.
Makefile:
CC = gcc
CFLAGS = -Wall -g -O0
LIBS = -lm
SRCS = $(wildcard *.c)
OBJS = $(SRCS:.c=.o)
MAIN = main
all: $(MAIN)
#echo Program has been compiled
$(MAIN): $(OBJS)
$(CC) $(CFLAGS) $(INCLUDES) -o $(MAIN) $(OBJS) $(LIBS)
clean:
$(RM) *.o *~ $(MAIN)
main.c:
#include <stdio.h>
void myfunc();
int main (int argc, char *argv[]) {
myfunc();
return 0;
}
myfunction.c:
#include <stdio.h>
void myfunc() { printf("hello world"); }
output after make:
gcc -Wall -g -O0 -c -o main.o main.c
gcc -Wall -g -O0 -c -o myfunction.o myfunction.c
gcc -Wall -g -O0 -o main main.o myfunction.o -lm
Undefined symbols for architecture x86_64:
"_myfunc", referenced from:
_main in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [main] Error 1
I had something nearly identical working in the past. I have since clean installed MacOS and updated to Big Sur. Is this the issue or have I overlooked something?
I fixed the issue. I’m not sure what part fixed it, but installed Homebrew and used it to install gcc-10. I also deleted the project and started over.
myfunc would define like file header
myfunc.h
void myfunc()
Declare in another file
myfunc.c
void myfunc() { printf("hello world"); }
Follow the following tutorial
https://developer.gnome.org/anjuta-build-tutorial/stable/build-make.html.en

Compile minimal test shared library using clang

I am trying to compile a minimal test shared library in FreeBSD using:
FreeBSD clang version 6.0.1 (tags/RELEASE_601/final 335540) (based on LLVM 6.0.1)
Target: x86_64-unknown-freebsd12.0
Thread model: posix
InstalledDir: /usr/bin
test.c
#include "test.h"
int SampleFunction(int a, int b)
{
return a * b;
}
test.h
#ifndef TESTLIB_H
#define TESTLIB_H
extern int SampleFunction(int a, int b);
#endif
Makefile
# Makefile TESTLIB
TEST_OBJS = test.o
TEST_HEADERS = test.h
TEST_LIB = test.so
CC = cc
testlib: $(TEST_OBJS)
$(CC) -fpic -o $(TEST_LIB) $(TEST_OBJS)
# Rebuilt if this Makefile or header changes
$(TEST_OBJS): Makefile $(TEST_HEADERS)
Output:
$ make testlib
cc -O2 -pipe -c test.c -o test.o
cc -fpic -o test.so test.o
/usr/bin/ld: error: undefined symbol: main
>>> referenced by crt1.c:76 (/usr/src/lib/csu/amd64/crt1.c:76)
>>> /usr/lib/crt1.o:(_start)
cc: error: linker command failed with exit code 1 (use -v to see invocation)
*** Error code 1
Stop.
make: stopped in /usr/home/user/testlib
As well as adding -shared to the linker stage (as mentioned by Oo.oO), you probably also want to compile with the -fPIC flag as well. So if you are using the makefile implicit rules for the compiling (looks like you are) then you will probably want to add that flag to CFLAGS. I don't think you need it for the linking stage:
# Makefile TESTLIB
TEST_OBJS = test.o
TEST_HEADERS = test.h
TEST_LIB = test.so
CFLAGS += -fPIC
CC = cc
testlib: $(TEST_OBJS)
$(CC) -shared -o $(TEST_LIB) $(TEST_OBJS)
# Rebuilt if this Makefile or header changes
$(TEST_OBJS): Makefile $(TEST_HEADERS)
I prefer using the OS-provided bsd.lib.mk for such building libraries. The following should do the right thing -- whatever it may be:
SHLIB_NAME= testlib
SRCS= test.c
.include <bsd.lib.mk>
(For building executables there is bsd.prog.mk, BTW.)

How to fix "fatal error: x.264 no such file or directory"

I wrote a makefile which builds a C program attaching the x.264 header. After trying to execute the makefile in terminal I receive the fatal error:
"example.c line [line of #include ] x264.h no such file or directory". Below you can find the C code and makefile (located in the same folder, the library - containing the x264.pc file- is in the folder libx264 of the parent folder). I would be very grateful if you could help with the linkage.
Makefile:
CC = gcc
CFLAGS = -c -Wall `export PKG_CONFIG_PATH=../libx264 && pkg-config --cflags x264`
LDFLAGS = -static `export PKG_CONFIG_PATH=../libx264 && pkg-config --libs --static libx264`
all: Release
Debug: CFLAGS += -g
Debug: example
Release: example
test: example.o
$(CC) -o example example.o $(LDFLAGS)
test.o: example.c
$(CC) $(CFLAGS) example.c -o example.o
clean:
rm -f example.o example
example.c code
#include <stdio.h>
#include <x264.h>
int main( int argc, char **argv )
{
int width, height;
return 0;
}
You'd need to tell the compiler (to be more precise: the preprocessor) where the header file is using the -I option:
CFLAGS = -c -Wall -I../libx264
If I'm right, you need to unpack that .pc file, so that x264.h is indeed in ../libx264.
Similar thing for the linker flags (assuming there's a libx264.a file in ../libx264), where you have to specify where the library is using the -L option:
LDFLAGS = -static -L../libx264 -lx264
Alternatively you could of course also write:
LDFLAGS = -static ../libx264/libx264.a

"undefined reference" error compiling a static library in C

I have a file main.c, a header rippledp.h and a library rippledp.a. The problem is: when I execute the "make" command, I get this output:
g++ -O2 -DNDEBUG -static -o rippledp main.o rippledp.a -lm -pthread
main.o: In function `main':
main.c:(.text+0x24): undefined reference to `rippledp_read'
main.c:(.text+0x39): undefined reference to `rippledp'
main.c:(.text+0x43): undefined reference to `rippledp_write'
collect2: ld returned 1 exit status
make: ** [rippledp] Erro 1
Here is the Makefile:
#--------------------------------------------------#
# Ripple-DP (ISPD2015 contest version) #
# Copyright (c) 2015 #
# Department of Computer Science and Engineering #
# The Chinese Univeristy of Hong Kong #
# #
# Contact: #
# Wing-Kai Chow <wkchow#cse.cuhk.edu.hk> #
# Evangeline F.Y. Young <fyyoung#cse.cuhk.edu.hk> #
#--------------------------------------------------#
OPT= -O2 -DNDEBUG
#OPT= -O0 -ggdb
TYPE= -static
#WFLAG= -Wall -Winline
CC= g++ $(OPT) $(TYPE) $(WFLAG) $(DEBUG)
LIBS= -lm -pthread
SRCS = ${OBJS:%.o=%.c}
BFILE = rippledp
all: $(BFILE)
#$(BFILE): main.o rippledp.a libdef.a liblef.a
# $(CC) -o $(BFILE) main.o rippledp.a libdef.a liblef.a $(LIBS)
$(BFILE): main.o rippledp.a
$(CC) -o $(BFILE) main.o rippledp.a $(LIBS)
%.o : %.c %.h
$(CC) -c $*.c
clean:
rm -f *.o $(BFILE) core
Here is main.c:
#include "rippledp.h"
int main(int argc, char **argv){
/* read benchmark files: tech.lef, cells.lef, floorplan.def */
/* read global placement solution: placed.def */
rippledp_read((char*) "tech.lef", (char*) "cells.lef", (char*) "floorplan.def", (char*) "placed.def");
/* detailed placement with target utility and maximum displacement constraint */
rippledp(0.8, 200000);
/* write the detailed placement solution to output file */
rippledp_write((char*)"dplaced.def");
return 0;
}
And here is rippledp.h:
/*--------------------------------------------------*/
/* Ripple-DP (ISPD2014 contest version) */
/* Copyright (c) 2014 */
/* Department of Computer Science and Engineering */
/* The Chinese Univeristy of Hong Kong */
/* */
/* Contact: */
/* Wing-Kai Chow <wkchow#cse.cuhk.edu.hk> */
/* Evangeline F.Y. Young <fyyoung#cse.cuhk.edu.hk> */
/*--------------------------------------------------*/
#ifndef _RIPPLEDP_H_
#define _RIPPLEDP_H_
/*read benchmarks and placed global placement solution*/
void rippledp_read(char *tech_file, char *cell_file, char *floorplan_file, char *placed_file);
/*Perform displacement-constrained legalization and detailed placement*/
/* target_util = target utility */
/* max_disp = maximum displacement constraint */
void rippledp(double target_util, double max_disp);
/*write placement result in DEF format*/
void rippledp_write(char *output_file);
#endif
I also tried to compile and link manually. I first compiled using:
gcc -c main.c
Then, I tried all these alternatives for linking (I renamed rippledp.a to librippledp.a):
gcc -o out -L. -lrippledp main.o
gcc -o out -L. main.o -lrippledp
gcc -o out main.o -L. -lrippledp
gcc main.o -o out -L. -lrippledp
gcc -o out -lrippledp -L. main.o
gcc -lrippledp -o out -L. main.o
and the output was the same.
I dont have access to the library content.
Your library is compiled with C++ and thus contains C++ mangled names. But you compiled main.c as C, so it looked for unmangled names and thus couldn't find them. Rename main.c to main.cpp and compile it with g++ to fix this issue.

Cygwin - Makefile-error: recipe for target `main.o' failed

I am currently failing to write a good makefile and don't know the reason why.. -.-
This is my main.c:
#include <windows.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("MEEEEEP");
return (0);
}
This is my makefile:
# make SYSTEM= OS= ENVIRONMENT=
# Binaries to use
ifeq ($(ENVIRONMENT),MINGW)
CXX = i686-pc-mingw32-g++
else
CXX = g++
endif
REMOVE = rm -vf
RC = windres
EXE = .exe
#############################################################
# Info
ifeq ($(CXX),g++)
INFO_CXX = g++ -dumpversion; g++ -dumpmachine
endif
#############################################################
# Flags
DEBUG = -DDEBUG -g
OPTIMIZATION = -O2 #-Winline -finline-functions
CFLAGS = -Wall -Wextra -W -static $(DEBUG) $(OPTIMIZATION) -D$(SYSTEM) -D$(OS) -D$(ENVIRONMENT) $(PRGFLAGS)
ifeq ($(SYSTEM),I686)
CFLAGS += -m32
ifeq ($(OS),WIN32)
CFLAGS += -D_WIN32
endif
ifeq ($(ENVIRONMENT),MINGW)
CFLAGS += -fexceptions
endif
endif
LFLAGS =
#############################################################
# Files
CFILES = main.c
OBJS = ${CFILES:.c=.o}
#############################################################
# Include
INCLUDES = -I.
#############################################################
# Library
LIBRARIES =
#############################################################
# Targets
.PHONY: all
all:
#echo == Standard build: make SYSTEM=I686 OS=WIN32 ENVIRONMENT=MINGW
#echo
#echo
make SYSTEM=I686 OS=WIN32 ENVIRONMENT=MINGW gyro
#############################################################
# Implicit rules and filename extensions...
.SUFFIXES: .h .o .c
.c.o: %.h
#echo Compiling $< for $(SYSTEM) $(OS) $(ENVIRONMENT) ...
#echo MEEP
$(CXX) $(CFLAGS) $(INCLUDES) -c $< -o $#
#echo MEEP2
#############################################################
# Target rules
gyro: $(OBJS)
#echo Building software for $(SYSTEM) ...
#echo
$(CXX) $(CFLAGS) $(LFLAGS) -o $#$(EXE) $(OBJS) $(LIBRARIES)
#############################################################
# Clean
.PHONY: clean
clean:
$(REMOVE) $(OBJS)
#############################################################
# Info
.PHONY: info
info:
#echo
#echo Information about C++ Compiler/Linker:
#echo
$(INFO_CXX)
When i type in make gyro,
i receive the output:
Compiling main.c for Windows_NT ...
MEEP
g++ -Wall -Wextra -W -static -DDEBUG -g -O2 -D -DWindows_NT -D -I. -c main.c -o main.o
makeNew.mak:83: recipe for target `main.o' failed
make: *** [main.o] Error 1
But Line number 83 is behind .c.o: %.h. And i don’t understand why.
Does anyone have a solution for me?
You see the two empty -D entries in the g++ command line? They're causing the problem. You must have values in the -D items e.g. -DWIN32
if you're insistent on using something like -D$(SYSTEM) -D$(ENVIRONMENT) then you can use something like:
SYSTEM ?= generic
ENVIRONMENT ?= generic
in the makefile which gives them default values.
Your output looks to be missing the all important output:
<command-line>:0:1: error: macro names must be identifiers
<command-line>:0:1: error: macro names must be identifiers
just to clarify, what actually got sent to g++ was -D -DWindows_NT, i.e. define a preprocessor macro called -DWindows_NT; which is of course not a valid identifier (similarly for -D -I.)

Resources