Skip to content

Commit 7632092

Browse files
committed
Add dev notes about macOS
1 parent ef8d7e9 commit 7632092

File tree

2 files changed

+122
-0
lines changed

2 files changed

+122
-0
lines changed

notes/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ The notes directory is sorted by platform.
1313

1414
## macOS
1515

16+
* [General](macos/README.md)
1617
* [Boost](macos/boost.md)
1718

1819
## Solaris

notes/macos/README.md

+121
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
# macOS Builds
2+
3+
## Xcode
4+
5+
Xcode contains the necessary tools to build packages on macOS such as `make`, `cc`, etc. Xcode is preinstalled on our macOS images. If it's missing or out of date, then the image will need to be updated.
6+
7+
The following command will show you where xcode is installed:
8+
9+
```
10+
# xcode-select -p
11+
/Library/Developer/CommandLineTools
12+
```
13+
14+
## Build Tools
15+
16+
Xcode ships a `gcc` binary, but it's actually clang(!)
17+
18+
```
19+
# which gcc
20+
/usr/bin/gcc
21+
# gcc --version
22+
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX12.1.sdk/usr/include/c++/4.2.1
23+
Apple clang version 13.0.0 (clang-1300.0.27.3)
24+
Target: x86_64-apple-darwin21.3.0
25+
Thread model: posix
26+
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
27+
```
28+
29+
## Homebrew
30+
31+
We use homebrew to install build dependencies like `automake`. It's a good idea to become [familiar with these Homebrew terms](https://docs.brew.sh/Manpage#terminology).
32+
33+
### Installation Directory
34+
35+
Homebrew installs itself into `/usr/local` on macOS Intel and [`/opt/homebrew` on macOS ARM](https://docs.brew.sh/FAQ#why-is-the-default-installation-prefix-opthomebrew-on-apple-silicon). To account for these differences you can use the [`brew` method in vanagon](https://github.com/puppetlabs/vanagon/commit/02134c79ce917fe82e6b201b9efd6faf73b1b116).
36+
37+
### Permissions
38+
39+
Homebrew does not allow itself to be run as root:
40+
41+
```
42+
# brew list
43+
Error: Running Homebrew as root is extremely dangerous and no longer supported.
44+
As Homebrew does not drop privileges on installation you would be giving all
45+
build scripts full access to your system
46+
```
47+
48+
So we create a `test` user and execute all `brew` commands as that user. Importantly, brew must be executed from a current working directory that the `test` user has access to, so you'll see things like:
49+
50+
```
51+
# cd /etc/homebrew
52+
# su test -c '/usr/local/bin/brew install cmake'
53+
```
54+
55+
### Symlinks
56+
57+
The `brew install <formula>` command will install a formula ("package definition from upstream sources") into the keg ("installation directory of a given formula version"). For example, if you `brew install cmake`, it will install into a versioned path such as:
58+
59+
```
60+
/usr/local/Cellar/cmake/3.29.2/bin/cmake
61+
```
62+
63+
Homebrew also creates symlinks in `/usr/local/bin`:
64+
65+
```
66+
# ls -la /usr/local/bin/cmake
67+
lrwxr-xr-x 1 test admin 32 May 6 20:42 /usr/local/bin/cmake -> ../Cellar/cmake/3.29.2/bin/cmake
68+
```
69+
70+
The symlinks are useful when installing a tool that needs to be executed during the build, such as cmake, autoconf, perl, etc.
71+
72+
However, you have to be careful when installing a homebrew formula (or one of its transitive dependencies) is also a vanagon component, such as `openssl`. For example, the `[email protected]` formula depends on `openssl@3` (currently 3.3.0). However, the agent's openssl component is currently `3.0.x`. By default, clang will prefer the headers that homebrew symlinked and compile against those. But at runtime, only the libraries that we built will be present.
73+
74+
To avoid conflicts, you should run `brew unlink <formula>` for any formula that is also a vanagon component.
75+
76+
One exception is if the formula is keg-only, which just means homebrew won't create symlinks. For example, [`readline` is keg-only](https://github.com/Homebrew/homebrew-core/blob/c0218d50084e300cba26da84028acfd4917ce623/Formula/r/readline.rb#L77)
77+
78+
## Troubleshooting
79+
80+
To view library dependencies, use `otool -L` (instead of `ldd`):
81+
82+
```
83+
# otool -L /opt/puppetlabs/puppet/lib/libcurl.dylib
84+
/opt/puppetlabs/puppet/lib/libcurl.dylib:
85+
/opt/puppetlabs/puppet/lib/libcurl.4.dylib (compatibility version 13.0.0, current version 13.0.0)
86+
/opt/puppetlabs/puppet/lib/libssl.3.dylib (compatibility version 3.0.0, current version 3.0.0)
87+
/opt/puppetlabs/puppet/lib/libcrypto.3.dylib (compatibility version 3.0.0, current version 3.0.0)
88+
/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.11)
89+
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1856.105.0)
90+
/System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices (compatibility version 1.0.0, current version 1141.1.0)
91+
/System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration (compatibility version 1.0.0, current version 1163.60.3)
92+
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1311.0.0)
93+
```
94+
95+
To view undefined symbols (which are expected to be defined in some other library). For example, `libcurl.dylib` expects the `_TLS_client_method` function to be defined in `libssl.dylib`:
96+
97+
```
98+
# nm -m /opt/puppetlabs/puppet/lib/libcurl.dylib | grep TLS_
99+
(undefined) external _TLS_client_method (from libssl)
100+
```
101+
102+
To view symbols defined in a library:
103+
104+
```
105+
# nm -gU /opt/puppetlabs/puppet/lib/libcurl.dylib | grep _curl_easy_init
106+
0000000000017fac T _curl_easy_init
107+
```
108+
109+
To trace how the dynamic loader (dyld) resolves library dependencies:
110+
111+
```
112+
# export DYLD_PRINT_LIBRARIES=1
113+
# /usr/local/Cellar/openssl\@3/3.3.0/bin/openssl version
114+
dyld[15123]: <E40CB605-B353-3E76-9988-2BD24334BDC1> /usr/local/Cellar/openssl@3/3.3.0/bin/openssl
115+
dyld[15123]: <EB3C4397-8AA0-3CCD-8235-34BE887EB194> /usr/local/Cellar/openssl@3/3.3.0/lib/libssl.3.dylib
116+
dyld[15123]: <71192998-23D0-3BAD-AAC9-DC90966A8177> /usr/local/Cellar/openssl@3/3.3.0/lib/libcrypto.3.dylib
117+
dyld[15123]: <155C5726-E0E6-3FAF-9CD5-CD8E043487D5> /usr/lib/libSystem.B.dylib
118+
dyld[15123]: <952A7572-D3ED-388C-8190-DD17DDCC6522> /usr/lib/system/libcache.dylib
119+
dyld[15123]: <9E46E39C-0DBB-333A-9597-23FA11E5B96C> /usr/lib/system/libcommonCrypto.dylib
120+
...
121+
```

0 commit comments

Comments
 (0)