从Linux切换到OS X的软件开发人员,有哪些陷阱?


50

我曾经使用过Ubuntu / Fedora / Red Hat / Suse,但根本没有使用过OSX。如果必须定期开始使用OS X,我应该注意些什么?

我使用的工具是GNU工具链,C ++ / Boost等。


您要开发更传统的Unix / Linux应用程序还是Mac OSX应用程序?
David Thornley,2010年

1
至少在起初,更多的是传统的Unix / Linux应用程序,我只是将OS X PC用作工作站。
grokus 2010年

Answers:


52

几年前,我也采取了同样的行动。这是我遇到的事情:

  • 您的普通台式机Linux具有比OS X更为丰富的用户空间。

    您可能会错过与我所使用的工具不同的工具,因此没有必要具体说明更换建议。

    相反,只需先安装FinkMacPortsHomebrew。这些系统提供了Linux或BSD典型的软件包管理系统。每个都有自己的风味和包装设置,因此正确的选择将取决于您的口味和需求。

    您可能会发现,没有一个软件包系统会包含您需要的每个程序。某些程序尚未移植到OS X,因此它们不会出现在任何软件包系统中。尽管如此,这些系统确实大大扩展了OS X附带的功能,并且将简化从Linux的过渡。

  • 现在,OS X命令行编译器默认情况下会生成64位可执行文件。

    在Leopard和更早版本中,编译器默认情况下构建32位可执行文件。这可能会以多种方式引起问题:也许您有旧的32位库,您不能重建但必须链接到它,也许您仍在32位模式下运行系统,等等。

    强制进行32位构建的一种方法是使用覆盖gcc构建系统中的默认设置gcc-4.0,即默认的旧32位Leopard编译器。(这gcc是到gcc-4.2Snow Leopard上默认情况下默认为64位的符号链接。)对于基于autoconf的构建系统,此方法有效:

    $ ./configure CC=gcc-4.0 CXX=g++-4.0
    

    CXX如果程序包含C ++组件,则仅需要此位。)

    另一种方法是传递-m32给编译器和链接器:

    $ ./configure CFLAGS=-m32 CXXFLAGS=-m32 LDFLAGS=-m32
    

    它的类型更多,但是它使您可以从较新的GCC中获得32位版本。

  • 动态链接有很大的不同。

    如果您喜欢ld手工编写命令,那么该打破这种习惯了。您应该改为通过编译器或类似的中介链接程序和库libtool。这些解决了特定于平台的轻巧链接方案的差异,因此您可以节省学习程序无法使用可移植机制而花的脑力。

    例如,您需要更新您的肌肉记忆,以便键入otool -L someprogram而不是ldd someprogram找出someprogram链接到哪些库。

    动态链接的另一个不同之处是,首先会使您不知所措的是,在OS X上,库的安装位置记录在库本身中,并且链接程序在链接时将其复制到可执行文件中。这意味着,如果您链​​接到已安装的库,/usr/local/lib但希望将其与可执行文件放置在同一目录中,则在安装过程中需要这样说:

    $ cp /usr/local/lib/libfoo.dylib .
    $ install_name_tool -id @loader_path/libfoo.dylib libfoo.dylib
    $ make LDFLAGS=-L. relink
    

    现在,以上大部分内容可能会因您的构建系统而有所不同,因此,仅以它为例,而不是一个诀窍。它的作用是使我们链接的库成为私有副本,将其共享库标识符从绝对路径更改为相对的含义,即“与可执行文件在同一目录中”,然后针对此修改后的副本强制重建可执行文件图书馆。

    install_name_tool是这里的核心命令。相反,如果您想将库安装在../lib相对于可执行文件的目录中,则-id必须使用参数@loader_path/../lib/libfoo.dylib

    Joe Di Pol 在这方面了一篇很好的文章,其中有很多详细信息。

  • 动态链接+第三方软件包可能会在早期引起头痛。

    一旦您开始尝试使用第三方程序包中没有将库安装到标准位置的库,则很可能会早日遇到动态链接问题。MacPorts会这样做,例如,将库安装到/opt/local/lib,而不是/usr/lib/usr/local/lib。遇到这种情况时,解决此问题的一个好方法是在您的计算机上添加以下内容.bash_profile

    # Tell the dynamic linker (dyld) where to find MacPorts package libs
    export DYLD_LIBRARY_PATH=/opt/local/lib:$DYLD_LIBRARY_PATH
    
    # Add MacPorts header file install dirs to your gcc and g++ include paths
    export C_INCLUDE_PATH=/opt/local/include:$C_INCLUDE_PATH
    export CPLUS_INCLUDE_PATH=/opt/local/include:$CPLUS_INCLUDE_PATH
    
  • OS X处理CPU兼容性问题的方式与Linux不同。

    在64位Linux上,无论出于何种原因您还必须支持32位,最终会得到诸如库之类的东西的两个副本,这些东西必须同时采用两种格式,而64位版本则位于与lib64目录平行的目录中。传统lib目录。

    OS X通过通用二进制概念以不同的方式解决了该问题,该概念使您可以将多个二进制文件放入单个文件中。当前,您可以具有支持多达4种CPU类型的可执行文件:32位和64位PowerPC,以及32位和64位Intel。

    使用Xcode构建通用二进制文件很容易,但是使用命令行工具有点麻烦。这使您可以使用基于Autoconf的构建系统进行通用的仅限Intel的构建:

    $ ./configure --disable-dependency-tracking CFLAGS='-arch i386 -arch x86_64' \
      LDFLAGS='-arch i386 -arch x86_64'
    

    添加-arch ppc -arch ppc64CFLAGSLDFLAGS如果需要PowerPC支持。

    如果您不禁用依赖关系跟踪,则最终只会为一个平台构建,因为第一个平台的新建.o文件的存在make(1)表明它也不需要为第二个平台构建。在上面的示例中,所有内容都必须构建两次。如果仍然需要PowerPC支持,则为完全通用的二进制文件四次。

    (有关更多信息,请参阅Apple技术说明TN2137。)

  • 默认情况下,开发人员工具未安装在OS X上。

    在Lion之前,为您的系统获取正确的开发工具的最可靠方法就是在OS光盘上。它们是可选安装。

    从OS光盘安装dev工具的好处是,您知道这些工具可以在OS上使用。作为苹果公司,您必须拥有最新版本的OS才能运行最新的编译器,而且它们并不总是能够下载旧工具,因此OS光盘通常是最简单的方法来找到给定的正确工具开发或测试框。

    有了Lion,他们正在努力消除安装媒体,因此,除非您购买昂贵的USB密钥版本,否则必须从App Store下载Xcode

    我建议您保留下载的Xcode DMG的至少几个版本。当Lion的后继产品问世一年或三年后,您可能会发现自己无法在Lion测试VM上同时安装Xcode版本。如果可用性问题和缺少OS介质导致无法获得旧版本的Xcode,请提前进行计划。


2
+1:专门提到动态链接。我发现它会非常相似。install_name的乐趣以及OSX动态链接编辑器如何dyld解决依赖关系!
Troubadour

关于保留旧版本的MacOS:如果要测试向后兼容性,请使用Parallel保持具有给定OS X版本的分离VM。我建议使用此工具或类似的工具进行应用测试。
ogerard

对于旧版本的开发人员工具,请访问connect.apple.com。我刚刚检查了一下,“开发人员工具”部分列出的第一个下载是2004年10月27日针对OS X 10.3+的Xcode 1.0。没有ProjectBuilder,但是Mac项目的SOP仅支持当前和以前的主要版本,因此10.3+绰绰有余。
Jeremy W. Sherman

@杰里米:更新。我不想向人们保证他们总是可以下载的,因为他们过去并不总是如此。
沃伦·杨

29

巨大的GOTCHA-Mac OS文件系统不区分大小写。


9
需要明确的是,它们是区分大小写的,默认情况下不区分大小写。因此,文件名的大小写将被保留,但是您可以通过任何大小写的变化来访问它。创建文件系统时,可以将其更改为区分大小写。
KeithB 2010年

9
@KeithB:但是,许多主流Mac应用程序都无法在区分大小写的文件系统上运行,例如Adobe CS甚至拒绝安装,并且《魔兽世界》也不会运行。我对此非常恼火,恢复的唯一方法是将系统备份并还原到重新格式化的磁盘上。
尼尔·梅

1
在处理版本控制以及在多平台团队中进行项目时,这主要是一个陷阱。
Arafangion 2010年

我创建了区分大小写的sparsebundle来解决此问题。幸运的是,我在此SSD上有一个未使用的分区。
dhchdhd 2012年

9

尽管Fink和MacPorts是在OS X上获取unix软件包的传统方法,但我还是建议您检阅一个更新的工具brew,该工具对我来说更有效,对系统的影响也更少,并且更易于使用。它基本上只是下载tarball并安装到/ usr / local,但是可以很好地自动完成整个过程。

http://mxcl.github.com/homebrew/


1
同意;与MacPorts相比,Homebrew为我工作的更加顺畅。
Jonik

4

巨大的GOTCHA-Mac OS文件系统不区分大小写。

您可以在Mac OS X上创建区分大小写的磁盘映像,该映像可以作为普通硬盘驱动器卷挂载。

# cf. http://codesnippets.joyent.com/posts/show/8617
IMAGE="${HOME}/Desktop/Case Sensitive Test.dmg"
VOLNAME="Case Sensitive Test"

hdiutil create "${IMAGE}" -size 10m -fs HFSX -volname "${VOLNAME}" -layout NONE

hdiutil attach "${IMAGE}"

cd "/Volumes/${VOLNAME}"
touch foo.txt Foo.txt
open .
ls -l [Ff]oo.txt
stat -f "inode: %i  --  name: %N" [Ff]oo.txt

cd ~
hdiutil detach "/Volumes/${VOLNAME}"


3

当将网络堆栈从Solaris,BSD,Linux和Windows移植到OSX时,引起关注的唯一要点是,就像FreeBSD一样,整个工具链都已经很老了。

苹果公司正在使用OSX Lion加快速度,但是Leopard,Snow Leopard远远落后于现代Linux发行版,并且不支持许多标准。以我为例,我感到非常不便,因为它缺少RFC 3678(用于多播源过滤器的套接字接口扩展)。

在OSX服务器上,我安装了区分大小写的文件系统,建议对HTTP服务这样做。

  • 老海湾合作委员会
  • 旧的Autoconf,Automake,libtool
  • 没有Pthread自旋锁,OSX提供了本机替代方案。
  • 重新租用的NSS API并不多。
  • 不太有用的/proc文件系统。
  • /dev/rtc/dev/hpet并且RDTSC似乎有些g。OSX提供了本机替代方案。
  • epoll,但您有poll和kqueue

1

OS X支持,pthread_cond_timedwait但是它使用绝对日历时间,并且无法使用单调增加的时间。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.