Problem while using objcopy with "thin archive" file - gcc

Please use following shell commands to reproduce the problem:
# create subdirectory
mkdir subdir
# create source files with dummy functions
echo 'void func1(){}' > file1.c
echo 'void func2(){}' > ./subdir/file2.c
# compiling sources into object files
gcc -c file1.c -o file1.o
gcc -c ./subdir/file2.c -o ./subdir/file2.o
# creating "thin archive" file from object files
ar crT out.a file1.o ./subdir/file2.o
# running objcopy, which leads to an error
objcopy out.a out_copy.a
As a result, following error occurs:
objcopy:st0AENRL/subdir/file2.o: No such file or directory
P.S. Problem with objcopy occurs when "thin" archive is composed of object files from subdirectories.
Does anybody know if such objcopy's behavior is ok?

This is really a bug.
It was reported here.
Support of thin archives was temporary disabled.

Related

How to create a makefile that will place object code in different folder

I am very new to Makefile. I had build the following makefile(Which don't work).I wan't put genarated object codes in differnt folder(the folder is in current directory).
$ ls
main.cpp Makefile object_code Time.cpp Time_.h
how can I do this ??
VER = Debug
CC = g++
OBJECTFIELS = ./object_code/main.o ./object_code/Time.o
../$(VER)/main: $(OBJECTFIELS)
$(CC) $(OBJECTFIELS) -o $#
$(OBJECTFIELS): Time_.h
./object_code/main.o: main.cpp
./object_code/Time.o: Time.cpp
clean:
rm $(OBJECTFIELS) main
this is error.
$ make
g++ ./object_code/main.o ./object_code/Time.o -o ../Debug/main
g++: error: ./object_code/main.o: No such file or directory
g++: error: ./object_code/Time.o: No such file or directory
g++: fatal error: no input files
compilation terminated.
Makefile:8: recipe for target '../Debug/main' failed
make: *** [../Debug/main] Error 1
please this is last question.
I don't see how you can possibly get that output given the makefile you've posted here.
Either the object files already exist in which case the link will succeed rather than printing that error.
Or the object files don't exist in which case make will complain because it doesn't know how to make them. There must be some difference between the makefile you're using and the one you've posted here.
In any event, make knows how to build a file foo.o from a file foo.cpp for any string foo. There's a built-in rule that tells it how to do that.
But, make doesn't know how to build a file ./object_code/foo.o from a file foo.cpp, regardless of foo. There's no built-in rule that tells make how to build object files in some random other directory. If you want make to do that, you'll have to tell it how. You should remove the lines:
./object_code/main.o: main.cpp
./object_code/Time.o: Time.cpp
and replace them with a pattern rule describing how to build object files into the object_code directory (I'm using CXX as the compiler variable here: by convention CC is the C compiler and CXX is the C++ compiler, and you should always stick with convention unless there's a good reason not to):
VER = Debug
CXX = g++
OBJECTFIELS = ./object_code/main.o ./object_code/Time.o
../$(VER)/main: $(OBJECTFIELS)
$(CXX) $(OBJECTFIELS) -o $#
$(OBJECTFIELS): Time_.h
./object_code/%.o : %.cpp
$(CXX) -c -o $# $<
clean:
rm $(OBJECTFIELS) main

How to generate dependency file for executable (during linking) with gcc

gcc has -M-class options (-MMD, -MF, etc.) that allows to generate dependency file during compiling source file. The dependency file contains Makefile rules describing on which source files and headers the generated object file depends on. The dependency file may be included into Makefile and then make will automatically recompile source file when headers are changed.
I need a similar option but for generating dependency file during linking an executable. The dependency file should contain list of libraries used for linking an executable, so if any of libraries is updated, make will re-execute linking of the executable automatically.
I tried to use the same flags (-MMD, -MF), but they doesn't work for linking. It seems they are only for generating dependency files during compiling.
Is there any other flags or means for generating dependency file for executable?
So far I have not found dedicated gcc options for generating dependency file for executable, but found the --trace option (-Wl,--trace when used with gcc). This option generates list of libraries used during linking. Its output has the next format:
gcc -Wl,--trace myprog.c -o myprog -L. -lmylib
-lmylib (./libmylib.a)
-lgcc_s (/usr/lib/x86_64-linux-gnu/gcc/x86_64-linux-gnu/4.5.2/libgcc_s.so)
...
The list of libraries then may be converted to Makefile rules using sed:
echo "myprog: " > myprog.dep
gcc -Wl,--trace myprog.c -o myprog -L. -lmylib \
| sed -n 's/.*(\(.*\)).*/\1 \\/p' >> myprog.dep
So myprog.dep will have the following content:
myprog: \
./libmylib.a \
/usr/lib/x86_64-linux-gnu/gcc/x86_64-linux-gnu/4.5.2/libgcc_s.so \
...
This dependency file may be included to Makefile and make will relink myprog if any of libraries are updated.
The dependency file doesn't contain list of object files, but the object files are usually known inside Makefile-script without help of compiler:
myprog: $(OBJS)
gcc -Wl,--trace $^ -o myprog -L. -lmylib | sed -n 's/.*(\(.*\)).*/\1 \\/p' >> myprog.dep

How to write Makefile to include multi directories

I have the following setup. Two folders named /driverlib and /inc on the main folder and on the same folder I have a linker file and two c files, startup_gcc and blink.c.
I followed a template I found online for STM32F4. I modified it and tried to include both directories on my folder. However I am getting the following error:
C:\Users\D\Documents\ARM-Tiva\blinky3>make
driverlib/adc.c:49:24: fatal error: inc/hw_adc.h: No such file or directory
compilation terminated.
make: *** [driverlib/adc.o] Error 1
Can somebody explain to me how to include both directories so that the /inc folder is visible to the /driverlib folder.
Here's the makefile:
OBJCOPY = $(TC)-objcopy
OBJDUMP = $(TC)-objdump
SIZE = $(TC)-size
###################################################
# Set Include Paths
INCLUDES = -I /inc
INCLUDES = -I /driverlib
# Set Sources
LIB_SRCS = $(wildcard driverlib/*.c)
USER_SRCS = $(wildcard src/*.c)
# Set Objects
LIB_OBJS = $(LIB_SRCS:.c=.o)
USER_OBJS = $(USER_SRCS:.c=.o) startup_gcc.o
# Set Libraries
LIBS = -lm -lc
###################################################
# Set Board
MCU = -mthumb -mcpu=cortex-m4
DEFINES = -DPART_LM4F120H5QR -DTARGET_IS_BLIZZARD_RA1
# Set Compilation and Linking Flags
CFLAGS = $(MCU) $(FPU) $(DEFINES) $(INCLUDES) \
-g -Wall -std=gnu90 -O0 -ffunction-sections -fdata-sections
ASFLAGS = $(MCU) $(FPU) -g -Wa,--warn -x assembler-with-cpp
LDFLAGS = $(MCU) $(FPU) -g -gdwarf-2 \
-Ttivalinker.ld \
-Xlinker --gc-sections -Wl,-Map=$(PROJ_NAME).map \
$(LIBS) \
-o $(PROJ_NAME).elf
###################################################
# Default Target
all: $(PROJ_NAME).bin info
# elf Target
$(PROJ_NAME).elf: $(LIB_OBJS) $(USER_OBJS)
#$(CC) $(LIB_OBJS) $(USER_OBJS) $(LDFLAGS)
#echo $#
# bin Target
$(PROJ_NAME).bin: $(PROJ_NAME).elf
#$(OBJCOPY) -O binary $(PROJ_NAME).elf $(PROJ_NAME).bin
#echo $#
#$(PROJ_NAME).hex: $(PROJ_NAME).elf
# #$(OBJCOPY) -O ihex $(PROJ_NAME).elf $(PROJ_NAME).hex
# #echo $#
#$(PROJ_NAME).lst: $(PROJ_NAME).elf
# #$(OBJDUMP) -h -S $(PROJ_NAME).elf > $(PROJ_NAME).lst
# #echo $#
# Display Memory Usage Info
info: $(PROJ_NAME).elf
#$(SIZE) --format=berkeley $(PROJ_NAME).elf
# Rule for .c files
.c.o:
#$(CC) $(CFLAGS) -c -o $# $<
#echo $#
# Rule for .s files
.s.o:
#$(CC) $(ASFLAGS) -c -o $# $<
#echo $#
# Clean Target
clean:
$(RM) $(LIB_OBJS)
$(RM) $(USER_OBJS)
$(RM) $(PROJ_NAME).elf
$(RM) $(PROJ_NAME).bin
$(RM) $(PROJ_NAME).map
The issue is obviously at this paragraph:
###################################################
# Set Include Paths
INCLUDES = -I /inc
INCLUDES = -I /driverlib
# Set Sources
LIB_SRCS = $(wildcard driverlib/*.c)
USER_SRCS = $(wildcard src/*.c)
# Set Objects
LIB_OBJS = $(LIB_SRCS:.c=.o)
USER_OBJS = $(USER_SRCS:.c=.o) startup_gcc.o
I cannot understand why driverlib does not include the inc directory files.
EDIT
I wanted to clarify my setup for future reference: On the main folder called blinky I have three folders : driverlib, inc and src. The driverlib and inc folders are taken from the TivaWARE folder while the src folder contains the blinky.c and startup_gcc.c file. Given the following if you use make you obtain the following :
C:\Users\D\Documents\ARM-Tiva\blinky>make
driverlib/adc.c:49:24: fatal error: inc/hw_adc.h: No such file or directory
compilation terminated.
make: *** [driverlib/adc.o] Error 1
This shows that the file adc.c in the driverlib folder cannot include the file hw_adc.h in
I modified the Makefile following the suggestions below:
# Set Sources
LIB_SRCS = $(wildcard driverlib/*.c)
USER_SRCS = $(wildcard src/*.c)
# Set Objects
LIB_OBJS = $(LIB_SRCS:.c=.o)
USER_OBJS = $(USER_SRCS:.c=.o) src/startup_gcc.o
# Set Include Paths
INCLUDES = -Idriverlib/ \
-Iinc \
-Isrc/
Betas solution was helpful , the only issue was that I did not want to edit all the files in the driverlib folder. The naming convention of the directories was not my decision. If you can see all the files in the driverlib folder you'll find out that each driver file , CAN driver for example or ADC) follows this convention :
#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_can.h"
#include "inc/hw_ints.h"
#include "inc/hw_nvic.h"
#include "inc/hw_memmap.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_types.h"
#include "driverlib/can.h"
#include "driverlib/debug.h"
#include "driverlib/interrupt.h"
So right now I understand where the issue is but I lack the understanding to edit the Makefile.
Normally if files can.c and can.h are in folder driverlib using #include "can.h" would suffice so I do not understand what's the point of using #include "driverlib/can.h" if all .h and .c files are in the same driverlib folder . If I edit all the inc/ header then I can get a working binary file. The aim however was not to modify the default stock driver files and folders obtained from TI but to use the Makefile.
So to clarify if you follow Betas solution and edit all the files , or if you put all the files in one big directory then you can get a working binary file. Also for future reference I found I could use Energia for what I am doing since it uses the same compiler and TIVA includes the complete peripheral library burned on ROM.
I don't know the cause of the error exactly, but this is not correct:
INCLUDES = -I /inc
# Now INCLUDES is "-I /inc"
INCLUDES = -I /driverlib
# Now INCLUDES is "-I /driverlib", and inc has been forgotten.
I think you mean this:
INCLUDES = -I /inc
INCLUDES += -I /driverlib
EDIT:
It's generally a bad idea to spell out paths in the #include directives. In adc.c, change this:
#include "inc/hw_adc.h"
to this:
#include "hw_adc.h"
and in the makefile remove the leading slashes (since you won't always be in the root directory):
INCLUDES = -I inc
INCLUDES += -I driverlib
The most helpful thing would have been if you had provided the actual complete path of one of the header files which is not being found, in your question, and an example compile line run by make in addition to the error message. Given that information it's trivial to see what's wrong.
It looks like some miscommunication is happening. You write two folders named /driverlib and /inc on the main folder. A folder name that begins with a / is by definition at the root of the directory structure, not within any other folder. I don't know what you mean by on the main folder.
The first thing I'll say is that you're using Windows (as can be seen by your command line prompt), and so you need to be sure that the version of make you're using will do the right thing converting Windows pathnames to UNIX pathnames. For example if you're using Cygwin version of GNU make, then I think the paths you're using are not correct.
Second, I note that you are using -I /inc; that is, the inc directory is at the root of your filesystem. Is that what you intended? Beta's answers have changed that to -I inc, which means the directory inc as a subdirectory of the current working directory, which could be quite different.
Third, if the pathname to the headers is /inc/hw_adc.h and you have -I /inc on your command line and #include "inc/hw_adc.h", I'm sure you can see how this will absolutely not work. The compiler will be looking for header files named /inc/inc/hw_adc.h. If you want to keep the relative pathname inc/hw_adc.h in your #include line, and the path to the header file is /inc/hw_adc.h, then you should use just -I / (the root directory) on the compile command line.
Lastly, I'll say that I actually don't agree with Beta's suggestion that it's a bad idea to spell out paths in include lines. This is common: if you are using a library that contains a lot of header files then typically the header files are collected in a subdirectory (consider things like Boost, or X11, etc.) and it's, IMO, good practice to use the name of the subdirectory in your #include lines in the source code.
On the other hand, though, I will agree with Beta that a directory name like inc is utterly lame and is of pretty much no use whatever. That directory should have a name which is somehow evocative of the kinds of headers that can be found inside it, not something uselessly generic like "inc".

g++: fatal error: cannot specify -o with -c, -S or -E with multiple files

I am trying to compile a library file using other library files. I am using the following line in my makefile to create gameobject.o:
lib/gameobject.o: src/gameobject.cpp src/vector.hpp lib/objectevent.o lib/sprite.o
g++ $^ -c -o $# $(SFML_FLAGS)
All the dependencies comile correctly, but I get the following error when it tries to compile gameobject.o:
g++: fatal error: cannot specify -o with -c, -S or -E with multiple files
I'm still a bit new to using make/separating compilation, so I'm not quite sure what I should do. Do I just have to compile it without setting an output? Do I have to compile gameobject.o without using any of my other .o files? If that's true, wouldn't compile times get pretty big for large objects if you can't compile libraries with other libraries? Or am I just reading this error completely wrong?
You're not building a library file here. A .o file is an object file. Typically there is one object file per source file. When you use the compiler's -c option, it takes a single source file and compiles it into a single object file. You cannot add other object files into an existing object file, so adding both .o and .cpp files into the same compiler line with -c is not going to work.
If you want to create a library, that would be something like libfoo.a (the "a" here stands for "archive"). If you want to create an executable you can do that as well.
You need to be more clear about exactly what result you want before we can describe how to get it.
I had the same problem after I combined some projects of a solution to a single one. I find out there was tow .cpp files with same names and after I did rename one of them It solved.
You can create only one object .o file from one source file.
If you are using makefile to build the project. Make sure you are doing $< instead of $^
# Correct one
%.o: %.cpp
$(CPP) $(CFLAGS) -c -o $# $<
# InCorrect one
%.o: %.cpp
$(CPP) $(CFLAGS) -c -o $# $^

GCC library linking issue

I am trying to compile Pro*C lib on Linux.I have following code in my make.
etc=$TABS_HOME/admin
export etc
if [ -f ${1}.pc ]
then
rm $1_x.o
compc $1
make -f $etc/proc64.mk $1_x.o
ar -cvq libtabs.a $1_x.o
else
make -f $etc/proc64.mk $1.o
ar -cvq libtabs.a $1.o
fi
Here is the final command that printed when compilation started:
/usr/bin/gcc -g -m64 -g -I/export/home/cl10gr2/oracle/rdbms/public -I/home/med/src/common -I/u01/app/oradb11r2/product/11.2.0/dbhome_3/rdbms/demo -
I/u01/app/oradb11r2/product/11.2.0/dbhome_3/rdbms/public -
I/u01/app/oradb11r2/product/11.2.0/dbhome_3/precomp/public -ltabs.a -lnapi.a -c commonutil_x.c
I am getting following warning/Error:
gcc: -ltabs.a: linker input file unused because linking not done
gcc: -lnapi.a: linker input file unused because linking not done
Can any please help me out why it is not linking the lib files?
Its not linking them because you aren't linking. You are passing the -c option:
-c Compile or assemble the source files, but do not link. The linking stage simply is not done. The ultimate output is in the form of an object file for each source file.
If you are building intermediate object files, you don't need the libraries until the very end. Include all of the object files and libraries you need in the final stage and link them all together.

Resources