I have been trying to create a neatly-organized makefile project template utilizing the ARM mbed library. I have already solved a few of the problems (see this post) related to header file paths. However, now I am having problems with the linker. My goal is to have sources and headers in src, object files in obj, and the final binaries in either debug or release.
Here is the error I am getting...
make
arm-none-eabi-g++ -DTARGET_M4 -DMBED_BUILD_TIMESTAMP=1453683815.81 -DTOOLCHAIN_GCC_ARM -DTOOLCHAIN_GCC -DTARGET_RTOS_M4_M7 -DTARGET_FF_MORPHO -DTARGET_CORTEX_M -D__FPU_PRESENT=1 -DTARGET_FF_ARDUINO -DTARGET_STM32F446RE -DTARGET_NUCLEO_F446RE -D__MBED__=1 -DTARGET_STM -DTARGET_STM32F4 -D__CORTEX_M4 -DARM_MATH_CM4 -std=c++98 -fno-rtti -I lib/ -I lib/mbed/ -I lib/mbed/TARGET_NUCLEO_F446RE/ -I lib/mbed/TARGET_NUCLEO_F446RE/TARGET_STM/ -I lib/mbed/TARGET_NUCLEO_F446RE/TARGET_STM/TARGET_STM32F4/ -I lib/mbed/TARGET_NUCLEO_F446RE/TOOLCHAIN_GCC_ARM/ -I lib/mbed/TARGET_NUCLEO_F446RE/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F446RE/ -o obj/main.o src/main.cc
/usr/lib/gcc/arm-none-eabi/6.1.1/../../../../arm-none-eabi/lib/libc.a(lib_a-exit.o): In function `exit':
exit.c:(.text.exit+0x2c): undefined reference to `_exit'
collect2: error: ld returned 1 exit status
make: *** [makefile:54: obj/main.o] Error 1
This is my makefile. I have denoted where the problem(s) might be, but I am not sure.
#Project parameters
PROJECT = Nucleo_blink
OBJECTS = obj/main.o
DEST = debug
VPATH = src lib $DEST
TARGET = NUCLEO_F446RE
#Compilation options
DEBUG = 1
#Tools
AS = $(GCC_BIN)arm-none-eabi-as
CC = $(GCC_BIN)arm-none-eabi-gcc
CXX = $(GCC_BIN)arm-none-eabi-g++
LD = $(GCC_BIN)arm-none-eabi-gcc
OBJCOPY = $(GCC_BIN)arm-none-eabi-objcopy
OBJDUMP = $(GCC_BIN)arm-none-eabi-objdump
SIZE = $(GCC_BIN)arm-none-eabi-size
include $(TARGET).mk
CFLAGS = $(INCLUDE_PATHS) $(CC_SYMBOLS) $(CPU) -c -g -fno-common -fmessage-length=0 -Wall -Wextra -fno-exceptions -ffunction-sections -fdata-sections -fomit-frame-pointer -MMD -MP
ifeq ($(HARDFP),1)
FLOAT_ABI = hard
else
FLOAT_ABI = softfp
endif
ifeq ($(DEBUG), 1)
CFLAGS += -DDEBUG -O0
else
CFLAGS += -DNDEBUG -Os
endif
#MY PROBLEM MAY BE HERE
LD_FLAGS = $(CPU) -Wl,--gc-sections --specs=nano.specs -Wl,--wrap,main -Wl,-Map=$(PROJECT).map,--cref
#`-u _printf_float -u _scanf_float` after -specs for floating point I/O
LD_SYS_LIBS = -lstdc++ -lsupc++ -lm -lc -lgcc -lnosys
LIBRARIES = -lmbed
.PHONY: all clean lst size
all: $(PROJECT).bin $(PROJECT).hex
clean:
rm -f debug/* obj/* asm/* $(DEPS)
obj/%.o: %.c
$(CC) $(CC_FLAGS) $(CC_SYMBOLS) -std=c99 $(INCLUDE_PATHS) -o $# $<
obj/%.o: %.cc
$(CXX) $(CC_FLAGS) $(CC_SYMBOLS) -std=c++98 -fno-rtti $(INCLUDE_PATHS) -o $# $<
obj/%.o: %.cpp
$(CXX) $(CC_FLAGS) $(CC_SYMBOLS) -std=c++98 -fno-rtti $(INCLUDE_PATHS) -o $# $<
obj/%.o: %.asm
$(CC) $(CPU) -c -x assembler-with-cpp -o asm/$# $<
#OR HERE
$(PROJECT).elf: $(OBJECTS) $(SYS_OBJECTS)
$(LD) $(LD_FLAGS) -T$(LINKER_SCRIPT) $(LIBRARY_PATHS) -o $(DEST)/$# $^ $(LIBRARIES) $(LD_SYS_LIBS) $(LIBRARIES) $(LD_SYS_LIBS)
$(PROJECT).bin: $(PROJECT).elf
$(OBJCOPY) -O binary $< $#
$(PROJECT).hex: $(PROJECT).elf
#$(OBJCOPY) -O ihex $< $#
$(PROJECT).lst: $(PROJECT).elf
#$(OBJDUMP) -Sdh $< > $#
lst: $(PROJECT).lst
size: $(PROJECT).elf
$(SIZE) $(PROJECT).elf
DEPS = $(OBJECTS:.o=.d) $(SYS_OBJECTS:.o=.d)
-include $(DEPS)
Before you ask, I have already tried changing --specs=nano.specs to --specs=nosys.specs. It does nothing. The strange part is that the linker settings above work fine for the automatically generated mbed makefile.
Here is the working makefile. It compiles without errors...
# This file was automagically generated by mbed.org. For more information,
# see http://mbed.org/handbook/Exporting-to-GCC-ARM-Embedded
GCC_BIN =
PROJECT = Nucleo_blink
OBJECTS = ./source/main.o
SYS_OBJECTS = #Long list of object files
INCLUDE_PATHS = -I. -I./source -I./mbed -I./mbed/TARGET_NUCLEO_F446RE -I./mbed/TARGET_NUCLEO_F446RE/TARGET_STM -I./mbed/TARGET_NUCLEO_F446RE/TARGET_STM/TARGET_STM32F4 -I./mbed/TARGET_NUCLEO_F446RE/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F446RE -I./mbed/TARGET_NUCLEO_F446RE/TOOLCHAIN_GCC_ARM
LIBRARY_PATHS = -L./mbed/TARGET_NUCLEO_F446RE/TOOLCHAIN_GCC_ARM
LIBRARIES = -lmbed
LINKER_SCRIPT = ./mbed/TARGET_NUCLEO_F446RE/TOOLCHAIN_GCC_ARM/STM32F446XE.ld
###############################################################################
AS = $(GCC_BIN)arm-none-eabi-as
CC = $(GCC_BIN)arm-none-eabi-gcc
CPP = $(GCC_BIN)arm-none-eabi-g++
LD = $(GCC_BIN)arm-none-eabi-gcc
OBJCOPY = $(GCC_BIN)arm-none-eabi-objcopy
OBJDUMP = $(GCC_BIN)arm-none-eabi-objdump
SIZE = $(GCC_BIN)arm-none-eabi-size
ifeq ($(HARDFP),1)
FLOAT_ABI = hard
else
FLOAT_ABI = softfp
endif
CPU = -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=$(FLOAT_ABI)
CC_FLAGS = $(CPU) -c -g -fno-common -fmessage-length=0 -Wall -Wextra -fno-exceptions -ffunction-sections -fdata-sections -fomit-frame-pointer -MMD -MP
CC_SYMBOLS = -DTARGET_M4 -DTARGET_FF_ARDUINO -DTOOLCHAIN_GCC_ARM -DTOOLCHAIN_GCC -DTARGET_RTOS_M4_M7 -DTARGET_FF_MORPHO -DTARGET_LIKE_MBED -DTARGET_CORTEX_M -D__FPU_PRESENT=1 -DTARGET_LIKE_CORTEX_M4 -DTARGET_NUCLEO_F446RE -D__MBED__=1 -DTARGET_STM -DMBED_BUILD_TIMESTAMP=1468213384.59 -DTARGET_STM32F446RE -DTARGET_STM32F4 -D__CORTEX_M4 -DARM_MATH_CM4
#My makefile above copies these two lines
LD_FLAGS = $(CPU) -Wl,--gc-sections --specs=nano.specs -u _printf_float -u _scanf_float -Wl,--wrap,main -Wl,-Map=$(PROJECT).map,--cref
LD_SYS_LIBS = -lstdc++ -lsupc++ -lm -lc -lgcc -lnosys
ifeq ($(DEBUG), 1)
CC_FLAGS += -DDEBUG -O0
else
CC_FLAGS += -DNDEBUG -Os
endif
.PHONY: all clean lst size
all: $(PROJECT).bin $(PROJECT).hex size
clean:
rm -f $(PROJECT).bin $(PROJECT).elf $(PROJECT).hex $(PROJECT).map $(PROJECT).lst $(OBJECTS) $(DEPS)
.asm.o:
$(CC) $(CPU) -c -x assembler-with-cpp -o $# $<
.s.o:
$(CC) $(CPU) -c -x assembler-with-cpp -o $# $<
.S.o:
$(CC) $(CPU) -c -x assembler-with-cpp -o $# $<
.c.o:
$(CC) $(CC_FLAGS) $(CC_SYMBOLS) -std=gnu99 $(INCLUDE_PATHS) -o $# $<
.cpp.o:
$(CPP) $(CC_FLAGS) $(CC_SYMBOLS) -std=gnu++98 -fno-rtti $(INCLUDE_PATHS) -o $# $<
$(PROJECT).elf: $(OBJECTS) $(SYS_OBJECTS)
$(LD) $(LD_FLAGS) -T$(LINKER_SCRIPT) $(LIBRARY_PATHS) -o $# $^ -Wl,--start-group $(LIBRARIES) $(LD_SYS_LIBS) -Wl,--end-group
$(PROJECT).bin: $(PROJECT).elf
$(OBJCOPY) -O binary $< $#
$(PROJECT).hex: $(PROJECT).elf
#$(OBJCOPY) -O ihex $< $#
$(PROJECT).lst: $(PROJECT).elf
#$(OBJDUMP) -Sdh $< > $#
lst: $(PROJECT).lst
size: $(PROJECT).elf
$(SIZE) $(PROJECT).elf
DEPS = $(OBJECTS:.o=.d) $(SYS_OBJECTS:.o=.d)
-include $(DEPS)
I think my problem is some sort of path error...
- The _exit symbol may be defined, but inaccessible by main.o
- There may be some major error in the makefile I'm missing
- Something totally different?
Feel free to comment any suggested changes to this question.
EDIT: All I had to do to fix the error was change CFLAGS to CCFLAGS. The answer I marked as the solution explained what was happening, and a potential way to fix it. Although I didn't need to use the suggested solution, the explanation of why it wasn't working is useful, and the information provided by both answers is useful.
Adding --specs=nosys.specs to your linker options may also solve this issue.
You can see exactly what this does by looking at the nosys.specs file which will be somewhere in your compiler directory.
See also: exit.c:(.text+0x18): undefined reference to `_exit' when using arm-none-eabi-gcc
_exit is a system call, as well as some other functions you probably will need later. When you compile a binary for (for example) Linux, these calls are serviced by the operating system. In bare-metal embedded project you need to define these functions by yourself. The common way is to create a file called syscalls.c or something like that and put all needed system calls there. Take a look at example of such file, rapidly found by google: https://github.com/bjornfor/stm32-test/blob/master/STM32L1xx_StdPeriph_Lib_V1.1.1/syscalls.c
As a bonus, if you properly implement _read and _write to work with UART, you will get a serial console capable to do formatted IO via printf and scanf .
The _exit symbol may be defined, but inaccessible by main.o - There may be some major error in the makefile I'm missing - Something totally different?
This happens when a call to a standard library method indirectly has a dependency on exit(). Often from automatically generated exception unwind code that's supposed to abort your process on exit, which obviously has different semantics in a bare metal application. The division-by-zero floating point exception is one such example. -fno-exceptions does not help with this.
You can of course supply a do-nothing exit() handler but your code would be smaller if the exception unwind code didn't get inserted in the first place.
I discovered by examining the generated assembler that you can replace the exception handlers with do-nothing versions like this in a compilation unit:
extern "C" void __wrap___aeabi_unwind_cpp_pr0() {}
extern "C" void __wrap___aeabi_unwind_cpp_pr1() {}
extern "C" void __wrap___aeabi_unwind_cpp_pr2() {}
and then link those in as replacements at link time with these additional linker arguments.
-Wl,-wrap,__aeabi_unwind_cpp_pr0,
-Wl,-wrap,__aeabi_unwind_cpp_pr1
-Wl,-wrap,__aeabi_unwind_cpp_pr2
Another benefit is that your code should shrink as a result. You may even want to insert your own implementations that reset the MCU.
For me it took both -fno-exceptions and --specs=nosys.specs in compiler flags.
It seems like you use stdlib. System cal exit(int) calls in-system function _exit(int).
For me decision was applying -nostdlib option because I wasn't going to use stdlib.
Thanks, UserHuman, https://stackoverflow.com/a/51657692/8313090
Related
I'm trying to move my Makefile to cmake. The problem is that when it comes to linking stage, it cannot find the shared library.
My cmake is:
set(PROJECT_LINK_LIBS libsr_tps.so)
link_directories(absolute/path/to/the/library)
I also tried:
find_library(PROJECT_LINK_LIBS NAMES sr_tps PATHS "${PROJECT_SOURCE_DIR}/lib")
and then:
add_executable(project ${SOURCE})
target_link_libraries(project ${PROJECT_LINK_LIBS})
The sources can be cross-compiled successfully. But after compiling, it always says:
/absolute/path/to/ld: cannot find -lsr_tps
collect2: ld returned 1 exit status
given that libsr_tps.so has already been pre-cross-compiled.
Makefile works fine for both compiling and generating the final executable.
I have been looking for the potential issue for many hours. The solutions just don't work.
What could be wrong?
Thanks.
Update:
The way for build with make:
Set some environment parameters, i.e. some export.
Makefile:
LDFLAGS += -L./lib
CFLAGS += -Wall -Wno-pointer-sign
LDLIBS = -lsr_tps
all: $(TARGET)
$(TARGET): $(OBJS) $(OBJS_ROS)
$(CC) $(LDFLAGS) $(OBJS) $(OBJS_ROS) $(LDLIBS) -o $(TARGET)
cp $^ ./$(BINARY)/$(OBJ_DIR)
mv $# ./$(BINARY)
.c.o: $(CC) $(CFLAGS) -o $# -c $<
Update 2:
Here is my Makefile:
TARGET = ros
LDFLAGS += -L./lib
CFLAGS += -Wall -Wno-pointer-sign -DWSU_5001 -I./include -I./include/WSU-5001_include -I./include/J2735 -I./ -pthread -O
LDLIBS = -lsr_tps -lrisapi -lrt -lipc -lm -ldot2 -ldot3 -lcrypto -lgps -ltpsapi
SHARED_FLAGS = -fPIC -shared
BINARY= bin
SRC_DIR = ./src
J2735_DIR = ./src/J2735
#OBJ_DIR = ./binary/obj
OBJ_DIR = obj
OBJS_TEST=${ASN_MODULE_SOURCES:.c=.o} ${ASN_CONVERTER_SOURCES:.c=.o}
OBJS=${ASN_MODULE_SOURCES:.c=.o}
OBJS_ROS = ros.o tx.o rx.o util.o config.o
all: $(TARGET)
mkdir -p $(BINARY)
mkdir -p $(BINARY)/$(OBJ_DIR)
$(TARGET): $(OBJS) $(OBJS_ROS)
$(CC) $(LDFLAGS) $(OBJS) $(OBJS_ROS) $(LDLIBS) -o $(TARGET)
cp $^ ./$(BINARY)/$(OBJ_DIR)
mv $# ./$(BINARY)
# $(TARGET): $(OBJS)
# $(CC) $(OBJS) $(CFLAGS) -o $#
.SUFFIXES:
.SUFFIXES: .c .o
.c.o:
$(CC) $(CFLAGS) -o $# -c $<
Command line after executing make:
path/to/powerpc-e300c3-linux-gnu-gcc -L./lib <all .o files> -lsr_tps -lrisapi -lrt -lipc -lm -ldot2 -ldot3 -lcrypto -lgps -ltpsapi -o ros
And below is my CMakeList:
cmake_minimum_required(VERSION 3.5.1)
project(Denso-ROS)
set(CMAKE_SYSTEM_NAME Denso-linux)
set(CMAKE_SYSTEM_PROCESSOR "^(powerpc|ppc)")
set(GCC_COVERAGE_COMPILE_FLAGS "-static -Wall -Wno-pointer-sign -DWSU_5001 -pthread -O")
#################
#problem
#set(GCC_COVERAGE_LINK_FLAGS "libsr_tps.so -lrisapi -lrt -lipc -lm -ldot2 -ldot3 -lcrypto -lgps -ltpsapi")
#set(GCC_COVERAGE_LINK_FLAGS "-L./lib")
#set(CMAKE_LINK_LIBRARY_FLAG "-lsr_tps -lrisapi -lrt -lipc -lm -ldot2 -ldot3 -lcrypto -lgps -ltpsapi")
#set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GCC_COVERAGE_LINK_FLAGS}" )
set(PROJECT_LINK_LIBS libsr_tps.so)
link_directories(home/yufeiyan/DENSO-WSU5K1-SDK_VM_Ubuntu_Peloton/Denso/lib)
#################
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}" )
set(tools ${PROJECT_SOURCE_DIR}/toolchain/bin)
set(CMAKE_C_COMPILER ${tools}/powerpc-e300c3-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER ${tools}/powerpc-e300c3-linux-gnu-g++)
find_library(DENSO_LIB NAMES sr_tps PATHS "${PROJECT_SOURCE_DIR}/lib")
message(STATUS "${DENSO_LIB}")
include_directories(
${PROJECT_SOURCE_DIR}
include
include/J2735
include/WSU-5001_include)
file(GLOB SOURCE ${PROJECT_SOURCE_DIR}/*.c src/*.c src/J2735/*.c)
list(REMOVE_ITEM SOURCE ${PROJECT_SOURCE_DIR}/src/J2735/converter-example.c)
list(REMOVE_ITEM SOURCE ${PROJECT_SOURCE_DIR}/src/J2735/test.c)
#add_executable(ros ${SOURCE1} ${SOURCE2} ${SOURCE3})
add_executable(ros ${SOURCE})
target_link_libraries(ros ${PROJECT_LINK_LIBS})
Command line after executing make:
path/to/powerpc-e300c3-linux-gnu-gcc -static -Wall -Wno-pointer-sign -DWSU_5001 -pthread -O <all .o files> -L/path/to/project/lib -lsr_tps -Wl,-rpath, path/to/project/lib path/tp/powerpc-e300c3-linux-gnu/bin/ld: cannot find -lsr_tps
Many thanks to Tsyvarev.
Let me sum up the issue and solution:
The linker can not find the library due to the incorrect path. I used link_directories(absolute/path/to/lib), and it returned a duplicate path. Instead, using link_directories(${PROJECT_SOURCE_DIR}/lib) solved the problem. The linker has the correct path and find the library.
In the meantime, I remove the -static option for CFLAGS. This option may also cause the linker not finding the library.
I'm doing a Makefile to make objects with the same gcc command. This file looks like this:
SRCLIB = main.c srv.c
OBJLIB = main.o srv.o
CC = gcc
CCFLAGS = -Wall -Werror
$(OBJLIB) : $(SRCLIB)
$(CC) $(CCFLAGS) -c $^ -o $#
The objetive is to execute this like:
gcc -Wall -c read_line.c -o read_line.o
gcc -Wall -c client.c -o client.o
But I don't know how to do it, and everything I tested is not working. Is it even possible to do this in a Makefile?
Your makefile expands to this, after the variables are expanded:
main.o srv.o : main.c srv.c
$(CC) $(CCFLAGS) -c $^ -o $#
In make, using multiple targets in explicit rules like this is the same as writing the rule multiple times, once for each target. So, this is the same as this:
main.o : main.c srv.c
$(CC) $(CCFLAGS) -c $^ -o $#
srv.o : main.c srv.c
$(CC) $(CCFLAGS) -c $^ -o $#
This means that if either of the source files changes, BOTH object files will be recreated (since each object depends on both sources, not just their own source file).
Further, in your compile line you use the variable $^ which expands to all the prerequisites. So your compile lines will expand to:
gcc -Wall -Werror -c main.c srv.c -o main.o
gcc -Wall -Werror -c main.c srv.c -o srv.o
which is illegal: if you use -c with the -o option you can only compile one source file.
Make has built-in rules that already know how to compile files, so there's no need to write your own. You can just write this:
SRCLIB = main.c srv.c
OBJLIB = main.o srv.o
CC = gcc
CCFLAGS = -Wall -Werror
.PHONY: all
all: $(OBJLIB)
and that's all you need.
I have written a scary-looking Makefile by copy/pasting suggestions from Stack Overflow. However, I have read that it might not be necessary to provide explicit compiler invocations so many times (for example, the -O3 flag is everywhere). How can I simplify this Makefile?
CFLAGS = -Weverything -Wno-padded -Wno-unused-parameter -Wno-unused-variable -Wno-sign-conversion
all: fianchetto.o util.o ttable.o movegen.o
clang -O3 $(CFLAGS) -D NDEBUG $^ -o fianchetto
debugf: fianchetto.o ttable.o movegen.o
clang -O3 $(CFLAGS) -g3 $^ -o fianchetto
clean:
rm *.o && rm *.gch & rm fianchetto && rm -rf fianchetto.dSYM
%.o: %.c
clang -O3 -c $(CFLAGS) $< -o $#
fianchetto.o: fianchetto.c
ttable.o: ttable.h ttable.c
movegen.o: movegen.h movegen.c
util.o: util.h util.c
I am mystified by a lot of the syntax, and would appreciate links or explanations of why simplifications work!
CFLAGS and defines (which should be in CPPFLAGS anyway) are useless when linking
You're reinventing make's built-in rules, make will automatically link a target if one of its dependencies is "target.o" (in this case fianchetto: fianchetto.o). Make also knows how to compile C source files (as long as the source and object path match), so your pattern rule is superfluous too.
The object prerequisites aren't necessary as both clang and GCC can generate dependencies for you with the -M set of flags.
Compiling release and debug builds in the same dir makes for a more simple makefile, although you will need to remember to clean the object files when switching.
By default make assigns cc to CC, and cc should be a link to your system's default compiler, so you might not even need the first line below
CC := clang
CPPFLAGS := -MMD -MP
CFLAGS := -Weverything -Wno-padded -Wno-unused-parameter -Wno-unused-variable -Wno-sign-conversion -O3
objs := fianchetto.o util.o ttable.o movegen.o
deps := $(objs:.o=.d)
.PHONY: all debugf clean
all: CPPFLAGS += -DNDEBUG
debugf: CFLAGS += -g3
all debugf: fianchetto
fianchetto: $(objs)
clean: ; $(RM) $(objs) $(deps) fianchetto fianchetto.dSYM
-include $(deps)
I am trying to create a very basic hand crafted Makefile to create a shared library to illustrate a point.
This is what I have so far:
SHELL = /bin/sh
CC = gcc
FLAGS = -std=gnu99 -Iinclude
CFLAGS = -fPIC -pedantic -Wall -Wextra -march=native -ggdb3
DEBUGFLAGS = -O0 -D _DEBUG
RELEASEFLAGS = -O2 -D NDEBUG -combine -fwhole-program
TARGET = example.so
SOURCES = $(shell echo src/*.c)
HEADERS = $(shell echo include/*.h)
OBJECTS = $(SOURCES:.c=.o)
PREFIX = $(DESTDIR)/usr/local
BINDIR = $(PREFIX)/bin
all: $(TARGET)
$(TARGET): $(OBJECTS)
$(CC) $(FLAGS) $(CFLAGS) $(DEBUGFLAGS) -o $(TARGET) $(OBJECTS)
When I run make, it attempts to build an application - and ld fails because it can't resolve main().
Problem seems to be with CFLAGS - I have specified -fPIC but that is not working - what am I doing wrong?
Edit
I added the -shared flag as suggested, when I run make, I got this error:
gcc -std=gnu99 -Iinclude -fPIC -shared -pedantic -Wall -Wextra -march=native -ggdb3 -O0 -D _DEBUG -o example.so src/example.o
/usr/bin/ld: src/example.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
src/example.o: could not read symbols: Bad value
collect2: ld returned 1 exit status
make: *** [example.so] Error 1
Which seems to be suggesting to revert back to -fPIC only.
BTW, my new CFLAGS setting is:
CFLAGS = -fPIC -shared -pedantic -Wall -Wextra -march=native -ggdb3
I am running gcc v4.4.3 on Ubuntu 10.0.4.
The solution was to modify the XXFLAGS as follows:
FLAGS = # -std=gnu99 -Iinclude
CFLAGS = -fPIC -g #-pedantic -Wall -Wextra -ggdb3
LDFLAGS = -shared
Compile with -shared:
gcc -o libfoo.so module1.o module2.o -shared
(This also works on MingW under Windows to produce DLLs.)
Example for C++ files. I've also included a clean target.
.PHONY : clean
CPPFLAGS= -fPIC -g
LDFLAGS= -shared
SOURCES = $(shell echo *.cpp)
HEADERS = $(shell echo *.h)
OBJECTS=$(SOURCES:.cpp=.o)
FIKSENGINE_LIBDIR=../../../../lib
FIKSENGINE_INCDIR=../../../../include
TARGET=$(FIKSENGINE_LIBDIR)/tinyxml.so
all: $(TARGET)
clean:
rm -f $(OBJECTS) $(TARGET)
$(TARGET) : $(OBJECTS)
$(CC) $(CPPFLAGS) $(OBJECTS) -o $# $(LDFLAGS)
Since you try to build so file, you probably need -shared.
this is my goto makefile rule for so files:
%.so: %.o ; $(LINK.c) $(LDFLAGS) -shared $^ -o $#
can be used like so
CFLAGS+=-fPIC
libmyfoo.so: # create from libmyfoo.o
# or
libmyfoo.so: myfoo.o # create from myfoo.o
I downloaded someone's source code for a program and i needed to make some changes.
Now i want to compile it but it doesn't seem to work.
PROGS = isotociso
COMMON = tools.o bn.o ec.o wiidisc.o rijndael.o
DEFINES = -DLARGE_FILES -D_FILE_OFFSET_BITS=64
LIBS = C:/Dev-Cpp/lib/libwsock32.a C:/Dev-Cpp/lib/libcrypto.a C:/Dev-Cpp/lib/libcomdlg32.a
CC = gcc
#CFLAGS = -Wall -W -Os -Ilibwbfs -I.
CFLAGS = -Wall -m32 -W -ggdb -Ilibwbfs -I.
LDFLAGS = -m32 -static
VPATH+=libwbfs
OBJS = $(patsubst %,%.o,$(PROGS)) $(COMMON)
all: $(PROGS)
$(PROGS): %: %.o $(COMMON) Makefile
$(CC) $(CFLAGS) $(LDFLAGS) $< $(COMMON) $(LIBS) -o $#
$(OBJS): %.o: %.c tools.h Makefile
$(CC) $(CFLAGS) $(DEFINES) -c $< -o $#
clean:
-rm -f $(OBJS) $(PROGS)
Output
C:\Users\Panda\Desktop\uloader_v4.1\src\isotociso\src>make
gcc -Wall -m32 -W -ggdb -Ilibwbfs -I. -DLARGE_FILES -D_FILE_OFFSET_BITS=64 -c i
sotociso.c -o isotociso.o
process_begin: CreateProcess((null), gcc -Wall -m32 -W -ggdb -Ilibwbfs -I. -DLAR
GE_FILES -D_FILE_OFFSET_BITS=64 -c isotociso.c -o isotociso.o, ...) failed.
make (e=2): The system cannot find the file specified.
make: *** [isotociso.o] Error 2
What would be the problem?
Looks to me as if gcc is not in your PATH.
It also looks like you need MinGW to get the libraries.
I am no expert in C(++) development under Windows, but my interpretation would be that it can't find the compiler itself. What development environment are you using?
It looks like it can't find a file. Are you sure you have all the required source files?