Loops in Makefile - refactoring

I have a lot of assignments where I have to continually update a Makefile as I add more subsequently numbered C programs. Is there a way to do this with a loop which iterates over the values 1.1, 1.2, 1.3, etc.?
all: 1.1 1.2 1.3 1.4 1.5 1.6 1.7. 1.8 1.9
1.1: 1.1.o
gcc -o 1.1 $(FLAGS) 1.1.o
1.1.o: 1.1.c
gcc -c $(FLAGS) 1.1.c
1.2: 1.2.o
gcc -o 1.2 $(FLAGS) 1.2.o
1.2.o: 1.2.c
gcc -c $(FLAGS) 1.2.c
1.3: 1.3.o
gcc -o 1.3 $(FLAGS) 1.3.o
1.3.o: 1.3.c
gcc -c $(FLAGS) 1.3.c
1.4: 1.4.o
gcc -o 1.4 $(FLAGS) 1.4.o
1.4.o: 1.4.c
gcc -c $(FLAGS) 1.4.c
1.5: 1.5.o
gcc -o 1.5 $(FLAGS) 1.5.o
1.5.o: 1.5.c
gcc -c $(FLAGS) 1.5.c
1.6: 1.6.o
gcc -o 1.6 $(FLAGS) 1.6.o
1.6.o: 1.6.c
gcc -c $(FLAGS) 1.6.c
1.7: 1.7.o
gcc -o 1.7 $(FLAGS) 1.7.o
1.7.o: 1.7.c
gcc -c $(FLAGS) 1.7.c
1.8: 1.8.o
gcc -o 1.8 $(FLAGS) 1.8.o
1.8.o: 1.8.c
gcc -c $(FLAGS) 1.8.c
1.9: 1.9.o
gcc -o 1.9 $(FLAGS) 1.9.o
1.9.o: 1.9.c
gcc -c $(FLAGS) 1.9.c
clean:
rm -f *.o
rm -f 1.1 1.2 1.3 1.4 1.5 1.6 1.7. 1.8 1.9

You want a suffix rule, not a loop.

Try a rule like:
OBJECTS = 1.1.o 1.2.o 1.3.o
all: $(OBJECTS)
%.o: %.c
gcc $(FLAGS) %< -o $*
Then you just need to add the extra object to the list and all is sweet.
Implicit rules help you really minimise the copy/paste cycle in your makefile.
http://www.gnu.org/software/autoconf/manual/make/Implicit-Rules.html#Implicit-Rules

Yes; you can use shell commands in a Makefile, and make itself may offer the looping you need. There are oodles of good examples all over the web; assuming from your use of gcc that you're also using GNU make, try here:
http://www.gnu.org/software/make/manual/make.html#Foreach-Function

Related

compiler error gcc-8: error: unrecognized command line option '-no-pie'

I am trying to compile using this makefile but got this error. I can compile using school's linux computer with gcc 6.3. I tried using my MacOS mojave using a few different version of gcc from homebrew (gcc-8, gcc-4.9, gcc-6) but I get this error consistently.
CC = gcc-8
OPT = -O3 -g
LIBS = -lz -lcvp -lz
FLAGS = -std=c++11 -L. $(LIBS) $(OPT) -no-pie
OBJ = myprogram.o
DEPS = cvp.h myprogram.h
all: cvp
cvp: $(OBJ)
$(CC) $(FLAGS) -o $# $^
%.o: %.cc $(DEPS)
$(CC) $(FLAGS) -c -o $# $<
.PHONY: clean
clean:
rm -f *.o cvp
Going off information found here: https://github.com/xd009642/tarpaulin/issues/7#issuecomment-317180523
The problem may very well be related to how gcc is built: "Builds of gcc that don't have the --enable-default-pie flag set at compile time because they are too old or have the --disable-default-pie flag just don't have the -no-pie linker flag"
You might need to update or recompile gcc for that environment to be able to use that flag if important to you.

How to build static library .a for ARM using cross compiler?

I was trying to compile statically cpp-netlib and rpclib for ARM device.(Same as ZEDboard)
Everything i did is changed the compiler and system settings in CMakeLists.txt file.
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_SYSROOT /home/a/buildroot-2018.05/output/host/arm-buildroot-linux-uclibcgnueabihf/sysroot/)
set(tools /home/a/buildroot-2018.05/output/host/bin/)
set(CMAKE_C_COMPILER ${tools}arm-buildroot-linux-uclibcgnueabihf-gcc)
set(CMAKE_CXX_COMPILER ${tools}arm-buildroot-linux-uclibcgnueabihf-g++)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
After Makefile is created by cmake i ran make and no output has been produced. As i understand build directories should appear.
For the rpclib things went better. It has compiled the librpc.a file but unftunately its not linking to my program.
arm-buildroot-linux-uclibcgnueabihf-g++ -I/home/a/rpclib/include/ -Xlinker -static /home/a/rpclib/librpc.a main.cpp
produces this output:
/home/a/buildroot-2018.05/output/host/lib/gcc/arm-buildroot-linux-uclibcgnueabihf/6.4.0/../../../../arm-buildroot-linux-uclibcgnueabihf/bin/ld: cannot find -lgcc_s
/home/a/buildroot-2018.05/output/host/lib/gcc/arm-buildroot-linux-uclibcgnueabihf/6.4.0/../../../../arm-buildroot-linux-uclibcgnueabihf/bin/ld: cannot find -lgcc_s
collect2: error: ld returned 1 exit status
but there is gcc_s in the sysroot directory.
~/buildroot-2018.05/output/host/arm-buildroot-linux-uclibcgnueabihf$ find ./ -name *gcc_s*
./sysroot/lib/libgcc_s.so
./sysroot/lib/libgcc_s.so.1
./sysroot/usr/include/boost/asio/detail/gcc_sync_fenced_block.hpp
./sysroot/usr/include/boost/atomic/detail/caps_gcc_sync.hpp
./sysroot/usr/include/boost/atomic/detail/ops_gcc_sync.hpp
./sysroot/usr/include/boost/atomic/detail/ops_gcc_sparc.hpp
./sysroot/usr/include/boost/atomic/detail/caps_gcc_sparc.hpp
./sysroot/usr/include/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp
./lib/libgcc_s.so
./lib/libgcc_s.so.1
I guess i am missing something important about cross-compilation.
So basically i have 3 questions:
Can you suggest some resources about cross-compilation for embdedd devices?
How to compile cpp-netlib?
How to link already compiled librpc?
Actually buildroot supports building static libraries.
Steps to build a custom library using buildroot:
Create a folder inside buildroot/package folder with the name of target library.
e.g. my path looks like this /home/a/buildroot-2018.05/package/rpclib
Create Config.in file in target library dir with the needed parameters which can be checked in buildroot manual or better
Create [package-name].mk
Then add entry in /buildroot/package/Config.in
Then package can be marked for installation in menuconfig/target pacckages
My Config.in file for rpclib
config BR2_PACKAGE_RPCLIB
bool "rpclib"
depends on BR2_INSTALL_LIBSTDCPP
depends on BR2_USE_WCHAR
help
rpclib is a modern C++ msgpack-RPC server and client library
http://rpclib.net
My rpclib.mk file
RPCLIB_VERSION = v2.2.1
RPCLIB_SITE = $(call github,rpclib,rpclib,$(RPCLIB_VERSION))
RPCLIB_INSTALL_STAGING = YES
RPCLIB_INSTALL_TARGET = NO
RPCLIB_CONF_OPTS = -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF
$(eval $(cmake-package))
And entry in Config.in in the buildroot/packages dir
source "package/rpclib/Config.in"
After executing make i received
./output/host/arm-buildroot-linux-uclibcgnueabihf/sysroot/usr/lib/librpc.a
Working in my little beatle (https://gitlab.com/melviso1/beatle) I have a custom makefile for building rpclib without using cmake stuff (I apologize but I really hate cmake and similar tools). Maybe that can help.
Put it in the root of rpclib for building, clean or install. Please review tabs in the following script, because my pasting here can make some loses.
I used this to compile rpclib inside arm. For cross-compiling you could edit and change build tools.
CXXFLAGS=-std=c++0x -O3 -pthread -DASIO_STANDALONE -DRPCLIB_ASIO=clmdep_asio -DRPCLIB_FMT=clmdep_fmt -DRPCLIB_MSGPACK=clmdep_msgpack -Wall
INCLUDE=-Iinclude -I./dependencies/include
OBJS=obj/format.o obj/posix.o obj/client.o obj/client_error.o obj/response.o obj/server_session.o obj/dispatcher.o obj/optional.o obj/rpc_error.o obj/server.o obj/this_handler.o obj/this_server.o obj/this_session.o
all: obj librpc.a
obj:
mkdir -p obj
librpc.a: $(OBJS)
ar -r -s librpc.a $(OBJS)
obj/format.o: dependencies/src/format.cc
g++ $(CXXFLAGS) $(INCLUDE) -c ./dependencies/src/format.cc -o obj/format.o
obj/posix.o: dependencies/src/posix.cc
g++ $(CXXFLAGS) $(INCLUDE) -c ./dependencies/src/posix.cc -o obj/posix.o
obj/client.o: lib/rpc/client.cc
g++ $(CXXFLAGS) $(INCLUDE) -c ./lib/rpc/client.cc -o obj/client.o
obj/client_error.o: lib/rpc/detail/client_error.cc
g++ $(CXXFLAGS) $(INCLUDE) -c ./lib/rpc/detail/client_error.cc -o obj/client_error.o
obj/response.o: lib/rpc/detail/response.cc
g++ $(CXXFLAGS) $(INCLUDE) -c ./lib/rpc/detail/response.cc -o obj/response.o
obj/server_session.o: lib/rpc/detail/server_session.cc
g++ $(CXXFLAGS) $(INCLUDE) -c ./lib/rpc/detail/server_session.cc -o obj/server_session.o
obj/dispatcher.o: lib/rpc/dispatcher.cc
g++ $(CXXFLAGS) $(INCLUDE) -c ./lib/rpc/dispatcher.cc -o obj/dispatcher.o
obj/optional.o: lib/rpc/nonstd/optional.cc
g++ $(CXXFLAGS) $(INCLUDE) -c $< -o $#
obj/rpc_error.o: lib/rpc/rpc_error.cc
g++ $(CXXFLAGS) $(INCLUDE) -c $< -o $#
obj/server.o: lib/rpc/server.cc
g++ $(CXXFLAGS) $(INCLUDE) -c $< -o $#
obj/this_handler.o: ./lib/rpc/this_handler.cc
g++ $(CXXFLAGS) $(INCLUDE) -c $< -o $#
obj/this_server.o: lib/rpc/this_server.cc
g++ $(CXXFLAGS) $(INCLUDE) -c $< -o $#
obj/this_session.o: ./lib/rpc/this_session.cc
g++ $(CXXFLAGS) $(INCLUDE) -c $< -o $#
install:
cp -rf include/rpc /usr/local/include/
cp librpc.a /usr/local/lib/
uninstall:
rm -rf /usr/local/include/rpc
rm /usr/local/lib/librpc.a
clean:
rm -f librpc.a
rm -f obj/*
.PHONY: obj clean install uninstall`

Makefile not generating neither object file not binary file

I tried the following make script but it is neither creating any object file not any binary file what is the mistake I have done?
SRC=src
INC=inc
OBJ=obj
BIN=bin
INCS=-I$(INC)
FLAGS=-g -Wall
CC=/usr/sfw/bin/gcc
SRCS=$(wildcard $(SRC)/*.cpp)
OBJS=$(SRCS:$(SRC)/%.cpp=$(OBJ)/%.o)
$(BIN)/out.exe: $(OBJS)
$(CC) $(INCS) $(LIBS) $(FLAGS) $(OBJS) -o $(BIN)/out.exe
$(OBJS) : $(SRCS)
$(CC) $(INCS) $(LIBS) $(FLAGS) -c $<
clean:
rm -f obj/*.o bin/ussd
Below I have given the list of make tools available in my system and their version
/bin - dmake - Sun Distributed Make 7.7
/usr/bin - dmake - Sun Distributed Make 7.7
/usr/ccs/bin - make - Unknow version
/usr/sfw/bin - gmake - GNU Make 3.80
/usr/xpg4/bin - Unknow version
/usr/local/bin - make - GNU Make version 3.79.1
I think you have problem with make targets for the objects files.
I don't have access to a Solaris machine at the moment, but this worked at my Linux machine.
SRC=src
INC=inc
OBJ=obj
BIN=bin
INCS=-I$(INC)
FLAGS=-g -Wall
CC=/usr/sfw/bin/gcc
SRCS=$(wildcard $(SRC)/*.cpp)
OBJS=$(SRCS:$(SRC)/%.cpp=$(OBJ)/%.o)
$(BIN)/out.exe: $(OBJS)
$(CC) $(INCS) $(LIBS) $(FLAGS) $(OBJS) -o $(BIN)/out.exe
$(OBJ)/%.o: $(SRC)/%.cpp
$(CC) $(INCS) $(LIBS) $(FLAGS) -c $< -o $#
clean:
rm -f obj/*.o bin/ussd

Fortran makefile recompiling every time

I'm trying to write a Fortran makefile: there is a single "main" file, but I've placed my modules in separate .f90 files. The makefile attached works, however even if I make no changes it forces a recompile. I'm running x86-64 Linux with gfortan 4.7.2 and GNU Make 3.81.
FC = gfortran
FCFLAGS += -ffree-line-length-none -finit-local-zero
#FCFLAGS += -fbounds-check -ffpe-trap=invalid
all: new
new: ALE.o curvilinear.o new.o
$(FC) $(FCFLAGS) -o new new.o ALE.o curvilinear.o
new.o: ALE.mod curvilinear.mod new.f90
$(FC) $(FCFLAGS) -c new.f90
ALE.o: ALE.f90
$(FC) $(FCFLAGS) -c ALE.f90
ALE.mod: ALE.o ALE.f90
curvilinear.o: ALE.o curvilinear.f90
$(FC) $(FCFLAGS) -c curvilinear.f90
curvilinear.mod: curvilinear.o curvilinear.f90
clean:
rm ale.mod curvilinear.mod ALE.o curvilinear.o new new.o
Output:
$ make clean
rm ale.mod curvilinear.mod ALE.o curvilinear.o new new.o
$ make
gfortran -ffree-line-length-none -finit-local-zero -c ALE.f90
gfortran -ffree-line-length-none -finit-local-zero -c curvilinear.f90
gfortran -ffree-line-length-none -finit-local-zero -c new.f90
gfortran -ffree-line-length-none -finit-local-zero -o new new.o ALE.o curvilinear.o
$ make
gfortran -ffree-line-length-none -finit-local-zero -c new.f90
gfortran -ffree-line-length-none -finit-local-zero -o new new.o ALE.o curvilinear.o
Why is "new" being recompiled when no changes have been made?
Didier's answer probably already solves your question, but I would like to add a nice and clean suggestion for Fortran makefiles (example for one main program):
# Main program
all: program
program: mod1.o mod2.o mod3.o
# Fortran module dependencies
mod1.o: mod2.o mod3.o
# Binary/object rules
%: %.o
$(FC) $(FCFLAGS) -o $# $^ $(LDFLAGS)
%.o: %.f90
$(FC) $(FCFLAGS) -c $<
As per your Makefile, new.o depends on ALE.mod and curvilinear.mod.
I guess these file do never exist, as they have dependencies, but no rule to make them.
Indeed, When trying to build new, make does not found the *.mod files. Hence, make runs the rules to make them, but there's no rule. However, make think that it has build them, and continues the build operation, thinking that these *.mod dependencies have been just rebuild, and are thus recent, triggering the rebuild of new.
To fix this, you should replace the line
new.o: ALE.mod curvilinear.mod new.f90
by
new.o: new.f90

How should a very simple Makefile look like for Cuda compiling under linux

I want to compile a very basic hello world level Cuda program under Linux. I have three files:
the kernel: helloWorld.cu
main method: helloWorld.cpp
common header: helloWorld.h
Could you write me a simple Makefile to compile this with nvcc and g++?
Thanks,
Gabor
I've never heard of Cuda before, but from the online documentation it looks as if X.cu is supposed to be compiled into X.o, so having helloWorld.cu and helloWorld.cpp is not a good idea. With your permission I'll rename the "kernel" helloKernel.cu, then this should work:
NVCC = nvcc
helloWorld.o: helloWorld.cpp helloWorld.h
$(NVCC) -c %&lt -o $#
helloKernel.o: helloKernel.cu
$(NVCC) -c %&lt -o $#
helloWorld: helloWorld.o helloKernel.o
$(NVCC) %^ -o $#
(Note that those leading spaces are tabs.)
If that works, try a slicker version:
NVCC = nvcc
helloWorld.o: %.o : %.cpp %.h
helloKernel.o: %.o : %.cu
%.o:
$(NVCC) -c %&lt -o $#
helloWorld: helloWorld.o helloKernel.o
$(NVCC) %^ -o $#
Just in case, here's my variant. I use it to compile CUDA projects on Mac, but I think it will suit Linux too. It requires CUDA SDK.
BINDIR = ./ # places compiled binary in current directory
EXECUTABLE := helloWorld
CCFILES := helloWorld.cpp
CUFILES := helloWorld.cu
# an ugly part - setting rootdir for CUDA SDK makefile
# look for common.mk - I don't know where SDK installs it on Linux -
# and change ROOTDIR accordingly
ROOTDIR := /Developer/GPU\ Computing/C/common
include $(ROOTDIR)/../common/common.mk
My version, verbose but transparent:
myapp: myapp.o
g++ -fPIC -o $# $< -L /usr/local/cuda/lib -lcudart
myapp.o: myapp.cu
/usr/local/cuda/bin/nvcc --compiler-options -fno-strict-aliasing \
-I/usr/local/cuda/include \
-DUNIX -O2 -o $# -c $<
matrixMul: matrixMul.o
g++ -fPIC -o $# $< -L /usr/local/cuda/lib -lcudart
# It MUST be named .cu or nvcc compiles as regular C !!! (no __global__)
matrixMul.o: matrixMul.cu
/usr/local/cuda/bin/nvcc --compiler-options -fno-strict-aliasing \
-I/usr/local/cuda/include \
-DUNIX -O2 -o $# -c $<
Here is an example what my current project looks like. As you can see there is a few OpenGL libraries
ce : cudaExample.c cudaExample.h
cp cudaExample.c cudaExample.cu
/usr/local/cuda/bin/nvcc -arch=sm_20 -o ce -lglut -lGL -lGLU -lXext -lXmu -lX11 -lm cudaExample.cu
then run make ce
and ./ce

Resources