Java detection improved
[Fobs.git] / scripts / fobscons.py
blob43be14a3bd69f2d3377b73e1627a49de30de8304
1 import os
2 import sys
3 import subprocess
5 import fobs
6 import string
8 import os
9 from string import Template
11 class pkgconfig(dict):
12 def __init__(self, package, paths):
13 self._user_paths = paths
14 self._load(package, paths)
16 def _load(self, package, paths):
17 _paths = ['/usr/lib/pkgconfig', '/usr/local/lib/pkgconfig'] + paths
18 for path in _paths:
19 fn = os.path.join(path, '%s.pc' % package)
20 if os.path.exists(fn):
21 self._parse(fn)
23 def _parse(self, filename):
24 lines = open(filename).readlines()
25 lokals = {}
27 for line in lines:
28 line = line.strip()
30 if not line:
31 continue
32 elif ':' in line: # exported variable
33 name, val = line.split(':')
34 val = val.strip()
35 if '$' in val:
36 try:
37 val = Template(val).substitute(lokals)
38 except ValueError:
39 raise ValueError("Error in variable substitution!")
40 self[name] = val
41 elif '=' in line: # local variable
42 name, val = line.split('=')
43 if '$' in val:
44 try:
45 val = Template(val).substitute(lokals)
46 except ValueError:
47 raise ValueError("Error in variable substitution!")
48 lokals[name] = val
50 for item in self.get('Requires','').split():
51 if item == '=':
52 break
53 pkgClass = pkgconfig(item, self._user_paths)
54 self.merge(pkgClass)
56 def merge(self, pkgc):
57 self['Libs']=self.get('Libs','')+' '+pkgc.get('Libs','')
58 self['Cflags']=self.get('Cflags','')+' '+pkgc.get('Cflags','')
60 def get_output(self):
61 return self['Libs']+" "+self['Cflags']
64 def CustomParseConfig(env, command):
65 newenv = os.environ
66 for k,v in env['ENV'].iteritems():
67 newenv[k]=v
68 proc = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE,stderr=subprocess.PIPE,env=newenv)
69 out = proc.stdout.read()
70 proc.stdout.close()
71 err = proc.stderr.read()
72 proc.stderr.close()
73 status = proc.wait()
74 if err:
75 sys.stderr.write(err)
76 if status:
77 raise OSError("'%s' exited %d" % (command,status))
78 return env.MergeFlags(out)
81 def walkDirs(path):
82 """helper function to get a list of all subdirectories"""
83 def addDirs(pathlist, dirname, names):
84 """internal function to pass to os.path.walk"""
85 for n in names:
86 f = os.path.join(dirname, n)
87 if os.path.isdir(f):
88 pathlist.append(f)
89 pathlist = [path]
90 os.path.walk(path, addDirs, pathlist)
91 return pathlist
93 def ConfigureJNI(env):
94 """Configure the given environment for compiling Java Native Interface
95 c or c++ language files."""
96 try:
97 # if not env.get('JAVAC'):
98 # print "The Java compiler must be installed and in the current path."
99 # return 0
101 # first look for a shell variable called JAVA_HOME
102 java_base = os.environ.get('JAVA_HOME')
103 if not java_base:
104 if sys.platform == 'darwin':
105 # Apple's OS X has its own special java base directory
106 java_base = '/System/Library/Frameworks/JavaVM.framework'
107 else:
108 # Search for the java compiler
109 print "JAVA_HOME environment variable is not set. Searching for java... ",
110 jcdir = os.path.dirname(os.path.realpath(env.WhereIs('javac')))
111 if not jcdir:
112 print "not found."
113 return False
114 # assuming the compiler found is in some directory like
115 # /usr/jdkX.X/bin/javac, java's home directory is /usr/jdkX.X
116 java_base = os.path.abspath(os.path.join(jcdir, ".."))
117 print "found."
119 if sys.platform=='win32':
120 java_base=os.path.abspath(java_base)
122 print "\tJava found in: ",java_base
123 #test if jni.h exists in the target dir
124 jni_h_name = os.path.join(java_base, 'include', 'jni.h')
125 if not os.path.exists(jni_h_name):
126 print "Java detected in %s, but jni.h could not be found. Is this a JDK or a JRE folder?"
127 return false
129 if sys.platform == 'cygwin':
130 # Cygwin and Sun Java have different ideas of how path names
131 # are defined. Use cygpath to convert the windows path to
132 # a cygwin path. i.e. C:\jdkX.X to /cygdrive/c/jdkX.X
133 java_base = string.replace( \
134 os.popen("cygpath -up '"+java_base+"'").read(), '\n', '')
136 if sys.platform == 'darwin':
137 # Apple does not use Sun's naming convention
138 java_headers = [os.path.join(java_base, 'Headers')]
139 java_libs = [os.path.join(java_base, 'Libraries')]
140 else:
141 # windows and linux
142 java_headers = [os.path.join(java_base, 'include')]
143 java_libs = [os.path.join(java_base, 'lib')]
144 # Sun's windows and linux JDKs keep system-specific header
145 # files in a sub-directory of include
147 if java_base == '/usr' or java_base == '/usr/local':
148 # too many possible subdirectories. Just use defaults
149 java_headers.append(os.path.join(java_headers[0], 'win32'))
150 java_headers.append(os.path.join(java_headers[0], 'linux'))
151 java_headers.append(os.path.join(java_headers[0], 'solaris'))
152 else:
153 # add all subdirs of 'include'. The system specific headers
154 # should be in there somewhere
155 java_headers = walkDirs(java_headers[0])
157 # add Java's include and lib directory to the environment
158 env.Append(CPPPATH = java_headers)
159 env.Append(LIBPATH = java_libs)
161 # add any special platform-specific compilation or linking flags
162 if sys.platform == 'darwin':
163 env.Append(SHLINKFLAGS = '-dynamiclib -framework JavaVM')
164 env['SHLIBSUFFIX'] = '.jnilib'
165 elif sys.platform == 'cygwin':
166 env.Append(CCFLAGS = '-mno-cygwin')
167 env.Append(SHLINKFLAGS = '-mno-cygwin -Wl,--kill-at')
168 # Add extra potentially useful environment variables
169 env['JAVA_HOME'] = java_base
170 env['JNI_CPPPATH'] = java_headers
171 env['JNI_LIBPATH'] = java_libs
172 return True
173 except:
174 return False