I have setup a simple project to test viability of VIM as C++ complier plus a simple makefile from a tutorial, but I can't seem to generate .clang_complete file from cc_args.py script.
Readme says I should run:
make CC='~/.vim/bin/cc_args.py gcc' CXX='~/.vim/bin/cc_args.py g++' -B
But it won't generate .clang_complete file from makefile.
Here is my simple project.
//hello.cpp
#include "hello.h"
int main(void)
{
hello();
return 0;
}
//hello_fn.cpp
#include <iostream>
#include "hello.h"
void hello()
{
std::cout << "Hello world!";
}
//hello.h
#ifndef HELLO_H
#define HELLO_H
void hello();
#endif
Makefile:
CC=g++
CFLAGS=-Ihead
DEPS = hello.h
OBJ = hello.cpp hello_fn.cpp
%.o: %.cpp $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
hello: $(OBJ)
g++ -o $# $^ $(CFLAGS)
hello.h is in directory called head.
Running:
make CC='.vim/bundle/clang_complete/bin/cc_args.py gcc' CXX='.vim/bundle/clang_complete/bin/cc_args.py g++' -B
or:
make CXX='.vim/bundle/clang_complete/bin/cc_args.py g++' -B
yields no .clang_complete file.
Your Makefile ignores the CC and CXX environmental variables and just uses g++ directly. Change the hello rule to
hello: $(OBJ)
$(CXX) -o $# $^ $(CFLAGS)
And then make CXX='.vim/bundle/clang_complete/bin/cc_args.py g++' -B should work.
The %.o: %.cpp $(DEPS) rule does use CC, but this rule is never used since your OBJS variable are all .cpp and not .o variables.
Related
I'm trying to run an implementation of an operating system and I get this error when I run make on the terminal, I use ubuntu 20.04.
This is the makefile:
C_SOURCES = $(wildcard kernel/*.c drivers/*.c cpu/*.c libc/*.c)
HEADERS = $(wildcard kernel/*.h drivers/*.h cpu/*.h libc/*.h)
# Nice syntax for file extension replacement
OBJ = ${C_SOURCES:.c=.o cpu/interrupt.o}
# Change this if your cross-compiler is somewhere else
CC = /usr/local/i386elfgcc/bin/i386-elf-gcc
GDB = /usr/local/i386elfgcc/bin/i386-elf-gdb
# -g: Use debugging symbols in gcc
CFLAGS = -g -ffreestanding -Wall -Wextra -fno-exceptions -m32
# First rule is run by default
os-image.bin: boot/bootsect.bin kernel.bin
cat $^ > os-image.bin
# '--oformat binary' deletes all symbols as a collateral, so we don't need
# to 'strip' them manually on this case
kernel.bin: boot/kernel_entry.o ${OBJ}
ld -melf_i386 -o -no-PIE $# -Ttext 0x1000 $^ --oformat binary
# Used for debugging purposes
kernel.elf: boot/kernel_entry.o ${OBJ}
ld -melf_i386 -o -no-PIE $# -Ttext 0x1000 $^
run: os-image.bin
qemu-system-i386 -fda os-image.bin
# Open the connection to qemu and load our kernel-object file with symbols
debug: os-image.bin kernel.elf
qemu-system-i386 -s -fda os-image.bin -d guest_errors,int &
${GDB} -ex "target remote localhost:1234" -ex "symbol-file kernel.elf"
# Generic rules for wildcards
# To make an object, always compile from its .c
%.o: %.c ${HEADERS}
${CC} ${CFLAGS} -c $< -o $#
%.o: %.asm
nasm $< -f elf -o $#
%.bin: %.asm
nasm $< -f bin -o $#
clean:
rm -rf *.bin *.dis *.o os-image.bin *.elf
rm -rf kernel/*.o boot/*.bin drivers/*.o boot/*.o cpu/*.o libc/*.o
And this is the source for the code, I wasn't able to install the cross compiler that is in the tutorial. So I tried to change the makefile to work with the default gcc:
source
You linker commands are buggy because you misplaced the -no-PIE option.
Instead of ld -o -no-PIE $#, write ld -o $# -no-PIE:
kernel.bin: boot/kernel_entry.o ${OBJ}
ld -melf_i386 -o $# -no-PIE -Ttext 0x1000 $^ --oformat binary
kernel.elf: boot/kernel_entry.o ${OBJ}
ld -melf_i386 -o $# -no-PIE -Ttext 0x1000 $^
$# is the target of your make command (here kernel.bin and kernel.elf). Misplacing it like you did, you are instructing ld to output the result as a file named -no-PIE and to use kernel.bin (resp. kernel.elf) as an input. Hence the error message since the input does not exist yet.
I have the following makefile. It works well for .f and .c files but when I have .f90 file and want to compile it with ifort does not work?
Could you please advise me where I should change and how?
Thanks you
FCOMPFLAGS = -O -ffixed-line-length-132
CCOMPFLAGS = -O
FFLAGS = $(FCOMPFLAGS) -fsecond-underscore
CFLAGS = $(CCOMPFLAGS)
LDFLAGS = $(FCOMPFLAGS)
LD = gfortran
FC = gfortran
MAKEFILE = Makefile
PROGRAM1 = f1
OBJS = f1.o \
f2.o \
f3.o
all: $(PROGRAM1)
$(PROGRAM1): $(OBJS) $(MAKEFILE)
$(LD) $(LDFLAGS) $(OBJS) -o $(PROGRAM1)
clean: #rm -f $(OBJS) core
when I execute "make" I get the following error,
make: *** No rule to make target `f1.o', needed by `f90_simple'. Stop.
It seems that My makefile does not recognize *.f90 files, and my other question is do we have flag for ifrot compiler to be used in makefile
Thanks
You need to add the implicit rule:
%.o : %.f90
<tab>$(FC) $(FCOMPLAGS) -c $<
I have an error while making my makefile in linux. Here's my code:
CC = gcc
CFLAGS = -Wall -m32 -g -fno-stack-protector -z execstack -O0
SHELL_SOURCES = Shell.c
SHELL = Shell
.PHONY: all target1 clean
all: target1
target1: $(SHELL)
$(SHELL): $(SHELL_SOURCES)
$(CC) $(CFLAGS) $^ -o $#
clean:
rm -rf $(SHELL)
The error I get is:
gcc -Wall -m32 -g -fno-stack-protector -z execstack -O0 Shell.c -o Shell
make: Shell: Command not found
Makefile:16: recipe for target 'Shell' failed
make: *** [Shell] Error 127
You can't use SHELL as a variable in a Makefile, it is used to know what shell (/bin/sh, /bin/bash, etc) will be used in your Makefile.
CC = gcc
CFLAGS = -Wall -m32 -g -fno-stack-protector -z execstack -O0
EXE_SOURCES = Shell.c
EXE = Shell
.PHONY: all target1 clean
all: target1
target1: $(EXE)
$(EXE): $(EXE_SOURCES)
$(CC) $(CFLAGS) $^ -o $#
clean:
rm -rf $(EXE)
Take more time to read documentation of GNU make
You should remove spaces around variable assignments, e.g. code
CC= gcc
Beware that tab characters are significant in Makefile-s (in rules, for their action lines). Use some editor aware of that (e.g. emacs has a mode for Makefile). See also this example (but the rule action should really start with a tab character). Notably, you need a tab just before the $(CC) $(CFLAGS) $^ -o $# and another one before rm.
Consider also using remake -x to debug your Makefile, or at least make --trace
But the main bug was indeed, as answered by Cpatricio, to use the SHELL variable. Be careful when using variables or names already known to make. Actually, I have the habit of prefixing my make variable names with a common prefix, so you could have defined your variables like JOJOIGA_SOURCES=$(wildcard *.c), JOJOIGA_SHELL=Shell etc....
I have a makefile that looks like this:
CS := a.c b.c
CPPS := foo.cpp bar.cpp
SOURCES := $(CS) $(CPPS)
OBJS := $(CS:%.c=$(OBJSDIR)/%.o) $(CPPS:%.cpp=$(OBJSDIR)/%.o)
I want to create a single rule to compile them all. But the only option I can think of is this:
$(OBJSDIR)/%.o: %.cpp
$(GXX) $(GXXFLAGS) -c $< -o $#
But of course it doesn't work because some of the object files don't have a matching C++ source file.
Any idea?
suppose you have a.cc, b.cc and c.cc, and on the other side, d.c, e.c and f.c
program_objs = a.o b.o c.o d.o e.o f.o
program: $(program_objs)
$(CC) $(LDFLAGS) -o $# $(program_objs)
You don't need anything more, as make will automatically detect which files are c++ and which ones are plain c and will select the proper compiler.
in case you want something special, not included in makefile, you can add some suffixes (file types) with the rule:
.SUFFIXES: .a .b .o
and then use the following rules to compile them to .o
.a.o:
$(COMPILER_A) $(COMPILER_A_FLAGS) -c $# -o $<
.b.o:
$(COMPILER_B) $(COMPILER_B_FLAGS) -c $# -o $<
and let makefile select the proper compiler (the one stored in variables COMPILER_A or COMPILER_B) to do the work.
Of course, you can compile something to a .o file with an explicit rule, as in:
a.o: a.cc
g++ -o a.o -c a.cc
b.o: b.cc
g++ -o b.o -c b.cc
c.o: c.cc
g++ -o c.o -c c.cc
d.o: d.c
gcc -o d.o -c d.c
e.o: e.c
gcc -o e.o -c e.c
f.o: f.c
gcc -o f.o -c f.c
Note #1:
Some sugestions have been made on GNU make % pattern to construct implicit rules for targets. Below is a rewritting of the implicit rules above to do the same thing:
%.o: %.a
$(COMPILER_A) $(COMPILER_A_FLAGS) -c $# -o $<
%.o: %.b
$(COMPILER_B) $(COMPILER_B_FLAGS) -c $# -o $<
As always, $# means the target of the rule and $< (you can use also $* for the file name without any matching suffixes) the left needed file. For a complete list of automatic variables that can be used, I suggest you to read your make manual. Take into account that the old suffix syntax is reversed from the new one (the target suffix appears last in the old syntax, the new syntax being more similar to a normal makefile rule with the target on the left side of the colon)
I want to create a single rule to compile them all.
As Etan Reisner said in the comment section, make already has implicit rules to compile .c and .cpp file, so the real answer to your question is:
Do not write anything to compile your object files.
That said, you should now remove those two variables: $(GXX) and $(GXXFLAGS).
To provide flags to cc or gcc one should use the CFLAGS built-in variable.
To provide flags to g++ one should use the CXXFLAGS built-in variable.
To provide flags to the preprocessor (cpp) one should use the CPPFLAGS variable.
Since you're mixing C and C++ source files, you should use the CXX variable as the linker command.
To compile two files i have created a makefile where i use to mention the object name or i can use the pattern rule using patsubst.
# ----------------------------------------------------------------------------
# Makefile for building tapp
#
# Copyright 2010 FriendlyARM (http://www.arm9.net/)
#
ifndef DESTDIR
DESTDIR ?= /opt/FriendlyARM/tiny6410/linux/rootfs_qtopia_qt4
endif
#CFLAGS = -c -Wall -O2 # wall is for warning show and 02 is optiminisation level 2
CFLAGS = -c -O2 # wall is for warning show and 02 is optiminisation level 2
#CC = arm-linux-gcc # compiler name
CC = gcc # compiler name
LD = ld
INSTALL = install #
TARGET = led_player_project
#OBJ = led-player_backup.o led-player.o
OBJ := $(patsubst %.c,%.o,$(wildcard *.c */*.c))
#OBJ = $(shell find . -name '*.c')
all: $(TARGET)
#all: $(OBJ)
led_player_project : $(OBJ)
$(LD) $(LDFLAGS) -o $# $(OBJ) $(LIBS)
# $(LD) $(LDFLAGS) -o $# $< $(LIBS)
%.o : %.c
$(CC) $(CFLAGS) $< -o $#
#$< -o $#
install: $(TARGET)
$(INSTALL) $^ $(DESTDIR)/usr/bin
clean :
rm -rf *.o $(TARGET) $(OBJ)
# ----------------------------------------------------------------------------
.PHONY: $(PHONY) install clean
# End of file
# vim: syntax=make
#EOF
Now if my project contains folder contains subfolders & they contains further files. Then can i write pattern rule to compile every file & create an common executable?
1> Do i will have to create makefile in every-subfolder so that i can invoke that makefile from main makefile, like integrating static driver to linux kernel each driver have respective makefile ?
2> Or common makefile for full project ?
3> can i use patsubst to compile every file without mentioning there name.
4> How can i combine every *.o to create on executable called main.
Edit :---
#Jan Hudec
I have modified my makefile as per your comment (i have posted it above). Now i am just trying with two folders inside my main folder. I am getting following error
Folder structure :--
main Folder ----> one Folder
----> two Folder
Folder Main contains :--
main.c
main.h
Makefile
Folder one contains :--
one.c
one.h
Folder two contains :--
two.c
two.h
main.c content :--
#include <stdio.h>
#include <stdlib.h>
#include "main.h"
int main()
{
char *p;
printf("\n\n main \n");
one();
two();
return 0;
}
main.h content :---
#include "one/one.h"
#include "two/two.h"
one.c content :---
#include <stdio.h>
#include <stdlib.h>
#include "one.h"
void one()
{
printf("\n one \n");
}
one.h content :---
void one();
two.c content :---
#include <stdio.h>
#include <stdlib.h>
#include "two.h"
void two()
{
printf("\n two \n");
}
two.h content :---
void two();
Error i got at make time :----
ignite#ignite:~/testing/main$ make
gcc -c -O2 main.c -o main.o
gcc -c -O2 one/one.c -o one/one.o
gcc -c -O2 two/two.c -o two/two.o
ld -o led_player_project main.o one/one.o two/two.o
ld: warning: cannot find entry symbol _start; defaulting to 0000000008048080
main.o: In function `main':
main.c:(.text.startup+0x11): undefined reference to `puts'
one/one.o: In function `one':
one.c:(.text+0xb): undefined reference to `puts'
two/two.o: In function `two':
two.c:(.text+0xb): undefined reference to `puts'
make: *** [led_player_project] Error 1
ignite#ignite:~/testing/main$
Ad 1 and 2: The filenames can safely include directories and % matches / as necessary. So you can easily have:
$(wildcard subdir/*.c) $(wildcard anotherdir/*.c)
or even
$(wildcard */*.c)
... or as suggested by keltar in comment
$(shell find . -name '*.c')
which is recursive.
Ad 3: You are doing it.
Ad 4: Create a target with $(OBJ) as dependencies and use the automatic variable just as you do for compilation:
main : $(OBJ)
$(LD) $(LDFLAGS) -o $# $< $(LIBS)
Perhaps another solution too. I have a source directory in my project dir which contains subdirectories. And I dont want have a Makefile in every subdirectories or something else. And I want to build everything only with one makefile in rootdir of project: So for my static library in c++ i did this makefile. Perhaps it could be a solution for you too. But I didnt test it well with paralell builds via "make -j4" or so.
BUILDCXX=g++-10
CHECKCXX=clang++-12
CXXFLAGS=-std=c++17 -Wall -Werror -Wextra -g -pg -O0 -I. -DDEBUG
CXXFLREL=-std=c++17 -Wall -Werror -Wextra -O3 -s -I. -DNDEBUG
CXXFLAGSLIB=$(CXXFLAGS)
CXXFLAGSTST=$(CXXFLAGS) -DRLOG_COMPONENT="clbc"
LDFLAGS=
LDFLAGSLIB=$(LDFLAGS)
LDFLAGSTST=$(LDFLAGS) -L./target/lib -lUnitTest++ -lclbc
OUTDIR=target
OUTDIRLIB=$(OUTDIR)/lib
OUTDIRTST=$(OUTDIR)/bin
OUTDIROBJ=$(OUTDIR)/obj
OUTFILELIB=libclbc.a
OUTFILETST=runtests
SRCDIR=source
SRCDIRLIB=$(SRCDIR)/lib
SRCDIRTST=$(SRCDIR)/test
SRCDIRSLIBR := $(shell find $(SRCDIRLIB) -maxdepth 3 -type d)
SRCFILESLIB := $(foreach dir,$(SRCDIRSLIBR),$(wildcard $(dir)/*.cpp))
OBJFILESLIB := $(addprefix $(OUTDIROBJ)/,$(notdir $(patsubst %.cpp,%.o,$(SRCFILESLIB))))
SRCDIRSTSTR := $(shell find $(SRCDIRTST) -maxdepth 3 -type d)
SRCFILESTST := $(foreach dir,$(SRCDIRSTSTR),$(wildcard $(dir)/*.cpp))
OBJFILESTST := $(addprefix $(OUTDIROBJ)/,$(notdir $(patsubst %.cpp,%.o,$(SRCFILESTST))))
.PHONY: all
all: clean lib
check-syntax:
$(CHECKCXX) $(CXXFLAGS) -s -o /dev/null -S $(CHK_SOURCES)
clean:
#rm -rf $(OUTDIR)
lib:$(OBJFILESLIB)
#mkdir -p $(OUTDIRLIB)
#echo " TargetLib :" $(OUTDIRLIB)/$(OUTFILELIB)
# ar rcs $(OUTDIRLIB)/$(OUTFILELIB) $^
test:$(OBJFILESTST)
#mkdir -p $(OUTDIRTST)
#echo "TargetTest :" $(OUTDIRTST)/$(OUTFILETST)
# $(BUILDCXX) $(OBJFILESTST) -o $(OUTDIRTST)/$(OUTFILETST) $(LDFLAGSTST)
release: CXXFLAGSLIB=$(CXXFLREL)
release:$(OBJFILESLIB)
#mkdir -p $(OUTDIRLIB)
#echo "RTargetLib :" $(OUTDIRLIB)/$(OUTFILELIB)
# ar rcs $(OUTDIRLIB)/$(OUTFILELIB) $^
define set_real_src_file
$(eval REAL_SRC_FILE=$(strip $(1)))
endef
define set_nothing
endef
define get_real_src_file
$(if $(strip $(findstring $(strip $(1)),$(strip $(2)))),$(call set_real_src_file,$(2)),$(call set_nothing))
endef
define get_source_file
#echo ObjectFile : $(1)
$(eval REAL_SRC_SEARCH=$(notdir $(patsubst %.o,%.cpp,$(1))))
$(eval REAL_SRC_FILE=)
$(foreach word,$(2), $(call get_real_src_file, $(REAL_SRC_SEARCH),$(word)))
endef
$(OBJFILESLIB): $(SRCFILESLIB)
#mkdir -p $(OUTDIROBJ)
$(call get_source_file,$#,$^,$<)
# $(BUILDCXX) $(CXXFLAGSLIB) -c $(REAL_SRC_FILE) -o $#
$(OBJFILESTST): $(SRCFILESTST)
#mkdir -p $(OUTDIROBJ)
$(call get_source_file,$#,$^,$<)
# $(BUILDCXX) $(CXXFLAGSTST) -c $(REAL_SRC_FILE) -o $#
But I guess it runs only with GNUMake and no other implementations of make.