I want my makefile to build the same binary 2 times, first compiling with gcc and then with mingw. So, I've written this, but it does not work:
OBJ_DIR = obj
SRC_DIR = src
BIN_DIR = bin
INCLUDE = -I./$(SRC_DIR)
LIBS =
_SRCS = print_current_dir.c test_main.c
_OBJS = print_current_dir.o test_main.o
SRCS = $(addprefix $(SRC_DIR)/,$(_SRCS))
OBJS = $(addprefix $(OBJ_DIR)/,$(_OBJS))
all: $(BIN_DIR)/pps-linux $(BIN_DIR)/pps-win32
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
$(CC) -c -o $# $< $(CFLAGS)
$(BIN_DIR)/pps-linux: CC = cc
$(BIN_DIR)/pps-linux: CFLAGS = -g -Wall $(INCLUDE) $(LIBS)
$(BIN_DIR)/pps-linux: $(OBJS)
$(CC) $(CFLAGS) $(OBJS) -o $#
$(BIN_DIR)/pps-win32: CC = i586-mingw32msvc-cc
$(BIN_DIR)/pps-win32: CFLAGS = -g -Wall $(INCLUDE) $(LIBS)
$(BIN_DIR)/pps-win32: $(OBJS)
$(CC) $(CFLAGS) $(OBJS) -o $#
Once it compiles the objects file in $(OBJS) with gcc for the target pps-linux, it tries to build pps-win32 with the very same objects file, obviously failing, and despite the fact that I redefined CC and CFLAGS for the target pps-win32.
Here is the output:
$ make
cc -c -o obj/print_current_dir.o src/print_current_dir.c -g -Wall -I./src
cc -c -o obj/test_main.o src/test_main.c -g -Wall -I./src
cc -g -Wall -I./src obj/print_current_dir.o obj/test_main.o -o bin/pps-linux
i586-mingw32msvc-cc -g -Wall -I./src obj/print_current_dir.o obj/test_main.o -o bin/pps-win32
obj/print_current_dir.o: In function `print_dir':
/home/matteo/Desktop/pps/src/print_dir.c:23: undefined reference to `get_current_dir_name'
/home/matteo/Desktop/pps/src/print_dir.c:25: undefined reference to `puts'
/home/matteo/Desktop/pps/src/print_dir.c:27: undefined reference to `free'
/usr/lib/gcc/i586-mingw32msvc/4.4.4/../../../../i586-mingw32msvc/lib/libmingw32.a(main.o):(.text+0x85): undefined reference to `_WinMain#16'
collect2: ld returned 1 exit status
make: *** [bin/pps-win32] Error 1
How do I force the recompilation of the objects file just compiled with a different compiler?
Thank you.
By making the object files compiler-dependent too, rather than trying to overwrite the same .o file in place with different contents, eg.
LINUX_OBJS = $(addprefix $(LINUX_OBJ_DIR)/,$(_OBJS))
...
$(BIN_DIR)/pps-linux: $(LINUX_OBJS)
NB. you may be able to do it more tidily by just using a target-dependent definition of OBJ_DIR, ie,
$(BIN_DIR)/pps-linux: OBJ_DIR = linux-obj
but I'd have to try it to be sure.
I would suggest using separate OBJ_DIR and BIN_DIR directories to accomplish this, with the names being constructed in part from the compiler vendor:
OBJ_DIR = obj-$(CC)
BIN_DIR = bin-$(CC)
I use a similar approach that has completely separate build directories, and installation directories, with the names constructed from:
compiler vendor
compiler version
architecture
libc version (if linux)
which results in directories named (for example):
gcc_3.4.6-x86-libc_2.3.4
forte_5.10-x64
gcc_4.2.3-x86
Related
I am using this Git for Zbspac.exe
https://github.com/uyjulian/zbspac
And the following for my MinGW Distro:
https://nuwen.net/mingw.html
I have a MinGW distro set up to target my zbspac.exe Makefile. However, I keep getting bounced for
make (e=2): The system cannot find the file specified.
make: *** [Makefile:25: BitStream.o] Error 2
I have BitStream.c and Bitstream.h in the main directory, but it seems the object file doesn't register for the Distro. I feel that it's going to be the same for all the other object files.
My first idea was to create a duplicate file for each .c file into a .o file. This helped clear the issues relating to the .o not being found (although, this solution is probably not ideal). Is there a way to fix this (besides creating duplicate files)?
It then gives me the error
i686-w64-mingw32-gcc -o zbspac.exe BitStream.o ByteArray.o CmdArgs.o FileSystem.o HuffmanDecoder.o HuffmanEncoder.o Logger.o LzssDecoder.o LzssEncoder.o MinHeap.o NexasPacker.o NexasUnpacker.o ScriptPacker.o ScriptUnpacker.o StringUtils.o zbspac.o external/zlib/adler32.o external/zlib/compress.o external/zlib/crc32.o external/zlib/deflate.o external/zlib/gzclose.o external/zlib/gzlib.o external/zlib/gzread.o external/zlib/gzwrite.o external/zlib/infback.o external/zlib/inffast.o external/zlib/inflate.o external/zlib/inftrees.o external/zlib/trees.o external/zlib/uncompr.o external/zlib/zutil.o -static -static-libstdc++ -static-libgcc
process_begin: CreateProcess(NULL, i686-w64-mingw32-gcc -o zbspac.exe BitStream.o ByteArray.o CmdArgs.o FileSystem.o HuffmanDecoder.o HuffmanEncoder.o Logger.o LzssDecoder.o LzssEncoder.o MinHeap.o NexasPacker.o NexasUnpacker.o ScriptPacker.o ScriptUnpacker.o StringUtils.o zbspac.o external/zlib/adler32.o external/zlib/compress.o external/zlib/crc32.o external/zlib/deflate.o external/zlib/gzclose.o external/zlib/gzlib.o external/zlib/gzread.o external/zlib/gzwrite.o external/zlib/infback.o external/zlib/inffast.o external/zlib/inflate.o external/zlib/inftrees.o external/zlib/trees.o external/zlib/uncompr.o external/zlib/zutil.o -static -static-libstdc++ -static-libgcc, ...) failed.
make (e=2): The system cannot find the file specified.
make: *** [Makefile:22: zbspac.exe] Error 2
, which is a self-referential error, since I want to be compiling zbspac.exe, not referring to it.
For reference, the Makefile, which has not been edited:
EXE_TARGET = zbspac.exe
TXTS = License.txt Readme.txt Instructions.txt PackageFormat.txt ScriptTxtFormat.txt
PROJECT_FILE = Makefile .project .cproject
SRC_DIST = zbspac-src.7z
BIN_DIST = zbspac-bin.7z
CC = i686-w64-mingw32-gcc
LD = i686-w64-mingw32-ld
CFLAGS = -O2 -std=c99 -Werror -Wall -pedantic -pedantic-errors -Iexternal/zlib
LIBS = -static -static-libstdc++ -static-libgcc
DIST_MAKE = 7za a
ZLIB_SRCS = external/zlib/adler32.c external/zlib/compress.c external/zlib/crc32.c external/zlib/deflate.c external/zlib/gzclose.c external/zlib/gzlib.c external/zlib/gzread.c external/zlib/gzwrite.c external/zlib/infback.c external/zlib/inffast.c external/zlib/inflate.c external/zlib/inftrees.c external/zlib/trees.c external/zlib/uncompr.c external/zlib/zutil.c
SRCS = $(wildcard *.c) $(ZLIB_SRCS)
HEADERS = $(wildcard *.h)
OBJS = $(patsubst %.c, %.o, $(SRCS))
all: $(EXE_TARGET)
$(EXE_TARGET): $(OBJS)
$(CC) -o $(EXE_TARGET) $(OBJS) $(LIBS)
%.o: %.c
$(CC) $(CFLAGS) -c -o $# $<
src_dist: $(SRC_DIST)
bin_dist: $(BIN_DIST)
$(SRC_DIST): $(SRCS) $(HEADERS) $(TXTS) $(PROJECT_FILE)
$(DIST_MAKE) $(SRC_DIST) $(SRCS) $(HEADERS) $(TXTS) $(PROJECT_FILE)
$(BIN_DIST): $(EXE_TARGET) $(TXTS)
$(DIST_MAKE) $(BIN_DIST) $(EXE_TARGET) $(TXTS)
.PHONY: clean
clean:
$(RM) $(OBJS) $(EXE_TARGET) $(SRC_DIST) $(BIN_DIST)
How do I solve this?
I am trying to successful execute a make file that comes from a new crytpo-coin called Sia Coin. It can be found here Sia Coin GPU Miner. It's relatively new and so some stuff requires more manual installation. I was getting the following error on Ubuntu 16.04 when using the make file. CL/cl.h was missing, and I was able to install and it is located at /usr/include/nvidia-361/CL/cl.h. However, when I ran the make file I still get errors so I think I need to include this path someone in the Make file, the problem is I am not familiar with make files at all. Below is the Make file I need to edit to include the path for compilation:
ifeq ($(shell uname -s),Darwin)
CC ?= clang
LDLIBS += -lcurl -framework OpenCL
else
CC ?= gcc
LDLIBS += -lOpenCL -lcurl
endif
CFLAGS += -c -std=c11 -Wall -pedantic -O2
TARGET = sia-gpu-miner
SOURCES = sia-gpu-miner.c network.c
OBJECTS = $(patsubst %.c,%.o,$(SOURCES))
all: $(TARGET)
%.o: %.c
$(CC) $(CFLAGS) -o $# $<
$(TARGET): $(OBJECTS)
$(CC) -o $# $^ $(LDLIBS)
clean:
rm -f $(TARGET) $(OBJECTS)
.PHONY: all clean
Any help toward solving this problem is greatly appreciated.
Edit:
A new message I am getting now adding
CFLAGS += -c -std=c11 -Wall -pedantic -O2 -I /usr/include/nvidia-361
is now:
-lOpenCL -lcurl /usr/bin/ld: cannot find -lOpenCL collect2: error: ld returned 1 exit status
Two files did compile:
sia-gpu-miner.c
network.c
But I don't know enough to know why the -lOpenCL is not found. No ld directory exists in that directory location in the error if that helps.
Try changing
CFLAGS += -c -std=c11 -Wall -pedantic -O2
to
CFLAGS += -c -std=c11 -Wall -pedantic -O2 -I /usr/include/nvidia-361
I am trying to compile a C language library as a shared object on my new install of Fedora 22. The project compiled fine on my old install of Fedora 20. But now, when I run my makefile:
CC=gcc
vpath %.c src
vpath %.h inc
CFLAGS = -fPIC
INCLUDE = -Iinc -I/usr/include -I/usr/local/include
LIBPATH = -L/usr/lib -L/lib64
LIBS = -lportaudio -lm -lpthread -ldl
OBJ_PATH = ./objs
SRCS = my_code1.c my_code2.c # etc.
OBJS = $(SRCS:.c=.o)
.PHONY: libmylib.so
all: libmylib.so
debug: $(CFLAGS) += -DDEBUG -O0 -g3 -DPD
debug: all
release: $(CFLAGS) += -DTESTING -O2 -DPD -funroll-loops -fomit-frame-pointer
release: all
%.o: %.c
$(CC) $(CFLAGS) $(INCLUDE) $(LIBPATH) $(LIBS) -c -o $# $^
libmylib.so: $(OBJS)
$(CC) -shared -Wl,-soname,libmylib.so \
-Wl,--no-undefined $(OBJS) -lc -lportaudio -ldl -lm -lpthread
mv libmylib.so ./bin
mv *.o $(OBJ_PATH)
clean:
rm $(OBJ_PATH)/*.o
rm bin/libmylib.so
I get very many undefined reference errors:
my_code1.o: In function `func_in_my_code1':
my_code1.c:(.text+0x1b8): undefined reference to `func_from_my_code2'
my_code2.o: In function `func_in_my_code2':
my_code2.c:(.text+0x310): undefined reference to `func_from_my_func1'
The functions in question are most certainly defined in the code. Presumably these are compiled into .o files in the compile stage.
The exact same build environment worked on my previous fedora installation. I am at a loss as to why I should get these errors.
Also, if I compile without the -Wl,--no-undefined flag, it compiles fine, but when I try to load the library from another application, it tosses the same set of undefined errors.
This may have nothing to do with the new version of Fedora. It is possible that there are some environment variables or something that didn't make through to my new install, but I have no idea what they could be.
Apparently I now need to insert the extern keyword into these functions. The code compiled and ran perfectly well before... I would like to reiterate, for posterity's sake, that I did post the entire makefile in my question.
A static library is linked fine in the command line, but not through makefile. Compiling part accessing include files seems ok, but ld process must be wrong in the makefile.
Thanks for your help in advance!
Here is my command line:
gcc -o quadEq.exe quadEq.c -I../include -L../lib -lnowic
Here is my Makefile:
CFLAGS = -Wall -g -c
INCLUDE = -I../include
LDFLAGS = -L../lib
LDLIBS = -lnowic
SOURCES = quadEq.c
OBJECTS = $(SOURCES:.c=.o)
EXE = quadEq
all: $(SOURCES) $(EXE)
$(EXE): $(OBJECTS)
gcc $(OBJECTS) $(LDFLAGS) $(LDLIBS) -o $#
.c.o:
gcc $(CFLAGS) $(INCLUDE) $< -o $#
Here is my screen capture that ran Makefile and the command line.
Static libraries care in which order you link them. If libA.a depends on libB.a, then you have to do -lB -lA.
If a libA.a symbol depends on libB.a that depends on a libA.a symbol, you have to cyclically link: -lB -lA -lB. I've seen some cycles get to about 3 or 4 loops, but generally 2 is enough in my experience.
This is different from dynamic library linking which not only doesn't care what order you link them, but you don't need to also link dependent libraries since the .so specifies them.
Based on Aggieboy's suggestions, I rewrote the makefile and made it work.;
CC = gcc
CFLAGS = -x c -Wall -g
INCPATH = -I../include
LIBPATH = -L../lib
LLIBS = -lnowic
%: %.c
$(CC) -o $# $(CFLAGS) $(INCPATH) $< $(LIBPATH) $(LLIBS)
By the way, this accepts a filename to make from the command line argument.
Thank you Aggieboy again!
I am trying to have the compiled obj files in two different folder
dobjects: where the objects have the debug symbol (gcc with -g option)
sobjects: where the objects are compiled without the debug symbols.
Source files are the same,
I have the following makefile.
CC = gcc
CFLAGS = -Wall
OBJS = a.o b.o
SRCS = a.c b.c
SOBJS_DIR = sobjects
DOBJS_DIR = dobjects
SOBJS = $(addprefix $(SOBJS_DIR)/, $(OBJS))
DOBJS = $(addprefix $(DOBJS_DIR)/, $(OBJS))
all: release debug
release: $(SOBJS)
debug: $(DOBJS)
$(DOBJS_DIR)/%.o: CFLAGS += -g
$(DOBJS_DIR)/%.o $(SOBJS_DIR)/%.o: %.c
$(CC) $(CFLAGS) -c $< -o $#
clean:
rm dobjects/*
rm sobjects/*
But every time I try "make" only one target is made.
$ make
gcc -Wall -c a.c -o sobjects/a.o
gcc -Wall -c b.c -o sobjects/b.o
$ make
gcc -Wall -g -c a.c -o dobjects/a.o
gcc -Wall -g -c b.c -o dobjects/b.o
any help would be greatly appreciated
This rule does not do what you think it does:
$(DOBJS_DIR)/%.o $(SOBJS_DIR)/%.o: %.c
$(CC) $(CFLAGS) -c $< -o $#
Pattern rules with multiple targets tell make that one single invocation of the recipe will build BOTH targets. So when make runs that rule to build $(DOBJS_DIR)/a.o, make believes that $(SOBJS_DIR)/a.o was also built, so it doesn't try to run the rule to build it. But your rule doesn't actually build it, so when you run make a second time it sees that object file is missing and runs the above rule again, to build the missing one.
You have to write this as two different rules:
$(DOBJS_DIR)/%.o: %.c
$(CC) $(CFLAGS) -c $< -o $#
$(SOBJS_DIR)/%.o: %.c
$(CC) $(CFLAGS) -c $< -o $#