I created an app on my Windows machine and now I want to install it on my Linux machine. It has several headers and source files so I thought it is best to upload it on Github. I did that and I also created a Makefile, but I get a lot of errors when I try to install it directly from the folder.
Given the fact that it is for personal use only, is there a way to manually compile each file and then run it as a whole?
Makefile:
.PHONY: all debug profile install uninstall clean
all: $(PROG)
$(PROG): $(FILES)
$(CC) $(CCFLAGS) -o $(PROG) $(FILES) $(LIBS)
debug: $(FILES)
$(CC) $(DEBUGFLAGS) -o $(PROG) $(FILES) $(LIBS)
profile: $(FILES)
$(CC) $(CCFLAGS) -pg -o $(PROG) $(FILES) $(LIBS)
install: $(PROG)
cp -f $(PROG) /usr/sbin/
cp -f $(PROG).1 /usr/man/man1/ || cp -f $(PROG).1 /usr/local/man/man1/
uninstall:
rm -f /usr/sbin/$(PROG)
rm -f /usr/man/man1/$(PROG).1 || rm -f /usr/local/man/man1/$(PROG).1
clean:
rm -f $(PROG)
While your basic approach is fine, you are missing a couple of details, and you are breaking a few conventions that were established for a reason.
Details:
Your definitions for $(PROG), $(FILES) and $(LIBS) aren't included.
You try to copy a file to a directory without ensuring its existence. The install utility is often used instead of cp to handle stuff like this.
Conventions:
You don't appear to use root privileges only when necessary. Compile as a regular user; only run make install as root, e.g. using sudo; or better, avoid even that.
You're trying to place files into /usr/bin/ and /usr/man, where the package management system installs files, so you risk confusing it. Don't. If you need to make third-party software, such as your own, available to all users on the system, just install to /usr/local/ or /opt, which exist for this purpose. Adjust $PATH and $MANPATH accordingly. If it's just for your own personal use, you can install to directories under $HOME.
Make the top level target directory to install to a variable in your Makefile. It is often called $(DESTDIR).
Related
I'm trying to do good logic in Makefile for my project. Let's assume i have a Makefile with rules:
...
NAME := prog_name
...
all: subsystem
subsystem:
#$(MAKE) -sC $(D_LIB)
#$(MAKE) -s $(NAME)
$(D_OBJ):
#mkdir -p $(D_OBJ)
$(NAME): $(D_OBJ) $(OBJ) $(H) $(LIB)
$(CC) ... -o $(NAME)
$(D_OBJ)%.o: $(D_SRC)%.c $(H) $(LIB)
#$(CC) ... -c $< -o $#
.PHONY: all subsystem
When i run command:
make (make all)
It check $(D_LIB) for any changes, then run make for $(NAME) rule. And if there were changes in the library or program files my program recompiles.
But if i run command:
make prog_name
It would not run subsystem rule and i will not know about the changes in the library in any way. Accordingly, the program won't be rebuilt. So I am tormented by the question of how to make it interconnected. If i run command make (all) or run command make prog_name, i should check every dependies for my programm and re-build it if necessary.
All I want to do is gather source files from different source directories into one folder and then do the build of those make files. After a make clean I have to run make command twice to do the build.
So first I run make clean, then i run make, which throws an error saying no -o files found. But when iIrun the make again, the build goes through and generates the build files.
My makefile looks like below
.PHONY: dirs all clean
all: dirs $(OBJ_DIR) $(OBJ_FILES)
"$(CC) -rvn fLib.a $(OBJ_FILES)
# clean build target. Remove all files without reporting errors in case they don't exist.
clean:
#rm -rf fLib.a $(OBJ_DIR)
# Build target for creating flat header file folder for SharedTrackerAPI (FLAT_INC_DIR)
# due to too long paths in Windows 7 build
dirs:
#echo 'Making flat source and header folders.'
#mkdir -p $(OBJ_DIR)
#for f in $(SRC_FILES); do cp $$f $(OBJ_DIR); done
#mkdir -p $(FLAT_INC_DIR)
#OLD_CWD=$(CURDIR)
#cd $(FLAT_INC_DIR)
#find $(STA_RADAR_TRACKER_IFACE) -name '*.h' | xargs -i cp -l {} $(FLAT_INC_DIR)
#cd $(OLD_CWD)
$(OBJ_DIR)/%.o: $(OBJ_DIR)/%.cpp
"$(TASKING_CTC_BIN)"/cctc.exe $(CXXFLAGS) -c -o $# $< $(CC_INCLUDE_PATH)
What am I doing wrong that I have to run make twice after a make clean.
The problem is that although dirs will place the source files in the flat source directory, Make doesn't know that. Before it executes the dirs rule, it has already determined that it knows no way to build the object files.
The quick and dirty solution is to tell Make "trust me, it'll be fine"; one way to do that is to modify the object rule like this:
$(OBJ_DIR)/%.o:
"$(TASKING_CTC_BIN)"/cctc.exe $(CXXFLAGS) -c -o $# $(OBJ_DIR)/$*.cpp $(CC_INCLUDE_PATH)
If you stop there, you will have a working solution.
If you want a more clean, efficient and flexible makefile, you must rethink the approach to finding source files. I see no good reason to use the flat source file approach, but if you really want to use it, here is a good way:
vpath %.cpp $(dir $(SRC_FILES))
$(OBJ_DIR)/%.cpp: %.cpp
#cp $< $#
Now you can get rid of dir and use your unmodified object rule:
$(OBJ_DIR)/%.o: $(OBJ_DIR)/%.cpp
"$(TASKING_CTC_BIN)"/cctc.exe $(CXXFLAGS) -c -o $# $< $(CC_INCLUDE_PATH)
How to handle the header files (FLAT_INC_DIR) is up to you, but I recommend vpath again.
My question is a real simple one I just want to export everything that is not source code to a bin folder but all the answers that I find seem to have either loose chunks of complex makefile code without any indication to where to place it or very complex makefiles in general. I have no experience with make files and the documentation seems extremely poor so if one can give me the simplest answer to this problem I'd be very happy.
#
# Makefile for 2INC0 Interprocess Communication
#
# (c) Fontys 2010, Joris Geurts
#
BIN=./bin/
BINARIES = $(BIN)prime
CC = gcc
CFLAGS = -Wall -g -c
LDLIBS = -lrt -lX11
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $(BIN)$#
all: $(BINARIES)
clean:
rm -f *.o $(BINARIES)
prime: prime.o
prime.o: prime.c prime.h
Try this modification:
$(BIN)%.o: %.c
$(CC) $(CFLAGS) -c $< -o $#
$(BIN)prime: $(BIN)prime.o
$(BIN)prime.o: prime.h
The (almost universally followed) convention is to have a special target install that unconditionally copies all of the required files from the build tree into place. That place is usually configurable with a variable.
That way, you can always just remove the build tree after you're done building and installing.
So if all of the files you need to copy are executables, you get something like this:
DESTDIR = /usr/local
OBJS = $(*.c:%c=%.o)
EXES = $(OBJS:%.o=)
install: $(EXES)
cp -p $+ $(DESTDIR/bin/
(beware: untested). Which version of which make are you using?
I have a simple makefile with 3 build rules:
clean (that cleans the .o)
debug (compiles my code with debgging stuff)
release (compiles my code with optimization stuff)
sometimes I want to switch between debug mode and release so I would issue this
make clean debug -j8
or
make clean release -j8
that has a drawback because while it's doing the clean stuff, the -j8 allows make to jump some command since the .o are still there Then those .o are removed by the clean rule and the compiler complains because it can't find those .o
I could do something like
make clean; make debug -j8
but since I use an odd makefile in another dir, the command becomes
make -C ../src -f nMakefile clean ; make -C ../src -f nMakefile -j8 release
that is more annoying. I was wondering if there was an hiddedn-guru-mode-rule that allows me to do it in one line
Hope it's clear enough...
I needed to solve this very same problem, and the solution I came up was to parse the MAKECMDGOALS for clean, and dispatch a shell command to do the actual cleaning work; RATHER than clean the build as a target. This way, any MAKECMDGOALS that include "clean" will clean the build as part of that build, first, sequentially, rather than clean running asynchronously as its own target.
-include $(deps)
bin/%.o : %.cpp
#mkdir -p $#D
g++ $(flags) $(includes) -MMD -c $< -o $#
.PHONY : clean
clean:
#echo rm -rf bin/
ifneq ($(filter clean,$(MAKECMDGOALS)),)
$(shell rm -rf bin/)
endif
As I stated above, the normal practice is to have different sub directories for the object files. As you are running in parallel I would think you need to enforce serial execution so that clean is completed before release. One way of doing it could be:
clean_release: clean
+#$(MAKE) -s --no-print-directory release
or if you prefer
clean_release:
+#$(MAKE) -s --no-print-directory clean && $(MAKE) -s --no-print-directory release
I'm having some trouble understanding how to design my makefile to build my project the way I want to. Specifically, I can't figure out how to keep all source files in a src directory, while putting all binaries in a bin directory except the linked executable, which goes in the project root.
This is my makefile:
# Compiler options
FC := mpif90
FFLAGS := -O3 -g -Wall -Warray-bounds -ffixed-line-length-none -fbounds-check
VPATH := src
BINDIR := bin
# Define file extensions
.SUFFIXES:
.SUFFIXES: .f .o .mod
# All modules
OBJS := $(BINDIR)/ratecoeffs.o $(BINDIR)/interpolation.o $(BINDIR)/io.o $(BINDIR)/eedf.o $(BINDIR)/single_particle.o $(BINDIR)/physics.o $(BINDIR)/random.o $(BINDIR)/mpi.o $(BINDIR)/precision.o $(BINDIR)/populations.o
# Build rules
all: runner | $(BINDIR)
$(BINDIR):
mkdir -p $(BINDIR)
$(BINDIR)/%.o: $(VPATH)/%.f | $(BINDIR)
$(FC) $(FFLAGS) -c $^ -o $#
runner: $(OBJS)
clean:
#rm -rf $(BINDIR)
Running make builds everything allright - it finds all source files in src and puts all .o files in bin - but the module files (.mod) that are generated by the compiler are put in the project root instead of in the bin directory. I realize I could just specify a rule to place them there, but that messes with the build order, and will sometimes break the build.
What is the "correct" way to get this behavior?
And yes, I've looked at autotools and automake, but I've never used them before and they seem to be overkill for this project. As I couldn't find any good tutorials on how they work (no, I didn't like the tutorial on gnu.org) I'd prefer if I could avoid having to learn this tool just to get this work...
Assuming your underlying Fortran compiler is gfortran, use the -J command line option.
$(FC) $(FFLAGS) -c $^ -o $# -J$(BINDIR)
With an eye to the future, you may be better off creating a MODDIR or similar variable, that you use instead of BINDIR. Object code (*.o) and mod files have different roles to play in later compilation and linking steps - in larger projects they are often kept separate.
It would be probably more in the sense of the make system to change into the obj-directory and do the compilation from there. Via the VPATH option you can let make to find your source files automatically. You could easily call your makefile recursively from the right directory. Below you find a trivial example which would be straightforward to adapt to your case. Please note, that it only works with GNU make.
ifeq (1,$(RECURSED))
VPATH = $(SRCDIR)
########################################################################
# Project specific makefile
########################################################################
FC = gfortran
FCOPTS =
LN = $(FC)
LNOPTS =
OBJS = accuracy.o eqsolver.o io.o linsolve.o
linsolve: $(OBJS)
$(LN) $(LNOPTS) -o $# $^
%.o: %.f90
$(FC) $(FCOPTS) -c $<
.PHONY: clean realclean
clean:
rm -f *.mod *.o
realclean: clean
rm -f linsolve
accuracy.o:
eqsolver.o: accuracy.o
io.o: accuracy.o
linsolve.o: accuracy.o eqsolver.o io.o
else
########################################################################
# Recusive invokation
########################################################################
BUILDDIR = _build
LOCALGOALS = $(BUILDDIR) distclean
RECURSIVEGOALS = $(filter-out $(LOCALGOALS), $(MAKECMDGOALS))
.PHONY: all $(RECURSIVE_GOALS) distclean
all $(RECURSIVEGOALS): $(BUILDDIR)
+$(MAKE) -C $(BUILDDIR) -f $(CURDIR)/GNUmakefile SRCDIR=$(CURDIR) \
RECURSED=1 $(RECURSIVEGOALS)
$(BUILDDIR):
mkdir $(BUILDDIR)
distclean:
rm -rf $(BUILDDIR)
endif
The principle is simple:
In the first part you write your normal makefile, as if you would create the object files in the source directory. However, additionally you add the VPATH option to make sure the source files are found (as make will be in the directory BUILDDIR when this part of the makefile is processed).
In the second part (which is executed first, when the variable RECURSED is not set yet), you change to the BUILDIR directory and invoke your makefile from there. You pass some helper variables (e.g. the current directory) and all make goals, apart of those, which must be executed from outside BUILDDIR (e.g. distclean and the one creating BUILDDIR itself). The rules for those goals you specify also in the second part.