If I decide to use a text editor like vim or emacs for coding, what is the best way to compile a C/C++ program with multiple files? Is makefiles the way to go or is there some alternative?
Building C/C++ project without IDE
Makefiles, for sure.
For large projects, GNU Autoconf is typically used to generate the configuration files and makefiles. But don't worry so much about autoconf tools. Simply using Makefiles is simple enough. There are also some hacks you can do to simplify things. For example, here's part of a Makefile I use at work:
# C++ compiler
CXX = g++
# C compiler
CC = gcc
# C compilation flags
CFLAGS = -std=c99 -Wall -pthread -DNDEBUG -O3
# Preprocessor definitions
C_DEFS = -D_POSIX_C_SOURCE=199309
# Linker flags
LDFLAGS += -lz -lm
# Build targets
all: program
# Rules for converting .c files into .o files
.SUFFIXES: .c
%.o: %.c
$(CC) $(C_DEFS) $(CFLAGS) -MMD -c $<
# List of source files
SRCS = SourceFile1.c \
SourceFile2.c \
SourceFile3.c \
main.c
OBJS = $(SRCS:.c=.o)
DEPS = $(OBJS:.o=.d)
# Include the .d dependency files
-include $(DEPS)
# Build the target "program"
program: $(OBJS)
$(CC) $(C_DEFS) $(CFLAGS) $^ $(LDFLAGS) -o $@
clean:
rm -f *.o *.d program
Basically, with this Makefile, I can easily change the compiler and compiler (and linker) flags to whatever I need. Adding a new file to the project is as simple as just adding it to SRCS. It also automatically detects header dependencies, so if source file main.c depends on header.h, and you modify header.h, it will rebuild main.c. You could modify it a bit to have a "program-d" target (for example) that makes a debug build if you wanted, too.
How is it done if I want to link my project to some 3rd party library/framework? If I'm using SDL for instance.
Specify them in your linker flags. Add them to your header includes paths as well. In the makefile.
How is it done if I want to link my project to some 3rd party library/framework? If I'm using SDL for instance.
In my Makefile, I wrote LDFLAGS += -lz -lm which says I'm linking to zlib (-lz) and the standard math library (-lm). If I needed to specify a path to the zlib library, I would have added -L/path/to/zlib/library before -lz. As Washu says, you'll need to include the header search path as well (which I typically do by adding -I/path/to/some/headers to CFLAGS).
If you're not very familiar with compiling from the command line, I would suggest starting out by manually typing in the compilation commands so that you start to learn them. Once you understand how to compile things from the command line (and specify all your dependencies and desired compiler flags), Makefiles are much easier to understand and use.
How is it done if I want to link my project to some 3rd party library/framework? If I'm using SDL for instance.
In my Makefile, I wrote LDFLAGS += -lz -lm which says I'm linking to zlib (-lz) and the standard math library (-lm). If I needed to specify a path to the zlib library, I would have added -L/path/to/zlib/library before -lz. As Washu says, you'll need to include the header search path as well (which I typically do by adding -I/path/to/some/headers to CFLAGS).
If you're not very familiar with compiling from the command line, I would suggest starting out by manually typing in the compilation commands so that you start to learn them. Once you understand how to compile things from the command line (and specify all your dependencies and desired compiler flags), Makefiles are much easier to understand and use.
Also, if you are using linux you can set the environment variable LD_LIBRARY_PATH instead of using -L/path/to/zlib/library and CPATH instead of using -I/path/to/some/headers. You may specify multiple paths by separating them with ":", for instance:
export LD_LIBRARY_PATH=/path/to/zlib/library:/path/to/another/library
If you'd like to be cross-platform, I'd go with CMake:
http://www.gamedev.net/topic/637413-cmake-or-make-for-c-projects/
For a discussion involving more options, see also:
http://www.reddit.com/r/cpp/comments/wvnko/build_systems_for_cc_projects/
Makefiles, for sure.
For large projects, GNU Autoconf is typically used to generate the configuration files and makefiles. But don't worry so much about autoconf tools. Simply using Makefiles is simple enough. There are also some hacks you can do to simplify things. For example, here's part of a Makefile I use at work:
# C++ compiler CXX = g++ # C compiler CC = gcc # C compilation flags CFLAGS = -std=c99 -Wall -pthread -DNDEBUG -O3 # Preprocessor definitions C_DEFS = -D_POSIX_C_SOURCE=199309 # Linker flags LDFLAGS += -lz -lm # Build targets all: program # Rules for converting .c files into .o files .SUFFIXES: .c %.o: %.c $(CC) $(C_DEFS) $(CFLAGS) -MMD -c $< # List of source files SRCS = SourceFile1.c \ SourceFile2.c \ SourceFile3.c \ main.c OBJS = $(SRCS:.c=.o) DEPS = $(OBJS:.o=.d) # Include the .d dependency files -include $(DEPS) # Build the target "program" program: $(OBJS) $(CC) $(C_DEFS) $(CFLAGS) $^ $(LDFLAGS) -o $@ clean: rm -f *.o *.d program
Basically, with this Makefile, I can easily change the compiler and compiler (and linker) flags to whatever I need. Adding a new file to the project is as simple as just adding it to SRCS. You could modify it a bit to have a "program-d" target (for example) that makes a debug build if you wanted, too.
A problem with this file though is that make won't detect changes to header files for you. For a more robust system, you'll want to put each source file in your project on a seperate line, and specify the files it depends upon. For example:
a_file.o: a_file.c a_file.h other_header.h
$(CC) $(C_DEFS) $(CFLAGS) -MMD -c a_file.c
Also beware, make requires TAB characters, not spaces for indent.
A problem with this file though is that make won't detect changes to header files for you. For a more robust system, you'll want to put each source file in your project on a seperate line, and specify the files it depends upon.
Actually, yes it will. The -MMD flag when building the .o files generates .d dependency files, which get included by -include $(DEPS). My makefile automatically detects and generates dependency lists (and updates them when you change files).