Linking LLVM IR Libraries - c++

I am following along with the LLVM Kaleidoscope Tutorial (Ch. 3), and am encountering errors (undoubtedly from my Makefile) after attempting to link LLVM IR libraries. My Makefile and project structure:
CPP=clang++
CFLAGS=-g -Wall -std=c++14
LDFLAGS:=$(shell llvm-config --cxxflags --ldflags --system-libs --libs core)
EXEC=comp.out
SRCS:=$(shell find src -type f -name '*.cpp')
OBJS:=$(patsubst %.cpp,%.o,$(SRCS))
all: $(EXEC)
$(EXEC): $(OBJS)
$(CPP) $(CFLAGS) -o $# $^
src/%.o: src/%.cpp
$(CPP) $(CFLAGS) $(LDFLAGS) -o $# $<
src/ast/%.o: src/ast/%.cpp
$(CPP) $(CFLAGS) $(LDFLAGS) -o $# $<
.PHONY: clean
clean:
rm -f $(shell find src -type f -name '*.o')
rm -f $(EXEC)
.
└── src
├── main.cpp
├── [.cpp files]
│
├── ast
│ ├── [.cpp files]
│ │
│   └── include
│ └── [.h files]
│
└── include
└── [.h files]
When Making, I get the error:
clang++ -g -Wall -std=c++14 -I/usr/local/Cellar/llvm/12.0.1/include -std=c++14 -stdlib=libc++ -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -L/usr/local/Cellar/llvm/12.0.1/lib -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM-12 src/IMRep.cpp -o src/IMRep.o
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-12: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [Makefile:19: src/IMRep.o] Error 1
From the error above, main.cpp is never compiled before compilation errors out. It only gets to the src/IMRep.cpp file (not sure if that matters). If I add the -c flag to make it:
src/%.o: src/%.cpp
$(CPP) $(CFLAGS) $(LDFLAGS) -c $< -o $#
src/ast/%.o: src/ast/%.cpp
$(CPP) $(CFLAGS) $(LDFLAGS) -c $< -o $#
I am able to run the program successfully despite the plethora of warning messages saying the linker inputs/arguments are unused. These warnings are expected because -c only compiles and doesn't link.
And in main.cpp:
#include <iostream>
int main(int argc, char *argv[])
{
return 0;
}
So this question doesn't get flagged as a dupe:
[1]: main.cpp is included in OBJS
[2]: Added -c flag and receive many warnings about unused linker arguments/input (because -c is for compilation, not linkage)
[3]: I only use $< where there is one dependency and $^ where there are multiple
[4]: Can't apply the answer to this question
[5]: All files in SRCS and OBJS are the correct files. I verified this by making a 'verbose' rule and printing those values and make verbose
Which leads me to believe that I am not linking in these libraries correctly.

Your question is, in fact, a duplicate of the #2 answer there.
When you want to create an object file you MUST use the -c option. That's what the -c option means.
If you don't want "a plethora of warning messages saying the linker inputs/arguments are unused" then, you know, don't add the linker inputs and arguments when you generate object files! Those arguments are for linking, not compiling.
Your .o rules should be:
src/%.o: src/%.cpp
$(CPP) $(CFLAGS) -c $< -o $#
src/ast/%.o: src/ast/%.cpp
$(CPP) $(CFLAGS) -c $< -o $#
Just to point out you don't need both of the above pattern rules. If you want the object files to live in the same directory as the source files you can just write:
%.o: %.cpp
$(CPP) $(CFLAGS) -c $< -o $#
And, if you switched to using the standard make variables instead of using non-standard ones:
# CPP is the C preprocessor, not C++
CXX = clang++
# CFLAGS is flags for the C compiler, not C++
CXXFLAGS := -g -Wall -std=c++14 $(shell llvm-config --cxxflags core)
LDFLAGS := $(shell llvm-config --ldflags --system-libs --libs core)
then you wouldn't need to define your own pattern rule at all because make has a built-in rule which knows how to compile a C++ source file into an object file.

Related

Makefile not giving the expected compilation results

I am quite new to Make. I am attempting to write a Makefile to build a medium-sized Linux C/C++ application as below.
Making a simple Makefile by having all source files in one location and explicitly listing the source files works ok for me but I would like it to be more generic.
I have all my source files (C and C++) in the src folder in different subdirectories. I have header files inside an inc and inc/common folder, and then libs inside a lib folder.
The Makefile is run on the same level :
SRC_DIR := src
OBJ_DIR := obj
BIN_DIR := bin
CXX := /bin/arm-linux-gnueabi-g++
EXE := $(BIN_DIR)/runfile
SRC := $(shell find $(SRC_DIR) -name *.cpp -or -name *.c)
OBJ := $(patsubst $(SRC_DIR)/%,$(OBJ_DIR)/%,$(addsuffix .o,$(basename $(SRC))))
CPPFLAGS := -Iinc -Iinc/common -MMD -MP
CXXFLAGS := -std=c++11 -Wall
LDFLAGS := -Llib
LDLIBS :=
.PHONY: all clean
all: $(EXE)
$(EXE): $(OBJ) | $(BIN_DIR)
$(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $#
$(OBJ_DIR)/%.o: $(SRC) | $(OBJ_DIR)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $#
$(BIN_DIR) $(OBJ_DIR):
mkdir -p $#
clean:
#$(RM) -rv $(BIN_DIR) $(OBJ_DIR)
-include $(OBJ:.o=.d)
I get lots of errors such as below when I run it, including problems opening dependency files. I think i'm almost there, but can't see my error exactly :
compilation terminated.
/bin/arm-linux-gnueabi-g++ -Iinc -Iinc/common -MMD -MP -std=c++11 -Wall -c -o obj/main.d.o
cc -Llib obj/main.d.o -o obj/main.d
/usr/bin/ld: obj/main.d.o: relocations in generic ELF (EM: 40)
/usr/bin/ld: obj/main.d.o: relocations in generic ELF (EM: 40)
/usr/bin/ld: obj/main.d.o: error adding symbols: file in wrong format
I don't see how the output you show can be generated from the makefile you show here but anyway.
This is not right:
$(OBJ_DIR)/%.o: $(SRC) | $(OBJ_DIR)
A pattern rule is a template that tells make "if you want to build a target that matches this pattern, then you can build it from the prerequisites that match this pattern".
Here you are listing ALL your source files as a prerequisite for EVERY object file. Suppose SRC is set to foo.c bar.c biz.c baz.c, then this expands to:
obj/%.o : foo.c bar.c biz.c baz.c | obj
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $#
You're telling make that every single .o target depends on ALL the source files, not just the one for that object file. Further, the automatic variable $< always expands to the first prerequisite, which here will always be foo.c. So, you're compiling foo.c four times, creating each of the object files.
The very first important rule when debugging makefiles is to look carefully at the output (command lines) that make prints. If they are not right, then your makefile is not right. If you do that you'll see all the compile lines are compiling the same source, like:
g++ -c foo.c -o obj/foo.o
g++ -c foo.c -o obj/bar.o
g++ -c foo.c -o obj/biz.o
g++ -c foo.c -o obj/baz.o
That clearly cannot work and it's why you get link errors trying to link together all these object files: they all have the same content.
You need this:
$(OBJ_DIR)/%.o : $(SRC_DIR)/%.cpp
#mkdir -p $(#D)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $#
which tells make how to build an object file from a single source file.
You also need to create the actual output directory that the object file will go into. Just creating $(OBJ_DIR) is not enough, if the object file appears in a subdirectory.

How to compile different files by storing their names in a variable in makefile

I have a problem with a makefile that I was not able to resolve.
I have this structure of files and folders.
├───bin
├───include
│ des.hh
│ des_CR.hh
│ des_CX.hh
│ des_JAK.hh
│ des_JK.hh
│ des_testbench.hh
│ des_VA1.hh
│
├───obj
└───src
des.cc
des_CR.cc
des_CX.cc
des_JAK.cc
des_JK.cc
des_testbench.cc
des_VA1.cc
main_des.cc
I write the makefile in this way (here I put a small part):
DESIGN_NAME=des
FULL_NAME=$(basename $(shell find ./src -name $(DESIGN_NAME)'_[A-Z]*.cc' -type f -printf "%f\t"))
EXECUTABLE=bin/$(DESIGN_NAME).x
SYSTEMC=$$SYSTEMC_HOME
LIBDIR = $(SYSC_LIBDIR)
LIBS = $(SYSC_LIBDIR)/libsystemc.a -lpthread
INCDIR = -I./include/ -I. -I$(SYSTEMC)/include/
CXX=g++
CFLAGS= -c
$(EXECUTABLE): obj/main_$(DESIGN_NAME).o obj/$(DESIGN_NAME)_testbench.o obj/$(FULL_NAME).o obj/$(DESIGN_NAME).o
#echo Building $#
$(CXX) -g $(INCDIR) -o $# $^ $(LIBDIR)/libsystemc.a -lpthread
obj/main_$(DESIGN_NAME).o: src/main_$(DESIGN_NAME).cc
#echo Building $#
$(CXX) -g $(CFLAGS) $(INCDIR) -o $# $<
obj/$(DESIGN_NAME)_testbench.o: src/$(DESIGN_NAME)_testbench.cc include/$(DESIGN_NAME)_testbench.hh
#echo Building $#
$(CXX) -g $(CFLAGS) $(INCDIR) -o $# $<
obj/$(FULL_NAME).o: src/$(FULL_NAME).cc include/$(FULL_NAME).hh
#echo Building $#
$(CXX) -g $(CFLAGS) $(INCDIR) -o $# $<
obj/$(DESIGN_NAME).o: src/$(DESIGN_NAME).cc include/$(DESIGN_NAME).hh
#echo Building $#
$(CXX) -g $(CFLAGS) $(INCDIR) -o $# $<
The variable FULL_NAME is used to get a list of all files that starts with "des_" and compile them.
All works, except for the fact that when FULL_NAME contains more file names, as it will be, it says this:
g++ src/des_CX.cc -o src/des_CX
src/des_CX.cc:1:29: fatal error: des_CX.hh: No such file or directory
compilation terminated.
<builtin>: recipe for target 'src/des_CX' failed
make: *** [src/des_CX] Error 1
Every cc file has an include directive like this (obviously with the corresponding correct name):
#include "des_CX.hh"
I repeat, it works if FULL_NAME has only one name, as the other variable, if it has more than one it returns the error.
Any suggestions? Maybe someone knows a better way to get file names, this is an attempt that i made but I'm not sure that it is correct, probably the error is here. Thank you in advance and sorry for the long message.

Makefile not building objects how I'm telling it to

This is my project directory file tree:
.
├── entity.cpp
├── entity.hpp
├── entitytypes.hpp
├── main.cpp
├── Makefile
├── player.cpp
└── player.hpp
Makefile's contents is this:
CC=g++
CFLAGS=-Wall -pg
LDFLAGS=-lsfml-graphics -lsfml-window -lsfml-system
EXE=gametest
all: $(EXE)
%.o: %.c
$(CC) -c $< -o $# $(CFLAGS)
$(EXE): main.o entity.o player.o
g++ $^ -o $# $(LDFLAGS)
And very oddly, this is the output when I type make:
g++ -c -o main.o main.cpp
g++ -c -o entity.o entity.cpp
g++ -c -o player.o player.cpp
g++ main.o entity.o player.o -o gametest -lsfml-graphics -lsfml-window -lsfml-system
So as you can see, the last line of the output corresponds to the $(EXE) section of the Makefile. It's linking the program with the correct flags, etc. My problem is that when each individual object file is build, it's not at all taking into account my %.o: %.c rule. This is clear since when it builds the objects, there is a long gap between g++ and -c, which I didn't write. Also, it's missing out my $(CFLAGS). Even weirder, when I comment out the %.o: %.c section, the Makefile does the exact same thing.
It seems to me like it's using some kind of default build command, and just ignoring mine.
I've looked at Makefiles I've written in the past which as far as I can tell use the exact same macros in the same way, so I'm very confused as to why this is happening.
You named your files as *.cpp while your rules said *.c, that's why.
It looks like a half converted Makefile for C. It uses the wrong variables and looks for C files rather than C++. Try this (untested):
CXX := g++
CXXFLAGS := -Wall -pg
LDFLAGS := -lsfml-graphics -lsfml-window -lsfml-system
EXE := gametest
all: $(EXE)
%.o: %.cpp
$(CXX) -c $(CXXFLAGS) -o $# $<
$(EXE): main.o entity.o player.o
$(CXX) -o $# $^ $(LDFLAGS)
C++ uses CXX whereas C uses CC, same with CXXFLAGS.
Note: Remember the indentations are TABs not spaces!
The built-in %.o: %.cpp rule uses CXX (not CC) to specify the compiler, and CXXFLAGS (not CFLAGS) for the flags. So re-write your Makefile to set those variables, and you don't need to specify the pattern rule yourself:
CXX = g++
CXXFLAGS = -Wall -Wextra -pg
LIBS = -lsfml-graphics -lsfml-window -lsfml-system
gametest: main.o entity.o player.o
gametest: LINK.o = LINK.cc

Makefile exits with fatal error

I have a project with following structure:
$ tree
.
├── bin
├── include
│   └── reader.h
├── Makefile
├── obj
└── src
├── main.cpp
└── reader.cpp
4 directories, 4 files
I want to have .cpp file in src/, headers in include/ , compile object files in obj/ and executables in bin/. I use GNU make in version 4.1, g++ in version 7.2.0 and Ubuntu 17.10. When I try to build it (I try to use ideas from here, slightly modified) I get following error:
$ make
make: Circular obj/main.o <- obj/main.o dependency dropped.
make: Circular obj/reader.o <- obj/main.o dependency dropped.
make: Circular obj/reader.o <- obj/reader.o dependency dropped.
g++ -c -o obj/obj/reader.o include/reader.h
In file included from <command-line>:0:0:
/usr/include/stdc-predef.h:1:0: fatal error: can’t create precompiled header obj/obj/reader.o: No such file or directory
/* Copyright (C) 1991-2017 Free Software Foundation, Inc.
compilation terminated.
Makefile:15: recipe for target 'obj/reader.o' failed
make: *** [obj/reader.o] Error 1
I am new to makefiles, so I guess it's something very basic. How can I fix this?
EDIT I forgot about Makefile`. Here we go:
IDIR = include
OBJDIR = obj
CXX = g++
CXXFLAGS = -g -Wall -std=c++14 -I$(IDIR)
DEPS = reader.h
_DEPS = reader.h
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
_OBJ = main.o reader.o
OBJ = $(patsubst %,$(OBJDIR)/%,$(_OBJ))
$(OBJDIR)/%.o: $(OBJ) $(DEPS)
$(CXX) -c -o $(OBJDIR)/$# $< $(CFLAGS)
main: $(OBJ)
$(CXX) -o $# $^ $(CXXFLAGS)
EDIT2 After changing language to English I understood the warnings I had.
I deleted redundant $(OBJDIR) part from $(OBJDIR)/%.o directive and ended up with something like this:
IDIR = include
OBJDIR = obj
CXX = g++
CXXFLAGS = -g -Wall -std=c++14 -I$(IDIR)
DEPS = reader.h
_DEPS = reader.h
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
_OBJ = main.o reader.o
OBJ = $(patsubst %,$(OBJDIR)/%,$(_OBJ))
$(OBJDIR)/%.o: $(OBJ) $(DEPS)
$(CXX) -c -o $# $< $(CFLAGS)
main: $(OBJ)
$(CXX) -o $# $^ $(CXXFLAGS)
and new errors:
$ make
make: Circular obj/main.o <- obj/main.o dependency dropped.
make: Circular obj/reader.o <- obj/main.o dependency dropped.
make: Circular obj/reader.o <- obj/reader.o dependency dropped.
g++ -c -o obj/main.o obj/reader.o
g++: warning: obj/reader.o: linker input file unused because linking not done
g++ -o main obj/main.o obj/reader.o -g -Wall -std=c++14 -Iinclude
g++: error: obj/main.o: No such file or directory
Makefile:18: recipe for target 'main' failed
make: *** [main] Error 1
$(OBJDIR)/%.o: $(OBJ) $(DEPS) makes no sense. You're saying every object file depends on itself (and also all other object files). That's why make is complaining Circular obj/main.o <- obj/main.o dependency dropped.. $(OBJ) shouldn't be there.
$(CXX) -c -o $# $< $(CFLAGS) is broken because $< is the first prerequisite, which in this case is obj/reader.o. It's like you're trying to compile one object file into another, which makes no sense.
Also, why are you using $(CFLAGS) here? You're compiling C++, so it should be $(CXXFLAGS) (your code never sets CFLAGS anyway).
Your Makefile never mentions any cpp files. This cannot work.
I would throw away your Makefile and start with something simple:
CXXFLAGS = -g -Wall -std=c++14 -Iinclude
bin/main: obj/main.o obj/reader.o
$(CXX) -o $# $(LDFLAGS) $+ $(LDLIBS)
obj/main.o: src/main.cpp include/reader.h
obj/reader.o: src/reader.cpp include/reader.h
This should be all you need.

Confused how my Makefile is remaking object files

My make file is failing to find my include directory when it tries to remake object files. For example, when I call make tests I get the output:
g++ -c -o sdl_class.o sdl_class.cpp
sdl_class.cpp:9:23: fatal error: sdl_class.h: No such file or directory
#include <sdl_class.h>
^
compilation terminated.
make: *** [sdl_class.o] Error 1
My Makefile is this:
#Originally from: http://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/
#But will be heavily modified
IDIR =../include
CC=g++
CFLAGS=-w -I$(IDIR)
#ODIR=obj
LDIR =../lib
LIBS=-lSDL2
_DEPS = sdl_class.h SDL_image.h
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
OBJ = sdl_class.o tests.o
#OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
%.o: %.cpp $(DEPS)
$(CC) -c -o $# $< $(CFLAGS) $(LIBS)
tests: sdl_class.o tests.o
$(CC) -o $# $^ $(CFLAGS) $(LIBS)
all: $(OBJ)
$(CC) -o $# $^ $(CFLAGS) $(LIBS)
.PHONY: clean
clean:
rm -f *.o *~ core $(IDIR)/*~
My understanding is that when I call make tests, that it should attempt to remake the sdl_class.o file. This should then call the %.o rule, which should try to make the object file by calling something like:
g++ -c -o sdl_class.o sdl_class.cpp -w -I../include -lSDL2
However, this is not the case as it looks like it is calling $(CC) -c -o $# $< $(CFLAGS) $(LIBS), as you can see from above.
Do I have a fundamental misunderstanding about how make builds its rules? Seems likely, this is my first Makefile. Perhaps I am confused on how compilation works in general, as I'm somewhat new to that as well.
I would say that the problem is that one or more of the files ../include/sdl_class.h or ../include/SDL_image.h does not exist. Because of that, make is deciding that your pattern rule does not match (because not all the prerequisites can be found or made) and it defaults to the built-in rule to create object files from .cpp files.
The built-in rules use the make variables CXX for the C++ compiler and CXXFLAGS for the C++ flags: the CC and CFLAGS variables are used for the C compiler. That's why your settings for CFLAGS are being ignored.
If you run make -d sdl_class.o you'll see which file make is looking for and why it decides to not use your pattern rule.
If you rewrite your rules like this it will work better:
%.o: %.cpp
$(CC) -c -o $# $< $(CFLAGS)
sdl_class.o tests.o: $(DEPS)
because make will now complain that the relevant files can't be found or created.
There are other issues, of course. You shouldn't be passing $(LIBS) to your compile command; that belongs only in your link line. And, you should probably stick to the standard variables CXX for the C++ compiler, CPPFLAGS for preprocessor flags like -I and -D, and CXXFLAGS for C++ compiler flags. Also, linker library flags like -L../lib go in LDFLAGS and linker libraries like -lSDL2 go in LDLIBS.
CC/CCFLAGS are for C compilation. You should use CXX and CXXFLAGS for C++. They are used in built-in rules and in the LINK.cc macro, making the Makefile much simpler, and thus less error prone.
CXXFLAGS = -Wall ...
prog : foo.o bar.o
$(LINK.cc) -o $# $^
see Default linker setting in Makefile for linking C++ object files