Multiple make targets in the same CMake project - makefile

In my project I have a makefile that looks like this:
CXX = clang++
CFLAGS = -std=c++11
COMMON_SOURCES = file1.cpp file2.cpp
TARGET_SOURCES = main.cpp
TEST_SOURCES = run_tests.cpp test_file1.cpp test_file2.cpp
COMMON_OBJECTS = $(COMMON_SOURCES:.c=.o)
TARGET_OBJECTS = $(TARGET_SOURCES:.c=.o)
TEST_OBJECTS = $(TEST_SOURCES:.c=.o)
EXECUTABLE = build/application
TEST_EXECUTABLE = build/tests
.PHONY: all target tests
all: target tests
target: $(EXECUTABLE)
tests: $(TEST_EXECUTABLE)
clean:
rm build/tests & rm build/application &
$(EXECUTABLE): $(COMMON_OBJECTS) $(TARGET_OBJECTS)
$(CXX) $(CFLAGS) $(LDFLAGS) $^ -o $#
$(TEST_EXECUTABLE): $(COMMON_OBJECTS) $(TEST_OBJECTS)
$(CXX) $(CFLAGS) $(LDFLAGS) $^ -o $#
.c.o:
$(CXX) $(CFLAGS) $< -o $#
This lets me run make tests or make target and it will build the appropriate executable.
How do I set up a CMakeLists file to get the same convenient build system?

Except for using clang++, I think if you put the following in a CMakeLists.txt file and then run your cmake configure step in a build directory (i.e., mkdir build; cd build; cmake ..), you should have what you are asking for.
project(myproject)
# I am not sure how you get cmake to use clang++ over g++
# CXX = clang++
add_definitions(-std=c++11)
set(COMMON_SOURCES file1.cpp file2.cpp)
set(TARGET_SOURCES main.cpp)
set(TEST_SOURCES run_tests.cpp test_file1.cpp test_file2.cpp)
add_executable(application ${COMMON_SOURCES} ${TARGET_SOURCES})
add_executable(tests ${COMMON_SOURCES} ${TEST_SOURCES})

Every add_custom_target() (and some other commands, like add_executable) actually adds target in the make sence.
add_custom_target(tests) # Note: without 'ALL'
add_executable(test_executable ...) # Note: without 'ALL'
add_dependencies(tests test_executable)
So, test_executable will be build on make tests, but not in case of simple make.

Related

Configure makefile for debug and release targets

Considering a Makefile similar to the following:
CC = gcc
CXX = g++
CXXFLAGS += -std=c++11
SRCDIR = .
OBJECTS = \
file1.o \
file2.o \
file3.o
THREADS = 1
all: release
release: CXXFLAGS += -DNUM_THREADS=$(THREADS)
release: main
debug: CXXFLAGS += -g -DDEBUG -DVERBOSENESS=3 -DNUM_THREADS=$(THREADS)
debug: main
# Build main executable...
main: $(OBJECTS)
$(CXX) $(CXXFLAGS) -o $# $^
# Compile all object files...
file1.o: $(SRCDIR)/file1.cpp
$(CXX) $(CXXFLAGS) -c $^
file2.o: $(SRCDIR)/file2.cpp
$(CXX) $(CXXFLAGS) -c $^
file3.o: $(SRCDIR)/file3.cpp
$(CXX) $(CXXFLAGS) -c $^
This works properly only for the first make: using other words, object files are not recompiled when I launch make with a different target respect to the previous one.
That said, how could I make the object files recompile if I change between debug or release target?
If you want to force recompilation strictly based on one label, say "Debug" vs. "Release", then you can do it by writing and depending on appropriate timestamp files, like so:
TYPE = Debug
#
# ... conditional settings based on $(TYPE) ...
#
OBJS = prog.o
all: test
prog: $(OBJS)
$(CC) -o $# $(OBJS)
$(OBJS): $(TYPE)-mode-stamp
$(TYPE)-mode-stamp: last-mode-stamp
touch $#
touch -r $# last-mode-stamp
last-mode-stamp:
touch $#
clean:
#rm *-mode-stamp $(OBJS) prog
That supposes you select the build type by setting variable $(TYPE), possibly via the command line. All the object files have $(TYPE)-mode-stamp as a prerequisite, so if that file is out of date then all of them will be rebuilt, along with anything that has any of them as a prerequisite. $(TYPE)-mode-stamp itself has last-mode-stamp as a prerequisite, so the former is updated if it is older than the latter, or if the latter itself is out of date. The recipe for $(TYPE)-mode-stamp sets both files timestamps to the current time, so that
$(TYPE)-mode-stamp is no longer out of date with respect to last-mode-stamp, and
last-mode-stamp is newer than any OtherType-mode-stamp that may be present.
A rule without any prerequisites (but with a recipe) creates last-mode-stamp if it does not initially exist.
Note well that this is altogether different from and orthogonal to monitoring whether any build tools or flags change.

How to maintain sequence of multiple targets in a makefile with -j option

I have a script which generates C++ files. First I want to generate these files.
Then compile them in a library.
I want to do this in a single Makefile.
TARGETS = GEN_FILE LIBNAME
GEN_FILE: input
BINARYTOGEN input
OBJ =(GENERATED_FILES:.cpp-.o)
LIBNAME: $(OBJ)
cc $(OBJ)
How can I make sure target GEN_FILE always run before LIBNAME in a parallel environment when used –j option.
One way is .NOTPARALLEL.
.generated_marker: a.gen b.gen
touch a.cpp
touch b.cpp
touch $#
SRCS = a.cpp b.cpp
$(SRCS): .generated_marker
OBJ = $(SRCS:.cpp=.o)
OUT = ./libutils.a
.PHONY: all
all: $(OUT)
.SUFFIXES: .cpp
LIBS = -L…
INCLUDES = -I…..
.cpp.o:
gcc $(INCLUDES) -g -c $< -o $#
$(OUT): $(OBJ)
ar rcs $(OUT) $(OBJ)
If your generator processes single source file and generates single output file, it is simple - just add pattern rule, e.g.:
all: a.out
%.c: %.gen
cp $< $#
SRCS:=a.c b.c
a.out: $(SRCS)
gcc $^
(I use cp for simplicity, it should be your actual generator, e.g. flex, bison, lemon, .....)
It is possible your generator produces a lot of files at once (or even all of them), then you probably need to create a flag file which timestamp will indicate latest re-generation, e.g.:
all: a.out
.generated_marker: a.gen b.gen
touch a.c
touch b.c
touch $#
SRCS:=a.c b.c
$(OBJS):=$(SRCS:.c=.o)
$(OBJS): .generated_marker
a.out: $(OBJS)
gcc $^

CMake with CLion

I have been using Kdevelop with a project, now im on a different laptop, and need to build the project with CLion and MinGW on Windows.
I had this makefile (works on KDevelop)
CC=gcc
DEPS = cmp_micris_defs.h
OBJ = cmp_micris_datos_msc.o cmp_micris_rutinas.o cmp_micris_UnixSocket.o cmp_micris_cfg.o cmp_micris_db.o cmp_micris_TCP.o cmp_micris_utiles.o cmp_micris_datos.o cmp_micris.o
LIBS = -lpthread -lmysqlclient
.PREFIXES = .c .o
.c.o:
$(CC) -std=gnu99 -c -I/home/borja/projects/micris2/proceso-micris2/proceso/ $< $(LIBS)
cmp_micris_borja: $(OBJ)
$(CC) -o $# $(OBJ) $(LIBS)
all: cmp_micris_borja
clean:
rm -rf $(OBJ) cmp_micris_borja
But CLion use Cmake to build, i have not used it before, what should i write in CMakeLists.txt to build like before with my makefile ?
Thanks.

Makefile not executing to the end

I have the following makefile but it just executes the 1st command where it builds me the .o files and not the .so files. What am I doing wrong?
Thanks,
SHELL = /bin/sh
CC = gcc
CFLAGS = -g -Wall
LDFLAGS = -shared
TARGET = Stepper.so
SOURCES = $(shell echo ./*.c)
HEADERS = $(shell echo ./*.h)
OBJECTS = $(SOURCES:.c=.o)
LIBS = liblua523.a
PREFIX = $(DESTDIR)/usr/local
BINDIR = $(PREFIX)/bin
$(OBJECTS): $(SOURCES) $(HEADERS)
$(CC) $(CFLAGS) -c $(SOURCES) -o $(OBJECTS)
$(TARGET): $(OBJECTS)
$(CC) $(LDFLAGS) -o $(TARGET) $(OBJECTS) $(LIBS)
clean:
rm $(OBJECTS)
Unless you specify a different target on the command line, make always builds the first real target found in the makefile. In this case, the first real target is the first object file, so that's all that's built.
This is why you typically see makefiles with a first target of all or similar, which just depends on the various other targets you want built during a standard invocation of "make" with no arguments.
However, your makefile is really not right, in a number of ways. The fact that it's running it all means you actually only have one source file. As soon as you have >1 it will fail.
This:
SOURCES = $(shell echo ./*.c)
is not very efficient; you should use wildcard here:
SOURCES = $(wildcard ./*.c)
This rule:
$(OBJECTS): $(SOURCES) $(HEADERS)
$(CC) $(CFLAGS) -c $(SOURCES) -o $(OBJECTS)
Tells make, "for every object file, if any source file or any header file has changed, recompile it". Basically, it means that if you change ANYTHING in the directory, EVERYTHING will rebuild. If you want that you might as well write a shell script and not bother with make at all.
Further, the compiler will fail when you have >1 source file, as it will try to run:
gcc -g -Wall -c foo.c bar.c -o foo.o bar.o
which is not right.
You don't need to define this rule at all; make has a built-in rule which knows how to build an object file from a source file. Just replace it with this:
$(OBJECTS): $(HEADERS)
(no recipe) so make knows that the objects depend on the headers as well as the source. Note this is not ideal since all objects rebuild if any header changes but it's fine for a simple program.

How to instruct Makefile to use different compilers

I have to build my code for two different platforms at once using two different compilers and libraries. How can I do this with single make file.
Currently my makefile contents are given below. How can I instruct it to change the compiler to gcc within the same makefile?
VPATH = /root/Documents/project/src
CROSS_COMPILE = /opt/compilers/bin/compiler1
CXX = $(CROSS_COMPILE)-g++
CC = $(CROSS_COMPILE)-gcc
AS = $(CROSS_COMPILE)-as
AR = $(CROSS_COMPILE)-ar
NM = $(CROSS_COMPILE)-nm
LD = $(CROSS_COMPILE)-ld
OBJDUMP = $(CROSS_COMPILE)-objdump
OBJCOPY = $(CROSS_COMPILE)-objcopy
RANLIB = $(CROSS_COMPILE)-ranlib
STRIP = $(CROSS_COMPILE)-strip
CFLAGS = -c -Wall -D_REENTRANT -DACE_HAS_AIO_CALLS -D_GNU_SOURCE -DACE_HAS_EXCEPTIONS -D__ACE_INLINE__
LDFLAGS = -L. -L/etc/ACE_wrappers/lib
CPPFLAGS += -I/etc/ACE_wrappers -I/etc/ACE_wrappers/ace
LDLIBS = -lACE
OUTPUT_DIRECTORY=/root/Documents/bin
OBJ=/root/Documents/obj
ifneq ($(OUTPUT_DIRECTORY),)
all: $(OUTPUT_DIRECTORY)
$(OUTPUT_DIRECTORY):
-#$(MKDIR) "$(OUTPUT_DIRECTORY)"
endif
ifneq ($(OBJ),)
all: $(OBJ)
$(OBJ_DIR):
-#$(MKDIR) "$(OBJ)"
endif
SOURCES=File_1.cpp File_2.cpp
OBJECTS=$(SOURCES:%.cpp=$(OBJ)/%.o)
$(OBJ)/%.o: %.cpp
#echo Building Objects
$(CC) $(CFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c -o $# $<
EXECUTABLE=MyExecutable
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
#echo $(SOURCES)
$(CC) $(LDFLAGS) $(OBJECTS) $(LDLIBS) -o $(OUTPUT_DIRECTORY)/$#
File_1.o:File_1.cpp
File_1.o:File_1.cpp
.PHONY: clean
clean:
rm $(OBJECTS) $(OUTPUT_DIRECTORY)/$(EXECUTABLE)
I'd start by putting all the platform-specific defines in a separate makefile. That way you can do:
include $(TARGET).make
Where $(TARGET).make defines CC and other variables for each particular platform. Then you can call make recursively setting TARGET to what you want. Something like:
build:
$(MAKE) TARGET=platform1 all
$(MAKE) TARGET=platform2 all
But really there are many, many ways in which you can achieve the same thing.
Use autoconf. When you configure the project with ./configure, it will automatically choose the one available.
That would be a lot easier to read if the linebreaks were properly preserved in your post.
Anyway, I expect that you're going to have to have two copies of a number of things in the Makefile, such that it's of the form
all : all-platform1 all-platform2
stuff-platform1 : requirements
$(CC1) whatever
stuff-platform2 : requirements
$(CC2) whatever
It's possible that you might be able to auto-generate a makefile like this, to save some effort though.

Resources