Thread Rating:
  • 0 Votes - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Building ohNet for Mac OS X
30-01-2012, 07:21 AM
Post: #1
Building ohNet for Mac OS X
I'm getting user requests for MinimServer on Mac OS X, so I'd like to build libohNet.so and libohNetJni.so for Mac OS X. I've arranged to borrow a Mac for doing that and testing the results.

Before I start work on this, I'd like to confirm that the current codebase builds and runs on Mac OS X. Any suggestions for what I need to do to set up a suitable build environment would be very helpful, as I've never used a Mac before.

Thanks!

Simon
Find all posts by this user
30-01-2012, 10:44 AM
Post: #2
RE: Building ohNet for Mac OS X
Simon,

I can confirm that the current codebase builds and runs on Mac OS X (we currently use the Mac build for SongCast).

The Java build hasn't been tested, so there may be some issues. This is on our todo list, but happy to accept any patches in the meantime Smile.


Perhaps one thing to look out for is if GCC is installed. If not, it's probably best to download Xcode.

You can download this for free here: http://developer.apple.com/technologies/tools/
You will need to create an Apple ID if you don't have one already.

To build, it's just the basic "make" command in terminal on the root directory of ohnet.

To attempt to build for java, the command is "make ohNetJavaAll"

Cheers

Chris
Find all posts by this user
31-01-2012, 10:57 AM
Post: #3
RE: Building ohNet for Mac OS X
HI Chris,
Thanks very much! I'll keep you informed of progress.

Simon
Find all posts by this user
19-03-2012, 10:31 PM
Post: #4
RE: Building ohNet for Mac OS X
Here's the list of changes that I needed to apply to Makefile to get ohNet (including Java support) to build and run OK under Mac OS X.

1) In line 22, replace
Code:
linkopts_ohNet =
by
Code:
linkopts_ohNet = -Wl,-install_name,@loader_path/libohNet.so

This change is essential to enable libohNetJni.so to work correctly. It's the Mac OS X equivalent of the -Wl,-soname,libohNet.so option that needed to be added for Linux.

2) In lines 105 and 106, replace
Code:
includes_jni = -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux
link_jvm = $(JAVA_HOME)/jre/lib/i386/server/libjvm.so
by
Code:
includes_jni = -I/System/Library/Frameworks/JavaVM.framework/Headers -I/usr/include/malloc
link_jvm = /System/Library/Frameworks/JavaVM.framework/JavaVM

3) In lines 108 and 109, replace
Code:
javac = $(JAVA_HOME)/bin/javac
jar = $(JAVA_HOME)/bin/jar
by
Code:
javac = /usr/bin/javac
jar = /usr/bin/jar

4) In line 123, comment out the line
Code:
include T4Linux.mak

This change is also needed when building on Linux.

At the moment, I've just edited Makefile with these changes rather than adding conditionals or variables. I'd be happy to add conditionals/variables as well, but I've been a bit hesitant to attempt this as I might do it in a way that doesn't fit in with your build arrangements.
Find all posts by this user
20-03-2012, 09:09 AM (This post was last modified: 20-03-2012 09:15 AM by simoncn.)
Post: #5
RE: Building ohNet for Mac OS X
(19-03-2012 10:31 PM)simoncn Wrote:  At the moment, I've just edited Makefile with these changes rather than adding conditionals or variables. I'd be happy to add conditionals/variables as well, but I've been a bit hesitant to attempt this as I might do it in a way that doesn't fit in with your build arrangements.

I decided to go ahead and finish the job. Smile

Attached is a new Makefile with conditionals to include points 1) 2) and 3) when building for Intel Mac and leave everything unchanged when building for other platforms. I haven't done anything for point 4) as I assume there's a reason for having it, even though it prevents Makefile from working when run natively on Linux or Mac.

I've tested this on Mac and on Linux ARM and it seems to work OK.


Attached File(s)
.zip  Makefile.zip (Size: 3.06 KB / Downloads: 5)
Find all posts by this user
20-03-2012, 02:24 PM (This post was last modified: 20-03-2012 02:25 PM by simonc.)
Post: #6
RE: Building ohNet for Mac OS X
Thanks. I'll try to look through / incorporate your changes in the next couple of days.

Note that T4Linux.mak is used to generate code & makefiles for the audio proxies/providers ohNet includes. It does this using a standard tool - TextTransform - that is written in C#. If you had mono installed, this dependency wouldn't cause you any problems. We shouldn't assume that everyone has mono however so I'll look into making this conditional on a uset4 option in the same way as happens for Windows builds.
Find all posts by this user
20-03-2012, 03:59 PM
Post: #7
RE: Building ohNet for Mac OS X
(20-03-2012 02:24 PM)simonc Wrote:  Thanks. I'll try to look through / incorporate your changes in the next couple of days.

Note that T4Linux.mak is used to generate code & makefiles for the audio proxies/providers ohNet includes. It does this using a standard tool - TextTransform - that is written in C#. If you had mono installed, this dependency wouldn't cause you any problems. We shouldn't assume that everyone has mono however so I'll look into making this conditional on a uset4 option in the same way as happens for Windows builds.

Thanks very much! It's a bit of a nuisance having to edit in these changes every time I pick up a new level of ohNet. The uset4 option will help as well.

When you've added these to the official code, I'll go through a similar exercise to merge in my gcc 4.1.1 changes and post a modified Makefile with suitable conditionals / variables showing what I've done.
Find all posts by this user
22-03-2012, 04:18 PM
Post: #8
RE: Building ohNet for Mac OS X
I've integrated your changes and tried to build them. Most of them are clearly correct but I don't fully understand the -install_name change...

I'm not familiar with the -install_name linker option but from what I've read would have thought it was something that should be applied by the person creating an installer which includes a shared object. Presumably we can't choose any one value in ohNet which'll please all clients?

As an example of that, the value in your patch doesn't allow ohNet's unit tests to pass. They fail with the error Test: org.openhome.net.controlpoint.tests.TestCpDeviceDv
Exception in thread "main" java.lang.UnsatisfiedLinkError: no ohNet in java.library.path
.

Please put me right if I'm mis-understanding how -install_name should be used. If I'm not on the wrong track here, it might be better for you to take libohnetcore.a as produced by the ohNet build and link your own libohnet.so with your preferred install name.

What do you think?
Find all posts by this user
23-03-2012, 12:22 PM (This post was last modified: 23-03-2012 12:24 PM by simoncn.)
Post: #9
RE: Building ohNet for Mac OS X
(22-03-2012 04:18 PM)simonc Wrote:  I've integrated your changes and tried to build them. Most of them are clearly correct but I don't fully understand the -install_name change...

I'm not familiar with the -install_name linker option but from what I've read would have thought it was something that should be applied by the person creating an installer which includes a shared object. Presumably we can't choose any one value in ohNet which'll please all clients?

As an example of that, the value in your patch doesn't allow ohNet's unit tests to pass. They fail with the error Test: org.openhome.net.controlpoint.tests.TestCpDeviceDv
Exception in thread "main" java.lang.UnsatisfiedLinkError: no ohNet in java.library.path
.

Please put me right if I'm mis-understanding how -install_name should be used. If I'm not on the wrong track here, it might be better for you to take libohnetcore.a as produced by the ohNet build and link your own libohnet.so with your preferred install name.

What do you think?

I think I've more or less figured out what's going on here. It's not a simple story, so bear with me. Smile

1) The problem with the test case isn't caused by the install_name setting. I tried removing this completely and the test case still failed.

2) The reason that the test case fails is that Mac OS X Java for some bizarre reason expects JNI libraries to have the extension .jnilib rather than .so. So when the Java code in InitParams.java (and other places) calls
System.loadLibrary("ohNet");
the Java runtime looks for a file named libohNet.jnilib, which doesn't exist.

3) MinimServer is working OK with libohNet.so because it uses a custom classloader that forces a search for a .so extension instead of the default .jnilib.

4) One way round this would be to produce a libohNet.so for non-Java use and an almost identical libohNet.jnilib for Java use. This seems very undesirable, and fortunately there's a better solution.

5) The better solution is to change the code in the .java files to remove all the calls to
System.loadLibrary("ohNet");
and retain all the calls to
System.loadLibrary("ohNetJni");
This is the recommended JNI pattern, as there no reason for Java to load libohNet.so itself. If Java loads libohNetJni.jnilib [**edited to correct typo**], the Mac OS X dynamic linker can pull in libohNet.so, and this should be the same libohNet.so that's used by non-Java code. This approach should work on all platforms.

I'm going to try making this change in all the Java files. When this part is working correctly and the test case is running, I'll move on to looking into the correct setting for install_name.
Find all posts by this user
25-03-2012, 09:28 PM
Post: #10
RE: Building ohNet for Mac OS X
(23-03-2012 12:22 PM)simoncn Wrote:  5) The better solution is to change the code in the .java files to remove all the calls to
System.loadLibrary("ohNet");
and retain all the calls to
System.loadLibrary("ohNetJni");
This is the recommended JNI pattern, as there no reason for Java to load libohNet.so itself. If Java loads libohNetJni.jnilib [**edited to correct typo**], the Mac OS X dynamic linker can pull in libohNet.so, and this should be the same libohNet.so that's used by non-Java code. This approach should work on all platforms.

I'm going to try making this change in all the Java files. When this part is working correctly and the test case is running, I'll move on to looking into the correct setting for install_name.

I've got this change working on Mac OS X, but unfortunately it causes problems with finding the ohNet library on other platforms, especially Windows.

I've been doing a bit more web searching to find another solution. On Mac OS X, the normal extension for shared libraries is .dylib, although .so is also allowed. Mac OS X Java accepts .dylib as an alternative to .jnilib for JNI libraries. So if libohNet.so and libohNetJni.so are renamed to libohNet.dylib and libohNetJni.dylib, the test cases work with no need to change the .java files. The change from .so to .dylib also has the advantage of conforming to standard Mac OS X naming conventions.

I'll produce an updated Makefile that does this, and I'll send another post tomorrow with details of the install_name issue.
Find all posts by this user


Forum Jump: