I have a Linux GNU C project that requires building output for two different hardware devices, using a common C source code base, but different makefiles. Presently I have two makefiles in the same folder, one for each device, and when I make a change to the code, I have to first do "make clean" to make the first model, then "make clean" to make the second model. This is because they use different compilers and processors. Even if a code file didn't change, I have to recompile it for the other device.
What I would like to do is use a different folder for the second model, so it stores a separate copy of *.d and *.o files. I would not have to "make clean", only recompile the changed sources. I have looked at makefile syntax, and being new to Linux, can only scratch my head at the cryptic nature of this stuff.
One method I'm considering would update the .c & .h files from model_1 folder into model_2 folder. Can someone provide me with a simple makefile that will copy only newer *.c and *.h files from one folder to another?
Alternatively, there must be a way to have a common source folder, and separate output folders, so duplicated source files are not required. Any help to achieve that is appreciated. I can provide the makefiles if you want to look at them.
You want to generated files (object and dependencies) put into a separate folder for each build type as it compiles. Here's what I had do that may work for you:
$(PRODUCT1_OBJDIR)/%.o $(PRODUCT1_OBJDIR)/%.d: %.cpp
#mkdir -p $(#D)
$(CXX) $(PRODUCT1_DEPSFLAGS) $(CXXFLAGS) $(INCLUDE_DIR) $< -o $(PRODUCT1_OBJDIR)/$*.o
$(PRODUCT2_OBJDIR)/%.o $(PRODUCT2_OBJDIR)/%.d: %.cpp
#mkdir -p $(#D)
$(CXX) $(PRODUCT2_DEPSFLAGS) $(CXXFLAGS) $(INCLUDE_DIR) $< -o $(PRODUCT2_OBJDIR)/$*.o
$PRODUCT1_OBJDIR and $PRODUCT2_OBJDIR are variables names for the directory where you wish to have the generated files stored. This will check for changes to dependencies and recompile if needed.
If you still have problems, get back with feedback, will try and sort you out.
You could compile your source files to object files in different directories ("folder" is not really the appropriate word on Unix). You just have to set appropriate make rules. And you might use other builders like omake, scons, ...
You could use remake to debug your GNU Makefile-s. You could have inside a rule like
$(OBJDIR)/%.o: $(SRCDIR)/%.c
$(COMPILE.c) -c $^ -o $#
And you could set (earlier in your Makefile) variables with e.g.
OBJDIR:=obj-$(shell uname -m)
or something better
I do suggest to read GNU make's manual; it has an introduction to makefiles.
This can be easily achieved with makepp's repository mechanism. If you call makepp -R../src ARCH=whatever then it will symbolically link all parts of ../src under the current directory and compile here.
You can even create a file .makepprc and put in any options specific to this architecture, so you'll never get confused which command to call where.
If your different architectures have identically produced files (like generated sources), you can even build in ../src and the other architecture will pick up everything that doesn't depend on your current compile options.
There is much more to makepp. Besides doing almost all that GNU make can, there are lots more useful things, and you can even extend your makefiles with some Perl programming.
Related
The problem is the following. I have a list of .c files in several directories that I wish to compile, one by one, into a .o file, located at BUILD_DIR folder, to be later linked. They are appended to the SOURCE_FILES_FREERTOS variable. The Makefile code section that attempts to perform this is:
OBJ_FILES_FREERTOS = $(SOURCE_FILES_FREERTOS:%.c=$(BUILD_DIR)/%.o)
# Build the Operating System Library
freertos: ${OBJ_FILES_FREERTOS}
${BUILD_DIR}/%.o : $(dir ${SOURCE_FILES_FREERTOS})/%.c
-mkdir -p ${BUILD_DIR}
$(CC) $(CFLAGS) ${INCLUDE_DIRS} -MMD -c $< -o $#
However, it does not work, saying there is no rule fore the first target file:
make: *** No rule to make target 'build/../../../FreeRTOS/Source/stream_buffer.o', needed by 'freertos'. Stop.
What seems to be the problem?
From a top-down perspective we first declare the objects to be part of the library:
OBJECT_FILES_FREERTOS := $(patsubst ...)
libfreertos.a: $(OBJECT_FILES_FREERTOS)
I cannot create OBJECT_FILES_FREERTOS from the variables in the question. You'd have to add more to it or figure it out yourself. Below I assume that all object files have $(BUILD_DIR)/-prefix and the same directory structure as the source it is derived from (which is a pain since Make does not create necessary directory hierarchy for you, but that's just how Make rolls).
Make now tries build object files from source files. By default searching for source files in the same directory as where the object files are expected to be. This is where it becomes tricky, since the source files (from looking at your error) is not in the source tree, making a relative path to god knows where. You need a different source-to-object map, here using static rules:
$(OBJECT_FILES_FREERTOS): $(BUILD_DIR)/%.o: $(FREERTOS_SRC_DIR)/%.c
No rule to make target means it cannot find a rule to build the file, most often because the source file is missing and Make does not know how to build it from nothing.
freertos has a dependency on build/../../../FreeRTOS/Source/stream_buffer.o but you don't have any rules that cover that file. This is your root cause for the build failure.
The pattern rule suggest you are putting the object files in $(BUILD_DIR) and not 3 levels up from it. This means that the pattern rule doesn't apply in this case.
I am taking a Coursera course and I am totally stuck in one of the project. Project demands us to create a makefile but I could not.
Here is my files and folders:
project
|---include
|---CMSIS
|---cmsis_gcc.h
|---core_cm4.h
|---core_cmFunc.h
|---core_cmInstr.h
|---ore_cmSimd.h
|------common
|---memory.h
|---platform.h
|------msp432
|---cmsis_gcc.h
|---msp_compatibility.h
|---syste_msp432.h
|---src
|---interr.c
|---main.c
|---memory.c
|---str.h
|---system_msp.h
|---makefile
|---msp432p401r.lds
|---sources.mk
Here is my sources.mk and makefile.
For now, I just want to check whether makefile succesfully find related source and include files but it does not.
I have checked several example makefiles and could not find where is the fault of mine? What I have got here is:
What I understand from error is it can not find related memory.h file. What can I do?
Any help will be appreciated.
Thanks.
Make searches for prerequisites in the working directory. It doesn't know that you have memory.h somewhere else, and will not go looking for without instructions.
One way to solve this is with the vpath directive:
vpath %.h common
You can use the same trick when you run into problems finding other prerequisites:
vpath %h common CMSIS
vpath %.c src
That will get echo "HI" to work, but you will have more trouble with a real rule that actually uses the prerequisites. To take a contrived example:
memory.o: memory.c memory.h
$(CC) -c $(CFLAGS) memory.c -o memory.o
This will fail because although Make can find the prerequisites, the compiler still doesn't know where they are.
We tell the compiler where memory.c is by referring it to the list of prerequisites:
memory.o: memory.c memory.h
$(CC) -c $(CFLAGS) $< -o memory.o
($< means the first prerequisite; Make will provide the path.) We could use the same trick (with some effort) to tell the compiler where to search for the header file, but it's usually simpler to put that in by hand:
memory.o: memory.c memory.h
$(CC) -c $(CFLAGS) -Icommon $< -o memory.o
It's important to understand that make and the compiler are two completely different programs, that do different things and work different ways. Make can run a compiler, but it can also do all sorts of other things: it could build documentation, or an entire website, or copy files, etc. Basically make is a general-purpose tool that can investigate when files are out of date and run any command you give it to make that file "up to date", whatever that may mean.
So, when you create a variable like INCLUDES = -I... that is setting a make variable to a flag that can tell the compiler where your header files are.
That means nothing to make.
Make sees this rule:
ysk: memory.h memory.c
and says "ok to build the file ysk I need to have memory.h and memory.c". It looks in the current directory and those files don't exist (because they are in src/memory.h and src/memory.c) so it fails.
You need to put the paths into your makefile, so make can find them.
I've read some articles explaining how recursive makefiles were evil in the case of compiling projects with subdirectories.
But, I found this handy way to automatically generate dependencies
exec = main
objs = main.o A.o B.o C.o # main and object modules
deps = $(objs:.o=.d) # dependencies file
all: $(deps)
$(MAKE) $(exec)
-include $(deps)
%.d: %.c # how to build dependency files
$(CC) -MM $(CFLAGS) $< > $#
main: $(objs) # How to build the main exec
Building the target "all" updates the dependency files if needed, and then considers rebuilding the main exec if needed.
Is there something fundamentally flawed with this approach?
If you're using GNU make, this hack is unnecessary. GNU make is smart enough to automatically rebuild any (make)file that is included, and then restart itself:
Since the ‘.d’ files are makefiles like any others, make will remake them as necessary with no further work from you. See Remaking Makefiles.
About other make implementations, the GNU make manual has this to say:
With old make programs, it was traditional practice to use [the -M] compiler feature to generate prerequisites on demand with a command like ‘make depend’. That command would create a file depend containing all the automatically-generated prerequisites; then the makefile could use include to read them in (see Include).
As remarked by other contributors, gnu make treats .d dependencies files as Makefile and rebuilds them automagically when needed.
This makes the recursive call unnecessary, and the question falls flat.
Of course, as usual, "considered harmful" paper titles have to be read with a grain of salt, if really read at all, from a long tradition (Knuth's "rebuttal" of Dijkstra's paper cites Disjktra own fear to be believed as terribly dogmatic" and "others making a religion of it". "Fanatical advocates going over the board" !).
I have following program structure:
main.c
Makefile
Submodule
--{somefiles}
--Makefile
Submodule is creating library submodule.a. It has many source files and it need some libraries.
All I want to know that
Makefile in submodule knows how to make submodule.a
Makefile in submodule sets variable SUBMODULE_LDFLAGS and SUBMODULE_LDLIBS
How can I write Makefile in root project directory that:
it would create submodule.a using Makefile in submodule
it would add SUBMODULE_LDFLAGS and SUBMODULE_LDLIBS to its own variable?
AT the end I want the following command in main Makefile works correctly:
TARGET = MyProgram
OBJS = $(TARGET).o submodule/submodule.a
$(TARGET): $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $# $(LDLIBS)
Now it creates MyProgram.o and cannot create MyProgram, because Makefile doesn't know how to make submodule/submodule.a.
I can add lines:
submodule/submodule.a:
make -C submodule
but it won't help me with missing libraries.
There is no direct way for the sub-Make to pass variables to the parent process. There are (at least) two indirect ways.
You could have the sub-Make write a file containing the variable values, which the parent Make could then read.
You could copy the part of submodule/Makefile that constructs those variables, and put it into Makefile. Better still, you could isolate that code in a separate file that both makefiles would then include.
EDIT:
One disadvantage of recursive Make is that it interrupts much of Make's dependency handling. In this case, there's no clean way to have the sub-make run when and only when one of the library's sources is changed.
You can put the list of submodule sources -- or the code that constructs the list -- in a separate file which both makefiles will include. Then those files can be among the prerequisites of $(TARGET).
Or, you could make submodule/submodule.a a PHONY target. In that case, Make will rebuild the binary every time, but otherwise it'll work perfectly.
I am new to Code::Blocks. For my studies I am programming several small programms in C (just to try things out).
I tried to put them all in one project, because they belong to the same topic, but that doesn't work because each of them has a main function.
Any ideas how I can put those files together somehow, but not depending on each other?
Suppose your source files are called
prog1.c
prog2.c
mylib.c
mylib.h
where prog1.c and prog2.c each contain a main() function and mylib.c (with the corresponding header file mylib.h) contains some library functions that should be linked to each program. In your Code::Blocks project you need to create multiple targets now. From the menu choose 'File/New/Build target...' and name them 'prog1' and 'prog2'. Now add all of your source files to the project (in case you haven't done so already).
Now right-click on prog1.c and select "Properties..." from the context menu. In the dialog box choose the 'Build' tab and make sure that under "Belongs to target" only "prog1" is checked. Do the same with prog2.c and the target "prog2". For "mylib.c" make sure that both "prog1" and "prog2" are checked.
Now you can easily choose in the UI which build target to build and run. Note that if you add another target, say "prog3", then you have to go to the build properties of prog1.c and prog2.c again and uncheck "prog3".
A C program should contain only one main function.. Divide all your separate programs as Functions and put them in a single C program or you can even put it in multiple files and compile them..
You can use a switch case for calling different functions..
Remove the main function from all the programs and convert them into functions..
Call them where ever required.. This will help you..
let's say that your project contains 3 c files and each c file is a separate program and it contains its own main function:
program1.c
program2.c
program3.c
So you can write a Makefile (its name in your computer should be "Makfile"). It will build the program you want separately
This is how your makefile looks:
all: program1 program2 program3
%.o: %.c
$(CC) $(CFLAGS) -c -o $# $^
program1: program1.o
$(CC) $(LDFLAGS) -o $# $^
program2: program2.o
$(CC) $(LDFLAGS) -o $# $^
program3: program3.o
$(CC) $(LDFLAGS) -o $# $^
clean:
rm -f *.o program1 program2 program3
with the above Makefile you can build each program separetly
example
$ make program1
will build only program1
or you can buil all programs with
$make all
It seems to me as if you are starting to build some nice utility functions. So follow the advice offered by raghu-srikanth-reddyce and create separate functions for each little program. However I would add that it would be better to create yourself a simple C library to keep them all in which you can link to at any time. Most professional programmers keep such libraries.
A simple makefile will enable you to build a final binary that you can link to.
Good luck with your programming ;)
If you want to compile in one file, you dont need a Project File then.
Just make a New File, then write all the code in a single file. Also use Function and Procedure if you need it.
This is quite late but since I was once here with the same question, and I believe most students had/ have/ will have this same question, let me elaborate where you have been played at.
In Educational Courses and in Real World, a project is (in general) some problem you work on, find a solution, then make a report (+ documentation) on it.
In Programming IDE, a project is the problem's solution itself. Hence, while you may have multiple individual problems within one project in any Python IDE, Any standard C/C++ IDE project must have only one 'main()' to rule them all (unless you know how to create makefiles).
What the AP tried to do is to put several different problem's solutions fit within one solution's space - not a possible thing to do in Code::Blocks. Even if all the problems may share the same topic (say, Graph Theory), they are individual problem (Dijkstra vs Floyd) themselves.