Building C/C++ project without IDE

Started by
10 comments, last by Cornstalks 10 years, 9 months ago

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?

Advertisement

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.

[size=2][ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

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.

In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.

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.

[size=2][ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

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

Currently working on a scene editor for ORX (http://orx-project.org), using kivy (http://kivy.org).

While make is the one command line build tool every C or C++ programmer should have at least passing familiarity with, it has enough issues that many, many alternatives have been created. Wikipedia has a list of alternatives.

If you'd like to be cross-platform, I'd go with CMake:

http://wiki.gamedev.com/CMake

http://www.gamedev.net/page/resources/_/technical/general-programming/cross-platform-test-driven-development-environment-using-cmake-part-1-r2986

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).

[size=2][ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

This topic is closed to new replies.

Advertisement