OCaml Makefile stops working after a small modification - makefile

I wish to compile my OCaml code with a Makefile at the root of the repository, this code is in another repository named step1. But for some reason, by simply adding the sources path the compilation does not work anymore?
Here is my Makefile:
DIR = step1
SRC = $(DIR)/door.ml\
$(DIR)/tile.ml\
$(DIR)/maze.ml\
$(DIR)/display.ml\
$(DIR)/main.ml
OCAMLFLAGS = -w Aelz -warn-error A -g
all: step1 step1.byte
step1: step1.native
cp $< $#
step1.byte: $(SRC)
ocamlc $(OCAMLFLAGS) $^ -o $#
step1.native: $(SRC)
ocamlopt $(OCAMLFLAGS) $^ -o $#
clean:
$(RM) *.cmo *.cmi *.o *.cmx
fclean: clean
$(RM) step1 step1.byte step1.native step2 step2.native step2.byte step3 step3.native step3.byte step4 step4.byte step4.native step5 step5.byte step5.native
re: fclean all
.PHONY: all clean fclean re
The error message I get is as follows:
ocamlopt -w Aelz -warn-error A -g step1/door.ml step1/tile.ml step1/maze.ml step1/display.ml step1/main.ml -o step1.native
File "step1/tile.ml", line 1, characters 0-9:
Error: Unbound module Door
Makefile:30: recipe for target 'step1.native' failed
make: *** [step1.native] Error 2
I have to compile using both ocamlc and ocamlopt and the executable has to be in the root of the repository.
What am I missing?

Related

How to fix "make (e=2): The system cannot find the file specified."

i want to use mingW32_make.exe to compile a C code on command prompt. The error message shows
rm -f obj/*.o
process_begin: CreateProcess(NULL, rm -f obj/*.o, ...) failed.
make (e=2): The system cannot find the file specified.
makefile:11: recipe for target 'all' failed
mingw32-make.exe: *** [all] Error 2
The makefile is show below
CC=gcc
INC_DIR=../include
LIBS=-lregex
ODIR=obj
_OBJ=main.o BVPA.o BVPA-cube.o BVPA-cif.o BVPA-hk.o BVPA-path.o BVPA-math.o BVPA-cmd.o BVPA-gui.o BVPA-vesta.o MT19937AR.o
OBJ=$(patsubst %,$(ODIR)/%,$(_OBJ))
TARGET=../bin/BVPA_win.exe
CFLAGS=-I$(INC_DIR) -Wall -g
all: $(TARGET)
rm -f $(ODIR)/*.o
$(TARGET): $(OBJ)
$(CC) $(CFLAGS) -o $# $^ $(LIBS)
$(ODIR)/%.o: %.c
$(CC) $(CFLAGS) -c -o $# $^
clean:
rm -f $(ODIR)/*.o
'''
I have encountered the same question and here is the fix. The reason is given from other's comments:
Windows does not understand rm.
When you run make clean, it will clear out all .o files.
clean:
del *.o
The answer for this question is actually simple. There is no obj folder in your current directory so the compiler doesn't know where to add or remove. You can simply add a obj folder in your source code directory.
I come across the same issue, and my solution is below
del /f $(ODIR)\*.o
Note that if I use "$(ODIR)/*.o" in the makefile, the error would still exist.

Makefile can't find input files in specified directory

I am working with the following Makefile:
CFLAGS=-g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG $(OPTFLAGS)
LIBS=-ldl $(OPTLIBS)
PREFIX?=/usr/local
SOURCES=$(wildcard src/lcthw/*.c src/*.c)
OBJECTS=$(patsubst %.c,%.o,$(SOURCES))
TEST_SRC=$(wildcard tests/*_tests.c)
TESTS=$(patsubst %.c,%,$(TEST_SRC))
TARGET=build/libYOUR_LIBRARY.a
SO_TARGET=$(patsubst %.a,%.so,$(TARGET))
all: $(TARGET) $(SO_TARGET) tests
dev: CFLAGS=-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
.PHONY: tests
tests: CFLAGS += $(TARGET)
tests: $(TESTS)
sh ./tests/runtests.sh
valgrind:
VALGRIND="valgrind --log-file=/tmp/valgrind-%p.log" $(MAKE)
# The Cleaner
clean:
rm -rf build $(OBJECTS) $(TESTS)
rm -f tests/tests.log
find . -name "*.gc*" -exec rm {} \;
rm -rf `find . -name "*.dSYM" -print`
install: all
install -d $(DESTDIR)/$(PREFIX)/lib/
install $(TARGET) $(DESTDIR)/$(PREFIX)/lib/
And I'm having trouble with this line:
$(CC) -shared -o $# $(OBJECTS)
I am getting the error:
cc: fatal error: no input files
when I try and run any of the following commands: make, make all and make dev. Why can't my makefile find the .c files in the directories I specified?
You need to specify the full paths in this line:
SOURCES=$(wildcard src/lcthw/.c src/.c)
OTW this becomes a constraint on where you can run the make command from. Possibly what's happening is that the wildcards are not being expanded since the directory you are sitting in, $(CURDIR) , makes it hard for it to see these paths.
You should try printing these variables from inside your makefile, by doing:
$(info source=$(SOURCES))
And if your .obj files are placed in a different location than the sources, then you need to account for that by including that place in the $(OBJECTS) as well.

Makefile - link input file from folder

I try to compile a project with generated object stored in a sub directory :
myproject:
|
src: .cpp, .cpp ...
|
release: .o, .o ...
Here's a part of Makefile:
SRC ?= src
OBJ_PATH = $(SRC)/Release
vpath %.o $(OBJ_PATH)
...
OBJS := $(addprefix $(OBJ_PATH)/,obj1.o obj2.o )
all: build
obj1.o: $(SRC)/Manager.cpp
$(EXEC) $(CC) $(INCLUDES) $(CCFLAGS) $(GNCD_FLGS) -c $(<) -o $(OBJ_PATH)/$# #-o $# -c $<
obj2.o: $(SRC)/Synth.cpp
$(EXEC) $(CC) $(INCLUDES) $(CCFLAGS) $(GNCD_FLGS) $(DEFS) -c $(<) -o $(OBJ_PATH)/$# #-o $# -c $<
myApp: obj1.o obj2.o
$(EXEC) $(CC) $(LDFLAGS) $(GNCD_FLGS) -o $# $(OBJS) $+ $(LIBS)
$(EXEC) mkdir -p $(OBJ_PATH)/$(TRGT_ARCH)/$(TRGT_OS)/$(BLD_TP)
$(EXEC) cp $# $(OBJ_PATH)/$(TRGT_ARCH)/$(TRGT_OS)/$(BLD_TP)
$(OBJECTS) : Stt.h
build: myApp
run: build
$(EXEC) ./myApp
..but i got an error link:
Could not open input file 'obj1.o'
Makefile:86: recipe for target 'myApp' failed
So it seems couldn't find object in src/Release dir;
any ideas ?
thank's
Your recipe for myApp use $+, which list the prerequisites. It expands in obj1.o obj2.o. But you build obj1.o and obj2.o in $(OBJ_PATH). So the linker try to find the objects in the root directory, but cannot find them, since they are in $(OBJ_PATH).
Since your recipe explicitely lists them (with $(OBJS)), you do not need the automatic variable.
Sidenote
According to Paul's Second rule of Makefiles, it is best that every rule updates a file corresponding exactly to the target name (including the path part) (in other words, always use $# in the recipe), in order to always know which is the exact file updated.
In your case, if you want to build the objects files in OBJ_PATH, you could use a rule of the form $(OBJ_PATH)/obj.o for each.
You could also replace the dependency of myApp by $(OBJS), and use the automatic variable (btw, is there a reason why you prefer $+ over $^ (does the same thing but do not conserv duplicates in the prerequisites list) ?).

Makefile to support 2 executables

I am trying to update my Makefile to support building a binary of my project, and a binary of some Unit Tests.
My directory structure is the following
|-code/
|--|--src/
|--|--inc/
|
|-tests/
|--|--src/
|--|--inc/
My makefile compiles the binary from code well, but is having some issues with the test. The test folder contains some unit test that tests some classes in code/src/. I have a file main.cpp in code/src/ that contains the main() function, and also another file, called test.cpp in tests/src that contains its own main() function.
This led me to this complicated Makefile:
CC = g++
FLAGS = -g -c -Wall
INCLUDEDIR = -Icode/inc -Itests/inc
BUILDDIR = build
SOURCEDIR = code/src
SOURCES = $(wildcard $(addsuffix /*.cpp,$(SOURCEDIR)))
TEMP_OBJ = $(SOURCES:%.cpp=%.o)
NOT_DIR = $(notdir $(TEMP_OBJ))
OBJECTS = $(addprefix $(BUILDDIR)/, $(NOT_DIR))
TEST_DIR = tests/src
TEST_SOURCES = $(wildcard $(addsuffix /*.cpp,$(TEST_DIR)))
TEST_TEMP_OBJ = $(TEST_SOURCES:%.cpp=%.o)
TEST_NOT_DIR = $(notdir $(TEST_TEMP_OBJ))
TEST_OBJECTS = $(addprefix $(BUILDDIR)/, $(TEST_NOT_DIR))
EXECUTABLE = Client
TEST_EXECUTABLE = TestUnit
all: $(BUILDDIR) $(BUILDDIR)/$(EXECUTABLE) $(BUILDDIR)/$(TEST_EXECUTABLE)
$(BUILDDIR):
mkdir -p $#
$(BUILDDIR)/$(EXECUTABLE): $(OBJECTS)
$(CC) $^ -o $#
$(BUILDDIR)/%.o : code/src/%.cpp
$(CC) $(FLAGS) $< $(INCLUDEDIR) -o $#
$(BUILDDIR)/$(TEST_EXECUTABLE): $(OBJECTS) $(TEST_OBJECTS)
#rm -f $(BUILDDIR)/main.o
$(CC) $^ -o $#
$(BUILDDIR)/%.o : tests/src/%.cpp
$(CC) $(FLAGS) $< $(INCLUDEDIR) -o $#
clean:
rm -rf $(BUILDDIR)
It fails with the error:
g++: error: build/main.o: No such file or directory
make: *** [build/TestUnit] Error 1
Which is because I have the line:
#rm -f $(BUILDDIR)/main.o
but otherwise I would get the error (there is main in main.cpp and test.cpp in code/src/ and tests/code/ respectively):
/tests/src/test.cpp:7: multiple definition of `main'
code/src/main.cpp:6: first defined here
collect2: error: ld returned 1 exit status
There is a lot of duplication in my Makefile, and I would love to get something more succinct that achieves the purpose of building 2 binaries from those 2 folders, although code is shared.
Any help would please be appreciated. Thank you very much!
There are a number of problems with this makefile.
First, there is no rule to build test object files, such as test.o. The only rule for building objects requires that the source be in code/src/; I don't know how you even get far enough to see a linker error.
Let's change the object rule to a static pattern rule:
$(OBJECTS) : $(BUILDDIR)/%.o : code/src/%.cpp
$(CC) $(FLAGS) $< $(INCLUDEDIR) -o $#
Then we can add an additional rule for the test objects:
$(TEST_OBJECTS) : $(BUILDDIR)/%.o : tests/src/%.cpp
$(CC) $(FLAGS) $< $(INCLUDEDIR) -o $#
(Never mind the redundancy for now-- we have to get it working first.)
Now we should see a linker error in this rule:
$(BUILDDIR)/$(TEST_EXECUTABLE): $(OBJECTS) $(TEST_OBJECTS)
...
In that list of prerequisites are two files, main.o and test.o fighting over who gets to define main(). We want test.o, so main.o must go:
$(BUILDDIR)/$(TEST_EXECUTABLE): $(filter-out build/main.o,$(OBJECTS)) $(TEST_OBJECTS)
...
Try this much and tell us the result. Once it's working we can slim it down.

Troubles with my Makefile

I downloaded this Makefile and I'm having a hard time understanding how it works.
I am programming in Ocaml and for some module, I implemented an interface (.mli). Strangely, even when I add the .mli file before the corresponding .ml file, the Makefile seems to skip it; so I'm getting the error
could not find the X.cmi for the module X.
Worse, I added some file without the required .mli and strangely again the Makefile automatically added them to the list of sources.
I'm saying strangely but perhaps its perfectly normal to Makefiles expert.
I'm not an expert when it comes to Makefile, can anyone help me understanding how this Makefile works?
The compilation works fine, when I replace the line
$(EXEC): $(OBJS)
$(CAMLC) $(CUSTOM) -o $(EXEC) $(LIBS) $(OBJS)
With
$(EXEC): $(SOURCES)
$(CAMLC) $(CUSTOM) -o $(EXEC) $(LIBS) $(SOURCES)
and add the required .mli
Try
# Makefile
PRG =
# Fichiers dans l'ordre
ML =
MLI =
CMO=${ML:.ml=.cmo}
CMX=${ML:.ml=.cmx}
CMI=${ML:.mli=.cmi}
OCAMLFLAGS = -I
OCAMLLD = -ccopt -L.
OCAMLOPT = ocamlopt.opt
OCAMLC = ocamlc.opt
OCAMLDEP = ocamldep
${PRG}: ${OCAMLOPT} ${OCAMLFLAGS} ${OCAMLLD} -o $# ${CMX}
make clean
.SUFFIXES: .ml .mli .cmo .cmx .cmi
.ml.cmx:
${OCAMLOPT} ${OCAMLFLAGS} ${OCAMLLD} -c $<
.ml.cmo:
${OCAMLC} -c $<
.mli.cmi:
${OCAMLC} -c $<
clean:
rm -f *~ *.o *.cm? *mli
fullclean: clean
rm -f .depend ${PRG}
depend: .depend
.depend: ${ML} ${MLI}
rm -f .depend
${OCAMLDEP} ${ML} ${MLI} > .depend
include .depend
You'll have to setup PRG, ML, MLI, FLAGS, LD. :)

Resources