I'm trying to create a makefile that will works on both OSX and Linux.
My problem is I need to change cflags and ldflags depending on OS the makefile is executed but I can't make it work. That's my makefile :
OS:=$(shell uname)
DST=hello
SRC=$(wildcard *.cpp)
OBJ=$(SRC:.cpp=.o)
CFLAGS=
all: clean DetectOS $(DST)
DetectOS:
ifeq ($(OS),Darwin)
#echo OS : $(OS)
CC=g++
LDFLAGS="-lm -framework OpenCL"
CFLAGS+=-O3
endif
ifeq ($(OS),Linux)
#Coming soon...
endif
$(DST): $(OBJ)
$(CC) -o $# $^ $(LDFLAGS)
%.o: %.cpp
$(CC) -o $# -c $< $(CFLAGS)
clean:
rm -rf *.o $(DST)
But when I run this code, neither cflags, ldflags or CC are updated in the ifeq conditional block. I get the following result :
$ make
rm -rf *.o hello
OS : Darwin
CC=g++
LDFLAGS="-lm -framework OpenCL"
CFLAGS+=-O3
cc -o opencl.o -c opencl.cpp
cc -o hello opencl.o
Undefined symbols for architecture x86_64:....
As you can see, the OS is detected because we went in the ifeq conditional block, but CC isn't updated and keep a non-initialized value of cc. Finally the linker process fails because OpenCL is not referenced in ldflags.
An other little point, if I don't put quotes in LDFLAGS="-lm -framework OpenCL" I get the error :
LDFLAGS=-lm -framework OpenCL
/bin/sh: -framework: command not found
make: *** [DetectOS] Error 127
And based on multiple exemples (here on stackoverflow) I should do it without quotes.
I'm currently on Mac OS X Yosemite.
I think the ifeq block should not go into the make target, but just to the front of the makefile (before all:).
I.e. like this:
OS:=$(shell uname)
DST=hello
SRC=$(wildcard *.cpp)
OBJ=$(SRC:.cpp=.o)
CFLAGS=
ifeq ($(OS),Darwin)
$(info OS is $(OS))
CC=g++
LDFLAGS=-lm -framework OpenCL
CFLAGS+=-O3
endif
ifeq ($(OS),Linux)
#Coming soon...
endif
all: clean $(DST)
...
(no "DetectOS" target, using info instead of echo)
Related
When I make the Makefile everything works fine, I get a library in the directory dir. And when I run "Make test" I get a testfile that I want to run. But when I want to run this file I get this weird error: ./programma: error while loading shared libraries: libprogramma.so: cannot open shared object file: No such file or directory. I have tried running the program on both WSL and Linux, but nothing makes this error go away. Can anyone help me?
Here I have my Makefile which makes the library and the executable:
INC_DIR = include
SRC_DIR = src
SOURCES = $(sort $(shell find $(SRC_DIR) -name '*.cc'))
OBJECTS = $(SOURCES:.cc=.o)
DEPS = $(OBJECTS:.o=.d)
TARGET = programma
CXX = g++
CFLAGS = -Wall -Wextra -Wpedantic -std=c++11
CPPFLAGS = $(addprefix -I, $(INC_DIR))
.PHONY: all clean debug release
release: CFLAGS += -O3 -DNDEBUG
release: all
debug: CFLAGS += -O0 -DDEBUG -ggdb3
debug: all
all: $(TARGET)
clean:
rm -f $(OBJECTS) $(DEPS) lib/*.so programma *.d
$(TARGET): $(OBJECTS)
$(CXX) $(CFLAGS) $(CPPFLAGS) -fPIC -shared -o lib/lib$#.so $^
-include $(DEPS)
%.o: %.cc
$(CXX) $(CFLAGS) $(CPPFLAGS) -fPIC -MMD -o $# -c $<
test:
$(CXX) $(CFLAGS) -L./lib $(CPPFLAGS) -MMD -o programma tests/main.cc -l$(TARGET)
Executables on Linux don't look for shared libraries in the directory they're located in, at least by default.
You can either fix that at link-time, by passing -Wl,-rpath='$ORIGIN', or at runtime, by setting LD_LIBRARY_PATH env variable to the directory with the library. (LD_LIBRARY_PATH=path/to/lib ./programma)
I'm trying to build a python wrapper using the following Makefile:
CC=/usr/local/opt/llvm/bin/clang
OS_NAME=$(shell uname -s)
ifeq ($(OS_NAME),Linux)
LAPACKLDFLAGS=/usr/lib64/atlas/libsatlas.so # single-threaded blas
#LAPACKLDFLAGS=/usr/lib64/atlas/libtatlas.so # multi-threaded blas
#BLAS_THREADING=-D MULTITHREADED_BLAS # remove this if wrong
endif
ifeq ($(OS_NAME),Darwin) # Mac OS X
LAPACKLDFLAGS=-framework Accelerate # for OS X
endif
LAPACKCFLAGS=-Dinteger=int $(BLAS_THREADING)
STATICLAPACKLDFLAGS=-fPIC -Wall -g -fopenmp -static -static-libstdc++ /home/lear/douze/tmp/jpeg-6b/libjpeg.a /usr/lib64/libpng.a /usr/lib64/libz.a /usr/lib64/libblas.a /usr/lib/gcc/x86_64-redhat-linux/4.9.2/libgfortran.a /usr/lib/gcc/x86_64-redhat-linux/4.9.2/libquadmath.a # statically linked version
CFLAGS= -fPIC -Wall -g -std=c++11 $(LAPACKCFLAGS) -fopenmp -DUSE_OPENMP -O3
LDFLAGS=-fPIC -Wall -g -ljpeg -lpng -fopenmp
CPYTHONFLAGS=-I/usr/include/python2.7
SOURCES := $(shell find . -name '*.cpp' ! -name 'deepmatching_matlab.cpp')
OBJ := $(SOURCES:%.cpp=%.o)
HEADERS := $(shell find . -name '*.h')
all: deepmatching
.cpp.o: %.cpp %.h
$(CC) -o $# $(CFLAGS) -c $+
deepmatching: $(HEADERS) $(OBJ)
$(CC) -o $# $^ $(LDFLAGS) $(LAPACKLDFLAGS)
deepmatching-static: $(HEADERS) $(OBJ)
$(CC) -o $# $^ $(STATICLAPACKLDFLAGS)
python: $(HEADERS) $(OBJ)
# swig -python $(CPYTHONFLAGS) deepmatching.i # not necessary, only do if you have swig compiler
/usr/local/opt/llvm/bin/clang $(CFLAGS) -c deepmatching_wrap.c $(CPYTHONFLAGS)
/usr/local/opt/llvm/bin/clang -shared $(LDFLAGS) $(LAPACKLDFLAGS) deepmatching_wrap.o $(OBJ) -o _deepmatching.so $(LIBFLAGS)
clean:
rm -f $(OBJ) deepmatching *~ *.pyc .gdb_history deepmatching_wrap.o _deepmatching.so deepmatching.mex???
Previously, CC was set to g++, however, when I tried to build it like this, I'd get "ERROR: clang: error: unsupported option '-fopenmp".
Now I installed "brew install llvm" as this comes with the -fopenmp option. The unsupported error is resolved for now, but now the compiler doesn't seem to find a header file:
(base) MacBook-Pro-van-Brent:deepmatching BrentDeHauwere$ make python
/usr/local/opt/llvm/bin/clang -o hog.o -fPIC -Wall -g -std=c++11 -Dinteger=int -fopenmp -DUSE_OPENMP -O3 -I/usr/local/opt/llvm/include -c hog.cpp
In file included from hog.cpp:18:
In file included from ./std.h:20:
/usr/local/opt/llvm/bin/../include/c++/v1/math.h:300:15: fatal error: 'math.h' file not found
#include_next <math.h>
^~~~~~~~
1 error generated.
make: *** [hog.o] Error 1
I've tried setting options (I might have set them incorrectly) like -L/usr/local/opt/llvm/lib and -I/usr/local/opt/llvm/include, but no result so far. Any idea how I could point the compiler to the right direction for the header files?
Try running xcode-select —install in your terminal. This installs the xcode command line tools which should also install system headers files (as part of the macos sdk) and set your system include paths.
I've written a simple generic makefile for c++. It works great on Debian/Ubuntu.
I would like to know if it could be running on MAC OS. I ask the question because i have no Mac OS at home and i can't test. Furthermore, if you have some advice, let's go.
I'm not sure about these lines
CXXFLAGS += -D OSX
LDFLAGS := -stdlib=libstdc++
I precise that it for build only STL C++ programm for the moment. No dynamic libraries.
# sources (*.cpp)
SRC := sources
# headers (*.cpp)
INC := include
MAIN := kwic_personnel.cpp
EXEC := prog
# main file is in current directory or in sources file
ifneq ("$(wildcard $(MAIN))","")
sources := $(MAIN) $(wildcard $(SRC)/*.cpp)
else
sources := $(wildcard $(SRC)/*.cpp)
endif
# obj files
objects := $(sources:.cpp=.o)
# dep files
deps := $(objects:.o=.d)
CXX := g++
CXXFLAGS := -I $(INC) -MMD -MP -g -std=c++17 -Wall -pedantic -Weffc++ -Werror
# OS name
UNAME := $(shell uname -s)
# if linux
ifeq ($(UNAME), Linux)
# my own choices on compilator with Debian
LDFLAGS := -L /usr/lib/x86_64-linux-gnu
LDLIBS := -lcurl
# else but mac OS
else
# NOT SURE ABOUT THAT
CXXFLAGS += -D OSX
LDFLAGS := -stdlib=libstdc++
endif
# linking
$(EXEC) : $(objects)
#echo "Generation du fichier executable..."
$(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $#
$(RM) $(objects) $(deps)
#echo "Compilation réussie !"
# compilation of cpp files
$(SRC)/%.o: $(SRC)/%.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $^ -o $#
# remove exec
.PHONY: clean
clean:
$(RM) $(EXEC)
# dependencies
-include $(deps)
I use gnu make on both Mac and Ubuntu. I do a bunch of things I'll explain.
First my Ubuntu is via a local Docker container, and it NFS mounts my local Mac work directory. So I can edit locally on my Mac but compile for Linux. This means if I build on both, I could have a mix of different targets being built. Clearly, this is problematic, so here are some tricks.
UNAME := $(shell uname)
MACAPPEND=
LIB_ARGS= -cvrU
ifeq ($(UNAME), Darwin)
MACAPPEND=-mac
CXX=clang++
LIB_ARGS= -cvr
endif
SRCDIR := src
OBJDIR := obj${MACAPPEND}
DEPDIR := .d
BINDIR := bin${MACAPPEND}
Then it's the same ${SRCDIR} for everything, but $OBJDIR} might resolve to obj or obj-mac. Same with bin and bin-mac. I compile with this:
${OBJDIR}/%.o : %.cpp
$(COMPILE.cc) ${CXXFLAGS} $(OUTPUT_OPTION) $<
Note that I do this stuff so much, that I produce a Makefile-Base and stuff it into /usr/local/etc and then can do this:
include /usr/local/etc/Makefile-Base
If I'm making a library:
LIBNAME=show${MACAPPEND}
LIB=lib/libshow${MACAPPEND}.a
lib: ${LIB}
${LIB}: ${LIB_OBJ}
#mkdir -p lib
ar ${LIB_ARGS} ${LIB} ${LIB_OBJ}
ranlib ${LIB}
See LIB_ARGS used here and defined near the top of this post.
Note that a LOT of what I'm doing is because of the way I share my directory across both environments and might be bulding in both. There are very few things that you need to do special on Mac.
I have created Eclipse Makefile c++ project with intention to build project also without Eclipse. But I got error while run make in terminal:
Makefile:15: *** Build mode not supported by this Makefile. Stop.
How to fix that? Why I should need Eclipse Makefile if I can't build it with make?
Makefile content:
PROJECT_ROOT = $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
OBJS = boiler.o
ifeq ($(BUILD_MODE),debug)
CFLAGS += -g
else ifeq ($(BUILD_MODE),profile)
CFLAGS += -O2
else ifeq ($(BUILD_MODE),run)
CFLAGS += -O2
else ifeq ($(BUILD_MODE),linuxtools)
CFLAGS += -g -pg -fprofile-arcs -ftest-coverage
LDFLAGS += -pg -fprofile-arcs -ftest-coverage
else
$(error Build mode $(BUILD_MODE) not supported by this Makefile)
endif
all: boiler
boiler: $(OBJS)
$(CXX) $(LDFLAGS) -o $# $^
%.o: $(PROJECT_ROOT)%.cpp
$(CXX) -c $(CFLAGS) $(CXXFLAGS) $(CPPFLAGS) -o $# $<
%.o: $(PROJECT_ROOT)%.c
$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $# $<
clean:
rm -fr boiler $(OBJS)
I'm not sure exactly how you created your Makefile ...
... but the problem is clearly that your Makefile happens to rely on the variable "$(BUILD_MODE)" ...
... and, the way you're running "make", BUILD_MODE isn't being set to one of your options, or isn't being set at all.
SUGGESTION: Type this on the command line: make BUILD_MODE=debug
PS:
Equivalently, you could define BUILD_MODE as an environment variable, e.g. set BUILD_MODE=debug (DOS prompt) or export BUILD_MODE-debug (Linux term)
"BUILD_MODE" isn't "required". It's just a convention. That your "Makefile generator" happened to add when it created your particular makefile.
I seem to be going from one problem to the next ever since I decided to organize my code into subdirectories. The problems are naturally arising from the Makefile. So here's what I've currently got:
UNAME := $(shell uname)
# Directories
SOURCEDIR = src/
BUILDDIR = build/
# Compiler options
CC = clang++
DEBUG = -g
CFLAGS = -std=c++11 -Wall -c $(DEBUG)
LFLAGS = -Wall $(DEBUG)
# Files
SRC = $(wildcard $(SOURCEDIR)*.cpp) $(wildcard $(SOURCEDIR)**/*.cpp)
OBJS = $(SRC:$(SOURCEDIR)%.cpp=$(BUILDDIR)%.o)
ifeq ($(UNAME), Darwin)
LIBS = -lglfw3 -framework OpenGL -lglew -framework IOKit -framework CoreFoundation -framework ApplicationServices -framework Foundation -framework AppKit
BUILDDIR = ./build/osx/
endif
ifeq ($(UNAME), Linux)
LIBS = -lglfw -lGL -lGLEW
BUILDDIR = ./build/linux/
endif
# Build target
TARGET = test
all: $(TARGET)
$(TARGET): $(OBJS)
$(CC) $(LFLAGS) $? -o $(TARGET) $(LIBS)
$(OBJS): $(BUILDDIR)%.o : $(SOURCEDIR)%.cpp
#mkdir -p $(dir $#)
$(CC) $(CFLAGS) $< -o $#
clean:
rm -rf $(BUILDDIR)*.o $(BUILDDIR)**/*.o $(TARGET)
I was really glad when it actually compiled everything! Except when I made a change to a file, and tried to make it again, it spat this at me:
Undefined symbols for architecture x86_64:
"_main", referenced from:
implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [test] Error 1
Thing is, when I make it once more, it works just fine. The problem seems to be with resolving dependencies? And for that, I need to specify a VPATH? Well, that's the closest I've gotten, except trying to specify a VPATH hasn't made a difference. I'm probably specifying it incorrectly, or then I'm taking the wrong approach to this.
I'm pretty inexperienced when it comes to Makefiles, so I'd really appreciate some guidance!
Thanks to Etan Reisner for the solution. The problem was with the difference between $? and $^. Here's the fixed version:
UNAME := $(shell uname)
# Directories
SOURCEDIR = src/
BUILDDIR = build/
# Compiler options
CC = clang++
DEBUG = -g
CFLAGS = -std=c++11 -Wall -c $(DEBUG)
LFLAGS = -Wall $(DEBUG)
# Files
SRC = $(wildcard $(SOURCEDIR)*.cpp) $(wildcard $(SOURCEDIR)*/*.cpp)
OBJS = $(SRC:$(SOURCEDIR)%.cpp=$(BUILDDIR)%.o)
ifeq ($(UNAME), Darwin)
LIBS = -lglfw3 -framework OpenGL -lglew -framework IOKit -framework CoreFoundation -framework ApplicationServices -framework Foundation -framework AppKit
BUILDDIR = ./build/osx/
endif
ifeq ($(UNAME), Linux)
LIBS = -lglfw -lGL -lGLEW
BUILDDIR = ./build/linux/
endif
# Build target
TARGET = test
all: $(TARGET)
$(TARGET): $(OBJS)
$(CC) $(LFLAGS) $^ -o $(TARGET) $(LIBS)
$(OBJS): $(BUILDDIR)%.o : $(SOURCEDIR)%.cpp
#mkdir -p $(dir $#)
$(CC) $(CFLAGS) $< -o $#
clean:
rm -rf $(BUILDDIR)*.o $(BUILDDIR)*/*.o $(TARGET)