Launch tests normally when not in debug mode - c++

For my C++ project have the following Makefile:
GDB=gdb
DEBUG ?= 1
ifeq ($(DEBUG), 1)
CCFLAGS =-DDEBUG
RUNPATH =${GDB}
else
CCFLAGS=-DNDEBUG
RUNPATH="/bin/sh -c"
endif
CPP=g++ ${CCFLAGS}
TESTGEN=cxxtestgen
CFLAGS_DBG=""
TEST_BUILD_PATH="./build/tests"
BUILD_PATH="./build"
TESTS_SRC_PATH="./tests"
SRC_PATH=""
# NORMAL TARGETS
# To Be filled
# RUN TESTS
test_command_parser_gen:
${TESTGEN} --error-printer -o ${TESTS_SRC_PATH}/CommandParser/runner.cpp ./tests/CommandParser/testCommandParser.h
test_command_parser_build: test_command_parser_gen
${CPP} -o ${TEST_BUILD_PATH}/commandParser ${TESTS_SRC_PATH}/CommandParser/runner.cpp ./src/tools/command_parser.cpp
test_command_parser_run: test_command_parser_build
${RUNPATH} ./build/tests/commandParser
clean:
find ./build ! -name '.gitkeep' -type f -exec rm -f {} + && find ./tests ! -name *.h -type f -exec rm -f {} +
When I launch the tests via the command:
make test_command_parser_run
As expected the gdb fires up and I can use it to debug the test. But sometimes I need just to run the test as is (eg. when in CI) therefore I use the following command to do so:
make test_command_parser_run DEBUG=0
But in that case I get the following error:
cxxtestgen --error-printer -o "./tests"/CommandParser/runner.cpp ./tests/CommandParser/testCommandParser.h
g++ -DNDEBUG -o "./build/tests"/commandParser "./tests"/CommandParser/runner.cpp ./src/tools/command_parser.cpp
"/bin/sh -c" ./build/tests/commandParser
/bin/sh: 1: /bin/sh -c: not found
Makefile:31: recipe for target 'test_command_parser_run' failed
make: *** [test_command_parser_run] Error 127
Therefore, I wanted to know how I can tell the make to execute the test without gdb when not in "debug" mode.
The whole idea behind this is somehow automatically debug my application without the need to remember the command and the compilation sequence to do so.

Remove quotes around /bin/sh -c, like so:
else
CCFLAGS=-DNDEBUG
RUNPATH=/bin/sh -c

Related

Build error: make: Nothing to be done for 'compile'

I need to add my own package to the openwrt image. On the wiki of the project I found this article.
I tried to follow the instructions for it, but in the end I did not manage to add my own package to the source code tree (the build ignored its presence).
Because of this, I tried to find some other way. And it turned out to be a this instruction. I followed the directions from there and compiled my own package.
But as you can see, the source code of that package does not depend on others and does not require any other build header files. Also, his Makefile completely includes instructions for compiling.
define Build/Compile
$(TARGET_CC) $(TARGET_CFLAGS) -o $(PKG_BUILD_DIR)/helloworld.o -c $(PKG_BUILD_DIR)/helloworld.c
$(TARGET_CC) $(TARGET_LDFLAGS) -o $(PKG_BUILD_DIR)/$1 $(PKG_BUILD_DIR)/helloworld.o
endef
But now this does not suit me, since another package that I want to add already has such dependencies.
I tried to bypass them like this (copy the source code to the build folder and call the makefile located there) but nothing came of it:
define Build/Prepare
echo $PKG_NAME
mkdir -p $(PKG_BUILD_DIR)
cp $(SOURCE_DIR)/* $(PKG_BUILD_DIR)
$(Build/Patch)
endef
define Build/Compile
$(PKG_BUILD_DIR) $(MAKE)
endef
I am getting next output:
$ make -C package/feeds/mypackages/helloworld compile TOPDIR=$PWD
make: Entering directory '/home/username/mypackages/examples/helloworld'
bash: mkhash: command not found
bash: mkhash: command not found
bash: mkhash: command not found
bash: mkhash: command not found
bash: mkhash: command not found
bash: mkhash: command not found
bash: mkhash: command not found
bash: mkhash: command not found
make: Nothing to be done for 'compile'.
make: Leaving directory '/home/username/mypackages/examples/helloworld'
My full Makefile for both package and binary:
include $(TOPDIR)/rules.mk
PKG_NAME:=helloworld
PKG_VERSION:=1.0
PKG_RELEASE:=1
SOURCE_DIR:=/home/username/helloworld
include $(INCLUDE_DIR)/package.mk
define Package/$(PKG_NAME)
SECTION:=utils
DEPENDS:= +libstdcpp
TITLE:=helloworld
endef
define Package/helloworld/description
A simple "Hello, world!" -application.
endef
define Build/Prepare
echo $PKG_NAME
mkdir -p $(PKG_BUILD_DIR)
cp $(SOURCE_DIR)/* $(PKG_BUILD_DIR)
$(Build/Patch)
endef
define Build/Compile
$(PKG_BUILD_DIR) $(MAKE)
endef
define Package/helloworld/install
# Install binary
#$(INSTALL_DIR) $(1)/usr/bin
#$(INSTALL_BIN) $(PKG_BUILD_DIR)/helloworld $(1)/usr/bin/
endef
$(eval $(call BuildPackage,$(PKG_NAME)))
,
TARGET = heloworld
OBJS = heloworld.o
CFLAGS += -Wall -Wextra
LDFLAGS += -lxsacpp -lxsac -lubus -lubox
CXXFLAGS += $(CFLAGS) -std=c++14
%.o : %.cpp
$(CXX) -c $(CXXFLAGS) $< -o $#
all: $(TARGET)
$(TARGET): $(OBJS)
$(CXX) $(LDFLAGS) -o $# $^
clean:
rm *.o $(TARGET)
And actually my question is, what needs to be set in the Makefile to copy files correctly and call the local Makefile for package binary?
In order to copy files and directories you can use below step:
# copy all files and directories using **cp -r -f **
define Build/Prepare
echo $PKG_NAME
mkdir -p $(PKG_BUILD_DIR)
cp -r -f $(SOURCE_DIR)/* $(PKG_BUILD_DIR)
$(Build/Patch)
endef
In order to execute the local makefile use below step:
# Execute local makefile by giving path using '-C' option
define Build/Compile
`$(MAKE) -C $(PKG_BUILD_DIR)`
endef

Error with gtest installation on home system

Im trying to setup my home computer the same way as the computers at my school so I can work on my assignments from here, but I can't for the life of me get gtest working correctly. I've run through the recommended install process and figured out that it needs the ".so" libraries to not throw 'pthread' not found errors.
Makefile:
PROJECT_DIR = Electra
PROGRAM_TEST = testProject
CXX = g++
CXXFLAGS = -std=c++11 -g -fprofile-arcs -ftest-coverage
LINKFLAGS = -lgtest
SRC_DIR = src
TEST_DIR = test
SRC_INCLUDE = include
INCLUDE = -I ${SRC_INCLUDE}
GCOV = gcov
LCOV = lcov
COVERAGE_RESULTS = results.coverage
COVERAGE_DIR = docs/code/coverage
STATIC_ANALYSIS = cppcheck
STYLE_CHECK = cpplint.py
DOXY_DIR = docs/code
#Targets
#
#.PHONY: all
#all: $(PROGRAM_TEST) memcheck coverage docs static style
#Temporary all target. use ^^^ this one once docs and coverage required
.PHONY: all
all: $(PROGRAM_TEST) memcheck static style
%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $#
.PHONY: clean
clean:
rm -rf *~ $(SRC)/*.o $(TEST_DIR)/output/*.dat \
*.gcov *.gcda *.gcno *.orig ???*/*.orig \
*.bak ???*/*.bak $(PROGRAM_GAME) \
???*/*~ ???*/???*/*~ $(COVERAGE_RESULTS) \
$(PROGRAM_TEST) $(MEMCHECK_RESULTS) $(COVERAGE_DIR) \
$(DOXY_DIR)/html obj bin
$(PROGRAM_TEST): $(TEST_DIR) $(SRC_DIR)
$(CXX) $(CXXFLAGS) -o $(PROGRAM_TEST) $(INCLUDE) \
$(TEST_DIR)/*.cpp $(SRC_DIR)/*.cpp $(LINKFLAGS)
tests: $(PROGRAM_TEST)
$(PROGRAM_TEST)
memcheck: $(PROGRAM_TEST)
valgrind --tool=memcheck --leak-check=yes $(PROGRAM_TEST)
fullmemcheck: $(PROGRAM_TEST)
valgrind --tool=memcheck --leak-check=full $(PROGRAM_TEST)
coverage: $(PROGRAM_TEST)
$(PROGRAM_TEST)
# Determine code coverage
$(LCOV) --capture --gcov-tool $(GCOV) --directory . --output-file $(COVERAGE_RESULTS)
# Only show code coverage for the source code files (not library files)
$(LCOV) --extract $(COVERAGE_RESULTS) */$(PROJECT_DIR)/$(SRC_DIR)/* -o $(COVERAGE_RESULTS)
#Generate the HTML reports
genhtml $(COVERAGE_RESULTS) --output-directory $(COVERAGE_DIR)
#Remove all of the generated files from gcov
rm -f *.gcda *.gcno
static: ${SRC_DIR} ${TEST_DIR}
${STATIC_ANALYSIS} --verbose --enable=all ${SRC_DIR} ${TEST_DIR} ${SRC_INCLUDE} --suppress=missingInclude
style: ${SRC_DIR} ${TEST_DIR} ${SRC_INCLUDE}
${STYLE_CHECK} $(SRC_INCLUDE)/* ${SRC_DIR}/* ${TEST_DIR}/*
#.PHONY: docs
#docs: ${SRC_INCLUDE}
# doxygen $(DOXY_DIR)/doxyfile
Running "make tests" results in the following
g++ -std=c++11 -g -fprofile-arcs -ftest-coverage -o testProject -I include \
test/*.cpp src/*.cpp -lgtest
testProject
make: testProject: Command not found
Makefile:53: recipe for target 'tests' failed
make: *** [tests] Error 127
Any idea as to why this wont work? Or how to even get started trying to resolve this? Its not a very detailed error. I don't want to change the Makefile, as it works for my school systems and this is a shared project.
My home system is running Windows 10, and im using the Ubuntu shell to run makefiles
In POSIX shells the current working directory is not searched by default. This is a safety measure that comes from POSIX's origins as a multi-user system: you don't want someone to be able to drop a program like ls in some directory and have unsuspecting people run it just by typing ls in that directory.
Apparently in your school systems, someone has added the current working directory (.) to your PATH environment variable, while at home you do not have it added.
Your makefile is wrong, the recipe should be:
tests: $(PROGRAM_TEST)
./$(PROGRAM_TEST)
to force the program from the current working directory to be run, instead of relying on the cwd appearing in the PATH (or running some other instance of testProgram that does happen to be on your PATH).
This will work on all your systems.

Make -j works but -jN is not working

My Makefile looks as follows:
test:
make clean
make test2
test2: CXX=g++
test2: all
CPP_FILES := $(wildcard tmp/*.cpp)
OBJ := $(CPP_FILES:.cpp=.o)
all: ${OBJ}
${CXX} ${OBJ} ${LIB_PATH} ${LIBS} ${CXX_FLAGS} -o output.exe
%.o: %.cpp
${CXX} ${CXX_FLAGS} ${INCLUDE_PATH} -c $< -o $#
All the .o files can (and should) be build in parallel. This is working if I execute "make -j" but it fails if I limit the number of processes to some fixed number (say 4) via "make -j4". This will result in the following message:
make[1]: warning: jobserver unavailable: using -j1. Add `+' to parent make rule.
Can someone please point me to my mistake? Why is "make -j" working while "make -j4" gives this error message?
Thanks!
Please read the documentation for recursive calls in GNU make. Essentially, you need to call $(MAKE) or ${MAKE} instead of plain make or at least prefix the line in the recipe with + so that the sub-make can properly communicate with the parent make. This is particularly useful when you ask for job control.

"ifort: no match" error in csh script

I'm trying to compile a program called ZEUS and I am following the included instructions exactly but I came across the following error.
The instructions asked me to type csh -v namelist.s in the folder containing namelist.s. This is a fairly large assembly file which invokes another file given in the source files called bldlibo which is the csh file mentioned in the title. The contents of this file are:
#==== SCRIPT TO BUILD AN OBJECT LIBRARY FROM A FORTRAN SOURCE FILE====#
#
# Syntax: bldlibo <library name> <source code>
# eg: bldlibo namelist.a namelist.f
#
rm -rf bldlibo.dir
mkdir bldlibo.dir
cp $2 bldlibo.dir
cd bldlibo.dir
fsplit $2 >& /dev/null
rm $2
#
# When -fast option is used, this leads to the __vsincos_ unsatisfied
# external errors when zeus is compiled with -g option. Thus, use -O4
# instead.
#
ifort -c -O4 *.f
#f77 -c -g -C -ftrap=common *.f
ar rv $1 *.o >& /dev/null
ranlib $1
cd ..
mv bldlibo.dir/$1 .
rm -r bldlibo.dir
When I run csh -v namelist.s it begins to run bldlibo and works fine up until ifort is invoked at which point it says ifort: no match. I have tried adding #!/bin/csh at the start and also source .../ifortvars.csh but that didn't work.
Can anybody help me, sorry if I haven't explained it well enough.

Issue with Makefile - section executed twice

I may not be a Makefile-guru, but I have some experience with them in the past. However, I've got a (rather unimportant) issue, which still baffles me.
Here's my Makefile :
#-------------------------
# Definitions
#-------------------------
APP = lgm
# Tools & commands
CC = gcc
LEX = lex
YACC = /usr/local/bin/bison
RM = rm
CP = cp
MV = mv
DMD = dmd
# Paths
SRC = src
BIN = bin
TEST = test
LIB = lib
# C stuff
CC_HEADERS = logramm.tab.h
CC_SOURCES = lex.yy.c logramm.tab.c
CC_OBJECTS = lex.yy.o logramm.tab.o
CC_LEXER = logramm.l
CC_PARSER = logramm.y
# D stuff
D_SOURCES = main.d
D_OBJECTS = main.o
D_LFLAGS = -m64
#-------------------------
# Main Functions
#-------------------------
all: ${APP} clean
${APP}: ${CC_OBJECTS} ${D_OBJECTS}
${DMD} ${CC_OBJECTS} ${D_OBJECTS} -of${APP} ${D_FLAGS}
${MV} ${APP} ${BIN}
${D_OBJECTS}:
${DMD} -c ${D_SOURCES}
${CC_OBJECTS}: ${CC_SOURCES}
${CC} -g -c ${CC_SOURCES}
${CC_SOURCES}: setup
${LEX} ${CC_LEXER}
${YACC} -d ${CC_PARSER}
setup:
${CP} ${SRC}/*.d .
${CP} ${SRC}/*.l .
${CP} ${SRC}/*.y .
clean:
${RM} *.d *.y *.l *.o *.hh *.c *.h
The trouble is :
When I'm looking at the output of make all, the ${CC_SOURCES} part is executed twice (2 lex, 2 bison commands). E.g. It outputs :
cp src/*.d .
cp src/*.l .
cp src/*.y .
lex logramm.l
/usr/local/bin/bison -d logramm.y
lex logramm.l
/usr/local/bin/bison -d logramm.y
gcc -g -c lex.yy.c logramm.tab.c
dmd -c main.d
dmd lex.yy.o logramm.tab.o main.o -oflgm
mv lgm bin
rm *.d *.y *.l *.o *.hh *.c *.h
rm: *.hh: No such file or directory
make: *** [clean] Error 1
Why is that? What am I doing wrong?
UPDATE :
I've just managed to fix it, by taking setup from ${CC_SOURCES} and putting it at the all section, like :
all: setup ${APP} clean
So, it's ok. However, I still don't understand why. Have I misinterpreted the way Makefiles are structured? Any input would be more than welcome! :-)
You have a basic misunderstanding of how make interprets rules with multiple targets: this makefile is really not going to work. Let's expand the rule that runs the lex/yacc:
lex.yy.c logramm.tab.c: setup
${LEX} ${CC_LEXER}
${YACC} -d ${CC_PARSER}
Make interprets this as if it were this (in an explicit rule, multiple targets create a separate rule for each target):
lex.yy.c: setup
${LEX} ${CC_LEXER}
${YACC} -d ${CC_PARSER}
logramm.tab.c: setup
${LEX} ${CC_LEXER}
${YACC} -d ${CC_PARSER}
Now you can probably see your issue. Make wants to build lex.yy.o and that depends on lex.yy.c, so make tries to build that. It sees that it depends on setup, which doesn't exist (because nothing creates it, but if someone WERE to create that file in your directory it would break badly). So, it run the lex and yacc steps (both, since that's the recipe) to build lex.yy.c.
Then it goes through exactly the same thing to build logramm.tab.c... thus the rules are run twice.
You have an identical problem with your object files; expanding that rule we see:
lex.yy.o logramm.tab.o: lex.yy.c logramm.tab.c
${CC} -g -c lex.yy.c logramm.tab.c
which is identical to:
lex.yy.o: lex.yy.c logramm.tab.c
${CC} -g -c lex.yy.c logramm.tab.c
logramm.tab.o: lex.yy.c logramm.tab.c
${CC} -g -c lex.yy.c logramm.tab.c
which is clearly not right.
Also, your setup rule (since it never exists) will cause everything to rebuild every time.
Your solution is better WRT setup, since the source files don't depend on it so they won't always be rebuilt. You still have the broken rules for object files. Also your solution will not work if you ever wanted to enable parallel builds, because the setup may be run in parallel with the other targets: you really WANT the dependency to ensure ordering.
In general when writing makefiles you should (a) have one rule to build one target, and (b) ensure the rule builds EXACTLY the target you told make it would build.
Try using this instead:
all: ${BIN}/${APP} clean
${BIN}/${APP}: ${APP}
${CP} $< $#
${APP}: ${CC_OBJECTS} ${D_OBJECTS}
${DMD} $^ -of$# ${D_FLAGS}
%.o : %.d
${DMD} -c $<
%.o: %.c
${CC} -g -c $<
%: ${SRC}/%
${CP} $< $#
lex.yy.c: ${CC_LEXER}
${LEX} $<
%.tab.c %.tab.h: %.y
${YACC} -d $<
clean:
${RM} *.d *.y *.l *.o *.hh *.c *.h
The trouble is that CC_SOURCES = lex.yy.c logramm.tab.c so the target line (plus actions):
${CC_SOURCES}: setup
${LEX} ${CC_LEXER}
${YACC} -d ${CC_PARSER}
is equivalent to:
lex.yy.c: setup
${LEX} ${CC_LEXER}
${YACC} -d ${CC_PARSER}
logramm.tab.c: setup
${LEX} ${CC_LEXER}
${YACC} -d ${CC_PARSER}
The setup rule has no dependencies, but isn't a (GNU make extension) .PHONY target either (and I'm not sure that being a phony target would help, either), so it doesn't exist. Therefore, when make is trying to ensure that lex.yy.c is up to date, it has to execute the rules for setup; ditto for logramm.tab.c; hence the double execution.
Your solution looks reasonable. You could explore .PHONY and see whether that helps if you're using GNU make and don't mind being tied to GNU make.
This comes down to the way make handles dependencies. You can always examine exactly what make is doing by passing the -d flag (at least for GNU Make, ymmv, also consider adding -r if you aren't using any built-in rules as they clutter the output substantially).
Here's what happens in the case where setup is a dependency of ${CC_SOURCES}
...
Does lex.yy.c exist? no, okay check its prerequisites
Does setup exist? no, okay check its prerequisites
No prerequisites, run the recipe
Prerequisites for lex.yy.c done, run the recipe
Does logramm.tab.c exist? yes, but check its prerequisites
We already built setup, so prune this prerequisite, but treat it as newer than logramm.tab.c
Prerequisites for logramm.tab.c done, run the recipe
...
Here's what happens in the case where setup is a dependency of all
...
Does setup exist? no, okay check its prerequisites
No prerequisites, run the recipe
...
Does lex.yy.c exist? no, okay check its prerequisites
No prerequisites, run the recipe
Does logramm.tab.c exist? yes, but check its prerequisites
No prerequisites, so done
...