I am learning c and trying to build using makefile. I am stuck on the following error and don't know what to do next.
the build command is 
gcc -o logfind logfind.o cmdargutils.o filesystem_utils.o file_utils.o strutils.o
If I need both file_utils.o and cmdargutils.o but if I add both I get the following error.
ERROR
file_utils.o:(.rodata+0x0): multiple definition of `MAX_LINE'
logfind.o:(.rodata+0x0): first defined here
collect2: error: ld returned 1 exit status
Makefile:2: recipe for target 'logfind' failed
make: *** [logfind] Error 1
The source is: Makefile
logfind: clean logfind.o
    gcc -o logfind logfind.o cmdargutils.o filesystem_utils.o file_utils.o strutils.o
logfind.o: logfind.c cmdargutils.o file_utils.o filesystem_utils.o strutils.o error_codes.h
    gcc -c logfind.c
cmdargutils.o: cmdargutils.c cmdargutils.h
    gcc -c cmdargutils.c
file_utils.o: file_utils.c file_utils.h
    gcc -c file_utils.c
filesystem_utils.o: filesystem_utils.c filesystem_utils.h
    gcc -c filesystem_utils.c
strutils.o: strutils.c strutils.h
    gcc -c strutils.c
clean:
    rm -f *.o logfind
cmdargutils.h
#ifndef CMD_ARG_UTILS
#define CMD_ARG_UTILS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>
#include "error_codes.h"
#include "strutils.h"
struct Argument {
    bool is_and_operation;
    int count;
    char **search_terms;
};
struct Argument *argument_create(int argc, char **argv, int start, bool is_and_operation);
void argument_destroy(struct Argument *argument);
struct Argument *parse_arguments(int argc, char **argv);
#endif
error_codes.h
#ifndef ERROR_CODES
#define ERROR_CODES
enum error_codes {
    MEMORY_ERROR,
    INPUT_ERROR
};
#endif
file_utils.h
#ifndef FILE_UTILS
#define FILE_UTILS
#define _GNU_SOURCE
#include <stdio.h>
#include <stdbool.h>
#include <string.h> 
#include <stdlib.h>
#include "cmdargutils.h"
const size_t MAX_LINE = 1024;
bool is_match(char *, struct Argument *); 
bool scan_file(char *, struct Argument *);
#endif
filesystem_utils.h
#ifndef FILESYSTEM_UTILS
#define FILESYSTEM_UTILS
#include <glob.h>
#include <string.h>
#include "strutils.h"
struct SearchFiles {
    int count;
    char **paths;
};
struct SearchFiles *search_files_create(int count, char** paths);
void search_files_destroy(struct SearchFiles *search_files);
struct SearchFiles *scan_directory(char *directory_path, char *pattern);
#endif
strutils.h
#ifndef STRUTILS
#define STRUTILS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "error_codes.h"
char *strdup(const char *source);
char **copy_string_array(char **source, int start, int end);
#endif
logfind.c
#include <stdio.h>
#include <stdlib.h>
#include <glob.h>
#include "cmdargutils.h"
#include "filesystem_utils.h"
#include "file_utils.h"
int main(int argc, char **argv) {
    struct Argument *argument = parse_arguments(argc, argv);
    int i = 0;
    struct SearchFiles *search_files = scan_directory(".", "*.*");
    for(i = 0; i < search_files->count; i++) {
        scan_file(search_files->paths[i], argument);
    }
    search_files_destroy(search_files);
    argument_destroy(argument);
    return 0;    
}
cmdargutils.c
#include "cmdargutils.h"
struct Argument *argument_create(int argc, char **argv, int start, bool is_and_operation){
    struct Argument *argument = (struct Argument *)malloc(sizeof(struct Argument));
    if(!argument) {
        printf("Could not initialize arguments.\n"); 
        exit(MEMORY_ERROR);
    }
    argument->count =  argc - start;
    argument->is_and_operation = is_and_operation;
    argument->search_terms = copy_string_array(argv, start, argc);
    return argument; 
}
void argument_destroy(struct Argument *argument){
    int i = 0;
    for(i = 0; i < argument->count; i++) {
        free(argument->search_terms[i]);
    }
    free(argument->search_terms); 
    free(argument);
    argument = NULL;    
}
struct Argument *parse_arguments(int argc, char **argv) {
    struct Argument *argument = NULL;
    bool is_and_operation = true;
    int start = 0;
    if(argc < 2) {
        printf("Not enough arguments\n");
        exit(INPUT_ERROR);
    }
    char *operation = argv[1];
    if(strcmp(operation, "-o") == 0) {
        is_and_operation = false;
        if(argc < 3) {
            printf("Not enough arguments\n");
            exit(INPUT_ERROR);
        }
    }
    start = is_and_operation ? 1 : 2;
    argument = argument_create(argc, argv, start, is_and_operation); 
    return argument;
}
file_utils.c
#include "file_utils.h"
bool is_match(char *line, struct Argument *argument) {
    int i = 0;
    bool isMatch = false;
    for(i = 0; i < argument->count; i++) {
        char *found = strcasestr(line, argument->search_terms[i]);
        if(!found) {
            if(argument->is_and_operation) {
                isMatch = false;
                break;
            } else {
                continue;
            }
        } else {
            isMatch = true;
            if(argument->is_and_operation) {
                continue;
            } else {
                break;
            }
        }
    }
    return isMatch;
}
bool scan_file(char *path, struct Argument *argument) {
    FILE *file = fopen(path, "r");
    int line_number = 0;
    char *line = malloc(MAX_LINE);
    while(fgets(line, MAX_LINE - 1, file)!= NULL) {
        ++line_number;
        if(is_match(line, argument)) {
            printf("%s:%d\n", path, line_number);
            printf("\t%s\n", line);
        }
    }
    free(line);
    fclose(file);
} 
filesystem_utils.c
#include "filesystem_utils.h"
struct SearchFiles *search_files_create(int count, char** paths) {
    struct SearchFiles *search_files = (struct SearchFiles *)malloc(sizeof(struct SearchFiles));
    search_files->count = count;
    search_files->paths = copy_string_array(paths, 0, count); 
    return search_files;    
}
void search_files_destroy(struct SearchFiles *search_files) {
    int i = 0;
    for(i = 0; i < search_files->count; i++) {
        free(search_files->paths[i]);    
    }
    free(search_files->paths);
    free(search_files);
    search_files = NULL;
}
struct SearchFiles *scan_directory(char *directory_path, char *pattern) {
    glob_t globbuf;
    int error = glob(pattern, GLOB_MARK, NULL, &globbuf);
    if(!error) {
        struct SearchFiles *search_files = search_files_create(globbuf.gl_pathc, globbuf.gl_pathv);
        globfree(&globbuf);
        return search_files;
    }
    return NULL;
}
strutils.c
#include "strutils.h"
char *strdup(const char *source) {
    char *dest = malloc(strlen(source) + 1);
    if(!dest) {
        printf("Memory allocation error\n");
        exit(MEMORY_ERROR);
    }
    strcpy(dest, source);
    return dest;
}
char **copy_string_array(char **source, int start, int end) {
    char **dest = (char **)malloc(sizeof(char *) * (end - start));
    int di = 0;
    int si = start;
    for(di = 0, si = start; si < end; 
        si++, di++) {
        dest[di] = strdup(source[si]);        
    }
    return dest;
}