This is the following Makefile at issue:
#
# Compiler flags
#
CC = gcc
CFLAGS = -Wall -Werror -Wextra
#
# Project files
# example -
# SRCS = hash_table.c linked_list.c utils.c common.c business_logic.c user_interface.c
# SRCS = test/gc_test.c src/gc.c
SRCS := $(shell find . -name "*")
OBJS = $(SRCS:.c=.o)
EXE = output.out
FILENAMES := $(shell find . -type f -name "*.c" -printf "%f\n")
FILENAMES_OUT = $(FILENAMES:.c=.o)
#
# Default build settings
#
BUILDDIR = build
BUILDCFLAGS = -g -O0
BUILDEXE = $(BUILDDIR)/$(EXE)
BUILDOBJS = $(addprefix $(BUILDDIR)/, $(FILENAMES_OUT))
# Rules for default build
all: clean build
build: $(BUILDEXE)
$(BUILDEXE): $(BUILDOBJS)
$(CC) $(CFLAGS) $(BUILDCFLAGS) -o $(BUILDEXE) $^ -lcunit
$(BUILDDIR)/%.o: %.c
$(CC) $(CFLAGS) $(BUILDCFLAGS) -c $< -o $#
memtest: $(BUILDEXE)
valgrind --leak-check=full ./$<
#
# Other rules
#
clean:
mkdir -p $(BUILDDIR)
PROBLEM -> make: *** No rule to make target `build/gc_test.o', needed by `build/output.out'. Stop.
PROJECT TREE
.
├── build
├── doc
│ └── design.md
├── Makefile
├── proj
│ ├── code_quality_report.md
│ ├── deviations.md
│ ├── individual_reflection.md
│ ├── team_reflection.md
│ └── test_report.md
├── README.md
├── src
│ ├── gc.c
│ └── headers
│ └── gc.h
└── tests
└── gc_test.c
The issue itself happens in $(BUILDEXE): $(BUILDOBJS) where the dependencies are gc_test.c gc.c. Those dependencies SHOULD get caught in the function below it, because it's input is all the .c files in the build directory. Those files SHOULD get properly matched and then compiled to .o files which then should climb up the tree and produce an executable. I'm confused because $(BUILDOBJS) should be the same as $(BUILDDIR)/%.o.
I'm new to making Makefiles, but I want to get better at it. Please point out better naming conventions or terminology that could have been used better for this post. Thanks!
The problem is here:
FILENAMES := $(shell find . -type f -name "*.c" -printf "%f\n")
This is wrong because -printf "%f\n" prints only the filenames, without any path. You're losing all information about the path where files are found, so how can make find them?
You should change this to simply -print then it will work.
Related
Already build a C program in Windows environment and make this makefile
# project name (generate executable with this name)
TARGET = Orga_L1_MATURANA
CC = gcc
# compiling flags here
CFLAGS = -Wall -I.
LINKER = gcc
# linking flags here
LFLAGS = -Wall -I. -lm
# change these to proper directories where each file should be
SRCDIR = src
OBJDIR = obj
BINDIR = bin
SOURCES := $(wildcard $(SRCDIR)/main.c)
OBJECTS := $(SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
rm = rm -f
$(BINDIR)/$(TARGET): $(OBJECTS)
#$(LINKER) $(OBJECTS) $(LFLAGS) -o $#
#echo "Linking complete!"
$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.c
#$(CC) $(CFLAGS) -c $< -o $#
#echo "Compiled "$<" successfully!"
and this tree's see of the code
.
├── bin
│ ├── lineasControl2.txt
│ ├── mipsEjemplo2.asm
│ └── Orga_L1_MATURANA
├── makefile
├── obj
│ └── main.o
├── README.md
└── src
├── 2EnlazadasCursor.c
├── cons.c
├── cons.h
├── funciones.c
├── funciones.h
├── main.c
├── operaciones.c
└── structs.h
its fine the way that im doing the makefile for both OS? Besides, i hear that ubuntu doesnt needs a makefile, is that right? I dont think so.
I have a more or less complicated LKM. This LKM contains the directories as shown below:
├── core.c
├── headers
│ ├── core.h
│ └── server.h
├── include
│ ├── headers
│ │ └── utils.h
│ └── utils.c
├── libs
│ ├── headers
│ │ └── syscalltable.h
│ └── syscalltable.c
├── LICENSE
├── Makefile
├── README.md
├── server.c
├── src
│ ├── getdents_hook.c
│ ├── headers
│ │ ├── getdents_hook.h
│ │ ├── module_hiding.h
│ │ ├── network_keylog.h
│ │ ├── packet_hiding.h
│ │ ├── port_knocking.h
│ │ ├── privilege_escalation.h
│ │ └── socket_hiding.h
│ ├── module_hiding.c
│ ├── network_keylog.c
│ ├── packet_hiding.c
│ ├── port_knocking.c
│ ├── privilege_escalation.c
│ └── socket_hiding.c
└── TASKS.md
It seems like a overhead for this small project, but the goal was to create a LKM that could be extended easily.
The problem lies in the Makefile. As every header file is in its respective headers subdirectory, I created a Makefile that looks like this:
# Module name
ROOTKIT = rootkit
# Build
CC = gcc
PWD = $(shell pwd)
UNAME = $(shell uname -r)
MODULEDIR = /lib/modules/$(UNAME)
BUILDDIR = $(MODULEDIR)/build
KERNELDIR = $(MODULEDIR)/kernel
# Headers
CORE_H = headers
LIBS_H = libs/headers
SRCS_H = src/headers
INCL_H = include/headers
# Files
CORE = $(wildcard *.c)
CORE_OBJS = $(patsubst %.c, %.o, $(CORE))
LIBS = $(wildcard libs/*.c)
LIBS_OBJS = $(patsubst %.c, %.o, $(LIBS))
INCL = $(wildcard include/*.c)
INCL_OBJS = $(patsubst %.c, %.o, $(INCL))
# Exception for this one file
NETW = src/network_keylog.c
NETW_OBJS = src/network_keylog.o
SRC = $(wildcard src/*.c)
SRCS = $(filter-out $(NETW), $(SRC))
SRCS_OBJS = $(patsubst %.c, %.o, $(SRCS))
# Objects
# $(CORE_OBJS): $(CORE)
# $(CC) -c -o $# $< -I$(CORE_H) -I$(INCL_H)
# $(LIBS_OBJS): $(LIBS)
# $(CC) -c -o $# $< -I$(LIBS_H) -I$(INCL_H)
# $(SRCS_OBJS): $(SRCS)
# $(CC) -c -o $# $< -I$(SRCS_H) -I$(INCL_H)
# $(NETW_OBJS): $(NETW)
# $(CC) -c -o $# $< -I$(SRCS_H) -I$(CORE_H) -I$(INCL_H)
# Module
obj-m += $(ROOTKIT).o
$(ROOTKIT)-y = $(CORE_OBJS) $(LIBS_OBJS) $(SRCS_OBJS) $(NETW_OBJS)
EXTRA_CFLAGS = -I$(CORE_H) -I$(INCL_H) -I$(LIBS_H) -I$(SRCS_H)
# Recipes
all:
$(MAKE) -C $(BUILDDIR) M=$(PWD) modules
load:
insmod $(KERNELDIR)/net/ipv4/netfilter/nf_reject_ipv4.ko
insmod $(KERNELDIR)/net/ipv6/netfilter/nf_reject_ipv6.ko
insmod rootkit.ko
clean:
$(MAKE) -C $(BUILDDIR) M=$(PWD) clean
However I only get this error:
make -C /lib/modules/4.9.0-3-amd64/build M=/home/croemheld/Repositories/lkm-rootkit modules
make[1]: Verzeichnis „/usr/src/linux-headers-4.9.0-3-amd64“ wird betreten
/bin/sh: 1: Syntax error: "(" unexpected
[...]
I know that the Makefile executes its procedure in a shell, but I can't understand what command the shell can't execute or why this is failing in general. Or is this approach completely wrong?
EDIT: Seems like I missed a missing $ in a -I flag...
However, it still does not compile. The problem is that every file includes the utils.h in include/headers/, and I don't know how to specify the compile procedure so that it works.
Currently:
all source files include my own header files (meaning in the *.c files are only includes like "xyz.h" and in the headers only <....h >)
the core.c and server.c include all other header files.
every source file includes the utils.h header and its "own" header file, except for network_keylog.c: this one also includes server.h.
Current output:
make -C /lib/modules/4.9.0-3-amd64/build M=/home/croemheld/Repositories/lkm-rootkit modules
make[1]: Verzeichnis „/usr/src/linux-headers-4.9.0-3-amd64“ wird betreten
CC [M] /home/croemheld/Repositories/lkm-rootkit/src/network_keylog.o
/home/croemheld/Repositories/lkm-rootkit/src/network_keylog.c:1:19: fatal error: utils.h: Datei oder Verzeichnis nicht gefunden
#include "utils.h"
^
compilation terminated.
/usr/src/linux-headers-4.9.0-3-common/scripts/Makefile.build:298: die Regel für Ziel „/home/croemheld/Repositories/lkm-rootkit/src/network_keylog.o“ scheiterte
make[4]: *** [/home/croemheld/Repositories/lkm-rootkit/src/network_keylog.o] Fehler 1
I use the check testing framework to unit test my C code. The test when it's run looks like this.
$ checkmk tst_bquotes.check > bquotes-test.c
dac#dac-Latitude-E7450:~/kth/os/lab3/openshell$ gcc -Wall -o bquotes-test util.c errors.c bquotes-test.c -lcheck -lsubunit -lrt -pthread -lm
dac#dac-Latitude-E7450:~/kth/os/lab3/openshell$ ./bquotes-test
Running suite(s): Core
100%: Checks: 1, Failures: 0, Errors: 0
How can I add this test to my cmake build script?
cmake_minimum_required(VERSION 3.0)
project(shell.test)
if (EDITLINE_LIBRARIES AND EDITLINE_INCLUDE_DIRS)
set(Editline_FIND_QUIETLY TRUE)
endif (EDITLINE_LIBRARIES AND EDITLINE_INCLUDE_DIRS)
find_path(EDITLINE_INCLUDE_DIRS NAMES editline/readline.h)
find_library(EDITLINE_LIBRARIES NAMES edit)
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Editline DEFAULT_MSG
EDITLINE_LIBRARIES
EDITLINE_INCLUDE_DIRS)
mark_as_advanced(EDITLINE_INCLUDE_DIRS EDITLINE_LIBRARIES)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -L/usr/local/include/ -L/usr/include -std=gnu99 -pedantic-errors -O3 -g -Wall -pedantic -ledit -ltermcap")
include_directories(/usr/local/include/ /usr/include)
link_directories(/usr/lib)
link_directories(/usr/local/lib)
add_executable(shell main.c errors.c util.c shellparser.c)
target_link_libraries(shell edit readline)
add_custom_target(shellparser DEPENDS ${CMAKE_SOURCE_DIR}/shellparser.c)
add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/shellparser.c COMMAND lemon -s ${CMAKE_SOURCE_DIR}/shellparser.y DEPENDS ${CMAKE_SOURCE_DIR}/shellparser.y)
add_dependencies(shell shellparser)
My project structure looks like:
$ tree
.
├── bquotes-test
├── bquotes-test.c
├── CMakeLists.txt
├── CommandEntry.h
├── do.h
├── errors.c
├── errors.h
├── integrationtest.sh
├── lemon.c
├── lempar.c
├── LICENSE
├── main.c
├── Makefile
├── openshell.h
├── README.md
├── shellparser.c
├── shellparser.h
├── shellparser.out
├── shellparser.y
├── stresstest.sh
├── tst_bquotes.check
├── tst_exp.sh
├── types.h
├── unittest.sh
└── util.c
0 directories, 25 files
My check test is
#include "openshell.h"
#include "errors.h"
#test myQtest
fail_unless(isBetweenQuotes(11, "abc'asdqerfdsdxcvc'xc") == 1, "isBetweenQuotes function borked");
fail_unless(isBetweenQuotes(5, "This has no quotes") == 0, "isBetweenQuotes2 function borked");
fail_unless(isBetweenQuotes(11, "This' is a sentence in 'quotes") == 1, "isBetweenQuotes3 function borked");
fail_unless(isBetweenQuotes(15, "\"This is a sentence in quotes\"") == 1, "isBetweenQuotes4 function borked");
/* gcc -Wall -o bquotes-test util.c errors.c bquotes-test.c -lcheck -lsubunit -lrt -pthread -lm */
/* checkmk tst_bquotes.check > bquotes-test.c */
I would try this. Create an external linux shell script, which has the line
checkmk tst_bquotes.check > bquotes-test.c
in it and call it something like prepare_test.sh. Then, I would add these lines to your CMakeLists.txt at the end:
execute_process(
COMMAND ./prepare_test.sh
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
RESULT_VARIABLE prep_test_result)
add_executable(bquotes-test util.c errors.c bquotes-test.c )
target_link_libraries(bquotes-test check subunit rt pthread m)
add_test(start_test_bquotes bquotes-test)
include(CTest)
After you've called cmake, you can then start the tests with make test.
I'm working on a C project, and I decided to put the source code and its objects in different directories. The root directory has something like that:
SmartC ▶ tree -L 1
.
├── built
├── doc
├── Makefile
├── README.md
├── src
├── tests
└── trash
So, inside both src and built directories, I put two others Makefiles to do the compile and link jobs.
The src directory (where I put the source code) has the following structure:
src
├── graph.c
├── graph.h
├── list.c
├── list.h
├── main.c
├── Makefile
├── node.c
├── node.h
├── tree.c
├── tree.h
└── types
├── complex.c
├── complex.h
├── matrix.c
└── matrix.h
and the built has the same structure, but it is intended to store all objects made by compilation.
My question is about my src/Makefile:
BINDIR = ../built/src
CC = gcc
CFLAGS = -g -Wall -O3
OBJECTS = \
$(BINDIR)/main.o \
$(BINDIR)/node.o \
$(BINDIR)/list.o \
$(BINDIR)/graph.o \
$(BINDIR)/tree.o \
$(BINDIR)/types/complex.o \
$(BINDIR)/types/matrix.o \
compile: $(OBJECTS)
$(BINDIR)/%.o: %.c
$(CC) -c $< -o $# $(CFLAGS)
This Makefile creates all the objects of the source code, inside src directory, and move them to built/src. But, every time I create a new source code file (*.c), I have to put the name of its object in this makefile, so it can be compiled. I'd like to do an automatic search, inside the src directory, and fill the "OBJECTS" variable with this search.
Is anyone has some idea of how to accomplish this? I mean, automatic search for source code inside an specific directory?
I even accept any other strategy rather than what I'm making.
=========== Answer ===============
I got the tip (in comments) about wildcards. So I did. Here is the solution I found.
src/Makefile
BINDIR = ../built/src
CC = gcc
CFLAGS = -g -Wall -O3
OBJECTS := $(patsubst %.c,$(BINDIR)/%.o,$(wildcard *.c */*.c))
compile: $(OBJECTS)
$(BINDIR)/%.o: %.c
$(CC) -c $< -o $# $(CFLAGS)
EDIT [Solved]
I like to do the following.
Create Variables to Each Directory of the Project
SRCDIR = src
OBJDIR = obj
LIBDIR = lib
DOCDIR = doc
HDRDIR = include
CFLAGS = -g -Wall -O3
Get Only the Internal Structure of SRCDIR Recursively
STRUCTURE := $(shell find $(SRCDIR) -type d)
Get All Files inside the STRUCTURE Variable
CODEFILES := $(addsuffix /*,$(STRUCTURE))
CODEFILES := $(wildcard $(CODEFILES))
Filter Out Only Specific Files
# Filter Only Specific Files
SRCFILES := $(filter %.c,$(CODEFILES))
HDRFILES := $(filter %.h,$(CODEFILES))
OBJFILES := $(subst $(SRCDIR),$(OBJDIR),$(SRCFILES:%.c=%.o))
# Filter Out Function main for Libraries
LIBDEPS := $(filter-out $(OBJDIR)/main.o,$(OBJFILES))
Now it is Time to create the Rules
compile: $(OBJFILES)
$(OBJDIR)/%.o: $(addprefix $(SRCDIR)/,%.c %.h)
$(CC) -c $< -o $# $(CFLAGS)
With this approach, you can see that I'm using the STRUCTURE variable only to get the files inside the SRCDIR directory, but it can be used for others purposes as well, like mirror the SRCDIR inside OBJDIR once STRUCTURE stores only the internal sub-directories. It is quite useful after clean operations like:
clean:
-rm -r $(OBJDIR)/*
NOTE: The compile rule only works well if for each *.c there is the corresponding *.h file (with the same base name, I mean).
How can I make a simple makefile to generate the object files and output binary in a bin directory from any number of c source and header files in a src directory? In this example structure, main includes module_a.h and module_b.h. module_a.h and module_b.h each only include stdio.h.
I can manage the clean rule, but do not know how to automatically generate the .o files and dependencies.
├── bin
├── makefile
├── README.md
└── src
├── main.c
├── module_a.c
├── module_a.h
├── module_b.c
└── module_b.h
This is a simple Makefile that I use. I'm not a Makefile guru so most likely it can be improved. But it should give you something to start with. The only tricky bit is the dependency handling. I am aware that there are other ways to do this. The example shows one way - generate .d files for each object file which lists the dependencies for that object file. Then include all the .d files into the Makefile to pick up all those dependency rules.
BIN := bin/my_binary
# Include all C files in the src directory
SRCS := $(shell find src -name '*.c')
# List of object files to link
OBJS := $(patsubst %.c,%.o,$(SRCS))
# Link rule
$(BIN): $(OBJS)
$(CC) -o $# $(OBJS)
# Include Dependency files
-include $(OBJS:.o=.d)
# Builds object file and generates dependency
%.o: %.c
$(CC) -c $(CFLAGS) $*.c -o $*.o
$(CC) -MM $(CFLAGS) $*.c > $*.d
mv -f $*.d $*.d.tmp
sed -e 's|.*:|$*.o:|' < $*.d.tmp > $*.d
rm $*.d.tmp