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.
Related
I would like to compile and run my program in two different environments. The libraries in both environments are installed on slightly different places, resulting in different makefile-lines:
In makefile A:
CXXFLAGS=-I$(DIR) -flto -fopenmp -O3 -g -march=native -std=gnu++17 -c -I/opt/interp2d/include -std=c++17 -I/opt/splinter/include -I/usr/include/eigen3
In makefile B:
CXXFLAGS=-I$(DIR) -nostindc++ -I~/local_opt/eigen/include/eigen3/ -I~/local_opt/boost/include -I~/local_opt/armadillo/include -flto -fopenmp -O3 -g -march=native -std=gnu++17 -c -I~/local_opt/interp2d/include -std=c++17 -I~/local_opt/splinterp/include -I/usr/include/eigen3
My problem now is that I am developing the program on the first machine, using makefile A, but also deploying it on the second machine. The deployment is done using git.
Every time I do a git pull on the second machine, I have to fix all the paths in the makefile in order to compile the program properly. Nevertheless I still would like to include the makefile in the git repository in order to keep both makefiles at the same level regarding compiling flags and linked libraries.
Thus, is there an easier way to still sync the makefile via git, while using different paths for the libraries and includes?
I think you could solve your problem by conditionally setting the variable CXXFLAGS in a common file (e.g.: config.mk) and by including that file in your makefiles.
The value used for setting the CXXFLAGS variable could, for example, depend on the value of the environment variable HOST:
ifeq ($(HOST),A)
CXXFLAGS = ... # for machine A
else # B
CXXFLAGS = ... # for machine B
endif
Then, include this config.mk makefile in both makefileA and makefileB:
include config.mk
I like this answer, however, I thought I'd mention this for completeness: If you have a lot of different hosts you can do something to the effect of:
include HostConfig_$(HOST).mk
And then create HostConfig_A.mk and HostConfig_B.mk which set host specific flags (Be it directories, etc). This is useful if you are managing a large project with lots of different host-specific variables.
As well, (for smaller projects), you could do something to the effect of:
CXX_INCLUDES_A = ...
CXX_INCLUDES_B = ...
CXX_FLAGS := -I$(DIR) -flto -fopenmp -O3 -g -march=native -std=gnu++17
CXX_FLAGS += $(CXX_INCLUDES_$(HOST))
The traditional answer to this problem is a configure script (see automake, autoconf for widely used framework). After checking out the source you run ./configure --with-eigen=~/local_opt/eigen/include/eigen3/ and it will adjust your Makefiles accordingly (usually generates Makefile from Makefile.in and only Makefile.in is in git).
Note: Properly done you only need to run configure on the first checkout, not on updates. make can generate Makefile again automatially as needed.
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.
I'm setting up Autotools for a large scientific code written primarily in C++, but also some CUDA. I've found an example for compiling & linking CUDA code to C code within Autotools, but I cannot duplicate that success with C++ code. I've heard that this is much easier with CMake, but we're committed to Autotools, unfortunately.
In our old hand-written Makefile, we simply use a make rule to compile 'cuda_kernels.cu' into 'cuda_kernels.o' using nvcc, and add cuda_kernels.o to the list of objects to be compiled into the final binary. Nice, simple, and it works.
The basic strategy with Autotools, on the other hand, seems to be to use Libtool to compile the .cu files into a 'libcudafiles.la', and then link the rest of the code against that library. However, this fails upon linking, with a whole bunch of "undefined reference to ..." statements coming from the linker. This seems like it might be a name-mangling issue with g++ vs. the nvcc compiler (which would explain why it works with C code), but I'm not sure what to do at this point.
All .cpp and .cu files are in the top/src directory, and all the compilation is done in the top/obj directory. Here's the relevant details of obj/Makefile.am:
cuda_kernals.cu.o:
$(NVCC) -gencode=arch=compute_20,code=sm_20 -o $# -c $<
libcudafiles_la_LINK= $(LIBTOOL) --mode=link $(CXX) -o $# $(CUDA_LDFLAGS) $(CUDA_LIBS)
noinst_LTLIBRARIES = libcudafiles.la
libcudafiles_la_SOURCES = ../src/cuda_kernels.cu
___bin_main_LDADD += libcudafiles.la
___bin_main_LDFLAGS += -static
For reference, the example which I managed to get working on our GPU cluster is available at clusterchimps.org.
Any help is appreciated!
libtool in conjunction with automake currently generates foo.lo (libtool-object metadata) files, the non-PIC (static) object foo.o, and the PIC object .libs/foo.o.
For consistent .lo files, I'd use a rule like:
.cu.lo:
$(LIBTOOL) --tag=CC --mode=compile $(NVCC) [options...] -c $<
I have no idea if, or how, -PIC flags are handled by nvcc. More options here. I don't know what calls you are making from the program, but are you forward declaring CUDA code with C linkage? e.g.,
extern "C" void cudamain (....);
It seems others have run up against the libtool problem. At worst, you might need a 'script' solution that mimics the .lo syntax and file locations, as described on the clusterchimps site.
Gooday everyone
I'm fairly new to ubuntu C programing although I'm
rather experienced in C programing in windows.
I have recently come accross a number of codes written
in 2005 which I'm interested in learning how they work.
Those codes needs BOOST library to compile, however they won't
compile on the newest BOOST version present on my ubuntu 12.04.
I set the gcc compiler on lenient so that it ignores all those error
messages. The code did compile and ran afterwards.
However, when I used GDB debugger to watch how the program flows
I noticed that there are likely errors in the way the program runs
due to using a different BOOST version rather than it's original. Hence
I like to install the BOOST version corresponding to the code I downloaded.
To do that, I installed Ubuntu 5.04 and BOOST 1.33.0 which seemed to have been created in late 2005. I downloaded it
but I didnt found any detailed instruction on how to install it.
Only vague description on using BOOST jam, I played around with BOOST
jam for quite awhile without success.
And this old BOOST does not have installation commands like
"sudo apt-install boost-dev" style option
Thus I like to ask if anyone can give a easy to understand step by step instruction
on how to install the BOOST library downloaded from the above link.
like.....
step1: download boost jam from boost webpage
step2: unpack it in home/boost/ then type make configure
...and so on...
Big thanks for any useful info.
New Contents appended here
in response to the comments given
Hi, I went through the info given by your link and
managed to run the boost library examples given by your link.
That is, I can compile a single cpp file with the command
g++ -I boost_1_33_0 test.cpp -o test
(I'm keeping the boost library and the cpp file to be compiled in the
same folder)
However, the program package I'm interested in is build with make (not cmake).
I have some experience writting cmake files but not make files.
And I do not see any link to boost library command in the make file of the
program package. The readme file only has one sentence that says I
need to have boost installed without explaining what that meant.
I assume it means that either I have to build and do makeinstall the boost or
I could add some lines in the makefile for a link. I thought
maybe you can quickly point out whats missing in the makefile.
The readme file:
To compile, go into the moses directory and do 'make'. You'll need the
latest boost libraries. If compilation still fails for weird reasons,
you could try g++ with the -fpermissive (newer versions reject lots of
code that was ok with older ones). If you are going to be making
changes and recompiling frequently you'll probably want to disable -O3
in the makefile (I use templates liberally, so -O3 really speeds up
the code, but really slows down compilation).
And the makefile:
CC = g++
PROJ_NAME = moses
LINK_FLAGS = -Wall -Iutils/ -Itrees/ -Irewrite -I./ -Imodeling/ -Ifitness/ \
-Ialignment/ -Isim/ -Ilocal/ -O3
COMP_FLAGS = -Wall -Wno-sign-compare -Iutils/ -Itrees/ -Irewrite -I./ \
-Imodeling/ -Ifitness/ -Ialignment/ -Isim/ -Ilocal/ -O3
src := $(wildcard *.cc) $(wildcard utils/*.cc) $(wildcard trees/*.cc) $(wildcard modeling/*.cc) $(wildcard fitness/*.cc) $(wildcard alignment/*.cc) $(wildcard main/*.cc) $(wildcard rewrite/*.cc) $(wildcard sim/*.cc) $(wildcard local/*.cc)
obj := $(patsubst %.cc,%.o,$(src))
all: $(PROJ_NAME)
%.o: %.cc
$(CC) $(COMP_FLAGS) $< -c -o $#
$(PROJ_NAME): $(obj)
$(CC) $(LINK_FLAGS) $^ -o $(PROJ_NAME)
run:
$(PROJ_NAME)
clean:
find -regex ".*~\|.*\.o"|xargs rm -f
rm -f $(PROJ_NAME)
rm -f $(PROJ_NAME).exe*
depend:
makedepend -Y -- $(COMP_FLAGS) -- $(src)
utils/exceptions.o: utils/exceptions.h utils/utils.h
utils/io_util.o: utils/io_util.h utils/tree.h utils/basic_types.h
# ......lots more lines like that.........
I have an old instruction flying around here for Boost 1.34.1, which reads like this (project-specific stuff cut away):
unpack boost sources
cd into tools/jam/src
run ./build.sh to build bjam
cd into the main source directory
tools/jam/src/bin.linux/bjam threading=multi --layout=system --toolset=gcc --without-python variant=release --prefix=/usr/local install
The --without-python was necessary as the target system didn't have Python installed, which caused the build to fail messily.
Obviously you can / need to fiddle with the individual settings (like threading support, release vs. debug variant) to suit your needs, but it should be a good starting point.
If you need ICU support (for Boost.Regex and Boost.Locale), it gets more complicated...
Note that the build process has changed over the years; you shouldn't use the same procedure for more up-to-date boost versions. It's just what I used back then.
Edit:
As for the second part of your question, the Makefile doesn't need to refer to Boost explicitly if boost is installed in the standard system directories.
You do not have to state -I /usr/include for compilation as that is searched automatically; the same goes for -L /usr/lib during linkage.
The fact that the author of the Makefile copied the compiler flags into the linker flags verbatim doesn't really help intuitivity either... ;-)
If you have Boost in a custom directory (either the headers only, or by stating a custom directory in the --prefix option of my build instructions), you need to make the following modifications (look for "boost"):
LINK_FLAGS = -Wall -Iutils/ -Itrees/ -Irewrite -I./ -Imodeling/ -Ifitness/ \
-Ialignment/ -Isim/ -Ilocal/ -L /path/to/boost/libs -O3
COMP_FLAGS = -Wall -Wno-sign-compare -Iutils/ -Itrees/ -Irewrite -I./ \
-Imodeling/ -Ifitness/ -Ialignment/ -Isim/ -Ilocal/ \
-I /path/to/boost/includes -O3
That should do the trick. As the Makefile does not link any of the Boost binaries (e.g. -l boost_program_options or somesuch), it seems that it makes use of the Boost headers only, which would make the -L /path/to/boost/libs part (and, actually, the whole compilation step detailed above) superfluous. You should be able to get away with simply unpacking the sources and giving the header directory as additional include directory using -I /path/to/boost/headers.
I am running Windows 7 with gcc/g++ under Cygwin. What would be the Makefile format (and extension, I think it's .mk?) for compiling a set of .cpp (C++ source) and .h (header) files into a static library (.dll). Say I have a variable set of files:
file1.cpp
file1.h
file2.cpp
file2.h
file3.cpp
file3.h
....
What would be the makefile format (and extension) for compiling these into a static library? (I'm very new to makefiles) What would be the fastest way to do this?
The extension would be none at all, and the file is called Makefile (or makefile) if you want GNU Make to find it automatically.
GNU Make, at least, lets you rely on certain automatic variables that alone give you control over much of the building process with C/C++ files as input. These variables include CC, CPP, CFLAGS, CPPFLAGS, CXX, CXXFLAGS, and LDFLAGS. These control the switches to the C/C++ preprocessor, compiler, and the linker (the program that in the end assembles your program) that make will use.
GNU Make also includes a lot of implicit rules designed to enable it automatically build programs from C/C++ source code, so you don't [always] have to write your own rules.
For instance, even without a makefile, if you try to run make foobar, GNU Make will attempt to first build foobar.o from foobar.c or foobar.cpp if it finds either, by invoking appropriate compiler, and then will attempt to build foobar by assembling (incl. linking) its parts from system libraries and foobar.o. In short, GNU Make knows how to build the foobar program even without a makefile being present -- thanks to implicit rules. You can see these rules by invoking make with the -p switch.
Some people like to rely on GNU Make's implicit rule database to have lean and short makefiles where only that specific to their project is specified, while some people may go as far as to disable the entire implicit rule database (using the -r switch) and have full control of the building process by specifying everything in their makefile(s). I won't comment on superiority of either strategy, rest assured both do work to some degree.
There are a lot of options you can set when building a dll, but here's a basic command that you could use if you were doing it from the command line:
gcc -shared -o mydll.dll file1.o file2.o file3.o
And here's a makefile (typically called Makefile) that will handle the whole build process:
# You will have to modify this line to list the actual files you use.
# You could set it to use all the "fileN" files that you have,
# but that's dangerous for a beginner.
FILES = file1 file2 file3
OBJECTS = $(addsuffix .o,$(FILES)) # This is "file1.o file2.o..."
# This is the rule it uses to assemble file1.o, file2.o... into mydll.dll
mydll.dll: $(OBJECTS)
gcc -shared $^ -o $# # The whitespace at the beginning of this line is a TAB.
# This is the rule it uses to compile fileN.cpp and fileN.h into fileN.o
$(OBJECTS): %.o : %.cpp %.h
g++ -c $< -o $# # Again, a TAB at the beginning.
Now to build mydll.dll, just type "make".
A couple of notes. If you just type "make" without specifying the makefile or the target (the thing to be built), Make will try to use the default makefile ("GNUMakefile", "makefile" or "Makefile") and the default target (the first one in the makefile, in this case mydll.dll).