Write proper Ansi C makefile for Windows [closed] - c

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I'm really desperate when trying to write a C makefile for windows for my school project. I already have my makefile written and used for ubuntu and it works perfectly like this:
all: clean install
install: dynarr.o broadcaster.o main.o
gcc -o freq dynarr.o broadcaster.o main.o
clean:
rm -f *.o
dynarr.o:
gcc -c dynarr.c
broadcaster.o:
gcc -c broadcaster.c
main.o:
gcc -c main.c
I've already tried just about 10 tutorials on various sites and it is getting on my nerve.
I need to compile dynarr.c broadcaster.c main.c in this particular order and the output should be freq.exe. Compiler on the school server is gcc for both versions(linux and windows).
Please help me.
Edit: For some reason our teacher's online validator required freq.exe for both windows and linux and he did not bother to mention it anywhere. Everything I had to edit was freq to freq.exe. Thanks for support.

On Windows, you expect the compiler to produce a file named freq.exe (or the test system does, anyway) but the command you issue tells GCC to emit a file named just freq, instead. The latter seems natural for Linux, so it is not surprising that your build works as expected there.
It is tricky to support different OS families with the same makefile, which is why utilities such as the Autotools and CMake were invented. Supposing that you only need a Makefile for Windows, this variation should suffice:
all: clean install
install: dynarr.o broadcaster.o main.o
gcc -o freq.exe dynarr.o broadcaster.o main.o
clean:
rm -f *.o
dynarr.o:
gcc -c dynarr.c
broadcaster.o:
gcc -c broadcaster.c
main.o:
gcc -c main.c
With that said, I have some suggestions for further improvement:
A rule for building a specific output file should name that file as its target.
Conversely, targets of rules that do not correspond to a file created by that rule should be declared "phony" by naming them as prerequisites of a target named .PHONY.
By convention, an "install" target copies built files from their build location to a permanent system location. Neither your install rule nor anything else in your makefile does that, so you probably don't need an "install" target.
It is perhaps intentional that your rule for the default target cleans before it builds, but that is abnormal, as it defeats one of the major reasons for using make in the first place: to avoid needless work.
It is good form and it protects against errors to use Make's automatic variables to avoid repeating yourself in rules.
There is some divergence of opinion, but I think the general consensus is that a clean target should clean up all built objects, not just intermediate ones.
Applying all those would yield a makefile such as this:
all: freq.exe
freq.exe: dynarr.o broadcaster.o main.o
gcc -o $# $^
clean:
rm -f freq.exe *.o
dynarr.o:
gcc -c dynarr.c
broadcaster.o:
gcc -c broadcaster.c
main.o:
gcc -c main.c
.PHONY: all clean
Personally, I would also suggest introducing variables for the executable target (which would make it easier to adapt the makefile between Windows and Linux / macOS) and for the required object files (which is typical, and which would allow the clean target to be more precise). You could also consider relying on Make's built-in rules for building .o files from .c files, as the explicit rules you're using don't do anything that the is not also done by the built-in one. The result might be:
PROG = freq.exe
OBJS = dynarr.o broadcaster.o main.o
all: $(PROG)
$(PROG): $(OBJS)
gcc -o $# $^
clean:
rm -f $(PROG) $(OBJS)
# Relies on the built-in rules for building object files from C sources
.PHONY: all clean

Related

Simplest C makefile using implicit rules

I know it is not optimal at all to rely on make's implicit rules but
my goal is to understand why they are not working in this case.
I want to write the simplest makefile one can write for a C project
without having to specify the sources.
I have tried to run make -d but the ouput is too big and verbose to
really be helpful.
I have written makefiles for some time and I believe I am familiar with how it
works. I am pretty sure I have managed to get implicit rules to work for me both
compiling and linking in the past but apparently I am forgetting something.
Here's what I have tried :
SRCS = $(wildcard *.c)
OBJS = ${SRCS:.c=.o}
NAME=exe
${NAME}: ${OBJS}
clean:
rm -rf *.o
fclean: clean
rm -rf ${NAME}
re: fclean ${NAME}
.PHONY: clean fclean re
It almost works but it doesn't link.
I am using gnu make version 4.3
Your Makefile doesn't execute the link step because there is only a very simple implicit rule for linking. From the documentation:
Linking a single object file
n is made automatically from n.o by running the C compiler to link the program. The precise recipe used is $(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS).
This rule does the right thing for a simple program with only one source file. It will also do the right thing if there are multiple object files (presumably coming from various other source files), one of which has a name matching that of the executable file. Thus,
x: y.o z.o
In other words, for your Makefile to work, NAME needs to match the basename of one of your object files.
For example, if I have your Makefile and a single source file named hello.c, I can run:
make NAME=hello
And see the result:
cc -c -o hello.o hello.c
cc hello.o -o hello

C Makefile with two executables and a common directory [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed last year.
Improve this question
I need to make a makefile which compiles two executables, cassini and saturnd
I've been having a ton of problems with this makefile I'm using. Sometimes it compiles, sometimes not.
Makefile
CC = gcc
CFLAGS = -std=c11 -Wall -Wextra -Wpedantic -Wstrict-aliasing -I include
SRCCASSINI = $(wildcard src/cassini/*.c)
SRCSATURND = $(wildcard src/saturnd/*.c)
SRCCOMMON = $(wildcard src/common/*.c)
OBJCASSINI = $(SRCCASSINI:.c=.o)
OBJSATURND = $(SRCSATURND:.c=.o)
OBJCOMMON = $(SRCCOMMON:.c=.o)
EXEC = cassini saturnd
all: objs $(EXEC)
objs: $(OBJCOMMON)
cassini : $(OBJCASSINI)
$(CC) -o $# $(OBJCASSINI) $(OBJCOMMON)
saturnd : $(OBJSATURND) objs
$(CC) -o $# $(OBJSATURND) $(OBJCOMMON)
%.o : %.c
$(CC) -o $# -c $< $(CFLAGS)
clean :
rm -f src/*/*.o $(EXEC)
distclean :
rm -f src/*/*/.o $(EXEC)
Project structure
Include dir:
include contains the .h files of all c files and more.
SRC dir:
SRC contains 3 directories:
cassini* contains all source files that should be compiled only with the cassini executable
saturnd contains all source files that should be compiled only with the saturnd executable
common contains all source files that should be compiled with both cassini and saturnd
Screenshot : https://prnt.sc/26brtpq
make will fill my screen with verbose output. Sometimes it compiles, sometimes not. For some reason.
Without knowing what kinds of problems, specifically, you see it's hard to say for sure. But, one issue is your cassini target doesn't list any of the common objects as prerequisites. That means when cassini is linked it might be using older, not-recompiled versions of the object files (or they might be missing altogether).
You should change your link targets to this:
cassini : $(OBJCASSINI) $(OBJCOMMON)
$(CC) -o $# $^
saturnd : $(OBJSATURND) $(OBJCOMMON)
$(CC) -o $# $^
and see if that works better. If that doesn't help then your makefile looks correct so it must be something you haven't shown us here, and the only way to help with that is to see exactly how you invoke make and some explicit errors; as mentioned above please don't attach, or link to, screenshots: instead edit your question and cut and paste the text, with formatting.
The trick is not to use a makefile. I've been programming for years and still can't reliably make one of those do what I want.
Instead, you use cmake. It has an easy syntax which you can mostly copy-paste from one project to another and generates makefiles which reliably Do The Right Thing™.
To use cmake, you make a file called CMakeLists.txt in the parent directory of src. Put this in the file:
cmake_minimum_required (VERSION 3.9)
project(cassini_saturn LANGUAGES C)
SET(common_files
src/common/g.c
src/common/h.c
src/common/i.c
)
add_executable(cassini
src/cassini/a.c
src/cassini/b.c
src/cassini/c.c
${common_files}
)
target_compile_features(cassini PRIVATE cxx_std_11)
target_compile_options(cassini PRIVATE -Wall -Wextra -Wpedantic -Wstrict-aliasing)
target_include_directories(cassini PRIVATE include)
add_executable(saturnd
src/saturnd/d.c
src/saturnd/e.c
src/saturnd/f.c
${common_files}
)
target_compile_features(saturnd PRIVATE cxx_std_11)
target_compile_options(saturnd PRIVATE -Wall -Wextra -Wpedantic -Wstrict-aliasing)
target_include_directories(saturnd PRIVATE include)
Edit the obvious places so that the files your project uses are each listed individually. It is a best practice to list all the files, rather than relying on wildcards and globs, though if you want to not follow best practices you can use, eg:
file(GLOB SRC_FILES src/common/*.c)
Now that your CMakeLists.txt file is set up, it's time to use it. To do so, you'll run the following:
mkdir build/
cd build/
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo ..
make
You make a directory called build (it could be named anything) to contain all the byproducts of building and compiling your project. That way, you can just rm -rf build/ to get a clean slate. This is called an out-of-source build and it is a best practice.
The line
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo ..
generates a makefile for your project that, when run, will build your project with optimizations and debugging info. Other options are Release (all optimizations, no debugging info) and Debug (no optimizations, debugging info).
The final line, make, runs the generated makefile and builds the executables inside the build directory.

Configure automake to target assembly

Is it possible to configure automake to generate a Makefile which, in addition to building the .o files and linked binary, also has targets for %.s? I want to be able to review the compiler output in a text format without having to invoke binutils on the .o files.
Specifically, if I have main.c as a source file, I want to be able to run make main.s. The desired recipe would be the same as that for main.o, but using CC1 := $(CC) -S.
The question is a little XY.
You want to be able make the intermediate assembly file foo.s, where
the source file foo.c is one of the sources in an autotooled project, using
a makefile that is generated by the project's ./configure script. You
assume that to do this you must do something to the automake inputs -
the Makefile.ams? - that will cause ./configure to generate Makefiles
that include assembly targets *.s matching all object targets *.o.
Well you could, but then your project would not be a regular autotooled
project as usually distributed, and there is no need to make it irregular
to get what you want.
The GCC option -save-temps
exists to let developers see the intermediate files of compilation - the preprocessor
output, the assembly.
$ gcc -c -o foo.o foo.c
outputs foo.o
$ gcc -save-temps -c -o foo.o foo.c
outputs:
foo.o
foo.i # preprocessed source
foo.s # assembly
As I expect you know, GNU Make receives compiler options from the make-variable
CFLAGS, and automake respects this convention, independently of and in addition to any compiler
options prescribed by the project's autotooling. So, if you would otherwise generate
makefiles with:
$ ./configure ...
then, to add -save-temps to the C compiler options, generate makefiles instead
with:
$ ./configure CFLAGS=-save-temps ...
And if you are already using CFLAGS, e.g.
$ ./configure CFLAGS="-g -O0" ...
then append -save-temps:
$ ./configure CFLAGS="-g -O0 -save-temps" ...
Then,
$ make main.o
will make main.o, main.i and main.s up-to-date.
To disable -save-temps, of course, rerun ./configure, removing it from
the CFLAGS.
If the project involves C++ compilation, then CXXFLAGS affects the C++
compiler in the same way that CFLAGS affects the C compiler. Note that
the generated preprocessed C++ sources will be called *.ii, not *.i.
With -save-temps enabled, make clean will not delete the *.i and *.s
files. You may not care, since compilation will always clobber them. If you
do care, you may take advantage of automake's standard phony target clean-local,
which is supported to let an autotooling maintainer extend the behaviour of
clean. Add the following recipe to the Makefile.am of each source directory
in the project:
clean-local:
$(RM) *.i *.ii *.s
Then update the autotooling and regenerate Makefiles:
$ autoreconf
$ ./configure ...
While the COMPILE variable in the generated Makefile.in is technically an internal detail, and this solution relies on the compiler to understand -c -S, adding:
.c.s:
$(COMPILE) -c -S $<
to the Makefile.am has worked for as long as I've been using the autotools. It might also be convenient to add:
clean-local:
rm -f *.s
I find this useful in development to have a look at the assembly output for specific configure and CC, CFLAGS options.
The COMPILE variable will be defined as something like:
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
Similarly, for C++ source we have:
.cc.s:
$(CXXCOMPILE) -c -S $<

How to make cc look into /usr/local/include for header files

I encountered this problem while installing some python modules in which had dependencies on their own C libraries. The problem is, cc is not looking into /usr/local/include at all for header files. I made it work for one of those (thinking it was a problem of the modules) by adding /usr/local/include as one of the external include directories.
Then, to test, I wrote a simple hello.c file and added #include "fftw3.h" / #include <fftw3.h> and it failed to compile if I didn't explicitly add -I/usr/local/include.
I added a line in my ~/.bash_profile to export the include the directory path to $PATH; didn't work either.
So, my question is, how do I make cc look for header files in /usr/local/include (or, for that matter, in any custom directory) always without passing -I flag?
FYI: I'm using macbook pro running OSX 10.11
If you are using GCC then you have three environment variables you can use:
CPATH
C_INCLUDE_PATH
CPLUS_INCLUDE_PATH
Take a look here.
EDIT: since you specified you are working with OS X (hence Clang), they should be supported too, take a look ad the end here. It's not uncommon to have Clang mimic GCC specs just to help in compatibility.
I think you should invest some time in understanding build systems. For example gnu make. Here, look at this:
CC = gcc
CFLAGS = -Wall
DEPS = primes.h
OBJ = go.o primes.o
%.o: %.c $(DEPS)
$(CC) $(CFLAGS) -c -o $# $<
go: $(OBJ)
gcc $(CFLAGS) -o $# $^
This gives you:
The freedom to add any compiler you want. In your case that would be cc, in this example it is gcc.
use cflags to control to adjust the compiler - in the example -Wall will turn on the warnings
make your build work reproducible
prepare recipe with complex rules for compilation as your application grow
More information is available here.

What is wrong with this Makefile? (header files not found)

I am modifying an old makefile in order to build a C extension for postgreSQL. The Makefile currently looks like this:
PGLIB = /usr/lib/postgresql/8.4/lib
PQINC = /usr/include/postgresql/8.4/server
CC=gcc
override CFLAGS+= $(CFLAGS_SL) -DPG_AGGREGATE
SHLIB = pg_myextlib
SRC = foo.c \
foobar.c
OBJS = foo.o \
foobar.o
all: $(OBJS)
$(CC) -shared -o $(SHLIB)$(DLSUFFIX) $(OBJS) -I$(PQINC)
cp *.so $(PGLIB)
clean:
rm -f $(SHLIB) $(OBJS)
The error I get when I run make is:
common.h:58:22: error: postgres.h: No such file or directory
Which suggests that the include path is not being added (the file exists in $PQINC).
Its a long time since I wrote the Makefile - and I haven't written many since. As an aside, I am pretty sure that 'shared' is not the gcc flag to build shared libs on Ubuntu (my current dev box) - I think the flag should be 'fPIC' - can someone confirm this?
I am runing gcc v4.4.3 on Ubuntu 10.0.4 and compiling for use with PG 8.4
Try moving the -I$(PQINC) from target all to the end of line that starts with override CFLAGS.
Placing -Isomething on the compiler line which turns object files, like those in $(OBJS), into executable will have no effect whatsoever.
You need to do it when you compile the source files.
Since your makefile doesn't explicitly show the rule for processing source files, it may well be using a default one, which is incredibly unlikely to know about PQINC.
You seem to be using the default rules to build foo.o from foo.c, which doesn't have your -I. Try adding the following rule to your Makefile:
.c.o:
$(CC) $(CFLAGS) -c $< -o $# -I$(PQINC)

Resources