Class: Funit::C_compile

Inherits:
Object
  • Object
show all
Defined in:
lib/funit/c_tools.rb

Instance Method Summary collapse

Constructor Details

#initializeC_compile

Returns a new instance of C_compile.



3
4
5
6
# File 'lib/funit/c_tools.rb', line 3

def initialize
  check_c_compiler
  @libraries = {}
end

Instance Method Details

#check_c_compilerObject



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/funit/c_tools.rb', line 8

def check_c_compiler
  if(ENV['CXX'].nil?) then
    puts "    \n      You have not specified a C++ compiler. Please specify a compiler via the $(CXX) environment variable.\n      \n      In bash, for example:\n        \n        export CXX=\"g++\"\n  \n    EOF\n  elsif(ENV['CC'].nil?) then\n    puts <<-EOF\n    \n      You have not specified a C compiler. Please specify a compiler via the $(CC) environment variable.\n      \n      In bash, for example:\n        \n        export CC=\"gcc\"\n        \n    EOF\n  exit\n  end\nend\n"

#clean_c_codeObject



79
80
81
82
83
84
85
86
87
88
# File 'lib/funit/c_tools.rb', line 79

def clean_c_code
  @libraries.keys.each do |k| 
    Dir.chdir(k) do
      puts "cleaning C code in #{k}"
      make_clean = "make -f makeTestRunner clean"
      system make_clean
      FileUtils.rm "makeTestRunner"
    end
  end
end

#compile_library(dir) ⇒ Object



33
34
35
36
37
38
39
# File 'lib/funit/c_tools.rb', line 33

def compile_library(dir)
  puts "building: #{dir}"
  Dir.chdir(dir) do
    static_lib = make_objs
    @libraries[dir]=static_lib.match(/lib(\w+)\.a/).captures.join
  end
end

#make_objs(dir = Dir.getwd) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/funit/c_tools.rb', line 41

def make_objs(dir=Dir.getwd)
  if File.exist?("Makefile.am")
    sources = parse_automake_file
    static_library = sources[0]
    File.open("makeTestRunner", "w") {|file| file.puts write_custom_c_makefile(sources)}
  else
static_library = "lib#{File.basename(Dir.getwd)}.a"
    File.open("makeTestRunner", "w") {|file| file.puts write_generic_c_makefile(static_library)}
  end
  compile = "make -f makeTestRunner"
  raise "Compile failed in #{dir}." unless system compile
  static_library
end

#parse_automake_fileObject



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/funit/c_tools.rb', line 55

def parse_automake_file
  sources = []
  lines = IO.readlines("Makefile.am")
  while line = lines.shift
    sources << $1 if line.match(/^\s*lib_LIBRARIES\s*=\s*(\w+\.a)/)
    if line.match(/^\s*\w+_SOURCES\s*=/)
      sources << line.scan(/\w+\.cpp/)
      while line.match(/\\\s*$/)
        line = lines.shift
        sources << line.scan(/(\w+\.cpp)|(\w+\.c)/)
      end
    end
  end
  sources.uniq.flatten.compact
end


71
72
73
74
75
76
77
# File 'lib/funit/c_tools.rb', line 71

def print_linker_flags
  output_string = ''
  @libraries.each do |k,v|
    output_string += " -L#{k} -l#{v}"
  end
  output_string += " -lstdc++"
end

#write_custom_c_makefile(sources) ⇒ Object



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/funit/c_tools.rb', line 149

def write_custom_c_makefile(sources)
  library = sources.shift
  source_files = sources.join(" ")
  c_makefile = %Q{
  # makefile to compile c++ code
  # Add .d to Make's recognized suffixes.
  SUFFIXES += .d
 
  #Archive command and options 
  AR = ar
  AR_OPTS = cru
   
  LIBRARY = #{library}
   
  SOURCES = #{source_files}
  
  #These are the dependency files, which make will clean up after it creates them
  CFILES:=$(SOURCES:.cpp=.c)
  DEPFILES:=$(CFILES:.c=.d)
 
  OBJS:=$(CFILES:.c=.o)
  
  all: $(LIBRARY)
 
  #Rule to create library archive 
  $(LIBRARY): $(OBJS)
  \t$(AR) $(AR_OPTS) $@ $^
  
  #Don't create dependencies when we're cleaning, for instance
  ifeq (0, $(words $(findstring $(MAKECMDGOALS), $(NODEPS))))
      #Chances are, these files don't exist.  GMake will create them and
      #clean up automatically afterwards
      -include $(DEPFILES)
  endif

  #This is the rule for creating the C++ dependency files
  %.d: %.cpp
  \t$(CXX) $(CXXFLAGS) -MM -MT '$(patsubst %.cpp,%.o,$<)' $< -MF $@
  
  #This is the rule for creating the C dependency files
  %.d: %.c
  \t$(CC) $(CFLAGS) -MM -MT '$(patsubst %.c,%.o,$<)' $< -MF $@
  
  #This rule does the compilation for C++ files
  %.o: %.cpp %.d %.h
  \t$(CXX) $(CXXFLAGS) -o $@ -c $<
  
  #This rule does the compilation for C files
  %.o: %.c %.d %.h
  \t$(CC) $(CFLAGS) -o $@ -c $<
  
  clean:
  \trm -rf *.o *.d *.a
  }.gsub!(/^      /,'')
end

#write_generic_c_makefile(library) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/funit/c_tools.rb', line 90

def write_generic_c_makefile(library)
  c_makefile = %Q{
  # makefile to compile c++ code
  # Add .d to Make's recognized suffixes.
  SUFFIXES += .d
  
  #Archive command and options 
  AR = ar
  AR_OPTS = cru
   
  LIBRARY = #{library}
   
  #We don't need to clean up when we're making these targets
  NODEPS:=clean tags svn
  #Find all the C++ files in this directory
  SOURCES:=$(shell find . -name "*.cpp")
  SOURCES+=$(shell find . -name "*.c")
  
  #These are the dependency files, which make will clean up after it creates them
  CFILES:=$(SOURCES:.cpp=.c)
  DEPFILES:=$(CFILES:.c=.d)
   
  OBJS:=$(CFILES:.c=.o)
  
  all: $(LIBRARY)
  
  #Rule to create library archive 
  $(LIBRARY): $(OBJS)
  \t$(AR) $(AR_OPTS) $@ $^

  #Don't create dependencies when we're cleaning, for instance
  ifeq (0, $(words $(findstring $(MAKECMDGOALS), $(NODEPS))))
      #Chances are, these files don't exist.  GMake will create them and
      #clean up automatically afterwards
      -include $(DEPFILES)
  endif

  #This is the rule for creating the C++ dependency files
  %.d: %.cpp
  \t$(CXX) $(CXXFLAGS) -MM -MT '$(patsubst %.cpp,%.o,$<)' $< -MF $@
  
  #This is the rule for creating the C dependency files
  %.d: %.c
  \t$(CC) $(CFLAGS) -MM -MT '$(patsubst %.c,%.o,$<)' $< -MF $@
  
  #This rule does the compilation for C++ files
  %.o: %.cpp %.d %.h
  \t$(CXX) $(CXXFLAGS) -o $@ -c $<
  
  #This rule does the compilation for C files
  %.o: %.c %.d %.h
  \t$(CC) $(CFLAGS) -o $@ -c $<
  
  clean:
  \trm -rf *.o *.d *.a

  }.gsub!(/^      /,'')
end