What should I do for my makefile to not only build and compile "test" but actually run it when typing "make test" in terminal, so I wouldn't have to do ./test every time?
LDFLAGS = -lm -L. -lhashi
CFLAGS = -g -Wall -std=c99
SRC=$(wildcard *.c)
OBJETS = $(SRC:.c=.o)
all : prog1 prog2 test
...
test : test_game1.o test_toolbox.o libhashi.a
$(CC) $^ $(LDFLAGS) -o $#
test_game1.o : test_game1.c game.h node.h test_toolbox.h test_game_eliott.c test_game_flo.c test_game_iana.c test_game_remi.c
test_toolbox.o : test_toolbox.c test_toolbox.h
clean :
rm -f ... test_game1.o test_toolbox.o test ...
You need a phony target. (https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html).
For example:
.PHONY: run-test
run-test: test
./test
test: test_game1.o test_toolbox.o libhashi.a
$(CC) $^ $(LDFLAGS) -o $#
Having a different target to run the test keeps the possibility to build the test without executing it.
Related
I am writing an makefile and I need to set up env.
I use source /opt/intel/oneapi/setvars.sh to set up my env but I want to make it in my Makefile.
I search for how to use source in Makefile and I learn to write this:
SHELL=/bin/bash
s:
source /opt/intel/oneapi/setvars.sh
CC = mpicc
OPT = -Ofast
CFLAGS = -Wall -std=c99 $(OPT) -fopenmp -march=native
LDFLAGS = -Wall -fopenmp
LDLIBS = $(LDFLAGS)
targets = benchmark-naive benchmark-omp benchmark-mpi
objects = check.o benchmark.o stencil-naive.o stencil-omp.o stencil-mpi.o
.PHONY : default
default : all
.PHONY : all
all : clean $(targets)
benchmark-naive : check.o benchmark.o stencil-naive.o
$(CC) -o $# $^ $(LDLIBS)
benchmark-omp : check.o benchmark.o stencil-omp.o
$(CC) -o $# $^ $(LDLIBS)
benchmark-mpi : check.o benchmark.o stencil-mpi.o
$(CC) -o $# $^ $(LDLIBS)
%.o : %.c common.h
$(CC) -c $(CFLAGS) $< -o $#
.PHONY: clean
clean:
rm -rf $(targets) $(objects)
But after run make it just load my env and do nothing. Can anyone help me to put my source in my makefile while keep my previous makefile content?
You have to call make with the env set recursively if it wasn't set:
ifndef <some test to see if env is missing>
%:
source /opt/intel/oneapi/setvars.sh $(MAKE) $(MAKECMDGOALS)
else
<normal makefile>
endif
You can look at the following makefile:
# makefile
all: prog
prog:
export ASD=asd
echo $$ASD
export ASD=asd; echo $$ASD
The output is:
export ASD=asd
echo $ASD
export ASD=asd; echo $ASD
asd
A makefile is not a bash script. 'make' is processing a makefile and it creates a child process for each line to run a shell to execute the statements. The variable that you set in a line is only valid for that child process, it will not be inherited back to the parent or to subsequent child processes.
I know this does not solve your issue, but at least it is some kind of an explanation why it does not work.
Can you try this :
SHELL=/bin/bash --rcfile /opt/intel/oneapi/setvars.sh
I have 2 .c files to build. I'd like to run them together (if possible. Or can I compile here then run in bash script?), and then run a .sh file to compare their output to expected (for testing).
My MakeFile currently:
CC=gcc
CFLAGS=-Wall -Werror -Wvla -std=gnu11 -fsanitize=address
PFLAGS=-fprofile-arcs -ftest-coverage
DFLAGS=-g
p1: file_1.c file_2.c file_1.h
$(CC) $(CFLAGS) $(PFLAGS) $^ -o $#
p2: p1
bash t.sh
Please find below code which will allow you to test and run a shell script along with parallel compilation.
.SILENT:
.PHONY:compile objs
TARGET = program.exe
CC=gcc
# INC variable contains path where your header files are available. Compiler will # search header files in this directory.
INC = ./inc
CFLAGS=-Wall -Werror -Wvla -std=gnu11 -fsanitize=address -I$(INC)
PFLAGS=-fprofile-arcs -ftest-coverage
DFLAGS=-g
SOURCES = file_1.c file_2.c
OBJ_FILES:= $(SOURCES:.c=.o)
objs: $(OBJ_FILES)
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $#
all: test
# Enable parallel compilation
compile:
make -j ${NUMBER_OF_PROCESSORS} -O objs
link : compile $(TARGET)
$(TARGET): $(OBJ_FILES)
$(CC) $(CFLAGS) $(OBJ_FILES) -o $#
test: link
# Execute test script
echo "Executing test script"
bash t.sh
Execute the command : make test or make all
If I have 3 files, function.h, function.c and my_program.c which calls a method in function.h all in the same directory, what would be the best way to write a makefile so that I end up with a my_program.bc that would actually run when I type in lli my_program.bc? (I need to run a user defined pass that would insert stuff into the functions - should I run the pass on function.bc and test.bc, or should I link before running the pass?)
I've tried llvm-link function.bc my_program.bc with no luck. I feel I'm either missing something simple or going about the whole thing wrong.
Current terrible none-working makefile:
.PHONY: all clean
CC = clang
CFLAGS = -std=gnu99 -D_POSIX_C_SOURCE=200809L -g -Wall
IRFLAGS = -O3 -emit-llvm
TARGET = test
DEPS = functions.h
all: $(TARGET)
bc: test2
%.o: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
%.bc: %.c $(DEPS)
$(CC) $(IRFLAGS) -c -o $# $<
test2: test.bc functions.bc
llvm-link -o test2.bc $< functions.bc
test: test.o functions.o
$(CC) $(CFLAGS) -o $# $^
clean:
$(RM) $(TARGET) *.o *.bc
Why not just write a normal Makefile to produce the desired executable,
then use wllvm?
Shameless plug for wllvm:
https://github.com/SRI-CSL/whole-program-llvm
I do not use lli, so I would be interested to hear about how it resolved
any reliance on stdlibc that your program may have.
So I am having a little bit of a tough time trying to figure out how to make my Makefile so that when I do make and it compiles a release version then later on do a make debug it compiles a debug version with the new -DDEBUG and -g set on gcc if the files have not been updated.
For example:
main.cpp is edited
run make
compiles main.cpp
run make debug
main.cpp is not recompiled because there were no changes even though the flags for compilation differ
Note I don't want to have to do a clean each time either because I dont want to have to recompile files if I do 2 makes in a row so setting clean as a dependency is not going to be a valid answer here
You may like to compile object files into a different directory depending on the build mode, e.g.:
# default mode, override with `make BUILD=release`
BUILD := debug
obj_dir := ${BUILD}
CFLAGS.debug := -g -O0
CFLAGS.release := -g -O3 -march=native -DNDEBUG
all : ${obj_dir}/test
# Example executable
${obj_dir}/test : ${obj_dir}/test.o
test.c :
echo "int main() { return 0; }" > $#
# Generic rules
${obj_dir} :
mkdir $#
${obj_dir}/%.o : %.c Makefile | ${obj_dir} # Also recompile when Makefile changes.
${CC} -c -o $# ${CPPFLAGS} ${CFLAGS} ${CFLAGS.${BUILD}} -MD -MP $<
${obj_dir}/% : Makefile | ${obj_dir} # Also re-link when Makefile changes.
${CC} -o $# ${LDFLAGS} $(filter-out Makefile,$^) ${LDLIBS}
clean :
rm -rf ${obj_dir}
-include $(wildcard ${obj_dir}/*.d)
${obj_dir}/*.d : ;
.PHONY: all clean
(Bonus feature: automatic dependency generation).
Usage:
[max#localhost:~/tmp] $ make
mkdir debug
echo "int main() { return 0; }" > test.c
cc -c -o debug/test.o -g -O0 -MD -MP test.c
cc -o debug/test debug/test.o
[max#localhost:~/tmp] $ make
make: Nothing to be done for 'all'.
[max#localhost:~/tmp] $ make BUILD=release
mkdir release
cc -c -o release/test.o -g -O3 -march=native -DNDEBUG -MD -MP test.c
cc -o release/test release/test.o
[max#localhost:~/tmp] $ make BUILD=release
make: Nothing to be done for 'all'.
First of all, you should not run make debug - that would mean, you want to build a different target (debug). But you don't, you want to build the same target, just with different options. That's what you do, you run a different option, a variable value
>make DEBUG=Y
When you run
>make
you also pass that variable really, just with the empty string as value.
Now, in order for this to work as you want in the Makefile, you would want to make it as if DEBUG was a prerequisite file, with recipes like this:
foobar.o: foobar.c DEBUG
gcc $(if $(DEBUG), -DDEBUG -g) -c $< -o $#
Of course, normally this won't work, because DEBUG is a variable, not a file. So you need a hack, that I call "dependable variables". It is basically a way to declare a variable to behave like a file. I describe this technique in one of my other answers:
How do I add a debug option to Makefile
I once did something like this, it looked like that (boiled down to the minimum):
EXE := a.out
SRC := $(wildcard *.c)
ifneq ($(MAKECMDGOALS),debug)
OBJ := $(SRC:.c=.o)
else
OBJ := $(SRC:.c=-d.o)
endif
.PHONY: all debug
all: $(EXE)
debug: CFLAGS += -g -DDEBUG
debug: $(EXE)
$(EXE): $(OBJ)
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $#
%.o %-d.o: %.c
$(CC) $(CPPFLAGS) $(CFLAGS) -o $# -c $<
The trick is to use two separate list of object files, and select one depending of the target.
Running into trouble with libraries in makefiles again. Every time I try to get back into C make gives me a pain with libs.
make -pf /dev/null says the correct vars should be LDLIBS and LOADLIBES but the following doesn't alter the run command at all:
LOADLIBES=testing
LDFLAGS=testing
LDLIBS=testing
Needless to say this gives me errors because the -L flags don't end up in the command. Anyone know what's going on?
Full makefile below (Derivitave of Z Shaw's makefile)
OPTLIBS=$(xml2-config --libs)
OPTFLAGS=$(xml2-config --cflags)
STD=c99
CFLAGS=-std=$(STD) -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG $(OPTFLAGS)
LDLIBS=-ldl $(OPTLIBS)
PREFIX?=/usr/local
SOURCES=$(wildcard src/**/*.c src/*.c)
OBJECTS=$(patsubst %.c,%.o,$(SOURCES))
TEST_SRC=$(wildcard tests/*_tests.c)
TESTS=$(patsubst %.c,%,$(TEST_SRC))
TARGET=build/lib.a
SO_TARGET=$(patsubst %.a,%.so,$(TARGET))
# The Target Build
all: cls $(TARGET) $(SO_TARGET) tests
dev: CFLAGS=-std=$(STD) -g -Wall -Isrc -Wall -Wextra $(OPTFLAGS)
dev: all
$(TARGET): CFLAGS += -fPIC
$(TARGET): build $(OBJECTS)
ar rcs $# $(OBJECTS)
ranlib $#
$(SO_TARGET): $(TARGET) $(OBJECTS)
$(CC) -shared -o $# $(OBJECTS)
build:
#mkdir -p build
#mkdir -p bin
# The Unit Tests
$(TESTS): $(TARGET)
.PHONY: tests
tests: LDLIBS += $(TARGET)
tests: $(TESTS)
sh ./tests/runtests.sh
valgrind:
VALGRIND="valgrind --log-file=/tmp/valgrind-%p.log" $(MAKE)
# The Cleaner
clean: cls
rm -rf build $(OBJECTS) $(TESTS)
rm -f tests/tests.log
find . -name "*.gc*" -exec rm {} \;
rm -rf `find . -name "*.dSYM" -print`
# The Install
install: all
install -d $(DESTDIR)/$(PREFIX)/lib/
install $(TARGET) $(DESTDIR)/$(PREFIX)/lib/
# The Checker
BADFUNCS='[^_.>a-zA-Z0-9](str(n?cpy|n?cat|xfrm|n?dup|str|pbrk|tok|_)|stpn?cpy|a?sn?printf|byte_)'
check:
#echo Files with potentially dangerous functions.
#egrep $(BADFUNCS) $(SOURCES) || true
# Clear screen for unspammy terminals
cls:
ifdef TERM
clear
endif
You aren't using LDFLAGS, etc in your link command. Make that something along the lines of:
$(SO_TARGET): $(TARGET) $(OBJECTS)
$(CC) -shared $(LDFLAGS) -o $# $(OBJECTS) $(LDLIBS)
It tells the linker to link the dl library, which is located at /usr/lib/libdl.so. -l is the switch to add a library, dl is the name of it (without the lib prefix or .so extension).
This library includes functions for dynamically loading shared libraries.