I am trying to compile a TBB and OpenMp comparison program that I made. It is compiling fine with the default visual studio compiler. So, I know that TBB is installed correctly. However, I would like to use g++ instead. I have created a Makefile, and from what I read the -ltbb flag is needed.
My error is, "c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: cannot find -ltbb".
I am not an expert when it comes to making sure I have everything linked correctly and am still trying to learn.
This is my current Makefile
CPLUSPLUS = g++
OPTFLAGS = -O3
TBB_INCLUDE_PATH = C:\tbb-2020.1-win\tbb\include
TBB_LIBRARY_PATH = C:\tbb\tbb\lib\intel64\vc14
all: pps
pps: avl.o main.o parPlaneSweep.o
$(CPLUSPLUS) -I$(TBB_INCLUDE_PATH) -L$(TBB_LIBRARY_PATH) $(OPTFLAGS) -o $# $^ -ltbb
avl.o: avl.h avl.c
$(CC) -c $(OPTFLAGS) -fPIC avl.c
main.o: main.cpp parPlaneSweep.h
$(CPLUSPLUS) -c $(OPTFLAGS) -fopenmp main.cpp
parPlaneSweep.o: parPlaneSweep.h parPlaneSweep.cpp
$(CPLUSPLUS) -c $(OPTFLAGS) -fPIC -fopenmp parPlaneSweep.cpp
clean:
rm *.o
rm pps
Please update your question rather than pointing people at other websites.
First, you should never use backslashes in makefiles, even on Windows (there are exceptions to this on Windows but they're very rare). Always use forward slashes as directory separators.
Second, you define the variables TBB_INCLUDE_PATH and TBB_LIBRARY_PATH but then you never use them. Just mentioning the name of the variable doesn't use the variable. You have to include it in $(...) to use it, like $(TBB_INCLUDE_PATH).
Finally, all common linkers are single-pass linkers, which means the order in which you put the libraries and object files on the link line is critically important. You should always put the object files first, and the libraries last. If you have multiple libraries the order in which they appear may be important as well. Your link line should be something like this:
pps: avl.o main.o parPlaneSweep.o
$(CPLUSPLUS) -I$(TBB_INCLUDE_PATH) -L$(TBB_LIBRARY_PATH) $(OPTFLAGS) -o $# $^ -ltbb
If you want to know what $# and $^ mean, you can read about automatic variables.
Related
Just taking a use case for this instance. I'm compiling a c++ file, and sometimes, I'd like to compile without debugging symbols i.e. the -g enabled and sometimes I would like to enable it.
So, I thought of just making two targets in which the second target would reassign a make variable(is it possible) and change the compiling options. I wonder if such a behaviour is possible to achieve with makefiles?
Below is some pseudocode demo and the user enters make first#bg into the command line:
gpp = g++ -std=c++17
first: hello.cpp
$(gpp) hello.cpp -o $#
#/* some other recipes, assuming the list is really long*/
first#bg: main.o
gpp = g++ -g -std=c++17
execute_all_recipe_of_first_target_which_is_really_long_to_copy()
main.o: main.cpp
$(gpp) main.cpp -c -o main.o #the value of gpp should'd also changed here since first#bg executed
If it is possible please provide me with the actual syntax for the demonstrated behaviour. Thanks in advance.
You can do something like this:
first#bg: gpp += -g
first#bg: first
Note that it's more idiomatic to define CXX=g++ and CXXFLAGS=-std=c++17 and then tweak CXXFLAGS, and use make DEBUG=1 for debug builds:
CXX=g++
CXXFLAGS=-std=c++17
ifeq ($(DEBUG), 1)
CXXFLAGS+=-g
endif
Then invoke the compiler as $(CXX) $(CXXFLAGS) hello.cpp -o $# for example. See also this link
I have a binary which is linked using a large number of object files with many interdependencies. Whenever I recompile even one of these, I need to link the entire binary.
Do linkers (specifically, those of GCC or Clang) support some method of "differential linking", in which enough information is kept about the inter-relations between all the other linked parts, so that the only work that needs to be done when a single part is recompiled is its relations to the other parts + putting them together in the binary?
Note: I'm mostly interested in C++ but I guess this question generalizes at least to C and probably to other compiled languages.
In MSVC this is called "incremental linking". Interestingly, what I've found that GCC might support that to some extent, try using the "-Wl,-i" or "-Wl,-r" parameters to GCC (should be actually also supported by CLang, as these "-Wl" parameters are just passed to ld).
I never used it before, but I made this work with the following makefile:
OBJS := a.o b.o c.o main.o
all: test_app
test_app: test_app.reloc
g++ -o $# $^
# build a "relocatable" object for incremental linking (either -i or -r)
test_app.reloc: $(OBJS)
g++ -Wl,-i -nostdlib -nostartfiles -o $# $^
$(OBJS): makefile
%.o: %.cpp
g++ -c -o $# $<
This builds the app, but I'm not entirely sure what it does internally, if it really does something like "incremental linking" done in MSVC.
In particular, the parameter "-nostdlib" is necessary when using the "-Wl,-i" so that the default libs will not be passed to the ld (which then can't find them - without it I had the error "/usr/bin/ld: cannot find -lgcc_s").
Another version which might actually work better (not sure, this would need to be tested on a bigger application to see if there is some gain in the link time for single object updates):
OBJS := a.ro b.ro c.ro main.ro
all: test_app
test_app: $(OBJS)
g++ -o $# $^
%.o: %.cpp
g++ -c -o $# $<
%.ro: %.o
g++ -Wl,-i -nostdlib -nostartfiles -o $# $<
Basically creating relocatable file for each object (which might be perhaps a significant portion of the linkage of obj files into the executable) and then just updating the relocatables necessary. For the final link step using the relocatables to link everything together (but part of the linkage has been already done before).
It is also possible to create "groups" of object files to be grouped in a single relocatable, so that there will be less of them at the end (not sure if that would bring anything at the end though).
I've been building a C++11 library, and the number of header/source files has grown to the point where compiling programs invoking it, entails passing 20+ .cpp files to g++. I've been reading up on shared libraries and it seems to be the best solution.
However, as headers/source change frequently, I'm hoping to create a makefile that would automatically generate all the .so files from the headers and source.
To better demonstrate what I'm trying to do, I'll take one of my sub-libraries, Chrono and show how I would do this manually.
I first create the object files like so,
$ g++ -std=c++11 -fPIC -g -c -Wall ../src/Chrono/cpp/DateTime.cpp
$ g++ -std=c++11 -fPIC -g -c -Wall ../src/Chrono/cpp/Schedule.cpp
$ g++ -std=c++11 -fPIC -g -c -Wall ../src/Chrono/cpp/Duration.cpp
$ g++ -std=c++11 -fPIC -g -c -Wall ../src/Chrono/cpp/DayCount.cpp
So that I now have DateTime.o, Schedule.o, Duration.o, and DayCount.o in the current directory. I then create the .so file,
$ g++ -shared -Wl,-soname,libChrono.so.1 -o libChrono.so.1.0.1 DateTime.o Schedule.o Duration.o DayCount.o -lc
I then go,
$ rm ./*.o && ldconfig -n ./
So that my working directory now contains, libChrono.so.1.0.1 and the symlink libChrono.so.1.
There are quite a few subdirectories I need to do this for, so you can see that this quickly grows inefficient whenever changes to headers/source are made. I would be grateful if anyone can help me design a makefile that accomplishes all this simply by invoking make.
Thanks!
UPDATE:
Based on goldilock's advice and some digging, I managed to bang together:
CXX=g++
CFLAGS=-std=c++11
TARGET=./lib/libChrono.so.1.0.1
CHRONODIR=./src/Chrono
CHRONOSRC=$(wildcard $(CHRONODIR)/cpp/*.cpp)
CHRONOOBJ=$(join $(addsuffix ../obj/, $(dir $(CHRONOSRC))), $(notdir (CHRONOSRC:.cpp=.o)))
all: $(TARGET)
#true
clean:
#-rm -f $(TARGET) $(CHRONOOBJ)
./lib/libChrono.so.1.0.1: $(CHRONOOBJ)
#echo "======================="
#echo "Creating library file $#"
#echo "======================="
#$(CXX) -shared -Wl,-soname,$(join $(basename $#), .1) -o $# $^ -l
#echo "-- $# file created --"
$(CHRONODIR)/cpp/../obj/%.o : $(CHRONOSRC)
#mkdir -p $(dir $#)
#echo "============="
#echo "Compiling $<"
#$(CXX) $(CFLAGS) -fPIC -g -Wall -c $< -o $#
4 .o files are produced in lib/ but I get multiple definition complaints from ld. Before I was compiling the object files separately, but this unwinds CHRONOOBJ on one line. Any ideas?
Fortunately you included the origin of your problem:
I've been building a C++11 library, and the number of header/source files has grown to the point where compiling programs invoking it, entails passing 20+ .cpp files to g++.
Because this reveals a potential XY problem. The straightforward solution to this is to put object files into an archive (aka. a static library) and use that.
GNU make has an implicit rule for creating C++ .o files. It amounts to this:
%.o: %.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $<
Meaning, if you make DateTime.o in a directory with a makefile that doesn't redefine this, it will make DateTime.o. You may want to add things to $(CXXFLAGS) however, e.g.:
CXXFLAGS += -Wall -Wextra --std=c++11
If you intend to stick with the shared lib route, -fPIC can go there too. That one line could be your entire makefile.
However, you also want to put these together, so you must first declare all the objects and a rule for combining them:
OBJS = DateTime.o Schedule.o Duration.o
libChrono.a: $(OBJS)
ar crvs $# $^
This last line (see man ar) creates the archive (libChrono.a) containing all the objects in $(OBJS). You can then use this with whatever program by placing it in the same directory (or a directory in the library path) and linking -lChrono. Only the necessary parts will be extracted and compiled in. This saves you having to maintain a shared lib in a system directory.
If you still think you need a shared lib, $# and $^ are automatic variables; you can use similar methodology to create a .so, something along the lines of:
SO_FLAGS = -shared
libChrono.so.1.0.1: $(OBJS)
$(CXX) $(SO_FLAGS) -Wl,-soname,libChrono.so.1 -o $# $^ -lc
If that is your first rule, make will take care of everything: building first the objects and then the library. Notice this one has excluded your normal $(CXXFLAGS) to duplicate exactly the compiler line from the question.
I'm trying to create a shared library on ubuntu using gcc
I just have one simple class(shared.h and shared.cpp) and one client to use it (main.cpp)
This is my makefile and I'm still not able to to get the program to compile.
all:
#compile object(fPIC: creates position independent code)
gcc -fPIC -Wall -g -c shared.cpp
#compile shared library
gcc -shared -Wl,-soname,libshared.so.1 -o libshared.so.1.0.1 shared.o -lc
#link shared library
gcc -g -o main main.cpp -L. -lshared
I'm confident the first line is correct
I am unsure what "-lc" does. I think it passes something to the linker?
I don't want to install the library, I just want to be able to link it from the current directory. I have tried: export LD_LIBRARY_PATH=.
but it does not seem to make a difference. Everything is in the current directory.
ERROR: /usr/bin/ld: cannot find -lshared
how do I get the compiler to check the current directory for my library?
The problem is not that it's not looking in the directory, the problem is that you've named the library "libshared.so.1.0.1". When you use -lshared, it's looking for a file named 'libshared.so' or 'libshared.a' in the library search path.
Most of the time, when using versioned system libraries, you'll provide a link to the latest one as 'libshared.so', even if you have installed 'libshared.so.1' or 'libshared.so.1.0.1'.
In your case, if you continue to leave the file named 'libshared.so.1.0.1', you'll want to create 2 symbolic links:
libshared.so - So that the library can be found using ld
libshared.so.1 - Since you declared the SO name as libshared.so.1 when building it, you need to provide this link, otherwise, the executable will not be able to find the proper shared library at runtime.
You don't write any dependencies, which is the purpose of Makefile-s. And you probably need to force the run path Perhaps something like
.PHONY: all clean
CXX=g++
CXXFLAGS=-g -Wall
all: main
main: main.o libshared.so
$(LINK.cpp) -o $# $< -Wl,-rpath,. -L. -lshared
libshared.so: shared.pic.o
$(LINK.cpp) -shared -o $^ $<
main.o: main.cc shared.hh
%.pic.o: %.cc
$(CXX) $(CXXFLAGS) -fPIC -c -o $# $<
#
clean:
rm -f *.o *.so main *~
I am taking a C++ course in college and they want us to manually type in all of the test files... I know, however, that there is a way to do it with out, which is how I ended up with the current(http://pastebin.com/6d9UtKM4) makefile. My question is, why is this makefile automatically removing all the .o files it uses for compiling when it is done? It's not killing me, but I would like to preserve the .o files. I have pasted the makefile here(http://pastebin.com/6d9UtKM4). I have also pasted the current result of running "make tests" here(http://pastebin.com/h3Ny3dib). (Note the part at the bottom of that page that removes all the .o files automatically.)
I would also like to be able to make it generate it like this:
g++ -o compileDir/assembler.o -c -Wall src/assembler.cpp
g++ -o compileDir/string.o -c -Wall src/string.cpp
g++ -c -Wall -o compileDir/test_assignment.o testSrc/test_assignment.cpp
g++ -o testDir/test_assignment compileDir/test_assignment.o compileDir/string.o compileDir/assembler.o
g++ -c -Wall -o compileDir/test_bracket.o testSrc/test_bracket.cpp
g++ -o testDir/test_bracket compileDir/test_bracket.o compileDir/string.o compileDir/assembler.o
testDir/test_bracket
testDir/test_assignment
In other words, I want it to compile everything, then run everything. I hope this isn't too much to ask!
Edit: Additional Information: (This is the code that does "make tests")
tests: assembler.o string.o $(test_output) $(test_stringOutput)
#echo '--- Testing complete ---'
$(testDir)%: $(compileDir)%.o string.o
g++ -o $# $< $(compileDir)string.o $(compileDir)assembler.o
$#
#echo ''
$(compileDir)%.o: $(testSourceDir)%.cpp
g++ -c -Wall -o $# $<
$(compileDir)%.o: $(testStringSrc)%.cpp
g++ -c -Wall -o $# $<
EDIT: -----------------------------------------
Resolved via comments:
Adding this line fixed it:
.PRECIOUS $(compileDir)%.o
You might add
.PRECIOUS: %.o
which should be implicit, but perhaps you've got a weird setup.
Make treats your .o files as intermediate and removes them. You can prevent automatic deletion of those by adding them a dependency of the special .SECONDARY target. See Chains of Implicit Rules for more details. Good luck!