Does not compile with a preprocessor value on the command-line - makefile

Where am I going wrong; I want to define a preprocessor value on the command-line for g++ but it fails. Below is sample code that replicate my problem:
[edit] I'm using:g++ (Debian 4.3.2-1.1) 4.3.2GNU Make 3.81
test.h
#ifndef _test_h_
#define _test_h_
#include "iostream"
#if defined(MY_DEFINED_VALUE)
#if (MY_DEFINED_VALUE != 5)
#undef MY_DEFINED_VALUE
#define MY_DEFINED_VALUE 3
#endif //(MY_DEFINED_VALUE != 5)
#else //defined(MY_DEFINED_VALUE)
#error Error - MY_DEFINED_VALUE is not defined
#endif //defined(MY_DEFINED_VALUE)
class test
{
public:
int val;
test() {}
void show() { std::cout << "val = " << val << "\n"; }
};
#endif //_test_h_
test.cpp
//#define MY_DEFINED_VALUE 5
#include "test.h"
int main()
{
test t;
t.val = MY_DEFINED_VALUE;
t.show();
return 0;
}
Makefile
#=====
CC = g++
LD = g++
USERDEFINES = -DMY_DEFINED_VALUE
CFLAGS = -Wall
LDFLAGS =
RM = /bin/rm -f
SRCS = test.cpp
OBJS = test.o
PROG = test
#=====
$(PROG): $(OBJS)
$(LD) $(LDFLAGS) $(OBJS) -o $(PROG)
#=====
%.o: %.c
$(CC) $(USERDEFINES) $(CFLAGS) -c $<
#=====
clean:
$(RM) $(PROG) $(OBJS)
If I uncomment the #define in test.cpp, all is well (prints 5). If I comment it I get the #error.

The problem is in your Makefile. The %.o: %.c rule doesn't match a .cpp file, so GNU Make's built-in %.o: %.cpp rule is being triggered instead.
If you change %.o: %.c to %.o: %.cpp, it'll run fine.

Related

Why does the definition of makefile not take effect using -D?

I wrote a simple c++ code. I wanted to choose to execute one of the codes through the -D option of makefile, but it didn't execute? For example, code1 and code2.
1.main.cpp
#include "./common.h"
#include "./ns_api.h"
int TestFunc3(void)
{
}
int test = 10;
int main(int argv, char **argc)
{
extern int b;
int a = b;
printf("This is a test!\n");
#ifdef TEST_ADD
printf("test_add!\n"); //code1
#endif
#if TEST_SUB
printf("test_sub!\n"); //code2
#endif
return 0;
}
int b;
2.makefile
root#cat makefile
GPP = g++
CFLAGS += -O3
objects = *.o
src = *.cpp
test:$(objects)
$(GPP) $(CFLAGS) -o test $(objects)
$(objects):$(src)
$(GPP) -c $(src)
.PHONY:clean
clean:
rm test *.o
3.compile
root#make CFLAGS=-DTEST_ADD CFLAGS+=-DTEST_SUB=1
g++ -c *.cpp
g++ -DTEST_ADD -DTEST_SUB=1 -o test *.o
4.result:
root#./test
This is a test!

How to properly use -MD flag in Makefile

I'm trying to create a Makefile where make only recompiles necessary .cpp files.
By default, it works well if I edit .cpp, however, when I edit .h files, it just ignores the changes.
So I've read of -MD flag and its friend -MP (used to avoid bugs when typing make).
However, I can't seem to make it working, if I use -MMD, it works perfectly but I rely on system includes too as I'm writing a library too that is evolving along with the project. Thus, if I update the libary header and reinstall the library, typing make in the main project should recompiles files that includes the changed header.
When using -MMD flag, it - as expected - does not recompile the project, however, using -MD flag, it does recompile everything. In fact, -MD recompiles everything every time, even when nothing changed.
Here is a minimal project structure that reproduce the issue:
./Makefile:
all: build
re: clean build
build: build_lib install_lib build_client
build_lib:
$(MAKE) -C lib
$(MAKE) install -C lib
build_client:
$(MAKE) -C client
install_lib:
$(MAKE) install -C lib
.PHONY: clean
clean: clean_lib clean_client
clean_lib:
$(MAKE) clean -C lib
clean_client:
$(MAKE) clean -C client
./client/Makefile:
CC = g++
INC = -I../lib
CXXFLAGS = -Wall $(INC) -g -MD -MP
EXEC_NAME = ../test
src = $(shell find $(SOURCEDIR) -name '*.cpp')
obj = $(src:.cpp=.o)
LIBRARIES = -ltest_lib
LDFLAGS = -rdynamic $(LIBRARIES)
all: $(EXEC_NAME)
re: clean $(EXEC_NAME)
$(EXEC_NAME): $(obj)
$(CC) -o $# $^ $(LDFLAGS)
-include $(obj:.o=.d)
.PHONY: clean
clean:
rm -f $(obj) $(EXEC_NAME)
./lib/Makefile:
.PHONY : clean
CXXFLAGS= -fPIC -g -Itest_lib/include -MMD -MP
LDFLAGS= -shared
SOURCES = $(shell find $(SOURCEDIR) -name '*.cpp')
HEADERS = $(shell find $(SOURCEDIR) -name '*.h')
OBJECTS=$(SOURCES:.cpp=.o)
TARGET=libtest_lib.so
INC_FOLDER=test_lib/include
CUR_DIR = $(shell pwd)
all: $(TARGET)
install:
sudo rm -rf /usr/local/lib/libtest_lib.so && sudo ln -s $(CUR_DIR)/$(TARGET) /usr/local/lib/libtest_lib.so
sudo rm -rf /usr/local/include/test_lib && sudo cp -r $(INC_FOLDER) /usr/local/include/test_lib
clean:
rm -f $(OBJECTS) $(TARGET)
$(TARGET) : $(OBJECTS)
$(CC) $(CFLAGS) $(OBJECTS) -o $# $(LDFLAGS)
-include $(OBJECTS:.o=.d)
./client/main.cpp:
#include "bar.h"
int main()
{
Bar b;
b.sayHello();
b.sayBye();
return 0;
}
./client/bar.h
#ifndef __BAR__
#define __BAR__
#include <test_lib/foo.h>
#include <iostream>
struct Bar : public Foo
{
Bar() {};
~Bar() {};
void sayBye() const {
std::cout << "Bye " << name << "..." << std::endl;
};
};
#endif
./lib/test_lib/include/foo.h
#ifndef __FOO__
#define __FOO__
struct Foo
{
const char *name;
Foo(const char *name = "world");
~Foo();
void sayHello() const;
};
#endif
./lib/test_lib/src
#include "foo.h"
#include <iostream>
Foo::Foo(const char *name) : name(name) {}
Foo::~Foo() {}
void Foo::sayHello() const
{
std::cout << "Hello " << name << " !" << std::endl;
}
Problem was that I copied the library headers all the time in /usr/local so the files got newer and the client make then thought every header of the library had changed.
A simple fix to this problem was to replace in the library Makefile the following line:
sudo rm -rf /usr/local/include/test_lib && sudo cp -r $(INC_FOLDER) /usr/local/include/test_lib
by
sudo rm -rf /usr/local/include/test_lib && sudo ln -s $(CUR_DIR)/$(INC_FOLDER) /usr/local/include/test_lib
On a side note, provided example is missing the removal of .d files on the clean rule.

make error : *** missing separator. Stop

This is my makefile:
OBJECTS = main.o
CFLAGS = -g -wall
NAME = make
CC = gcc
build: $(OBJECTS)
$(CC) $(CFLAGS) $(OBJECTS) -o $(NAME)
I'm getting below error when I tried to make(Applied tab before gcc command) :
makefile:6: *** missing separator. Stop.
How can I fix this?
First of all, it looks like you have spaces instead of tab.
As for the Makefile itself, I'd make it little bit simpler. For a source file main.c:
int main() {
return 0;
}
I would go with Makefile:
CFLAGS = -g -wall
CC = gcc
main: main.c
$(CC) $(CFLAGS) $< -o $#

Makefile not pulling in include dependency

Here's the directory structure for my setup:
Matrix
│ Makefile
│
├───bin
├───include
│ matrix.h
│
├───lib
├───obj
├───rc
│ matrix.rc
│
└───src
matrix.c
matrix_mem.c
Here's the Makefile:
# This Makefile will build the Matrix Library.
TOOLCHAIN := C:\MinGW
SRCTREE := C:\Users\admin\Desktop\Matrix\Matrix
CC := $(TOOLCHAIN)\bin\gcc.exe
AR := $(TOOLCHAIN)\bin\ar.exe
WINDRES := $(TOOLCHAIN)\bin\windres.exe
SRCDIR := $(SRCTREE)\SRC
OUTDIR := $(SRCTREE)\BIN
OBJDIR := $(SRCTREE)\OBJ
RESDIR := $(SRCTREE)\RC
LIBDIR := $(SRCTREE)\LIB
INCDIR := $(SRCTREE)\INCLUDE
CFLAGS := -O3 -std=gnu89 -Wall
CFLAGS_EXTRA :=
OBJS := $(shell find $(OBJDIR) -name '*.o')
DEPS := $(OBJS:.o=.d)
-include $(DEPS)
all: dll
dll: CFLAGS_EXTRA := -DMATRIX_USE_DLL -DDLL_EXPORTS
dll: matrix.dll
static: CFLAGS_EXTRA :=
static: matrix.lib
matrix.dll: matrix_mem.o matrix.o resource.o
matrix.lib: matrix_mem.o matrix.o
%.o: $(SRCDIR)\%.c
$(CC) $(CFLAGS) -I $(INCDIR) $(CFLAGS_EXTRA) -MM -MT $(OBJDIR)\$# -MF $(patsubst %.o,%.d,$(OBJDIR)\$#) $<
$(CC) -c $(CFLAGS) -I $(INCDIR) $(CFLAGS_EXTRA) -o $(OBJDIR)\$# $<
#echo ...$(OBJS)...
%.dll:
$(CC) -shared -s -o $(OUTDIR)\$# $(patsubst %,$(OBJDIR)\\%,$^) -Wl,--subsystem,windows,--output-def,$(OUTDIR)\$*.def,--out-implib,$(OUTDIR)\$*.lib
%.lib:
$(AR) -ru $(OUTDIR)\$# $(patsubst %,$(OBJDIR)\\%,$^)
resource.o: $(RESDIR)\matrix.rc
$(WINDRES) -i $< -o $(OBJDIR)\$#
clean::
-rm $(OBJDIR)\matrix.o
-rm $(OBJDIR)\matrix_mem.o
-rm $(OBJDIR)\matrix.d
-rm $(OBJDIR)\matrix_mem.d
-rm $(OBJDIR)\resource.o
-rm $(OUTDIR)\matrix.def
-rm $(OUTDIR)\matrix.lib
-rm $(OUTDIR)\matrix.dll
The Makefile works ok under MinGW and Cygwin.
I'm still having difficulties in getting the include dependency to work.
It appears that the .d files are not getting included. Since the code compiles fine across GCC variants, I was wanting to try to compile it on Linux. I want to make minimum changes to the Makefile.
I understand that I'll have to change the path styles and other compile options.
But, as of here, how can I get make to treat include dependencies correctly, without much intertwining with the shell? I'm using make 3.80 version.
Here's a minimal source implementation:
matrix.h:
/*----------------------------- matrix.h ------------------------------*/
#ifndef __MATRIX_H_INCLUDED__
#define __MATRIX_H_INCLUDED__
#ifdef _WIN32
#ifdef MATRIX_USE_DLL
#ifdef DLL_EXPORTS
#define MATRIX_API __declspec(dllexport)
#else
#define MATRIX_API __declspec(dllimport)
#endif
#else
#define MATRIX_API
#endif
#define MATRIX_CALL __stdcall
#else
#define MATRIX_API
#define MATRIX_CALL
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef struct _Matrix {
double **data;
int m;
int n;
} Matrix;
MATRIX_API void MATRIX_CALL dummy_func2();
MATRIX_API void MATRIX_CALL dummy_func2();
#ifdef __cplusplus
}
#endif
#endif
/*---------------------------------------------------------------------*/
matrix.c:
/*----------------------------- matrix.c ------------------------------*/
#include "matrix.h"
MATRIX_API void MATRIX_CALL dummy_func1() {
return;
}
/*---------------------------------------------------------------------*/
matrix_mem.c:
/*--------------------------- matrix_mem.c ----------------------------*/
#include "matrix.h"
MATRIX_API void MATRIX_CALL dummy_func2() {
return;
}
/*---------------------------------------------------------------------*/

error: expected expression when using lambda expression in C++

When using a lambda expression my compiler shows me an error. This is the implementation (where name is a std::string&):
auto expression = [name](const Item* x) -> bool { return x->get_name() == name; };
This is the error:
items/container.cpp:20:27: error: expected expression
auto expression = [name](const Item* x) -> bool { return x->get_name() == name; };
These are my compiler flags:
CFLAGS=$(-std=c++11 -stdlib=libc++ -g -Wall -Werror -Wextra -I.)
All other C++11 features I have used have worked so far. I am using MacOS 10.11.3.
>> clang --version
Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin15.3.0
Thread model: posix
>> clang++ --version
Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin15.3.0
Thread model: posix
Unfortunately this did not help me: Clang 3.1 and C++11 support status
UPDATE: After creating a minimal example as suggested by the comments below it worked! The problem must lie in my makefile. This reproduces the error:
CC=clang++
CFLAGS=$(-stdlib=libc++ -std=c++11 -g -Wall -Werror -Wextra -I.)
all: main
main: main.o
$(CC) $(CFLAGS) -o main *.o
main.o: main.cpp
$(CC) $(CFLAGS) -c main.cpp
My main.cpp file:
#include <iostream>
#include <string>
int main() {
auto lambda = [](const std::string& str) { return str == "whatever"; };
std::string s1 = "something else";
std::string s2 = "whatever";
std::cout << "should be false: " << lambda(s1) << std::endl;
std::cout << "should be true: " << lambda(s2) << std::endl;
return 0;
}
You're misusing the $ sign in your makefile. It's for substitutions of variables so $(-stdlib=libc++ ...) would suggest you had a variable whose name started with -stdlib=... (I'm surprised this isn't giving you an error)
If you don't want a substitution and just want literal content, write it after the = sign unescaped:
CC=clang++
CFLAGS=-stdlib=libc++ -std=c++11 -g -Wall -Werror -Wextra -I.
all: main
main: main.o
$(CC) $(CFLAGS) -o main *.o
main.o: main.cpp
$(CC) $(CFLAGS) -c main.cpp

Resources