// Builds the FFmpeg 6.0 libraries mcap uses on macOS (avformat, avcodec, avutil, swscale and // swresample) from the release's source, its SHA-256 checked, and puts them in macos/ with the // headers the bindings are made from (generate.jai) in macos-build/install/include. The same version // as the Windows DLLs (windows/), so the two sets of bindings match. // // cd modules/ffmpeg && jai build_macos.jai // // An LGPL build: no GPL parts (the Windows DLLs are a GPL build with libx264), nothing from outside // macOS (--disable-autodetect, pkg-config pointed nowhere, so nothing from Homebrew is linked), and // VideoToolbox and AudioToolbox for the hardware codecs. Needs Apple's command line tools: curl, // tar, make and clang. A few minutes on Apple silicon. FFMPEG_VERSION :: "6.0"; FFMPEG_ARCHIVE :: "ffmpeg-6.0.tar.xz"; FFMPEG_SHA256 :: "57be87c22d9b49c112b6d24bc67d42508660e6b718b3db89c44e47e289137082"; BUILD_FOLDER :: "macos-build"; // the source, the build and the installed headers; not in git OUTPUT_FOLDER :: "macos"; // the libraries, in git as windows/ is // Each library as its major version names it, which is how they find each other (@rpath/...). LIBRARIES :: string.["libavcodec.60.dylib", "libavformat.60.dylib", "libavutil.58.dylib", "libswresample.4.dylib", "libswscale.7.dylib"]; CONFIGURE_OPTIONS :: string.[ "--install-name-dir=@rpath", "--enable-shared", "--disable-static", "--disable-programs", "--disable-doc", "--disable-avdevice", "--disable-avfilter", "--disable-postproc", "--disable-network", "--disable-autodetect", "--enable-videotoolbox", "--enable-audiotoolbox", "--enable-zlib", "--enable-bzlib", "--extra-cflags=-mmacosx-version-min=14.0", "--extra-ldflags=-mmacosx-version-min=14.0", ]; #run,stallable { set_build_options_dc(.{do_output = false}); #if OS != .MACOS { log_error("build_macos.jai builds on a Mac only."); return; } if !build() compiler_set_workspace_status(.FAILED); } build :: () -> bool { here := get_working_directory(); build_folder := tprint("%/%", here, BUILD_FOLDER); make_directory_if_it_does_not_exist(build_folder); archive := tprint("%/%", build_folder, FFMPEG_ARCHIVE); if !file_exists(archive) || sha256_of(archive) != FFMPEG_SHA256 { url := tprint("https://ffmpeg.org/releases/%", FFMPEG_ARCHIVE); log("Downloading %...", url); result := run_command("curl", "-L", "--fail", "--progress-bar", "-o", archive, url); if result.exit_code != 0 { log_error("curl failed (exit code %).", result.exit_code); return false; } hash := sha256_of(archive); if hash != FFMPEG_SHA256 { log_error("% has SHA-256 %, expected %; it was not used.", archive, hash, FFMPEG_SHA256); return false; } } source := tprint("%/ffmpeg-%", build_folder, FFMPEG_VERSION); install := tprint("%/install", build_folder); run_command("rm", "-rf", source, install); result := run_command("tar", "xf", archive, "-C", build_folder); if result.exit_code != 0 { log_error("tar could not unpack %.", archive); return false; } log("Configuring..."); arguments: [..] string; array_add(*arguments, "env", "PKG_CONFIG_LIBDIR=", "PKG_CONFIG_PATH=", "./configure", tprint("--prefix=%", install)); array_add(*arguments, ..CONFIGURE_OPTIONS); result = run_command(..arguments, working_directory = source); if result.exit_code != 0 { log_error("configure failed; see %/ffbuild/config.log.", source); return false; } log("Building..."); cpus := get_number_of_processors(); result = run_command("make", tprint("-j%", cpus), working_directory = source); if result.exit_code != 0 { log_error("make failed."); return false; } result = run_command("make", "install", working_directory = source); if result.exit_code != 0 { log_error("make install failed."); return false; } output := tprint("%/%", here, OUTPUT_FOLDER); run_command("rm", "-rf", output); make_directory_if_it_does_not_exist(output); for LIBRARIES { // The major-version name is a link to the full one; the file itself is copied under that name. if !copy_file(tprint("%/lib/%", install, it), tprint("%/%", output, it)) { log_error("Could not copy %.", it); return false; } run_command("strip", "-x", tprint("%/%", output, it)); } write_entire_file(tprint("%/LICENSE-BUILD.txt", output), tprint(LICENSE_TEXT, FFMPEG_VERSION, FFMPEG_ARCHIVE, FFMPEG_SHA256, join(..CONFIGURE_OPTIONS, "\n "))); log("Put % libraries in % and the headers in %/include (FFmpeg %, LGPL).", LIBRARIES.count, output, install, FFMPEG_VERSION); return true; } LICENSE_TEXT :: #string TEXT FFmpeg % shared libraries for macOS on Apple silicon, built by modules/ffmpeg/build_macos.jai. Source: https://ffmpeg.org/releases/% SHA-256: % License: LGPL version 2.1 or later (no GPL or non-free parts). The source is at the address above; the libraries are built from it unchanged, with these configure options: % TEXT // Lowercase hex, or "" when it could not be worked out. sha256_of :: (path: string) -> string { result, output := run_command("shasum", "-a", "256", path, capture_and_return_output = true); if result.exit_code != 0 return ""; return to_lower_copy(trim(split(output, " ")[0])); } #import "Basic"; #import "Compiler"; #import "File"; #import "File_Utilities"; #import "Process"; #import "String"; #import "System";