• Advertisement
Sign in to follow this  

Building C/C++ project without IDE

This topic is 1665 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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?

Share this post


Link to post
Share on other sites
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.

Edited by Cornstalks

Share this post


Link to post
Share on other sites

How is it done if I want to link my project to some 3rd party library/framework? If I'm using SDL for instance.

Share this post


Link to post
Share on other sites

Specify them in your linker flags. Add them to your header includes paths as well. In the makefile.

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

 

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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

I would go with CMake as Matt-D suggested.

 

Alternatively, SCons is also really simple to use and will output the final executable with just one command.

 

In my opinion you should try to stay away from pure make, it will probably only give you headaches.

Share this post


Link to post
Share on other sites

In my opinion you should try to stay away from pure make, it will probably only give you headaches.

I would say knowing how to use Makefiles is a very valuable skill. I don't think you have to have extensive knowledge of Make, but it's certainly something everyone should have at least some experience with and be able to use at least on a basic level. If you develop in C or C++, you will, at some point, have to deal with Make and Makefiles, even if you hate them bitterly. I personally think he should at least use Makefiles for a little bit, maybe for a project or two, and then move onto something else, if he wishes.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement