I am attempting to wrap a text file with ld into a .o. Given how the Makefiles for my project are set up, the full path to the text file is being passed to ld. This causes the generated names to include that path. I don't want that as I can't link against that name in my C++ source.
Is there a way to change the names or prefixes when I run ld?
ld -r -b binary /path/to/source/Value.txt -o Value.o
objdump -x Value.o | grep binary
0000000000000142 g .data 0000000000000000 _binary__path_to_source_Value_txt_end
0000000000000142 g *ABS* 0000000000000000 _binary__path_to_source_Value_txt_size
0000000000000000 g .data 0000000000000000 _binary__path_to_source_Value_txt_start
I would like to see names like _binary_Value_txt_end.
Based on Captain Oblivious' comment, I was able to develop a Makefile rule:
%.o: %.txt
pushd $(dir $<) ; $(LD) -r -b binary $(notdir $<) -o $# ; popd
This changes to the directory location of the text file so that ld creates nice, known names. I needed to do some work to ensure that $# was an absolute path so the .o would be created in the build directory.
Related
I am trying to compile ICU 49.1.2 on AIX 7.1 with vaC++ 11.1.
By default ICU make files are configured to generate .a files instead of .so files.
There is an option to change the type of shared library extension inside /source/config/mh-aix-va file.
SO = a -> this can be changed to so to generate so files.
But when I change it to so, I get error as below. Any idea what else has to be done to generate .so files?
gmake[1]: Leaving directory `/export/home/cmbabu/xml/icu/source/common'
gmake[1]: Entering directory `/export/home/cmbabu/xml/icu/source/common'
gmake[1]: * No rule to make target `../lib/libicuuc.so', needed by `all-local'. Stop.
gmake[1]: Leaving directory `/export/home/cmbabu/xml/icu/source/common'
gmake: *** [all-recursive] Error 2
Thanks in advance.
To get rid of the error and successfully generate so files, I did lot of trial and errors and finally came up with a solution to as described below.
I had to modify few existing rules and add few more rules in config/mh-aix-va file.
Changes are...
line# 17 and 18: uncomment line #18
# If you readd this line, you must change the SO value
LDFLAGS += -brtl
line # 80 and 81: change the line # 81
# without the -brtl option, the library names use .a. AIX is funny that way.
SO= so
line # 92 to 99:
comment all these lines
#%.a : %.so
# ln -f $< $(SHARED_OBJECT_NO_VERSION)
# $(AIX_PREDELETE) $(AR) $(ARFLAGS) $# $(SHARED_OBJECT_NO_VERSION)
# rm -f $(SHARED_OBJECT_NO_VERSION)
#$(LIBDIR)/%.a : %.so
# ln -f $< $(SHARED_OBJECT_NO_VERSION)
# $(AIX_PREDELETE) $(AR) $(ARFLAGS) $# $(SHARED_OBJECT_NO_VERSION)
# rm -f $(SHARED_OBJECT_NO_VERSION)
Add below lines at line # 100:
$(LIBDIR)/%.so : %.so
ln -f $< $#
$(LIBDIR)/%$(SO_TARGET_VERSION).so : %.so
ln -s $< $#
$(LIBDIR)/%$(SO_TARGET_VERSION_MAJOR).so : %.so
ln -s $< $#
AIX by default (unless you link with -brtl) expects shared libraries to have the suffix .a. So you should not be changing SO=a to SO=so unless you also uncomment the -brtl flag in the makefile.
This is alluded to by the comment in the makefile:
without the -brtl option, the library names use .a. AIX is funny that way.
My current directory looks as follow:
root
|___src
| |
| |____Makefile
| |____a.cpp
| |____b.cpp
| |____c.h
| |____tests
| |
|______________|____test.cpp
Is there a way from the makefile to force all files under tests directory to include c.h
You haven't answered either of my questions, so I'll have to make some guesses.
This may be what you're looking for:
%.o: %.cpp
#$(CXX) -c $< -o $#
tests/%.o: tests/%.cpp
#$(CXX) -include c.h -c $< -o $#
EDIT:
If you want to insert #include "c.h" at the top of a source file, you can use this sed command:
sed -i "" '1{h;s/.*/#include "c.h"/;G;}' filename
If you want to be sure you don't do so more than once, you can do this:
sed -i "" '1{h;s/.*/#include "c.h"/;G;s/\(.*\)\n\1$/\1/;}' filename
There are several different ways to do this with a makefile. Here is one crude-but-effective approach:
tests/%.o: tests/%.cpp
#sed -i "" '1{h;s/.*/#include "c.h"/;G;s/\(.*\)\n\1$/\1/;}' $<
#$(CXX) -c $< -o $#
But Make will work better if you run sed on each source file only once. This can be done, but it requires more careful thought about priorities.
gcc and clang support -include file command line option.
gcc documentation:
-include file
Process file as if #include "file" appeared as the first line of the primary source file. However, the first directory searched for file is the preprocessor's working directory instead of the directory containing the main source file. If not found there, it is searched for in the remainder of the #include "..." search chain as normal.
Other compilers may have a similar option.
C++ newbie here my command is g++ main.cpp -o main gives me linking errors like the following
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
if i pass c++ files g++ main.cpp myfile.cpp -o main everything is correct
any ideas how to compile multiple c++ files without passing everything in command line.
Thanks
any ideas how to compile multiple c++ files without passing everything in command line.
To build an application you need all object files, so you have to pass all cpp files to compiler.
But for simple cases when all cpp-files stay at single folder, you can
use command (simple, but slow method):
g++ *.cpp -o main
any ideas how to compile multiple c++ files without passing everything in command line.
First create object files:
g++ -c main.cpp -o main.o
g++ -c myfile.cpp -o myfile.o
Then pass them to the linker:
g++ main.o myfile.o -o main
Though there is a fairly large learning curve for Make, a make file is the preferred solution. On SO, I have also noticed significant use of CMake.
Additional ideas for your Makefile:
The following two rules handle 90% of my simpler unit test executables:
R01 handles files with both .cc and .hh
R02 handles files with only .cc
# pattern rule R01
# when any ARCHIVE changes, trigger a rebuild
% : %.cc %.hh $(LIB_ARCHIVEs)
#echo
#echo R01: $<
rm -f $#
$(CC) $(CC_FLAGS) $< -o $# $(LIB_DIRs) $(LIB_NMs)
# pattern rule R02
# when any ARCHIVE changes, trigger a rebuild
% : %.cc $(LIB_ARCHIVEs)
#echo
#echo R02: $<
rm -f $#
$(CC) $(CC_FLAGS) $< -o $# $(LIB_DIRs) $(LIB_NMs)
Occasionally, I will add specific LIB names and directories ... directly to the LIB_DIRs and LIB_NMs definition in the Makefile. For example, here I have added -lrt and -pthread:
LIB_NMs += -lbag_i686 -lposix_i686 -lrt -pthread
bag_i686 and posix_i686 are libraries I built ... simple C++ class wrappers around the linux and posix functions. Most of my unit tests do not use much of posix stuff, but I get no grief including it.
With C++ std::thread, I seldom use -pthread. However, I occasionally use posix semaphore.
My compile command line access (in emacs on Ubuntu) provides a history, so the occasional change or addition to the command line is only a 'bother' one time. From then on, the newer command is available in history.
The emacs I launch is configured with an 'embedded' pre-defined compile command:
USER_FLAGS='-O0 ' ; export USER_FLAGS ; time make CC='g++ -m64' -j 2 -k
This command shows up the 1st time I launch the compiler from within emacs. Emacs presents it as if the command is already in 'compile-command history'.
I manually shorten this if I'm not rebuilding all, usually I only build a single ut:
USER_FLAGS='-O0 ' ; export USER_FLAGS ; time make CC='g++ -m64'
So, for example, when I am ready to compile dumy431.cc, I invoke:
USER_FLAGS='-O0 ' ; export USER_FLAGS ; time make CC='g++ -m64' dumy431
The next build I launch (from within emacs compile) starts with the previous command, and up/down arrow roll through any other versions of the command.
With this form of the command, I can trivially change from g++ to clang++ by inserting "clan" at the appropriate place:
USER_FLAGS='-O0 ' ; export USER_FLAGS ; time make CC='clang++ -m64'
clang++ often provides additional diagnostics that g++ does not report. To roll back to g++, I can up-arrow in the compiler command panel (or edit the command).
Here is a small example where my unit test code has multiple src files. Often, the non-main files (such as eng_format.*) are code that I plan to capture to one of my libraries for future use:
FMssb.o : FMssb.cc FMssb.hh
#echo
#echo R_FMssb.o: $<
rm -f $#
$(CC) $(CC_FLAGS) -c $< -o $#
FMssb_ut : FMssb_ut.cc eng_format.o FMssb.o $(LIB_ARCHIVEs)
#echo
#echo R_FMssb_ut: $<
rm -f $#
$(CC) $(CC_FLAGS) $< -o $# eng_format.o FMssb.o $(LIB_DIRs) $(LIB_NMs)
eng_format.o : eng_format.cpp eng_format.hpp $(LIB_ARCHIVEs)
#echo
#echo R_EF: $<
rm -f $#
$(CC) $(CC_FLAGS) -c $< -o $# $(LIB_DIRs) $(LIB_NMs)
I have following Makefile:
TOP = ../Bank/src
CC = gcc
CFLAGS = -g -Wall -std=c99
LDFLAGS = -L$(TOP)
LFLAGS = -lVirtualBank
INCLUDES = -I$(TOP)/VirtualBank/
LIBS = VirtualBank.a
BANK_SOURCES = $(TOP)/bank.c
VirtualBank_SOURCES = $(TOP)/VirtualBank/bankServer.c $(TOP)/VirtualBank/dataBase.c $(TOP)/VirtualBank/account.c
BANK_OBJECTS = $(BANK_SOURCES:.c=.o)
VirtualBank_OBJECTS = $(VirtualBank_SOURCES:.c=.o)
TARGET = bank
all: VirtualBank.a $(TARGET)
VirtualBank.a:$(VirtualBank_OBJECTS)
rm -f $#
ar cq $# $(VirtualBank_OBJECTS)
mv *.a $(TOP)/
$(VirtualBank_OBJECTS):$(VirtualBank_SOURCES)
$(CC) -c $(CFLAGS) $(INCLUDES) $(VirtualBank_SOURCES)
mv *.o $(TOP)/VirtualBank/
$(TARGET):$(BANK_OBJECTS)
$(CC) $(CFLAGS) $(INCLUDES) $(BANK_OBJECTS) -o $(TARGET) $(LDFLAGS) $(LFLAGS)
chmod +x $(TARGET)
$(BANK_OBJECTS):$(BANK_SOURCES)
$(CC) $(CFLAGS) -c $(INCLUDES) $(BANK_SOURCES)
mv *.o $(TOP)/
clean:
cd ../Bank
rm -rf *.o bank
cd $(TOP)
rm -rf *.o *.a
cd $(TOP)/VirtualBank
rm -rf *.o
It is from this project: https://github.com/MihaiPro/Bank
When I run make command, commpiler doesn't find VirtualBank library. I think the problem is on -l command, I read again about this command, but I don't find what is problem.
Can you help me?
Thanks!
EDIT
Error message:
gcc -g -Wall -std=c99 -I../Bank/src/VirtualBank/ ../Bank/src/bank.o -o bank -L../Bank/src -lVirtualBank
/usr/bin/ld: cannot find -lVirtualBank
collect2: error: ld returned 1 exit status
make: *** [bank] Error 1
From ld(1):
-l namespec
--library=namespec
Add the archive or object file specified by namespec to the list of files to link. This option may be used any number of times. If namespec is of the form :filename, ld will search the library path for a file called filename, otherwise it will search the library path for a file called libnamespec.a.
On systems which support shared libraries, ld may also search for files other than libnamespec.a. Specifically, on ELF and SunOS systems, ld will search a directory for a library called libnamespec.so before searching for one called libnamespec.a. (By convention, a ".so" extension indicates a shared library.) Note that this behavior does not apply to :filename, which always specifies a file called filename.
The linker will search an archive only once, at the location where it is specified on the command line. If the archive defines a symbol which was undefined in some object which appeared before the archive on the command line, the linker will include the appropriate file(s) from the archive. However, an undefined symbol in an object appearing later on the command line will not cause the linker to search the archive again.
See the -( option for a way to force the linker to search archives multiple times.
You may list the same archive multiple times on the command line.
This type of archive searching is standard for Unix linkers. However, if you are using ld on AIX , note that it is different from the behaviour of the AIX linker.
Your library is called VirtualBank.a, but ld will look for libVirtualBank.a.
I have a list of library folders that I'm specifying in a make file:
LIBRARIES = Ethernet \
SPI \
SD
I also have a number of rules for compiling each one into a local obj folder of my project:
obj/SPI/%.cpp.o: $(LIBS_DIR)/SPI/%.cpp
#echo "Compiling $<"
obj/SD/%.cpp.o: $(LIBS_DIR)/SD/%.cpp
#echo "Compiling $<"
obj/Ethernet/%.cpp.o: $(LIBS_DIR)/Ethernet/%.cpp
#echo "Compiling $<"
(Note that each one uses it's own sub-folder). How can I generate these rules from $(LIBRARIES) automatically so that I don't have to duplicate them like this?
You can just do:
obj/%.cpp.o : $(LIBS_DIR)/%.cpp
g++ -c -o $# ${CPPFLAGS} ${CXXFLAGS} $<
In the above % captures dir/src part.
If you'd like the output directories to be created automatically it can be done with secondary expansion make feature:
.SECONDEXPANSION:
obj/%.cpp.o : $(LIBS_DIR)/%.cpp | $${#D} # object file depends on its directory
g++ -c -o $# ${CPPFLAGS} ${CXXFLAGS} $<
obj/% : # directory creation rule
mkdir -p $#
Sufficiently new versions of GNU make support the eval function. You can use it like this:
define SUBDIR_RULE
obj/$1/%.cpp.o: $(LIBS_DIR)/$1/%.cpp
#echo "Compiling $$<"
enddef
$(foreach D,$(LIBRARIES),$(eval $(call SUBDIR_RULE,$D)))
If you don't want to rely on that you can use auto-generated makefiles, which have been a feature of GNU make for much much longer. But this method is slightly trickier to use.