Jump to content
SSForum.net is back!

Recommended Posts

Posted

I'm trying to create a makefile to build the modules part of Discretion, but I'm running into some trouble. The modules structure is fairly organized, so I was hoping to have a single makefile to create all of them, rather than a makefile for each individual module. The dependencies are like this:

 

the makefile is in the modules directory. Inside this directory there is a folder for each module. I want the .so file produced to have the same name as the folder. Inside each folder can be a set of .h and .cpp files. A .o (or is it .obj for c++?) file should be created for each .cpp file which depends on the corresponding .cpp and .h files. The .so file should be created with the sane name as the directory, and depend on each of the .o files. The .so file should be placed in a different location "$(BIN_DIR)".

 

After trying to do this for a few hours I got something like this:

 

CC=g++
GLOBAL_CPPFLAGS=
GLOBAL_LDFLAGS=

BIN_DIR=../../bin/bin

UNAME := $(shell uname)

ifeq ($(UNAME), Linux)
# Linux specific macros
GLOBAL_CPPFLAGS += -DLINKING_LINUX
else
# Windows specific macros
GLOBAL_CPPFLAGS += -DLINKING_WINDOWS
endif

######################
# Rules 
MODULES = $(shell ls -d */)

# remove the '/' from all directories
MODULES := $(subst /,,$(MODULES))

# remove non modules which have directories
MODULES := $(subst Shared,,$(MODULES))
MODULES := $(subst MapLoader,,$(MODULES))
MODULES := $(subst Module,,$(MODULES))

# generate variable for the final SO files: "$(BIN_DIR)/$(module).so"
SO_FILES := $(foreach module,$(MODULES),$(BIN_DIR)/$(module).so)

.PHONY : all clean modules 
modules: $(SO_FILES)

all: modules


# I want: each so file depends on all the .cpp and .h files in its directory     

%.so : ../../src/Modules/%/Animations.cpp
	echo deps = $^

 

When I run this, it works ok for the first module (Animations), since Animations.cpp is hardcoded in the makefile. What I actually want, though, is for the dependencies to be ALL the .cpp files (I'll eventually substitute .cpp for .o). When I replace the dependency line with this, though:

 

%.so : ../../src/Modules/%/*.cpp
	echo deps = $^

 

 

It tells me there's no rule to make ../../bin/bin/Animations.so.

 

If you want to try it out you can get the DiscretionClient source from mercurial (hg clone http://hg.code.sf.net/p/ss-discretion/client ss-discretion-client) and put the pasted makefile into src/Modules/

  • 4 weeks later...
Posted

I figured it out. You can use $(shell ls) in a makefile to spawn a shell and run commands, but that's to slow to do for every module (~35). So instead I made the following makefile, which scans the sources for known #includes so it knows what libraries to include automatically, as well as using gcc's dependency generation so exactly the correct files will be compiled when changes are detected. It also detects shared objects and includes them in the shared object files (.so or .dll) correctly.

 

 # A global makefile for creating Discretion. This should be in the src directory.# BaK, 3-28-2013 # standard variablesCC=g++LN=g++CPPFLAGS=-I./Modules/ -O3 -WallLDFLAGS=-shared # directoriesBIN_DIR=../bin/bin/MODULES_DIR=./Modules/  UNAME := $(shell uname) ifeq ($(UNAME), Linux)# Linux specific macrosLDFLAGS += -selse# Windows specific macrosLDFLAGS += -sendif ####################### Rules  .PHONY : all clean  # extract module namesMODULE_NAMES := $(wildcard $(MODULES_DIR)*)MODULE_NAMES := $(notdir $(MODULE_NAMES)) # remove non-modulesMODULE_NAMES := $(subst Shared ,,$(MODULE_NAMES)) SO_FILES := $(addprefix $(BIN_DIR), $(MODULE_NAMES))SO_FILES := $(addsuffix .so,$(SO_FILES)) all: $(SO_FILES) clean: rm -vf $(BIN_DIR)*.so $(MODULES_DIR)*/*.o $(MODULES_DIR)*/*.d $(MODULES_DIR)*/*.deps # pull in dependency info for *existing* .o files (redirect errors away from terminal in case .d files don't exist)DEP_FILES := $(shell ls $(MODULES_DIR)*/*.d 2> .junk ; rm -f .junk)-include $(DEP_FILES) define make_so# param 1 is name of so file # general rule for making  .so files, first make .o.deps and .ld.deps$(BIN_DIR)$(1).so: $(MODULES_DIR)$(1)/$(1).o.deps $(MODULES_DIR)$(1)/$(1).ld.deps $(CC) $(LDFLAGS)  -o $$@ `cat $(MODULES_DIR)$(1)/$(1).o.deps` `cat $(MODULES_DIR)$(1)/$(1).ld.deps` ### tracks which libraries should be linked with the .so #### 1. create a blank .ld.deps file# 2. create an entry if SDL.h is detected# 3. create an entry if SDL_net.h is detected# 4. create an entry if SDL_image.h is detected# 5. create and entry if zlib.h is detected$(MODULES_DIR)$(1)/$(1).ld.deps: $(MODULES_DIR)$(1)/*.cppecho -n > $(MODULES_DIR)$(1)/$(1).ld.deps && \\if [ `cat $(MODULES_DIR)$(1)/*.cpp | grep SDL.h -c` -ne 0 ]; \then echo -n "-lSDL " >> $(MODULES_DIR)$(1)/$(1).ld.deps; fi && \\if [ `cat $(MODULES_DIR)$(1)/*.cpp | grep SDL_net.h -c` -ne 0 ]; \then echo -n "-lSDL_net " >> $(MODULES_DIR)$(1)/$(1).ld.deps; fi && \\if [ `cat $(MODULES_DIR)$(1)/*.cpp | grep SDL_image.h -c` -ne 0 ]; \then echo -n "-lSDL_image " >> $(MODULES_DIR)$(1)/$(1).ld.deps; fi && \\if [ `cat $(MODULES_DIR)$(1)/*.cpp | grep zlib.h -c` -ne 0 ]; \then echo -n "-lzdll " >> $(MODULES_DIR)$(1)/$(1).ld.deps; fi #### tracks which .o files need to be built and included in the .so #### 1. create a .o.deps entry for every .cpp file in the module's directory# 2. create .o.deps entry if StringManip.h is used# 3. create .o.deps entry if LittleEndian.h is used# 4. create the .so.deps file from the now complete .o.deps file# 5. recursive call to make so that the .so dependecies get included and the proper .o files get made$(MODULES_DIR)$(1)/$(1).o.deps: $(MODULES_DIR)$(1)/*.cpp+ ls $(MODULES_DIR)$(1)/*.cpp | tr '\n' ' ' | sed -e 's/\.cpp/\.o/g' > $(MODULES_DIR)$(1)/$(1).o.deps && \\if [ `cat $(MODULES_DIR)$(1)/*.cpp | grep StringManip.h -c` -ne 0 ]; \then echo -n " "$(MODULES_DIR)Shared/StringManip.o >> $(MODULES_DIR)$(1)/$(1).o.deps; fi && \\if [ `cat $(MODULES_DIR)$(1)/*.cpp | grep LittleEndian.h -c` -ne 0 ]; \then echo -n " "$(MODULES_DIR)Shared/LittleEndian.o >> $(MODULES_DIR)$(1)/$(1).o.deps; fi && \\echo -n "$(BIN_DIR)$(1).so: " > $(MODULES_DIR)$(1)/$(1).so.deps; cat $(MODULES_DIR)$(1)/$(1).o.deps >> $(MODULES_DIR)$(1)/$(1).so.deps && \\$(MAKE) `cat $(MODULES_DIR)$(1)/$(1).o.deps` --no-print-directory # includes the generated dependencies for the .so (this takes effect in the recursive make call from the .o.deps rule)-include $(MODULES_DIR)$(1)/$(1).so.deps endef $(foreach modname,$(MODULE_NAMES),$(eval $(call make_so,$(modname)))) #for number in 1 2 3 4 ; do \#    ./a.out $$number ; \#done %.o : %.cpp$(CC) -MMD -c $(CPPFLAGS) $< -o $@

Posted

I wanted to edit the above since apparently pasting into code blocks didn't work. When I hit edit, though, both Chrome and Iexplorer freeze, so I've just tried again here with a quote block.

 

 

# A global makefile for creating Discretion. This should be in the src directory.
# BaK, 3-28-2013
 
# standard variables
CC=g++
LN=g++
CPPFLAGS=-I./Modules/ -O3 -Wall
LDFLAGS=-shared
 
# directories
BIN_DIR=../bin/bin/
MODULES_DIR=./Modules/
 
 
UNAME := $(shell uname)
 
ifeq ($(UNAME), Linux)
# Linux specific macros
LDFLAGS += -s
else
# Windows specific macros
LDFLAGS += -s
endif
 
######################
# Rules 
 
.PHONY : all clean 
 
# extract module names
MODULE_NAMES := $(wildcard $(MODULES_DIR)*)
MODULE_NAMES := $(notdir $(MODULE_NAMES))
 
# remove non-modules
MODULE_NAMES := $(subst Shared ,,$(MODULE_NAMES))
 
SO_FILES := $(addprefix $(BIN_DIR), $(MODULE_NAMES))
SO_FILES := $(addsuffix .so,$(SO_FILES))
 
all: $(SO_FILES)
 
clean: 
rm -vf $(BIN_DIR)*.so $(MODULES_DIR)*/*.o $(MODULES_DIR)*/*.d $(MODULES_DIR)*/*.deps
 
# pull in dependency info for *existing* .o files (redirect errors away from terminal in case .d files don't exist)
DEP_FILES := $(shell ls $(MODULES_DIR)*/*.d 2> .junk ; rm -f .junk)
-include $(DEP_FILES)
 
define make_so
# param 1 is name of so file
 
# general rule for making  .so files, first make .o.deps and .ld.deps
$(BIN_DIR)$(1).so: $(MODULES_DIR)$(1)/$(1).o.deps $(MODULES_DIR)$(1)/$(1).ld.deps 
$(CC) $(LDFLAGS)  -o $$@ `cat $(MODULES_DIR)$(1)/$(1).o.deps` `cat $(MODULES_DIR)$(1)/$(1).ld.deps`
 
### tracks which libraries should be linked with the .so ###
# 1. create a blank .ld.deps file
# 2. create an entry if SDL.h is detected
# 3. create an entry if SDL_net.h is detected
# 4. create an entry if SDL_image.h is detected
# 5. create and entry if zlib.h is detected
$(MODULES_DIR)$(1)/$(1).ld.deps: $(MODULES_DIR)$(1)/*.cpp
echo -n > $(MODULES_DIR)$(1)/$(1).ld.deps && \
\
if [ `cat $(MODULES_DIR)$(1)/*.cpp | grep SDL.h -c` -ne 0 ]; \
then echo -n "-lSDL " >> $(MODULES_DIR)$(1)/$(1).ld.deps; fi && \
\
if [ `cat $(MODULES_DIR)$(1)/*.cpp | grep SDL_net.h -c` -ne 0 ]; \
then echo -n "-lSDL_net " >> $(MODULES_DIR)$(1)/$(1).ld.deps; fi && \
\
if [ `cat $(MODULES_DIR)$(1)/*.cpp | grep SDL_image.h -c` -ne 0 ]; \
then echo -n "-lSDL_image " >> $(MODULES_DIR)$(1)/$(1).ld.deps; fi && \
\
if [ `cat $(MODULES_DIR)$(1)/*.cpp | grep zlib.h -c` -ne 0 ]; \
then echo -n "-lzdll " >> $(MODULES_DIR)$(1)/$(1).ld.deps; fi
 
#### tracks which .o files need to be built and included in the .so ###
# 1. create a .o.deps entry for every .cpp file in the module's directory
# 2. create .o.deps entry if StringManip.h is used
# 3. create .o.deps entry if LittleEndian.h is used
# 4. create the .so.deps file from the now complete .o.deps file
# 5. recursive call to make so that the .so dependecies get included and the proper .o files get made
$(MODULES_DIR)$(1)/$(1).o.deps: $(MODULES_DIR)$(1)/*.cpp
+ ls $(MODULES_DIR)$(1)/*.cpp | tr '\n' ' ' | sed -e 's/\.cpp/\.o/g' > $(MODULES_DIR)$(1)/$(1).o.deps && \
\
if [ `cat $(MODULES_DIR)$(1)/*.cpp | grep StringManip.h -c` -ne 0 ]; \
then echo -n " "$(MODULES_DIR)Shared/StringManip.o >> $(MODULES_DIR)$(1)/$(1).o.deps; fi && \
\
if [ `cat $(MODULES_DIR)$(1)/*.cpp | grep LittleEndian.h -c` -ne 0 ]; \
then echo -n " "$(MODULES_DIR)Shared/LittleEndian.o >> $(MODULES_DIR)$(1)/$(1).o.deps; fi && \
\
echo -n "$(BIN_DIR)$(1).so: " > $(MODULES_DIR)$(1)/$(1).so.deps; cat $(MODULES_DIR)$(1)/$(1).o.deps >> $(MODULES_DIR)$(1)/$(1).so.deps && \
\
$(MAKE) `cat $(MODULES_DIR)$(1)/$(1).o.deps` --no-print-directory
 
# includes the generated dependencies for the .so (this takes effect in the recursive make call from the .o.deps rule)
-include $(MODULES_DIR)$(1)/$(1).so.deps
 
endef
 
$(foreach modname,$(MODULE_NAMES),$(eval $(call make_so,$(modname))))
 
#for number in 1 2 3 4 ; do \
#    ./a.out $$number ; \
#done
 
%.o : %.cpp
$(CC) -MMD -c $(CPPFLAGS) $< -o $@
 

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...