Missing separator in Makefile?

The following Makefile is not working and I am not sure what’s going on.

CC = gcc
CFLAGS = -Wall -g

demo:
    ${CC} ${CFLAGS} demo.c -o demo
lib:
    ${CC} ${CFLAGS} lib.c -o lib
clean:
    rm -f lib demo

Demo has the main function and lib has a set of methods used in demo.

I added the -c flag to lib. However when I run make, I get:

Makefile:5: *** missing separator.  Stop.

Solution:

Given your update with the error, check what you have on the line before those ${CC} commands. Many make programs require a real tab character before the commands and editors that put in eight spaces (for example) will break them. That’s more often than not the cause of the “Missing separator” errors.

You can see that with the following transcript. In the file, there are four spaces before the $(xyzzy):

xyzzy=echo
all:
    $(xyzzy) hello

So, when I make it, I get the same error as you:

pax> make
makefile:3: *** missing separator.  Stop.

But, when I edit it and turn those four spaces into a tab, it works fine:

pax> make
echo hello
hello

You also have a problem with the way you’re trying to combine the source files together.

Without a -c flag to gcc, it will try to create a separate executable from each of those commands, almost certainly leading to linker errors. You’re going to need something like (simple):

CC = gcc
CFLAGS = -Wall -g

# Just compile/link all files in one hit.
demo: demo.c lib.c
   ${CC} ${CFLAGS} -o demo demo.c lib.c

clean:
    rm -f demo

or (slightly more complex):

CC = gcc
CFLAGS1 = -Wall -g -c
CFLAGS2 = -g

# Link the two object files together.

demo: demo.o lib.o
   ${CC} ${CFLAGS2} -o demo demo.o lib.o

# Compile each source file to an object.

demo.o: demo.c
   ${CC} ${CFLAGS1} -o demo.o demo.c

lib.o: lib.c
   ${CC} ${CFLAGS1} -o lib.o lib.c

clean:
    rm -f demo

The problem with the first solution is that it unnecessarily compiles both programs even when only one is out of date. The second solution is a little more intelligent.

Linking library (from assembly files) with main.c in Makefile

Im passionate about assembly and wanted to start coding from home on linux instead of mac I usually use.

I really struggle for 4 days about this issue.

you can find my makefile and clone repository at the following url:

<code>NAME =                libfts.a
ASM_FILES =         ft_isascii  \

OS := $(shell uname)
ifeq ($(OS), Darwin)
ASM_COMPILER =      ~/.brew/bin/nasm -f macho64 -g
else
ASM_COMPILER =      nasm -f elf64 -g
endif
ASM_SRC_DIR =       srcs/
ASM_OBJ_DIR_NAME =  obj
ASM_OBJ_DIR =       $(ASM_OBJ_DIR_NAME)/
ASM_OBJ :=          $(addsuffix .o,$(ASM_FILES))
ASM_OBJ :=          $(addprefix $(ASM_OBJ_DIR),$(ASM_OBJ))
TEST =              maintest.out
TEST_FILES =        maintest
C_COMPILER =        clang -Wall -Werror -Wextra -O3
TEST_DIR_NAME =     test
TEST_DIR =          $(TEST_DIR_NAME)/
TEST_OBJ :=         $(addsuffix .o,$(TEST_FILES))
TEST_OBJ :=         $(addprefix $(TEST_DIR),$(TEST_OBJ))
OBJ_PATHS :=        $(ASM_OBJ) $(TEST_OBJ)
all: $(NAME)
$(NAME): $(ASM_OBJ)
    ar rc $(NAME) $(ASM_OBJ)
test: re $(TEST_OBJ)
    $(C_COMPILER) -L. $(NAME) $(TEST_OBJ) -o $(TEST)
$(ASM_OBJ): $(ASM_OBJ_DIR)%.o: $(ASM_SRC_DIR)%.s
    @/bin/mkdir -p $(ASM_OBJ_DIR)
    $(ASM_COMPILER) $< -o $@
$(TEST_OBJ): $(TEST_DIR)%.o: $(TEST_DIR)%.c
    $(C_COMPILER) -c -I. $< -o $@
clean:
    -/bin/rm -f $(OBJ_PATHS)
    /usr/bin/find . -name "$(ASM_OBJ_DIR_NAME)" -maxdepth 1 -type d -empty -delete
fclean: clean
    -/bin/rm -f $(NAME)
    -/bin/rm -f $(TEST)
re: fclean all
.PHONY: all clean fclean re

I have this error message when I try “make test” on the linux:

    test/maintest.o: In function `main':
    test/maintest.c:(.text+0x33): undefined reference to `ft_isascii'
    undefined reference to etc.

.h content:

#ifndef _LIBFTS
# define _LIBFTS

#include <stddef.h>

int         ft_isascii(int c);

#endif

ft_isascii.s content:

global _ft_isascii

section .text

_ft_isascii:                ; int ft_isascii
    and     edi, 0xffffff80 ; mask with the 128 firsts bits left to 0 as ASCII range from 0 to 7f in hexa (just below 80)
    sete    al              ; SETE sets AL to 1 if above condition code means "equal", otherwise it sets AL to 0.
    movzx   eax, al
    ret

I would REALLY be thanksful for any tips to solve this issue…

Regards,

Solution:

There are two problems to be fixed:

First, on ELF targets (most Unixes except macOS), C functions are not decorated with an underscore. To fix your code, remove the leading underscore from all symbols. Make sure to remove it everywhere.

Second, the linker when looking at an archive (.a file) only picks files it needs right now to satisfy dependencies. So when you pass the archive before maintest.o, the linker doesn’t take anything from the archive at all as it doesn’t need any ft_... symbols at that point. These symbols are only needed once the linker has seen maintest.o. To fix this issue, move the $(NAME) operand to after $(TEST_OBJ). As a general rule of thumb, always place libraries after object files on the linker command line.

On macOS, you won’t observe this problem because they use lld, the LLVM linker, which is a bit unconventional in that it defers the choice which objects to take out of archives until it has looked at the symbol tables of all operands, making your actually broken invocation work. Don’t depend on this behaviour, please.

Make C and ASM files in the same makefile fails

I have written a Makefile to generate a kernel image from both ASM and C sources however it fails to compile the C sources. I think the error is in using two object lists one for ASM and one for C. If there are other issues with the file please feel free to tell me.

Terminal Output

arm-none-eabi-as -I source/ source/maths.s -o build/maths.o
arm-none-eabi-as -I source/ source/tags.s -o build/tags.o
make: *** No rule to make target 'build/firstCFile.o', needed by 'build/output.elf'.  Stop.

Makefile

# The toolchain to use. arm-none-eabi works, but there does exist 
# arm-bcm2708-linux-gnueabi.
ARMGNU ?= arm-none-eabi

# The intermediate directory for compiled object files.
BUILD = build/

# The directory in which source files are stored.
SOURCE = source/

# The name of the output file to generate.
TARGET = bin/kernel.img

# The name of the assembler listing file to generate.
LIST = bin/kernel.list

# The name of the map file to generate.
MAP = bin/kernel.map

# The name of the linker script to use.
LINKER = kernel.ld

# The names of libraries to use.
LIBRARIES := csud

# The names of all object files that must be generated. Deduced from the 
# assembly code files in source.
OBJECTS := $(patsubst $(SOURCE)%.s,$(BUILD)%.o,$(wildcard $(SOURCE)*.s))

OBJECTS2 := $(patsubst $(SOURCE)%.c,$(BUILD)%.o,$(wildcard $(SOURCE)*.c))

# Rule to make everything.
all: $(TARGET) $(LIST)

# Rule to remake everything. Does not include clean.
rebuild: all

# Rule to make the listing file.
$(LIST) : $(BUILD)output.elf
    $(ARMGNU)-objdump -d $(BUILD)output.elf > $(LIST)

# Rule to make the image file.
$(TARGET) : $(BUILD)output.elf
    $(ARMGNU)-objcopy $(BUILD)output.elf -O binary $(TARGET) 

# Rule to make the elf file.
$(BUILD)output.elf : $(OBJECTS) $(OBJECTS2) $(LINKER)
    $(ARMGNU)-ld --no-undefined $(OBJECTS) $(OBJECTS2) -L. $(patsubst %,-l %,$(LIBRARIES)) -Map $(MAP) -o $(BUILD)output.elf -T $(LINKER)

# Rule to make the object files.
$(BUILD)%.o: $(SOURCE)%.s
    $(ARMGNU)-as -I $(SOURCE) $< -o $@

$(BUILD):
    mkdir $@

Solution:

I think you need a rule to make from the c source:

$(BUILD)%.o : $(SOURCE)%.c ; $(ARMGNU)-cc -I $(SOURCE) $< -o $@

Macro not found in libgcrypt on Centos 7

I have a C program that uses libgcrypt.
I put this string in the builder to install the libraries for Centos 7:

yum -y install json-c-devel expat-devel libpcap-devel flex-devel automake libtool bison libuv-devel openssl-devel libgcrypt-devel

and no problem come out.

Unfortunately, the compilation of the code terminate with an error caused by a macro cannot be found:

error: ‘GCRY_CIPHER_MODE_GCM’ undeclared (first use in this function)

The macro is inside the libgcrypt for sure, so I really don’t understand how cannot be found at all.

If I compile the same code in Debian, it works well and the macro is resolved properly.

P.S. My system is Debian 8 and I use docker for Centos 7

Solution:

CentOS-7 uses libgcrypt and libgcrypt-devel version 1.5 (patched), which seems to not include GCRY_CIPHER_MODE_GCM declaration.

Looking at the git commits, it seems to have been available in 1.6+.

https://git.gnupg.org/cgi-bin/gitweb.cgi?p=libgcrypt.git;a=commit;h=90cce18b9eced4f412ceeec5bcae18c4493322df

On a newer version, you would see a line in /usr/include/gcrypt.h, like the following:

GCRY_CIPHER_MODE_GCM      = 9,   /* Galois Counter Mode. */

fatal error: addFunc.h: No such file or directory

i have created a Makefile to run C program in shell script.but i get as error fatal error: addFunc.h: No such file or directory in mainProg.c page and addFunc.c page.i tried my best to solve this problem.but i didn’t get a solution.i have mentioned my code below.

mainProg.c

#include <stdio.h>
#include "/home/name/Desktop/add/addFunc.h"
int main(){
int a,b;
printf("Enter two numbers\n");
scanf("%d%d",&a,&b);
printf("sum:%d\n",add(a,b));
return 0;
}

addFunc.h

int add(int a, int b)

addFunc.c

#include "/home/name/Desktop/add/addFunc.h"
int add(int a,int b){
return (a+b);
}

Makefile

Add: mainProg.c addFunc.c
    gcc -o Add mainProg.c addFunc.c -I.

Solution:

You really should be cutting and pasting, because clearly the text you’ve pasted here is nothing like what you’re actually using (you have tons of syntax errors here).

However, the problem is that the compiler can’t find your header file. This can be solved in one (or both) of two ways:

First, you should use the #include <...> form only for system headers like stdio.h etc. For your personal headers, you should use the form #include "..." instead. The difference is implementation-specific but for most compilers it is that include files using <...> are never looked for in the current directory but only in system directories and directories given with -I, while include file using "..." are looked for also in the current directory.

You could also simply ask the compiler to always look in the current directory by adding the -I. option to your compile line in your makefile.