Question:
I have the following problem, assuming my project structure is as follows ( /
is the root).
/bin # Directorio vacío, es la salida del makefile.
/include/*.h # assembler.h core.h utils.h, Todos los headers estan aquí.
/src/assembler/*.c # assembler.c tokenizer.c y otras herramientas del ensamblador.
/src/core/*.c # utils.c core.c y todos los ficheros del núcleo compartido.
/src/machine/*.c # bla.c foo.c .... Todos los ficheros de la máquina virtual.
All projects under /src
have a dependency on the core
project, but have access to the headers of the /include
directory.
Using GNU make
I need to be able to compile only one of the projects I am working on, without the need to alter other projects, so far I have used the following Makefile
:
# #$@% Makefile
CC=gcc
FLAGS=-Wall -Wextra -Wpedantic -Werror -std=c11 -O3
INCLUDES=-Iinclude
checkbin:
# Ensure bin is there.
@if [ ! -e "bin" ]; then mkdir "bin"; fi
assembler: checkbin # First check for binaries folder.
$(CC) -o bin/assembler $(INCLUDES) $(FLAGS) src/core/*.c src/assembler/*.c
vm: checkbin
$(CC) -o bin/vm $(INCLUDES) $(FLAGS) src/core/*.c src/machine/*.c
clean:
@if [ -e "bin" ]; then \
rm -rf "bin"; \
fi
default: assembler # set assembler to default...
The Makefile
does the job, but it does a lot of work; it is recompiling the core
every time i go to compile some other project like machine
or assembler
.
To compile them separately I know I have to use gcc
's -c
flag, but inputting multiple files with this flag doesn't allow me to use the -o
flag to specify the output, for example:
$(CC) -c $(FLAGS) $(INCLUDES) /src/core/*.c
# Si intento poner -o "bin/core" en este caso, me arroja error
How can I move the compiled files of the dependency project, in this case core
, into their respective /bin/core
directory so that it can be used later to compile any other project?
For example:
/bin/core/utils.o
/bin/core/core.o
And binds to the following statement:
# Asumiendo los valores puestos arriba:
assembler: checkbin
@if [ ! -e "bin/assembler" ]; then mkdir "bin/assembler"; fi
# ... <- instrucción que pondrá los .o en el directorio /bin/assembler/*.o
$(CC) -o /bin/assembler/assembler /bin/core/*.o /bin/assembler/*.o
# Sólo necesitamos enlazar los archivos objeto.
Answer:
The basic solution was as Trauma described in his comment, for this I had to re-structure the project in such a way that it would be as follows:
/components/*.h # Todos los archivos cabecera
/core/bin # Carpeta que contendra los archivos objeto.
/core/*.c # Archivos de codigo del core
/core/Makefile # Makefile del proyecto Core
/hasm/bin
/hasm/*.c # Codigo del proyecto assembler
/hasm/Makefile
/machine/bin
/machine/*.c # Codigo del proyecto machine
/machine/Makefile
And configure the Makefile
in each project that needs core
so that it will verify if it is compiled and thus copy its object files, otherwise, it compiles the project. Staying as follows:
# hasm makefile.
CC=gcc
FLAGS=-Wall -Wextra -Wpedantic -Werror -O3 -std=c11 -c
INCLUDES=-I../components
OUTPUT=hasm # Cambia con el nombre del proyecto.
default: build
# Crea un objetivo condicionalmente, si existen los binarios del proyecto Core.
ifeq ("$(wildcard $(ls ../core/bin/*.o 2> /dev/null))","") # Verifica si hay archivos en /core/bin
dependencies:
@make -C ../core;
else
dependencies:
@echo "Core good.";
endif
# Mira a ver si existe el foder bin en el directorio actual.
checkbin:
@if [ ! -e "bin" ]; then mkdir "bin"; echo "Created!"; else echo "Exists!"; fi
# Construye el proyecto.
build: dependencies checkbin
@echo "Building project..."
$(CC) $(FLAGS) $(INCLUDES) src/*.c # Compila con el flag -c los archivos del proyecto.
@mv *.o bin/ # Mueve todos los archivos objeto al folder bin.
@cp ../core/bin/*.o bin/; # Copia los archivos de "../core/bin/" a "./bin/"
$(CC) -o bin/$(OUTPUT) bin/*.o # Enlaza con gcc.
# Elimina el folder bin y algun .o que quede en el directorio actual.
clean:
@if [ -e "bin" ]; then rm -rf "bin"; fi
@if [ -f *.o ]; then rm -f *.o; fi
When making make
, the build
recipe is executed, which has dependencies
as a prerequisite and checkbin
, in dependencies
, takes care of calling make -C ../core
, where -C
specifies that the Makefile
is located in the directory to your right, this compiles the dependencies of the project, i.e. core
.
After that, proceed to copy the object files inside the /core/bin/
folder to the folder of the project you are working on and link them without problem.