#!/usr/bin/env python ## Copyright (c) 2015 Olivier Gayot ## ## ## Permission is hereby granted, free of charge, to any person obtaining a ## copy of this software and associated documentation files (the "Software"), to ## deal in the Software without restriction, including without limitation the ## rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ## sell copies of the Software, and to permit persons to whom the Software is ## furnished to do so, subject to the following conditions: ## ## The above copyright notice and this permission notice shall be included in ## all copies or substantial portions of the Software. ## ## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ## SOFTWARE. class makefile_generator(): def __init__(self): self._binary = 'a.out' self.phony = [] def append_variable(self, name, value=''): print('%s%.*s= %s' % (name, 16 - len(name), ' ', value)) def append_separator(self): print('') def append_rule(self, target, dep='', cmds=[]): print('%s: %s' % (target, dep)) for cmd in cmds: print('\t%s' % (cmd)) self.append_separator() def append_static_rule(self, target, dep='', cmds=[]): self.append_rule(target, dep, cmds) self.phony.append(target) def gen(self): # mandatory input self.append_variable('NAME', self._binary) self.append_variable('SRC', '$(wildcard *.%s)' % (self._extension)) self.append_separator() # optional input self.append_variable('CPPFLAGS') self.append_variable('LDFLAGS') self.append_variable(self._compiler_flags_var, self._compiler_flags) self.append_separator() self.append_variable(self._compiler_var, self._compiler) self.append_separator() # make use of implicit rules self.append_variable('OBJ', '$(SRC:.%s=.o)' % (self._extension)) self.append_variable('DEP', '$(SRC:.%s=.d)' % (self._extension)) self.append_separator() # first rule to be evaluated self.append_static_rule('all', '$(NAME)') # linkage self.append_rule('$(NAME)', '$(OBJ)', [ '$(%s) -o "$@" $^ $(LDFLAGS)' % (self._compiler_var) ]) # include dependencies print('-include $(DEP)') self.append_separator() # rule to generate dependencies self.append_rule('%.d', '%%.%s' % (self._extension), [ '$(%s) -MM $(CPPFLAGS) $(%s) $< -MF $@ -MT "$*.o $@"' % (self._compiler_var, self._compiler_flags_var), ]) self.append_static_rule('clean', cmds=[ '$(RM) $(OBJ)', '$(RM) $(NAME)', ]) self.append_static_rule('mrproper', 'clean', [ '$(RM) $(DEP)', ]) self.append_static_rule('distclean', 'mrproper', [ '$(RM) $(addsuffix ~,$(SRC))', ]) # phony rule self.append_rule('.PHONY', ' '.join(self.phony)) class makefile_generator_c(makefile_generator): def __init__(self): self._compiler_var = 'CC' self._compiler_flags_var = 'CFLAGS' self._compiler = 'gcc' self._compiler_flags = '-W -Wall -Wextra -std=gnu99' self._extension = 'c' super().__init__() class makefile_generator_cpp(makefile_generator): def __init__(self): self._compiler_var = 'CXX' self._compiler_flags_var = 'CXXFLAGS' self._compiler = 'g++' self._compiler_flags = '-W -Wall -Wextra -Weffc++' self._extension = 'cpp' super().__init__() def main(): generator = makefile_generator_c() generator.gen() if __name__ == '__main__': main()