I am learning linux, and my first step is to adapt my project for running on linux. Here is simple makefile (in educational purposes mostly), which generates out file:
#------------------------BUILD VARIABLES-----------------------------
# Directories, containing headers
INCLUDE_DIR = ../Include/
# Output directory which will contain output compiled file
OUTPUT_DIR = ../Bin/Debug/
SOURCES = EngineManager.cpp Geometry.cpp Main.cpp Model.cpp \
Shaders.cpp TGAImage.cpp
HEADERS = EngineManager.h Geometry.h Line.h Model.h Shaders.h \
TGAImage.h Triangle.h
#------------------------BUILD_RULES---------------------------------
TinyRenderBuilding : $(addprefix $(INCLUDE_DIR), $(HEADERS)) $(SOURCES)
mkdir -p $(OUTPUT_DIR)
g++ -std=c++14 -o $(OUTPUT_DIR)TinyRender.out -g -I$(INCLUDE_DIR) $(SOURCES)
I cannot understand, why does g++ not generate debug symbols? -g option is presented
To include debug symbols when compiling with g++ you need to pass the -g option.
In a make make file this usually means adding it to to CXXFLAGS.
Also make sure you pass the -g option when you create the executable: when you compile you turn .cpp files into .o files, when you do the linking you turn those .o files into your executable).
If you change the options before running make again be sure to run a make clean cause otherwise it won't get recompiled.
Finally, make sure that you do not have additional steps like strips command run on the executable (which would remove debugging symbols).
you can use
objdump --syms <executable-file>
to check if an executable have symbols.
when it doesn't have symbols it will say something like:
SYMBOL TABLE:
no symbols
(I'm no experto of C / C++ programming, I just run into this while I was trying to debug someone else code)
According to your makefile g++ should produce debug symbols (-g option is presented). To confirm this you can run file on resulting binary:
$ file a.out
a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=9fe588c18099ef418daf288931bb033cc287922e, with debug_info, not stripped
(Note with debug_info string in output)
I'm not entirely sure, but you can try -g or -ggdb.You can do some research on these. We were using these parameters to debug the C program with the gdb tool.
Related
I am using Intel Pin to compile a C source and header file along with my c++ pintool. To do so I have added the following makefile rules in my makefile.rules file -
# Build the intermediate object file.
$(OBJDIR)testcpp$(OBJ_SUFFIX): testcpp.cpp
$(CXX) $(TOOL_CXXFLAGS_NOOPT) $(COMP_OBJ)$# $<
# Build the intermediate object file.
$(OBJDIR)test$(OBJ_SUFFIX): test.c test.h
$(CC) $(TOOL_CXXFLAGS) $(COMP_OBJ)$# $<
# Build the tool as a dll (shared object).
$(OBJDIR)testcpp$(PINTOOL_SUFFIX): $(OBJDIR)test$(OBJ_SUFFIX) test.h
$(LINKER) $(TOOL_LDFLAGS_NOOPT) $(LINK_EXE)$# $(^:%.h=) $(TOOL_LPATHS) $(TOOL_LIBS)
testcpp.cpp is my pintool in C++ , test.c and test.h are my C source and header files.
I am using the rules mentioned in this link - https://software.intel.com/sites/landingpage/pintool/docs/97438/Pin/html/index.html#MAKEFILES
I removed this option from the file makefile.unix.config -
TOOL_CXXFLAGS_NOOPT += -fno-rtti
as this option is specifically for C++ and C does not use it. Since I am compiling both of them using the same compiler options, removing the option seemed better than adding a new rule for C and C++
I am able to make my program using the command "make". It generated a directory obj-intel64 with the object files test.o and testcpp.so, so my compiling worked fine.
For executing my program I use the following command -
$PIN_ROOT/pin -t obj-intel64/testcpp.so -- my_application_program
I get the following output -
E: Unable to load obj-intel64/testcpp.so
The file testcpp.so is present in the obj-intel64 directory, yet I am unable to load it.
Any hints as to where I am going wrong?
I have a project that I am still trying to setup using Clang and Visual Studio on Windows. As a caveat, I've worked on several c++ projects but they've all been mature projects where I haven't had to be involved in setting up make files or resolving dependencies hence why I want some experience in doing so.
As a clarification, I am not using the LLVM built into visual studio thing. My goal was to have visual studio be a convenience on top of having a project that can be built with make files but not using CMake.
So far, I have a solution with a single nmake project. This nmake project calls a build.bat file which calls into a make file. This make file looks like this:
# Based on PUXAN tutorial
# http://www.puxan.com/web/howto-write-generic-makefiles/
# Compiler choice
CC = clang++ -g -O0
CC_OBJ_FLAGS = -w -v -c
# Name of our executable and also the main run target
EXEC = ../bin/output.exe
# Here we get every cpp file in the source directory to make a list of source files
SOURCES = $(wildcard ../src/*.cpp)
# Here we have mapped all the cpp files to o files and now have a list of o files
TMP_OBJECTS = $(SOURCES:.cpp=.o)
OBJECTS = $(foreach obj,$(TMP_OBJECTS),$(subst src,obj,$(obj)))
INC = -I../lib/glfw-3.2.1/include
LINK = -L../lib/glfw-3.2.1/lib-vc2015 -lglfw3dll -lglfw3 -lopengl32
# compile list of o files into executable
# NOTE: when make is run without a target, the first target is chosen. This target
# should remain the first at all times
$(EXEC): $(OBJECTS)
$(CC) $(LINK) $(OBJECTS) -o $(EXEC)
# As each o file becomes a target, compile the associated cpp file into the o file
../obj/%.o: ../src/%.cpp
$(CC) $(CC_OBJ_FLAGS) $(INC) $< -o $#
# Remove the entire list of objects and the executable
clean:
rm -f $(EXEC) $(OBJECTS)
rebuild:
make -B
You'll notice that I've included the -g and -O0 flags which should output symbols and sure enough, I get a pdb file generated for output.exe (and also all the o files but I can clean that up later). When I go to debug the project in Visual Studio however, it says the symbols for the module are loaded but breakpoints aren't hitting which I think is pointing to the pdb not having references to the source. Here is the debug output in Visual Studio:
'output.exe' (Win32): Loaded 'W:\Scratch\Engine\bin\output.exe'. Symbols loaded.
Posts about Clang from 2016 and earlier mention that it doesn't generate PDB files yet and that thats a work in progress and sure enough the Clang compability site (https://clang.llvm.org/docs/MSVCCompatibility.html) mentions how debug info is a work in progress but that I should be able to generate CodeView info using /Z with 7 or i. I have tried passing both /Zi and /Z7 to clang and to the linker directly but clang complains about them and the linker ignores them with a warning. This documentation claims to be from Clang 6 that is, from what I can tell, not released yet and is experimental. However, using Clang 4.0 with -g flag, I am indeed able to generate pdb files.
Does anyone have any further information on this? Is there anything else I can provide to determine if I have set all this up correctly? Am I just missing a flag that would correctly provide the sources or am I missing a setting in visual studio to pick the sources? I tried setting sources manually in visual studio at the project and solution level to no effect. Should I look at the pdb file with a pdb viewer of some kind and see if the source paths are there?
Thanks in advance to any help.
The clang option equivalent to -Z7/-Zi is called -gcodeview (and has to be used in addition to -g). For MSVC-style command line options, you need to use the clang-cl compiler driver instead.
For the MSVC Version ( https://llvm.org/builds/) it works like in the following picture but to set clang on VS2017 up you need to install Microsoft's Platform Toolset V1.40 first:
VS2017 Clang debug
Project -> Properties -> C/C++ -> Commandline -> Options: "/Z7"
I have a project directory structure of:
Root
Source
Common
MyFolder
++ My 3 source files and header
When I am building my project it generates 3 to 4 shared libraries. Lib1 compiled using c++98 and others using c++11. Flags are added in CmakeList.txt which is at root.
I need my 3 source files to be compiled for Lib1 and for other Libs as as well. but here what happens is compiler is first compiling my source file for lib using c++11 and then it is trying to use same .o file for Lib1 as well. So for .o file which is generated using c++11 is throwing exception when same is used for c++98 compiled library.
So how do write this in CmakeList.txt such that compiler rather than trying to use same .o file will compile source file again for Lib1(c++98 compiled library)
Is there any flag I can specify so that it won't take precompiled .o file and will compile it again ?
Here flags are not being overridden for different shared libraries but actually same object file by make file is being used for different flags
This is sort of counter to how makefiles and cmake usually work.
Most users consider it really important that make performs an incremental build.
The usual way with makefiles is to do make clean which is supposed to remove any binaries and object files that were created.
However, sometimes I write cmake scripts that use globbing over the source directory to assemble the project. (That means, it says "just grab all *.cpp files in the /src folder and make an executable from them".) A makefile cannot check what files in a directory, so the make build will be broken after I add a new file, and make clean won't fix it -- the whole makefile will need to be regenerated by cmake.
Usually what I do is, I write a simple bash script, named rebuild.sh or something,
#!/bin/bash
rm -rf build
mkdir build
cd build
cmake ..
make -j3
./tests
And I put that in the root of my repository, and add /build to my .gitignore. I call that when I want to do a full rebuild -- it nukes the build directory, so its foolproof. When I want an incremental rebuild, I just type make again in the /build directory.
The rebuild.sh script can also serve a double purpose if you use travis-ci for continuous integration.
Most build system assume the compiled objects remain the same within the same pass. To avoid shooting your foot I would suggest telling the build system they were actually different objects, while still compiled from same source files.
I'm not familiar with cmake but this is how you do with make:
For example you have a a.cpp which you want to compile 2 times for different compiler options:
#include <stdio.h>
int main(int argc, char* argv[]) {
printf ("Hello %d\n", TOKEN);
return 0;
}
And the Makefile would looks like:
SRC := $(wildcard *.cpp)
OBJ_1 := $(patsubst %.cpp,%_1.o,$(SRC))
OBJ_2 := $(patsubst %.cpp,%_2.o,$(SRC))
all: pass1 pass2
pass1: $(OBJ_1)
gcc -o $# $(OBJ_1) -lstdc++
pass2: $(OBJ_2)
gcc -o $# $(OBJ_2) -lstdc++
%_1.o: %.cpp
gcc -DTOKEN=1 -c $< -o $#
%_2.o: %.cpp
gcc -DTOKEN=2 -c $< -o $#
clean:
rm -f $(OBJ_1) $(OBJ_2)
What I do here is generate two different list of object from the same source files, which you can even do the same for dependency(-MMD -MP flags).
I cannot find an option for the ARM GNU toolchain to compile multiple c files at the same time. I use make -j5 all the time when compiling using gcc. Helps speed up compile time dramatically. Be nice if ARM GNU had a similar option.
Here is my setup:
--Fedora 20
--Core i5
--Eclipse with ARM GNU plugin
--ARM GNU 4.8-2014-q1-update (from here: https://launchpad.net/gcc-arm-embedded)
--Target uP: STM32F205RB
I've tried to get CodeSourcery GCC working, unsuccessfully. ARM GNU seemed to work well after little setup. CodeSourcery GCC should have a -j option, as we cross compile all the time for embedded linux.
GCC is not multi-threaded. The -j<n> switch is specific to make build system, not the compiler. It tells make how many tasks it can run in parallel.
If you run make -j4 you can observe in your task manager/top/process list that it tries to run 4 instances of GCC compiling 4 independent *.c files at the same time.
To make use of -j command you must have a Makefile in your project that can benefit from it. It should have multiple independent targets, so that they can be launched in parallel.
If you are lost in the terminology, I advice you to look at make tutorial, such as this one:
http://mrbook.org/tutorials/make/
The usual strategy here is to have a separate target for every c or cpp file in our project. That way make can easily spawn multiple compiler processes for each compilation unit. Once all *.o files are generated, they are linked.
Let's see at this example snippet:
SRCS := main.c func.c other.c another_file.c ...
OBJS := $(SRCS:.c=.o)
objects: $(OBJS)
%.o: %.c
gcc -o $(#) -c $(<)
We pass a list of c files, change them to corresponding o file using suffix substitution and treat the list of *.o files as targets. Now the make can compile each c file in parallel.
In contrast, if we do something like this:
SRCS := main.c func.c other.c another_file.c ...
all:
gcc $(SRCS) -o a.out
...we won't benefit from -j switch at all, because there is only one target.
I have a Makefile for a c++ Linux project:
MODE ?= dbg
DIR = ../../../../../somdir/$(MODE)
SRC_FILES = a.cpp b.cpp
H_FILES = a.h
LDFLAGS += -L$(DIR)/lib/linux '-Wl,-R$$ORIGIN'
CPPFLAGS = -I$(DIR)/include
LIBRARIES = -lsomeso
ifeq (rel, $(MODE))
CFLAGS = -Wall -g -DNDEBUG
else
CFLAGS = -Wall -ansi -pedantic -Wconversion -g -DDEBUG -D_DEBUG
endif
sample: $(SRC_FILES) $(H_FILES) Makefile
g++ $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $(LIBRARIES) $(SRC_FILES) -o sample
when i run 'make' it builds the project, with no errors.
but when i run the project it complains that:
error while loading shared libraries: libsomeso.so: cannot open shared object file: No such file or directory
The path that i give in DIR goes to the folder where the shared object is held(relatively to where the makefile is placed), and if it was the wrong path why didn't it complain during the make process.
does someone know what am i missing?
Thanks
Matt
LDFLAGS += -L$(DIR)/lib/linux '-Wl,-R$$ORIGIN'
The above should be:
LDFLAGS += -L$(DIR)/lib/linux -Wl,-R$(DIR)/lib/linux '-Wl,-R$$ORIGIN'
That is, for each non-standard dynamic library location -L a corresponding -Wl,-R should be specified. $ORIGIN is needed to locate dynamic libraries relative to the executable, not sure if you need it here.
People often advise using LD_LIBRARY_PATH. This is a bad advice, in my opinion, because it makes deployment more complicated.
When you run your application, location of libsomeso.so should be in LD_LIBRARY_PATH environment variable. Try running program like this:
LD_LIBRARY_PATH="path_to_libsomeso_so:$LD_LIBRARY_PATH" myprogram
Here path_to_libsomeso_so is full path to a directory where libsomeso.so is located, and myprogram is your program executable. Note, that you should specify path to a directory containing libsomeso.so, not to libsomeso.so file itself.
The trouble is not during compilation time. Everything goes fine. There's a problem at runtime.
Indeed, your program has been linked with a shared object library. Therefore, at runtime, it need to load this shared object file. During compilation, you instructs the compiler where this file was with the -L flag.
For the runtime, you have to set the LD_LIBRARY_PATH environment variable to point to the directory where your libsomeso.so file resides.
Alternatively, you can place this file in one of the standard directory where these shared object files are searched for: /usr/local/lib, /usr/lib, /lib, but this should be what you'll do for the final distributed version of your library.
As told from Maxim Egorushkin, LD_LIBRARY_PATH is a bad choice. Meanwhile, using -L$(your lib path) -l$(your lib name) gcc/g++ argument to link shared library isn't a good choice. Because, after build the exe, you should told exe where the shared library directory is. By default, executable file only search shared library at /usr/lib or /usr/local/lib. Although, you have told makefile where the shared library is when build the executable file. But when you execute this exe file, they are different.
However, link static library don't have such problem.
So, the best way to deal with your problem is change the way you link your custom shared file. Like this:
DYNAMIC_LIB_DIR = ../lib (your lib path ,this is a example)
OBJLIBS = xxx.so (your lib name)
gcc/g++ -o exe_name sourcefile/object_file $(DYNAMIC_LIB_DIR)/$(OBJLIBS)
Refresh that dynamic library cache!
After adding a custom, non-standard library to /usr/local/lib, first check that /usr/local/lib is listed under /etc/ld.so.conf.d/libc.conf.
Then, finish off with a dynamic link library cache refresh:
$ sudo ldconfig