First, I should admit makefiles are something that I'm very inexperienced at, so I apologize if this is an error that I should have been able to solve myself, but I have spent several hours on this, including reading the various answers on this site, and have been unable to discover a solution.
With that said, I have created the following makefile to compile my code on a Linux machine; it completes the sub compilations just fine, but when it comes to making the output itself, xPlatST, it throws an error.
g++ -std=c+=11 -g -Wall -pthread -c -o xPlatST.o xPlatST.cpp
g++ -std=c+=11 -g -Wall -pthread -c -o stdafx.o stdafx.cpp
g++ -std=c+=11 -g -Wall -pthread -c xPlatST xPlatST.o stdafx.o -L../hwloc
g++ error: xPlatST: No such file or directory
make: *** [xPlatST] Error 1
I believe it seems to think that the xPlatST is one of it's compilation files and thus can't find it, but for the life of me I can't work out why.
hwloc is a third party library, and should be unrelated to this issue. The code compiles just fine when compiled from the command line directly.
My files are xPlatST.cpp, xPlatST.h, stdafx.cpp, stdafh.h
Code is as follows:
CXX = g++ -std=c++11
INCLUDES =
LIBS = -L../hwloc
CXXFLAGS = -Wall -g -pthread
OBJS = xPlatST.o stdafx.o
xPlatST: ${OBJS}
${CXX} ${CXXFLAGS} ${INCLUDES} -c $# ${OBJS} ${LIBS}
clean:
-rm xPlatST *.o
Any help would be greatly appreciated; thank you in advance.
Your assumption is correct. Your recipe is trying to use xPlatST as a source. Change the -c into a -o in your rule:
${CXX} ${CXXFLAGS} ${INCLUDES} -o $# ${OBJS} ${LIBS}
The -c flag tells the compiler to take all files, compile, and assemble them into an object file (.o). The -o flag specifies the destination file.
Related
Im a Windows dev who has no expirience on building C/C++ programs on Linux, but now I need to. Right way would be to go and learn Make and g++ compiler, but before I commit to that I want to figure out some basic stuff.
So I have .c program which is compiled with this makefile:
CUDA_VER=11.5
ifeq ($(CUDA_VER),)
$(error "CUDA_VER is not set")
endif
APP:= deepstream-test3-app
TARGET_DEVICE = $(shell gcc -dumpmachine | cut -f1 -d -)
NVDS_VERSION:=6.0
LIB_INSTALL_DIR?=/opt/nvidia/deepstream/deepstream-$(NVDS_VERSION)/lib/
APP_INSTALL_DIR?=/opt/nvidia/deepstream/deepstream-$(NVDS_VERSION)/bin/
ifeq ($(TARGET_DEVICE),aarch64)
CFLAGS:= -DPLATFORM_TEGRA
endif
SRCS:= $(wildcard *.c)
$(info info is $(SRCS))
INCS:= $(wildcard *.h)
PKGS:= gstreamer-1.0
OBJS:= $(SRCS:.c=.o)
CFLAGS+= -I../../../includes \
-I /usr/local/cuda-$(CUDA_VER)/include
CFLAGS+= $(shell pkg-config --cflags $(PKGS))
LIBS:= $(shell pkg-config --libs $(PKGS))
LIBS+= -L/usr/local/cuda-$(CUDA_VER)/lib64/ -lcudart -lnvdsgst_helper -lm \
-L$(LIB_INSTALL_DIR) -lnvdsgst_meta -lnvds_meta \
-lcuda -Wl,-rpath,$(LIB_INSTALL_DIR)
$(info info is $(CFLAGS))
all: $(APP)
%.o: %.c $(INCS) Makefile
gcc -c -o $# $(CFLAGS) $<
$(APP): $(OBJS) Makefile
gcc -o $(APP) $(OBJS) $(LIBS)
install: $(APP)
cp -rv $(APP) $(APP_INSTALL_DIR)
clean:
rm -rf $(OBJS) $(APP)
First thing I tried is to change this Makefile to compile it as C++ program. I changed .c file into .cpp, in makefile I change gcc to g++ everywhere and .c to .cpp everywhere. It gave me error that it couldnt find "main" entry point.
I gave up on that pretty fast and decided just to use lines output of original makefile, ending up with this:
g++ -c -o deepstream_test3_app.o -I../../../includes -I /usr/local/cuda-11.5/include -pthread -I/usr/include/gstreamer-1.0 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include ./deepstream_test3_app.cpp
g++ -o deepstream-test3-app deepstream_test3_app.o -lgstreamer-1.0 -lgobject-2.0 -lglib-2.0 -L/usr/local/cuda-11.5/lib64/ -lcudart -lnvdsgst_helper -lm -L/opt/nvidia/deepstream/deepstream-6.0/lib/ -lnvdsgst_meta -lnvds_meta -lcuda -Wl,-rpath,/opt/nvidia/deepstream/deepstream-6.0/lib/
First question, can I combine this 2 launches of g++ into one?
Second, when I make changes to "./deepstream_test3_app.cpp" they are not noticed by compiler. I added
#include <iostream>
...
std::cout << "hello!" << std::endl;
and they are ignored. Its like g++ gets as input some other copy/older version of the file and I dont understand how to go about it.
Hope for any help, sorry if it's all sounds stupid.
Ignoring for the moment the issues surrounding compiling C code with a C++ compiler,
g++ -c -o deepstream_test3_app.o -I../../../includes -I /usr/local/cuda-11.5/include -pthread -I/usr/include/gstreamer-1.0 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include ./deepstream_test3_app.cpp
g++ -o deepstream-test3-app deepstream_test3_app.o -lgstreamer-1.0 -lgobject-2.0 -lglib-2.0 -L/usr/local/cuda-11.5/lib64/ -lcudart -lnvdsgst_helper -lm -L/opt/nvidia/deepstream/deepstream-6.0/lib/ -lnvdsgst_meta -lnvds_meta -lcuda -Wl,-rpath,/opt/nvidia/deepstream/deepstream-6.0/lib/
First question, can I combine this 2 launches of g++ into one?
Yes. It is a common practice in makefiles to separate the compilation and linking steps, but that is not mandatory. When there are multiple sources, the separation makes it possible to limit recompilations to only the source files that have changed, but it doesn't make much difference, makefile or not, when there is only one source file.
The one-command version would be mostly a concatenation of the two commands you gave. One would omit the -c option, which instructs g++ to compile but not link, and one would omit the -o deepstream_test3_app.o, which specifies the name of the object file that we are no longer going to create. One would also omit the appearance of deepstream_test3_app.o drawn from the link (second) command, as we are going straight from source file to program. The rest of the options can be reordered to some extent, but all the -l options need to remain in the same order relative to each other and to any object files among the inputs. Here is how I would write it:
g++ -c -o deepstream_test3_app -I../../../includes -I /usr/local/cuda-11.5/include -pthread -I/usr/include/gstreamer-1.0 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -Wl,-rpath,/opt/nvidia/deepstream/deepstream-6.0/lib/ ./deepstream_test3_app.cpp -lgstreamer-1.0 -lgobject-2.0 -lglib-2.0 -L/usr/local/cuda-11.5/lib64/ -lcudart -lnvdsgst_helper -lm -L/opt/nvidia/deepstream/deepstream-6.0/lib/ -lnvdsgst_meta -lnvds_meta -lcuda
Second, when I make changes to "./deepstream_test3_app.cpp" they are not noticed by compiler.
The compiler compiles the source file(s) you tell it to.
Its like g++ gets as input some other copy/older version of the file
It is possible that you are indeed telling it to compile a different version than the one you modified. It is also possible that compilation fails, so you don't get a new executable. And it is possible that when you try to run the result, you are not running the program you think you are running. We don't have enough information to know.
With regard to the last, however, do be aware that on Linux, unlike on Windows, the working directory is not automatically in the executable search path. If you want to run the compiled result from the above command, you would want to specify the path to it, which you could most easily do by prepending ./ to its simple name: ./deepstream-test3-app.
My Makefile:
helloworldlib.obj: helloworldlib.cpp
g++ -Wall -o helloworldlib.obj -c helloworldlib.cpp
helloworld.obj: source.cpp
g++ -Wall -o helloworld.obj -c source.cpp
helloworld.exe: source.cpp helloworld.obj
g++ -Wall -o helloworld.exe helloworld.obj helloworldlib.obj
I'm not sure what's wrong with this, when I run mingw32-make it only executes the first g++ -Wall -o helloworldlib.obj -c helloworldlib.cpp.
As far as I know this makefile is syntactically correct, mingw just doesn't seem to be able to find the other lines.
This is how make works. If no target is provided on the command line (e.g. mingw32-make helloworld.exe), by default it builds the first target defined in the file. See for instance: https://stackoverflow.com/a/2057716/2249356.
As a quick fix, you can just move the rule for helloworld.exe to the top of the file and then make will build all.
And, I think that the last rule is supposed to read
helloworld.exe: helloworld.obj helloworldlib.obj
g++ -Wall -o helloworld.exe helloworld.obj helloworldlib.obj
rather then with the source.cpp and its object code helloworld.obj as dependencies.
I want to compile a shared library on MBP and based on the advise given here, I have switched to clang (from gcc) to create the shared library. My makefile is:
CC = clang
CFLAGS = -c -fPIC -Wall -O3 -lpthread -g
BaseDir = /Users/admin/Prog/
Include = -I$(BaseDir)UMFPACK/Include -I$(BaseDir)AMD/Include -I$(BaseDir)SuiteSparse_config
Lib = -L$(BaseDir)UMFPACK/Lib -L$(BaseDir)AMD/Lib -L$(BaseDir)GotoBLAS2 -L$(BaseDir)SuiteSparse_config
AddFiles = -lumfpack -lamd -lgoto2 -lsuitesparseconfig
StaticLibs = $(BaseDir)GotoBLAS2/libgoto2.a $(BaseDir)UMFPACK/Lib/libumfpack.a $(BaseDir)AMD/Lib/libamd.a $(BaseDir)SuiteSparse_config/libsuitesparseconfig.a
all: TDS.o TDSJac.o ExtraRoutines.o CalcVFC.o TDS.h
$(CC) $(Include) $(Lib) $(AddFiles) -dynamiclib -lpthread -o libTDS.so $^ -lm -g $(StaticLibs)
TDS.o: TDS.c TDS.h
$(CC) $(Include) $(CFLAGS) $^
TDSJac.o: TDSJac.c TDS.h
$(CC) $(CFLAGS) $^
ExtraRoutines.o: ExtraRoutines.c TDS.h
$(CC) $(CFLAGS) $^
CalcVFC.o: CalcVFC.c TDS.h
$(CC) $(CFLAGS) $^
MexFile: TDSGateway.c
mex -g -largeArrayDims -ldl TDSGateway.c
Move:
mv libTDS.so ../../
mv TDSGateway.mexmaci64 ../../
What I do here is:
1) Only compile TDS.c, TDSJac.c, ExtraRoutines.c, and CalcVFC.c to create four corresponding object files.
2) Merging object files and creating a shared library using following command:
clang -I(Some folders) -L(Some folders) -l(Some libraries) -shared -lpthread -o libTDS.so TDS.o TDSJac.o ExtraRoutines.o CalcVFC.o TDS.h -lm -g
clang: error: cannot specify -o when generating multiple output files
As I am absolutely new to clang, I do not know what is wrong with Makefile. (If I replace CC=clang with CC=gcc, everything works good.)
I searched the internet with no success. Manual page of clang says nothing about shared library. I could not even get anything out of clang homepage. It is appreciated if help me to work around this problem.
Thanks for your help in advance.
I had yesterday almost the same problem.
But i never used cmake. I'm using an own makefile system of my company, so I just can tell you, what fixed the problem for me so far.
Clang has still some trouble with giving you the right hints on errorcase.
The linking error was:
/usr/bin/ld: /usr/lib/crt1.o: relocation R_X86_64_32 against `_DYNAMIC' can not be used when making a shared object; recompile with -fPIC
I solved the problem as I figgered out, that the -shared Parameter has to be behind the -o X.o parameters. As I see this is not made in your case, too. You should try that first.
In our case I also had to parse the LFlags with -WL, or -L, (afaik it doesn't matter which one you take but I read about a clang bug in relation to -Wl,).
But idk in how far you have to parse LFlags or not, when using cmake.
You've listed headers (TDS.h) as dependencies, which is fine, but you've then used $^ as inputs, which includes all dependencies. You should not list a header as an input. It should not be on the command-line at all, and in clang this is actually an error.
The error message is obscure but easy to resolve. You have 2 choices:
Be explicit instead of using $^. You could use a variable for inputs and another for dependencies, e.g.; or
Use intermediate .o files instead of .c files as inputs to a .so. The *.o files can depend on any .h they include.
I am pretty new to Makefiles and i am trying to build an executable from 3 files, file1.c, file2.c, and file1.h into an executable called exFile. Here's what I got:
all: exFile
exFile: file1.o file2.o
gcc -Wall -g -m32 repeat.o show.o -o repeat
file1.o: file1.c file1.h
gcc -Wall -g -m32 -S file1.c -o file1.o
file2.o: file2.c
gcc -Wall -g -m32 -S file2.c -o file2.o
I've searched the web for makefiles in this format, but i came up empty handed so i was wondering if someone can help. When it tries to compile i get:
usr/bin/ld:file1.o:1: file format not recognized; treating as linker script
I've compiled programs using assembly files but I'm not to sure what to do with c files or the file1.h file. file1.c includes file1.h so i have to link them (I think?). Any suggestions or links to a reference would be appreciated
You have two problems with your gcc command-line. First, you're specifying the -S flag, which causes gcc to emit assembly code, rather than object code. Second, you're missing the -c flag, which tells gcc to compile the file to an object file, but not link it. If you just remove -S and change nothing else, you'll end up with an executable program named file1.o and another named file2.o, rather than two object files.
Besides those errors, you could simplify your makefile by the use of pattern rules. I suggest you try the following instead:
all: exFile
exFile: file1.o file2.o
gcc -Wall -g -m32 $^ -o $#
%.o: %.c
gcc -Wall -g -m32 -c $< -o $#
file1.o: file1.h
Or, as EmployedRussian points out, you can go with something even more minimal that leverages more of the built-in features of GNU make:
CC=gcc
CFLAGS=-Wall -g -m32
all: exFile
exFile: file1.o file2.o
$(LINK.c) $^ -o $#
file1.o: file1.h
The -S switch to gcc tells it to output assembler so this:
gcc -Wall -g -m32 -S file1.c -o file1.o
Is putting assembler into file1.o but you want, presumably, to compile file1.c into object code:
gcc -Wall -g -m32 file1.c -o file1.o
When the linker gets your file1.o it is confused because file1.o is assembler when the linker is expecting object code, hence your error.
So get rid of the -S switches for file1.o and file2.o.
I get this error when I do the make:
relocation R_X86_64_32 against `vtable for Torch::MemoryDataSet' can not be used
when making a shared object; recompile with -fPIC
It says that I should recompile with the -fPIC option. I did that, adding
the -fPIC option to CFLAGS and CXXFLAGS, but I still get the same error. Is there any way to solve this? I have seen that this problem is related with the use of a 64-bit machine, and it is true that I am using one.
I had this problem quite a while back and if I remember correctly, the fix was moving the placement of -fPIC just after gcc in the command line. Made absolutely no sense, and less so now, but as I remember, that fixed it.
I encountered the same problem, but it had an extra twist. The answer by #clintm solved it, but I thought I would describe my variation of the problem here for future reference...
Makefile on 32-bit machine:
CXX=g++
CXXFLAGS= -O3 -Wall
...
...
%.o: %.c
$(CXX) $(CXXFLAGS) -fpic -c $<
libmylibrary.so: $(OBJECTS)
$(CXX) -shared -Wl,-soname,$# -o $# $(OBJECTS)
This compiled correctly. But the same Makefile failed when I tried it on a 64-bit machine. I changed "-fpic" to "-fPIC" and it still failed. I changed the object rule to:
%.o: %.c
$(CXX) -fPIC $(CXXFLAGS) -c $<
and it still failed.
Finally, I placed "-fPIC" in the actual compiler variable (so that now "-fPIC" appears in the rule for each object and the rule for the shared library):
CXX=g++ -fPIC
CXXFLAGS= -g -O3 -Wall
...
%.o: %.c
$(CXX) $(CXXFLAGS) -c -o $# $<
libalglib.so: $(OBJECTS)
$(CXX) -shared -Wl,-soname,$# -o $# $(OBJECTS)
And it worked!
Let's say you have some makefile like:
CFLAGS = -g -Wall
SOURCES = $(wildcard *.c)
OBJECTS = ...
TARGET = libmyawesomelib.a
all: $(TARGET) main
just add the -fPIC flag like so:
$(TARGET): CFLAGS += -fPIC
$(TARGET): $(OBJECTS)
.
.
.
so on so forth with the rest of the makefile.
I ran into this problem cross-compiling with the android-ndk toolchain. I ended up having to use
CC="$CROSS/bin/arm-linux-androideabi-gcc -pie --sysroot=$SYSROOT"
Neither -fPIC nor -fPIE worked for me in this situation.
I was cross compiling shadowsocks-libev on a CentOS 7 machine, the same problem happened to me, it works perfectly on my laptop with
CC=mipsel-unknown-linux-uclibc-gcc CXX=mipsel-unknown-linux-uclibc-g++ AR=mipsel-unknown-linux-uclibc-ar RANLIB=mipsel-unknown-linux-uclibc-ranlib make SHARED=1 CFLAGS=-fPIC
but on travis ci, it did not work, I have to add -fPIC to CC and CXX in order to get it to work
CC="mipsel-unknown-linux-uclibc-gcc -fPIC" CXX="mipsel-unknown-linux-uclibc-g++ -fPIC" AR=mipsel-unknown-linux-uclibc-ar RANLIB=mipsel-unknown-linux-uclibc-ranlib make SHARED=1
I had this issue after I upgraded gcc. I had one .o file (sqlite) that hadn't been cleaned by the Makefile and as a result I had this issue (assuming because it was compiled with an older version of gcc). After removing that file and rebuilding this error went away.
if the project you'd like to compile has a correct configure script use like this:
$ ./configure 'CFLAGS=-g -O2 -fPIC ....' --enable-some-thing
so the flag will be all the Makefile's rule ...
few days before i've need an elder ver. of VLC to compile on an x64 machine, it has a nice configure script ;-)